From 7776a0c400810ce92397a1a75e27ecb93cc0bfcc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 01:23:19 +0000 Subject: [PATCH 01/36] Bump cypress from 15.12.0 to 15.13.0 in /ui-tests Bumps [cypress](https://github.com/cypress-io/cypress) from 15.12.0 to 15.13.0. - [Release notes](https://github.com/cypress-io/cypress/releases) - [Changelog](https://github.com/cypress-io/cypress/blob/develop/CHANGELOG.md) - [Commits](https://github.com/cypress-io/cypress/compare/v15.12.0...v15.13.0) --- updated-dependencies: - dependency-name: cypress dependency-version: 15.13.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- ui-tests/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui-tests/package-lock.json b/ui-tests/package-lock.json index 12b38960975..69b828083d7 100644 --- a/ui-tests/package-lock.json +++ b/ui-tests/package-lock.json @@ -1351,9 +1351,9 @@ } }, "node_modules/cypress": { - "version": "15.12.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-15.12.0.tgz", - "integrity": "sha512-B2BRcudLfA4NZZP5QpA45J70bu1heCH59V1yKRLHAtiC49r7RV03X5ifUh7Nfbk8QNg93RAsc6oAmodm/+j0pA==", + "version": "15.13.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-15.13.0.tgz", + "integrity": "sha512-hJ9sY++TUC/HlUzHVJpIrDyqKMjlhx5PTXl/A7eA91JNEtUWkJAqefQR5mo9AtLra/9+m+JJaMg2U5Qd0a74Fw==", "hasInstallScript": true, "license": "MIT", "dependencies": { From eec44d64167d5bd06a2e5b381034a6af5e8c815f Mon Sep 17 00:00:00 2001 From: Hakan Date: Thu, 2 Apr 2026 11:34:48 +0300 Subject: [PATCH 02/36] Update countly.install_rhel.sh to keep only raven-release Removed installation of ipa-gothic-fonts package for RHEL. --- bin/countly.install_rhel.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/countly.install_rhel.sh b/bin/countly.install_rhel.sh index 80b5bb61e8f..fbcbbf4ccf0 100644 --- a/bin/countly.install_rhel.sh +++ b/bin/countly.install_rhel.sh @@ -53,7 +53,6 @@ if [[ "$CENTOS_MAJOR" = "9" ]]; then else curl -L -O -J "https://box.tools.count.ly/public.php/dav/files/Wj8opzNdyE5DyDX/?accept=zip" sudo yum install -y raven-release.el8.noarch.rpm - sudo yum install -y ipa-gothic-fonts fi #Install dependancies required by the puppeteer From 6beb0304b10b18fc7319be9f7da5ab4a2d72ee2b Mon Sep 17 00:00:00 2001 From: Hakan Date: Thu, 2 Apr 2026 11:35:36 +0300 Subject: [PATCH 03/36] Remove ipa-gothic-fonts installation Removed installation of ipa-gothic-fonts from Dockerfile. --- Dockerfile-centos-api | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile-centos-api b/Dockerfile-centos-api index df38125e16d..2bf0c27fa90 100644 --- a/Dockerfile-centos-api +++ b/Dockerfile-centos-api @@ -52,7 +52,6 @@ RUN curl -s -L -o /tmp/tini.rpm "https://github.com/krallin/tini/releases/downlo yum install -y pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc && \ curl -L -O -J "https://box.tools.count.ly/public.php/dav/files/Wj8opzNdyE5DyDX/?accept=zip" && \ yum install -y raven-release.el8.noarch.rpm && \ - yum install -y ipa-gothic-fonts && \ yum install -y wget openssl-devel make git libsqlite* sqlite unzip bzip2 && \ # modify standard distribution ./bin/docker/modify.sh && \ From a2cfed5d173a804716ea039c20daf8e4159f861c Mon Sep 17 00:00:00 2001 From: Danu Widatama Date: Fri, 3 Apr 2026 18:55:46 +0700 Subject: [PATCH 04/36] [data-manager] Add new message for user property update --- .../frontend/public/localization/data-manager.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/data-manager/frontend/public/localization/data-manager.properties b/plugins/data-manager/frontend/public/localization/data-manager.properties index 69377808b86..c8fc93ed2ea 100644 --- a/plugins/data-manager/frontend/public/localization/data-manager.properties +++ b/plugins/data-manager/frontend/public/localization/data-manager.properties @@ -26,6 +26,8 @@ data-manager.validations = Validations data-manager.user-properties = User Properties data-manager.custom-property = Custom Property data-manager.user-property = User Property +data-manager.user-property.update-success = User property changes saved successfully +data-manager.user-property.update-fail = Failed saving user property changes data-manager.all-data-sources = All data sources data-manager.created = Transformation Created! data-manager.saved = Transformation Saved! From 40aa83d4b0234ad2eb7da6ae822801896356b790 Mon Sep 17 00:00:00 2001 From: Danu Widatama Date: Fri, 3 Apr 2026 19:20:20 +0700 Subject: [PATCH 05/36] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecfbf3aeaac..1b4bc34c982 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ Fixes: - [core] Fixed duplicate conditional in form field template +Enterprise Fixes: +- [data-manager] Fix notification message after editing user property +- [white-labeling] Update newsletter setting description + ## Version 25.03.41 Fixes: - [push] Fix: Cannot create a push notification when configuration _id is a string From 704867e1f48ada23935dec59c822f0ca3e9fcc3d Mon Sep 17 00:00:00 2001 From: Cihad Tekin Date: Mon, 6 Apr 2026 17:07:26 +0300 Subject: [PATCH 06/36] [core] A script to fix the missing custom user properties in drill meta --- .../fix-data/fix_missing_custom_user_props.js | 379 ++++++++++++++++++ 1 file changed, 379 insertions(+) create mode 100644 bin/scripts/fix-data/fix_missing_custom_user_props.js diff --git a/bin/scripts/fix-data/fix_missing_custom_user_props.js b/bin/scripts/fix-data/fix_missing_custom_user_props.js new file mode 100644 index 00000000000..73c8a35729b --- /dev/null +++ b/bin/scripts/fix-data/fix_missing_custom_user_props.js @@ -0,0 +1,379 @@ +/** + * Description: This script fixes missing custom user properties in drill_meta + * or adds new values to existing biglist properties. + * It scans the app_users collection for the specified custom properties and + * ensures they are present in drill_meta with correct types and values. + * Path: $(countly dir)/bin/scripts/fix-data + * Command: node fix_missing_custom_user_props.js + */ + +const pluginManager = require('../../../plugins/pluginManager.js'); + +const APP_ID = ""; // required: set the app ID to process +const PROPS = []; // required: specify custom property names to fix, e.g. ["myProp1", "myProp2"] +const START = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); // default: 30 days ago +const END = new Date(); // default: now +const dry_run = true; + +let LIST_LIMIT = 100; +let BIG_LIST_LIMIT = 1000; + +if (!APP_ID) { + console.error("Error: APP_ID is required. Please set it in the script."); + process.exit(1); +} + +if (!PROPS.length) { + console.error("Error: PROPS is required. Please specify at least one property name to fix."); + process.exit(1); +} + +Promise.all([ + pluginManager.dbConnection("countly"), + pluginManager.dbConnection("countly_drill") +]).then(async function([countlyDb, drillDb]) { + console.log("Connected to databases..."); + console.log("Date range: " + START.toISOString() + " - " + END.toISOString()); + console.log("Properties to fix: " + PROPS.join(", ")); + + var lacStart = Math.round(START.getTime() / 1000); + var lacEnd = Math.round(END.getTime() / 1000); + var lacMatch = {$gt: lacStart, $lt: lacEnd}; + var collection = "app_users" + APP_ID; + + try { + // Load drill config limits from the database if available + var pluginsDoc = await countlyDb.collection("plugins").findOne({_id: "plugins"}); + if (pluginsDoc && pluginsDoc.drill) { + if (pluginsDoc.drill.list_limit !== undefined) { + LIST_LIMIT = parseInt(pluginsDoc.drill.list_limit, 10) || LIST_LIMIT; + } + if (pluginsDoc.drill.big_list_limit !== undefined) { + BIG_LIST_LIMIT = parseInt(pluginsDoc.drill.big_list_limit, 10) || BIG_LIST_LIMIT; + } + } + console.log("Limits: list_limit=" + LIST_LIMIT + ", big_list_limit=" + BIG_LIST_LIMIT); + + // Get existing drill_meta for user properties + var metaDoc = await drillDb + .collection("drill_meta") + .findOne({_id: APP_ID + "_meta_up"}); + var existingCustom = (metaDoc && metaDoc.custom) ? metaDoc.custom : {}; + console.log("Existing custom keys in drill_meta: " + Object.keys(existingCustom).length); + + // Load existing biglist documents for the requested props + var existingBigLists = {}; + for (var p = 0; p < PROPS.length; p++) { + var bigListId = APP_ID + "_meta_up_custom." + encodeKey(PROPS[p]); + var bigListDoc = await drillDb.collection("drill_meta").findOne({_id: bigListId}); + if (bigListDoc && bigListDoc.values) { + existingBigLists[PROPS[p]] = bigListDoc.values; + } + } + + // Process each property + var mainDocUpdate = {}; + var bigListUpdates = []; + var bigListCreates = []; + + for (var pi = 0; pi < PROPS.length; pi++) { + var prop = PROPS[pi]; + var fieldPath = "custom." + prop; + var existingMeta = existingCustom[prop]; + + console.log("[" + (pi + 1) + "/" + PROPS.length + "] Processing \"" + prop + "\"..."); + + // If property already exists and is not a list type, skip entirely + if (existingMeta && existingMeta.type !== "l" && existingMeta.type !== "a" && existingMeta.type !== "bl") { + console.log(" [SKIP] Already exists with type: " + existingMeta.type + " (not a list type, nothing to update)"); + continue; + } + + if (!existingMeta) { + // New property — determine type from a small sample first + var samples = await countlyDb.collection(collection).aggregate([ + {$match: {lac: lacMatch, [fieldPath]: {$exists: true}}}, + {$project: {_id: 0, val: "$" + fieldPath}}, + {$limit: 100} + ]).toArray(); + + if (samples.length === 0) { + console.log(" No users with this property in the given date range."); + continue; + } + + var isArray = samples.some(function(s) { + return Array.isArray(s.val); + }); + var sampleValues = []; + for (var si = 0; si < samples.length; si++) { + if (Array.isArray(samples[si].val)) { + for (var ai = 0; ai < samples[si].val.length; ai++) { + sampleValues.push(samples[si].val[ai] + ""); + } + } + else { + sampleValues.push(samples[si].val + ""); + } + } + + var type = determineType(sampleValues, isArray); + + if (type === "n" || type === "d") { + console.log(" [NEW] type: " + type + " (determined from " + samples.length + " samples, no values to collect)"); + mainDocUpdate["custom." + prop + ".type"] = type; + continue; + } + + // List/array type — need full distinct values aggregation + console.log(" [NEW] type: " + type + ", collecting distinct values..."); + var distinctValues = await aggregateDistinctValues(countlyDb, collection, fieldPath, lacMatch, isArray); + var totalDistinct = Object.keys(distinctValues).length; + console.log(" Found " + totalDistinct + " distinct value(s)"); + + // Apply limits + if (totalDistinct > BIG_LIST_LIMIT) { + // Too many values — convert to string type, no values tracked + console.log(" [WARNING] " + totalDistinct + " values exceeds big_list_limit (" + BIG_LIST_LIMIT + "). Setting type to 's' (string). Values will not be tracked."); + mainDocUpdate["custom." + prop + ".type"] = "s"; + continue; + } + + if (totalDistinct > LIST_LIMIT) { + // Between list_limit and big_list_limit — use bl type + console.log(" [INFO] " + totalDistinct + " values exceeds list_limit (" + LIST_LIMIT + "). Setting type to 'bl' (big list) instead of '" + type + "'."); + type = "bl"; + } + + mainDocUpdate["custom." + prop + ".type"] = type; + + var createValues = {}; + for (var cv in distinctValues) { + var enc = encodeKey(cv).trim(); + if (enc !== "") { + createValues[enc] = true; + } + } + bigListCreates.push({ + _id: APP_ID + "_meta_up_custom." + encodeKey(prop), + app_id: APP_ID, + type: "up", + e: "custom", + biglist: true, + values: createValues + }); + } + else { + // Existing list type — collect distinct values and find new ones + console.log(" Existing type: " + existingMeta.type + ", collecting distinct values..."); + + var isArrayExisting = existingMeta.type === "a"; + var distinctValuesExisting = await aggregateDistinctValues(countlyDb, collection, fieldPath, lacMatch, isArrayExisting); + var existingValues = existingBigLists[prop] || {}; + var existingCount = Object.keys(existingValues).length; + + var newValues = {}; + for (var dv in distinctValuesExisting) { + var enc2 = encodeKey(dv).trim(); + if (enc2 !== "" && !existingValues[enc2]) { + newValues[enc2] = true; + } + } + + var newCount = Object.keys(newValues).length; + if (newCount === 0) { + console.log(" [SKIP] No new values (all " + Object.keys(distinctValuesExisting).length + " already in biglist)"); + continue; + } + + var totalAfterUpdate = existingCount + newCount; + + // Check if adding new values would exceed big_list_limit + if (totalAfterUpdate > BIG_LIST_LIMIT) { + console.log(" [WARNING] Adding " + newCount + " new values would bring total to " + totalAfterUpdate + ", exceeding big_list_limit (" + BIG_LIST_LIMIT + "). Converting type to 's' (string). Values will no longer be tracked."); + mainDocUpdate["custom." + prop + ".type"] = "s"; + // Don't add values — the biglist doc will become stale but that's consistent + // with how drill.js handles this (checkListsInMeta deletes it later) + continue; + } + + // Check if adding new values would cross the list_limit threshold (l -> bl) + if (existingMeta.type === "l" && totalAfterUpdate > LIST_LIMIT) { + console.log(" [INFO] Adding " + newCount + " new values would bring total to " + totalAfterUpdate + ", exceeding list_limit (" + LIST_LIMIT + "). Upgrading type from 'l' to 'bl' (big list)."); + mainDocUpdate["custom." + prop + ".type"] = "bl"; + } + + console.log(" [UPDATE] " + newCount + " new value(s) to add (existing: " + existingCount + ", after: " + totalAfterUpdate + ")"); + bigListUpdates.push({ + id: APP_ID + "_meta_up_custom." + encodeKey(prop), + propKey: prop, + newValues: newValues + }); + } + } + + // Check if there's anything to do + if (Object.keys(mainDocUpdate).length === 0 && bigListCreates.length === 0 && bigListUpdates.length === 0) { + console.log("\nNothing to update."); + return; + } + + if (dry_run) { + if (Object.keys(mainDocUpdate).length > 0) { + console.log("\nDRY RUN: Would update main meta document (" + APP_ID + "_meta_up) with:"); + console.log(JSON.stringify(mainDocUpdate, null, 2)); + } + if (bigListCreates.length > 0) { + console.log("DRY RUN: Would create " + bigListCreates.length + " biglist document(s):"); + for (var b = 0; b < bigListCreates.length; b++) { + console.log(" _id: " + bigListCreates[b]._id + " (" + Object.keys(bigListCreates[b].values).length + " values)"); + } + } + if (bigListUpdates.length > 0) { + console.log("DRY RUN: Would update " + bigListUpdates.length + " existing biglist document(s):"); + for (var u = 0; u < bigListUpdates.length; u++) { + console.log(" _id: " + bigListUpdates[u].id + " (+" + Object.keys(bigListUpdates[u].newValues).length + " new values)"); + } + } + } + else { + // Update main meta_up document for new properties + if (Object.keys(mainDocUpdate).length > 0) { + await drillDb.collection("drill_meta").updateOne( + {_id: APP_ID + "_meta_up"}, + {$set: mainDocUpdate}, + {upsert: true} + ); + console.log("Updated main meta document."); + } + + var bulk = null; + + // Create new biglist documents + for (var b2 = 0; b2 < bigListCreates.length; b2++) { + if (!bulk) { + bulk = drillDb.collection("drill_meta").initializeUnorderedBulkOp(); + } + var doc = bigListCreates[b2]; + var docId = doc._id; + delete doc._id; + bulk.find({_id: docId}).upsert().updateOne({$set: doc}); + } + + // Update existing biglist documents with new values + for (var u2 = 0; u2 < bigListUpdates.length; u2++) { + if (!bulk) { + bulk = drillDb.collection("drill_meta").initializeUnorderedBulkOp(); + } + var setObj = {}; + var nv = bigListUpdates[u2].newValues; + for (var vk in nv) { + setObj["values." + vk] = true; + } + bulk.find({_id: bigListUpdates[u2].id}).upsert().updateOne({$set: setObj}); + } + + if (bulk) { + await bulk.execute(); + console.log("Executed " + (bigListCreates.length + bigListUpdates.length) + " biglist operation(s)."); + } + } + } + catch (err) { + console.error("Error:", err); + } + finally { + countlyDb.close(); + drillDb.close(); + console.log("\nDone."); + } +}); + +/** + * Aggregate distinct values for a custom property using MongoDB aggregation + * @param {Db} db - database connection + * @param {string} collectionName - app_users collection name + * @param {string} fieldPath - dot-notation field path (e.g. "custom.myProp") + * @param {object} lacMatch - lac range filter ({$gt, $lt}) + * @param {boolean} isArray - whether to unwind array values + * @returns {object} map of distinct values {value: true, ...} + */ +async function aggregateDistinctValues(db, collectionName, fieldPath, lacMatch, isArray) { + var pipeline = [ + {$match: {lac: lacMatch, [fieldPath]: {$exists: true}}} + ]; + + if (isArray) { + pipeline.push({$unwind: {path: "$" + fieldPath, preserveNullAndEmptyArrays: false}}); + } + + pipeline.push({$group: {_id: "$" + fieldPath}}); + + var results = await db.collection(collectionName).aggregate(pipeline, {allowDiskUse: true}).toArray(); + var values = {}; + for (var i = 0; i < results.length; i++) { + if (results[i]._id !== null && results[i]._id !== undefined) { + values[results[i]._id + ""] = true; + } + } + return values; +} + +/** + * Determine the type of a property based on its values + * Types: "n" (number), "d" (date), "l" (list/string), "a" (array) + * @param {string[]} values - array of string-encoded values + * @param {boolean} isArray - whether any user had this as an array value + * @returns {string} type code + */ +function determineType(values, isArray) { + if (isArray) { + return "a"; + } + + var isNumber = true; + var isDate = true; + + for (var i = 0; i < values.length; i++) { + if (!isNumeric(values[i]) || values[i].length > 16) { + isNumber = false; + isDate = false; + break; + } + if (values[i].length !== 10 && values[i].length !== 13) { + isDate = false; + } + } + + if (isNumber && isDate) { + return "d"; + } + if (isNumber) { + return "n"; + } + return "l"; +} + +/** + * Check if value is numeric + * @param {*} val - value to check + * @returns {boolean} true if numeric + */ +function isNumeric(val) { + if (typeof val === "number") { + return true; + } + if (typeof val === "string" && val.trim() !== "") { + return !isNaN(Number(val)); + } + return false; +} + +/** + * Encode key for MongoDB storage (replace $ and . characters) + * @param {string} key - key to encode + * @returns {string} encoded key + */ +function encodeKey(key) { + return (key + "").replace(/^\$/g, "$").replace(/\./g, '.'); +} From 476e01036d8cb5c28b2d614e327d9f80c437ca58 Mon Sep 17 00:00:00 2001 From: Gabriel Oliveira Date: Mon, 6 Apr 2026 16:31:47 +0000 Subject: [PATCH 07/36] chore: Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54c7d95f855..96c701095a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Fixes: Enterprise Fixes: - [surveys] Fixed widget asset path with subdirectory +- [journey-engin] Added new image handling mechanism for modal and half-modal content blocks ## Version 25.03.40 Fixes: From 872735bb517c96209666cf9f02f4d6ea55946cff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 29 Mar 2026 04:25:15 +0000 Subject: [PATCH 08/36] Bump brace-expansion from 2.0.2 to 2.0.3 in /plugins/hooks Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 2.0.2 to 2.0.3. - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v2.0.2...v2.0.3) --- updated-dependencies: - dependency-name: brace-expansion dependency-version: 2.0.3 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- plugins/hooks/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/hooks/package-lock.json b/plugins/hooks/package-lock.json index 86369330e25..6a77c9549d3 100644 --- a/plugins/hooks/package-lock.json +++ b/plugins/hooks/package-lock.json @@ -161,9 +161,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" From ec65b197803a87a64af2a23fef52843e746a103c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 29 Mar 2026 04:25:23 +0000 Subject: [PATCH 09/36] Bump brace-expansion from 1.1.12 to 1.1.13 Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.12 to 1.1.13. - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v1.1.12...v1.1.13) --- updated-dependencies: - dependency-name: brace-expansion dependency-version: 1.1.13 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 102 +++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2ae19f2b123..179cdddb24b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -501,9 +501,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "license": "MIT", "dependencies": { @@ -589,9 +589,9 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "license": "MIT", "dependencies": { @@ -2458,9 +2458,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2807,9 +2807,9 @@ } }, "node_modules/archiver-utils/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -3340,9 +3340,9 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -3507,9 +3507,9 @@ } }, "node_modules/cacache/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "license": "MIT", "optional": true, "dependencies": { @@ -5056,9 +5056,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "license": "MIT", "dependencies": { @@ -6404,9 +6404,9 @@ } }, "node_modules/globule/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "license": "MIT", "dependencies": { @@ -6992,9 +6992,9 @@ } }, "node_modules/grunt/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -7823,9 +7823,9 @@ } }, "node_modules/istanbul-lib-processinfo/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9669,9 +9669,9 @@ } }, "node_modules/mv/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "license": "MIT", "optional": true, "dependencies": { @@ -9842,9 +9842,9 @@ } }, "node_modules/node-gyp/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "license": "MIT", "optional": true, "dependencies": { @@ -10048,9 +10048,9 @@ } }, "node_modules/nyc/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11590,9 +11590,9 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "devOptional": true, "license": "MIT", "dependencies": { @@ -12211,9 +12211,9 @@ } }, "node_modules/spawn-wrap/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12803,9 +12803,9 @@ } }, "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13912,9 +13912,9 @@ } }, "node_modules/zip-stream/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", From 5e35c8e448025332cf12a05b3f0a5f599e33dbe5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 29 Mar 2026 04:25:16 +0000 Subject: [PATCH 10/36] Bump path-to-regexp from 0.1.12 to 0.1.13 Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) from 0.1.12 to 0.1.13. - [Release notes](https://github.com/pillarjs/path-to-regexp/releases) - [Changelog](https://github.com/pillarjs/path-to-regexp/blob/v.0.1.13/History.md) - [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.12...v.0.1.13) --- updated-dependencies: - dependency-name: path-to-regexp dependency-version: 0.1.13 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 179cdddb24b..48e595f12c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10786,9 +10786,9 @@ "license": "ISC" }, "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, "node_modules/pbf": { From ace6ed2533cdefb2e7ff3a97ae909c23d392c2c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 08:36:21 +0000 Subject: [PATCH 11/36] Bump lodash from 4.17.23 to 4.18.1 in /bin/scripts/device_list Bumps [lodash](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.23...4.18.1) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.18.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- bin/scripts/device_list/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/scripts/device_list/package-lock.json b/bin/scripts/device_list/package-lock.json index 209c9899140..5a82822b54d 100644 --- a/bin/scripts/device_list/package-lock.json +++ b/bin/scripts/device_list/package-lock.json @@ -28,9 +28,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" } } From 91c1ee1f1bc8156b7467cad925dc88574558d39d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:45:11 +0000 Subject: [PATCH 12/36] Bump lodash from 4.17.23 to 4.18.1 Bumps [lodash](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.23...4.18.1) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.18.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- package-lock.json | 26 ++++++++++++++++++++++---- package.json | 2 +- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 48e595f12c3..3e5545efbdb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,7 +48,7 @@ "json2csv": "5.0.7", "jsonwebtoken": "^9.0.1", "later": "1.2.0", - "lodash": "4.17.23", + "lodash": "4.18.1", "lru-cache": "7.18.3", "mcc-mnc-list": "1.1.11", "method-override": "3.0.0", @@ -6928,6 +6928,12 @@ "node": ">=10" } }, + "node_modules/grunt-legacy-log-utils/node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" + }, "node_modules/grunt-legacy-log/node_modules/colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", @@ -6937,6 +6943,12 @@ "node": ">=0.1.90" } }, + "node_modules/grunt-legacy-log/node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" + }, "node_modules/grunt-legacy-util": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.1.tgz", @@ -6955,6 +6967,12 @@ "node": ">=10" } }, + "node_modules/grunt-legacy-util/node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" + }, "node_modules/grunt-mocha-nyc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/grunt-mocha-nyc/-/grunt-mocha-nyc-1.0.3.tgz", @@ -8503,9 +8521,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash.defaults": { diff --git a/package.json b/package.json index 9554af05f0b..f1dc9ba5796 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "json2csv": "5.0.7", "jsonwebtoken": "^9.0.1", "later": "1.2.0", - "lodash": "4.17.23", + "lodash": "4.18.1", "lru-cache": "7.18.3", "mcc-mnc-list": "1.1.11", "method-override": "3.0.0", From 0da1b32e9d9562f8ec9411cc7bd79199a506f571 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:07:11 +0000 Subject: [PATCH 13/36] Bump lodash from 4.17.23 to 4.18.1 in /plugins/hooks Bumps [lodash](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.23...4.18.1) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.18.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- plugins/hooks/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/hooks/package-lock.json b/plugins/hooks/package-lock.json index 6a77c9549d3..127661a553e 100644 --- a/plugins/hooks/package-lock.json +++ b/plugins/hooks/package-lock.json @@ -730,9 +730,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lru-cache": { From 764245c30a76e3d9184d752b49ec50024839f7a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 08:36:07 +0000 Subject: [PATCH 14/36] Bump lodash from 4.17.23 to 4.18.1 in /ui-tests Bumps [lodash](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.23...4.18.1) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.18.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- ui-tests/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui-tests/package-lock.json b/ui-tests/package-lock.json index 69b828083d7..2162d8421e9 100644 --- a/ui-tests/package-lock.json +++ b/ui-tests/package-lock.json @@ -2103,9 +2103,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash.once": { From a101e4d054dac6aa2718674bb2464ac66dc16a2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:14:00 +0000 Subject: [PATCH 15/36] Bump geoip-lite from 2.0.0 to 2.0.1 Bumps [geoip-lite](https://github.com/geoip-lite/node-geoip) from 2.0.0 to 2.0.1. - [Release notes](https://github.com/geoip-lite/node-geoip/releases) - [Commits](https://github.com/geoip-lite/node-geoip/compare/v2.0.0...v2.0.1) --- updated-dependencies: - dependency-name: geoip-lite dependency-version: 2.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 23 ++++++++++++++++++----- package.json | 2 +- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3e5545efbdb..40111a120b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "form-data": "^4.0.0", "formidable": "2.1.3", "fs-extra": "11.3.4", - "geoip-lite": "2.0.0", + "geoip-lite": "2.0.1", "get-random-values": "^4.0.0", "grunt": "1.6.1", "grunt-cli": "1.5.0", @@ -6114,16 +6114,16 @@ } }, "node_modules/geoip-lite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/geoip-lite/-/geoip-lite-2.0.0.tgz", - "integrity": "sha512-7f6o1VDcFzB4J7pVko7qOtF9OsrJ/nZjCJ2dIquZzUoHjWGDPm0Sa1wOmW1caxcJDTo4C+MpLZUrokCCpPAamQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/geoip-lite/-/geoip-lite-2.0.1.tgz", + "integrity": "sha512-cR9E28nu1a6dsvzB1tANhdmCyXWV1L4AiSCT9alHLIUl06599EGu33mqY99ieU0twQob0kfcDQ/sAUBvHb7swA==", "license": "Apache-2.0", "dependencies": { "chalk": "4.1 - 4.1.2", "iconv-lite": "0.4.13 - 0.6.3", "ip-address": "5.8.9 - 5.9.4", "lazy": "1.0.11", - "yauzl": "2.9.2 - 2.10.0" + "yauzl": "^3.2.1" }, "engines": { "node": ">=24.0.0" @@ -6161,6 +6161,19 @@ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", "license": "BSD-3-Clause" }, + "node_modules/geoip-lite/node_modules/yauzl": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.3.0.tgz", + "integrity": "sha512-PtGEvEP30p7sbIBJKUBjUnqgTVOyMURc4dLo9iNyAJnNIEz9pm88cCXF21w94Kg3k6RXkeZh5DHOGS0qEONvNQ==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "pend": "~1.2.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", diff --git a/package.json b/package.json index f1dc9ba5796..6833f4634bd 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "form-data": "^4.0.0", "formidable": "2.1.3", "fs-extra": "11.3.4", - "geoip-lite": "2.0.0", + "geoip-lite": "2.0.1", "get-random-values": "^4.0.0", "grunt": "1.6.1", "grunt-cli": "1.5.0", From c1113a207902e7e1d7bd167f730ec09228f5fa90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 01:23:12 +0000 Subject: [PATCH 16/36] Bump cypress from 15.13.0 to 15.13.1 in /ui-tests Bumps [cypress](https://github.com/cypress-io/cypress) from 15.13.0 to 15.13.1. - [Release notes](https://github.com/cypress-io/cypress/releases) - [Changelog](https://github.com/cypress-io/cypress/blob/develop/CHANGELOG.md) - [Commits](https://github.com/cypress-io/cypress/compare/v15.13.0...v15.13.1) --- updated-dependencies: - dependency-name: cypress dependency-version: 15.13.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- ui-tests/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui-tests/package-lock.json b/ui-tests/package-lock.json index 2162d8421e9..7e17baa89ab 100644 --- a/ui-tests/package-lock.json +++ b/ui-tests/package-lock.json @@ -1351,9 +1351,9 @@ } }, "node_modules/cypress": { - "version": "15.13.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-15.13.0.tgz", - "integrity": "sha512-hJ9sY++TUC/HlUzHVJpIrDyqKMjlhx5PTXl/A7eA91JNEtUWkJAqefQR5mo9AtLra/9+m+JJaMg2U5Qd0a74Fw==", + "version": "15.13.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-15.13.1.tgz", + "integrity": "sha512-jLkgo75zlwo7PhXp0XJot+zIfFSDzN1SvTml6Xf3ETM1XHRWnH3Q4LAR3orCo/BsnxPnhjG3m5HYSvn9DAtwBg==", "hasInstallScript": true, "license": "MIT", "dependencies": { From 2d46360893d95b97c337d1abea16ec88a5702507 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:14:08 +0000 Subject: [PATCH 17/36] Bump picomatch Bumps and [picomatch](https://github.com/micromatch/picomatch). These dependencies needed to be updated together. Updates `picomatch` from 2.3.1 to 2.3.2 - [Release notes](https://github.com/micromatch/picomatch/releases) - [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2) Updates `picomatch` from 4.0.3 to 4.0.4 - [Release notes](https://github.com/micromatch/picomatch/releases) - [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2) --- updated-dependencies: - dependency-name: picomatch dependency-version: 2.3.2 dependency-type: indirect - dependency-name: picomatch dependency-version: 4.0.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 40111a120b0..0487d91214b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2735,9 +2735,9 @@ } }, "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -9051,9 +9051,9 @@ } }, "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -9485,9 +9485,9 @@ } }, "node_modules/mocha/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -10861,9 +10861,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "devOptional": true, "license": "MIT", "engines": { From 83b6aea6317dcf84f87f6378eece0ad02ba3024a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 01:25:20 +0000 Subject: [PATCH 18/36] Bump docker/login-action from 4.0.0 to 4.1.0 in the actions group Bumps the actions group with 1 update: [docker/login-action](https://github.com/docker/login-action). Updates `docker/login-action` from 4.0.0 to 4.1.0 - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/b45d80f862d83dbcd57f89517bcf500b2ab88fb2...4907a6ddec9925e35a0a9e82d7399ccc52663121) --- updated-dependencies: - dependency-name: docker/login-action dependency-version: 4.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] --- .github/workflows/deploy.yml | 2 +- .github/workflows/docker-image.yml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2475322047c..9c95ee55fb6 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -48,7 +48,7 @@ jobs: uses: actions/checkout@v6 - name: Log in to Docker Hub - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 8e80a14b49b..a84624b3a1c 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -26,7 +26,7 @@ jobs: echo ${{ steps.vars.outputs.tag }} - name: Log in to Docker Hub - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -57,7 +57,7 @@ jobs: echo ${{ steps.vars.outputs.tag }} - name: Log in to Docker Hub - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -88,7 +88,7 @@ jobs: echo ${{ steps.vars.outputs.tag }} - name: Log in to Docker Hub - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -119,7 +119,7 @@ jobs: echo ${{ steps.vars.outputs.tag }} - name: Log in to Docker Hub - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} From 93f121636cecd81e13a50ec3b771a249896ed8c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:41:11 +0000 Subject: [PATCH 19/36] Bump lint-staged from 16.3.2 to 16.4.0 Bumps [lint-staged](https://github.com/lint-staged/lint-staged) from 16.3.2 to 16.4.0. - [Release notes](https://github.com/lint-staged/lint-staged/releases) - [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md) - [Commits](https://github.com/lint-staged/lint-staged/compare/v16.3.2...v16.4.0) --- updated-dependencies: - dependency-name: lint-staged dependency-version: 16.4.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0487d91214b..f97de975512 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8374,17 +8374,17 @@ "license": "MIT" }, "node_modules/lint-staged": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.3.2.tgz", - "integrity": "sha512-xKqhC2AeXLwiAHXguxBjuChoTTWFC6Pees0SHPwOpwlvI3BH7ZADFPddAdN3pgo3aiKgPUx/bxE78JfUnxQnlg==", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.4.0.tgz", + "integrity": "sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==", "dev": true, "license": "MIT", "dependencies": { "commander": "^14.0.3", "listr2": "^9.0.5", - "micromatch": "^4.0.8", + "picomatch": "^4.0.3", "string-argv": "^0.3.2", - "tinyexec": "^1.0.2", + "tinyexec": "^1.0.4", "yaml": "^2.8.2" }, "bin": { @@ -12955,9 +12955,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", + "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", "dev": true, "license": "MIT", "engines": { From e60de2dd8074d49c5a36fd230d8bff1d77787932 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:41:11 +0000 Subject: [PATCH 20/36] Bump puppeteer from 24.39.1 to 24.40.0 Bumps [puppeteer](https://github.com/puppeteer/puppeteer) from 24.39.1 to 24.40.0. - [Release notes](https://github.com/puppeteer/puppeteer/releases) - [Changelog](https://github.com/puppeteer/puppeteer/blob/main/CHANGELOG.md) - [Commits](https://github.com/puppeteer/puppeteer/compare/puppeteer-v24.39.1...puppeteer-v24.40.0) --- updated-dependencies: - dependency-name: puppeteer dependency-version: 24.40.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 48 +++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index f97de975512..74fd6d45b22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3059,9 +3059,9 @@ } }, "node_modules/bare-fs": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.6.tgz", - "integrity": "sha512-1QovqDrR80Pmt5HPAsMsXTCFcDYr+NSUKW6nd6WO5v0JBmnItc/irNRzm2KOQ5oZ69P37y+AMujNyNtG+1Rggw==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.6.0.tgz", + "integrity": "sha512-2YkS7NuiJceSEbyEOdSNLE9tsGd+f4+f7C+Nik/MCk27SYdwIMPT/yRKvg++FZhQXgk0KWJKJyXX9RhVV0RGqA==", "license": "Apache-2.0", "dependencies": { "bare-events": "^2.5.4", @@ -3083,9 +3083,9 @@ } }, "node_modules/bare-os": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.8.0.tgz", - "integrity": "sha512-Dc9/SlwfxkXIGYhvMQNUtKaXCaGkZYGcd1vuNUUADVqzu4/vQfvnMkYYOUnt2VwQ2AqKr/8qAVFRtwETljgeFg==", + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.8.7.tgz", + "integrity": "sha512-G4Gr1UsGeEy2qtDTZwL7JFLo2wapUarz7iTMcYcMFdS89AIQuBoyjgXZz0Utv7uHs3xA9LckhVbeBi8lEQrC+w==", "license": "Apache-2.0", "engines": { "bare": ">=1.14.0" @@ -3101,19 +3101,23 @@ } }, "node_modules/bare-stream": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.10.0.tgz", - "integrity": "sha512-DOPZF/DDcDruKDA43cOw6e9Quq5daua7ygcAwJE/pKJsRWhgSSemi7qVNGE5kyDIxIeN1533G/zfbvWX7Wcb9w==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.12.0.tgz", + "integrity": "sha512-w28i8lkBgREV3rPXGbgK+BO66q+ZpKqRWrZLiCdmmUlLPrQ45CzkvRhN+7lnv00Gpi2zy5naRxnUFAxCECDm9g==", "license": "Apache-2.0", "dependencies": { "streamx": "^2.25.0", "teex": "^1.0.1" }, "peerDependencies": { + "bare-abort-controller": "*", "bare-buffer": "*", "bare-events": "*" }, "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + }, "bare-buffer": { "optional": true }, @@ -9795,9 +9799,9 @@ } }, "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.0.tgz", + "integrity": "sha512-z9sZrk6wyf8/NDKKqe+Tyl58XtgkYrV4kgt1O8xrzYvpl1LvPacPo0imMLHfpStk3kgCIq1ksJ2bmJn9hue2lQ==", "license": "MIT", "engines": { "node": ">= 0.4.0" @@ -11223,9 +11227,9 @@ } }, "node_modules/puppeteer": { - "version": "24.39.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.39.1.tgz", - "integrity": "sha512-68Zc9QpcVvfxp2C+3UL88TyUogEAn5tSylXidbEuEXvhiqK1+v65zeBU5ubinAgEHMGr3dcSYqvYrGtdzsPI3w==", + "version": "24.40.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.40.0.tgz", + "integrity": "sha512-IxQbDq93XHVVLWHrAkFP7F7iHvb9o0mgfsSIMlhHb+JM+JjM1V4v4MNSQfcRWJopx9dsNOr9adYv0U5fm9BJBQ==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -11233,7 +11237,7 @@ "chromium-bidi": "14.0.0", "cosmiconfig": "^9.0.0", "devtools-protocol": "0.0.1581282", - "puppeteer-core": "24.39.1", + "puppeteer-core": "24.40.0", "typed-query-selector": "^2.12.1" }, "bin": { @@ -11244,9 +11248,9 @@ } }, "node_modules/puppeteer-core": { - "version": "24.39.1", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.39.1.tgz", - "integrity": "sha512-AMqQIKoEhPS6CilDzw0Gd1brLri3emkC+1N2J6ZCCuY1Cglo56M63S0jOeBZDQlemOiRd686MYVMl9ELJBzN3A==", + "version": "24.40.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.40.0.tgz", + "integrity": "sha512-MWL3XbUCfVgGR0gRsidzT6oKJT2QydPLhMITU6HoVWiiv4gkb6gJi3pcdAa8q4HwjBTbqISOWVP4aJiiyUJvag==", "license": "Apache-2.0", "dependencies": { "@puppeteer/browsers": "2.13.0", @@ -13687,9 +13691,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", "license": "MIT", "engines": { "node": ">=10.0.0" From d644bcbf013c4ab4b8926ca8f3c71920c68a3629 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 19:31:51 +0000 Subject: [PATCH 21/36] Bump moment-timezone from 0.6.0 to 0.6.1 Bumps [moment-timezone](https://github.com/moment/moment-timezone) from 0.6.0 to 0.6.1. - [Release notes](https://github.com/moment/moment-timezone/releases) - [Changelog](https://github.com/moment/moment-timezone/blob/develop/changelog.md) - [Commits](https://github.com/moment/moment-timezone/compare/0.6.0...0.6.1) --- updated-dependencies: - dependency-name: moment-timezone dependency-version: 0.6.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 74fd6d45b22..dbd7dc8a0c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,7 +53,7 @@ "mcc-mnc-list": "1.1.11", "method-override": "3.0.0", "moment": "2.30.1", - "moment-timezone": "0.6.0", + "moment-timezone": "0.6.1", "mongodb": "6.20.0", "mongodb-connection-string-url": "^7.0.1", "nginx-conf": "2.1.0", @@ -9593,9 +9593,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.0.tgz", - "integrity": "sha512-ldA5lRNm3iJCWZcBCab4pnNL3HSZYXVb/3TYr75/1WCTWYuTqYUb5f/S384pncYjJ88lbO8Z4uPDvmoluHJc8Q==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.1.tgz", + "integrity": "sha512-1B9lmAhB9D9/sHaPC1N7wLFEVUoFldxOpOO96lOD1PvJ43vCd0ozDPbu0FEL3++VvawOlDkq8YD373tJmP5JHw==", "license": "MIT", "dependencies": { "moment": "^2.29.4" diff --git a/package.json b/package.json index 6833f4634bd..e018a6be40a 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "mcc-mnc-list": "1.1.11", "method-override": "3.0.0", "moment": "2.30.1", - "moment-timezone": "0.6.0", + "moment-timezone": "0.6.1", "mongodb": "6.20.0", "mongodb-connection-string-url": "^7.0.1", "nginx-conf": "2.1.0", From bdaa8fb32020581318700fa4ff6dce9bd08c7f10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 06:55:57 +0000 Subject: [PATCH 22/36] Bump nodemailer from 8.0.2 to 8.0.5 Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 8.0.2 to 8.0.5. - [Release notes](https://github.com/nodemailer/nodemailer/releases) - [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodemailer/nodemailer/compare/v8.0.2...v8.0.5) --- updated-dependencies: - dependency-name: nodemailer dependency-version: 8.0.5 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index dbd7dc8a0c5..51b4f9bc074 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,7 +57,7 @@ "mongodb": "6.20.0", "mongodb-connection-string-url": "^7.0.1", "nginx-conf": "2.1.0", - "nodemailer": "8.0.2", + "nodemailer": "8.0.5", "object-hash": "3.0.0", "offline-geocoder": "git+https://github.com/Countly/offline-geocoder.git", "properties-parser": "0.6.0", @@ -9959,9 +9959,9 @@ "license": "MIT" }, "node_modules/nodemailer": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.2.tgz", - "integrity": "sha512-zbj002pZAIkWQFxyAaqoxvn+zoIwRnS40hgjqTXudKOOJkiFFgBeNqjgD3/YCR12sZnrghWYBY+yP1ZucdDRpw==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.5.tgz", + "integrity": "sha512-0PF8Yb1yZuQfQbq+5/pZJrtF6WQcjTd5/S4JOHs9PGFxuTqoB/icwuB44pOdURHJbRKX1PPoJZtY7R4VUoCC8w==", "license": "MIT-0", "engines": { "node": ">=6.0.0" diff --git a/package.json b/package.json index e018a6be40a..438923f89fa 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "mongodb": "6.20.0", "mongodb-connection-string-url": "^7.0.1", "nginx-conf": "2.1.0", - "nodemailer": "8.0.2", + "nodemailer": "8.0.5", "object-hash": "3.0.0", "offline-geocoder": "git+https://github.com/Countly/offline-geocoder.git", "properties-parser": "0.6.0", From afc4b28ad67ede949599904383dcddb335d71536 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 07:08:20 +0000 Subject: [PATCH 23/36] Bump basic-ftp from 5.2.0 to 5.2.1 Bumps [basic-ftp](https://github.com/patrickjuchli/basic-ftp) from 5.2.0 to 5.2.1. - [Release notes](https://github.com/patrickjuchli/basic-ftp/releases) - [Changelog](https://github.com/patrickjuchli/basic-ftp/blob/master/CHANGELOG.md) - [Commits](https://github.com/patrickjuchli/basic-ftp/compare/v5.2.0...v5.2.1) --- updated-dependencies: - dependency-name: basic-ftp dependency-version: 5.2.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 51b4f9bc074..e403acda9d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3181,9 +3181,9 @@ } }, "node_modules/basic-ftp": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.0.tgz", - "integrity": "sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.1.tgz", + "integrity": "sha512-0yaL8JdxTknKDILitVpfYfV2Ob6yb3udX/hK97M7I3jOeznBNxQPtVvTUtnhUkyHlxFWyr5Lvknmgzoc7jf+1Q==", "license": "MIT", "engines": { "node": ">=10.0.0" From 166b0ec028f83d5d099e4d2c638f0062a6ae1a1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 07:56:16 +0000 Subject: [PATCH 24/36] Bump sass from 1.98.0 to 1.99.0 Bumps [sass](https://github.com/sass/dart-sass) from 1.98.0 to 1.99.0. - [Release notes](https://github.com/sass/dart-sass/releases) - [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md) - [Commits](https://github.com/sass/dart-sass/compare/1.98.0...1.99.0) --- updated-dependencies: - dependency-name: sass dependency-version: 1.99.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index e403acda9d7..9af01363ac9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,7 +63,7 @@ "properties-parser": "0.6.0", "puppeteer": "^24.6.1", "rate-limiter-flexible": "^9.0.1", - "sass": "1.98.0", + "sass": "1.99.0", "semver": "^7.7.1", "sharp": "^0.34.2", "sqlite3": "^5.1.7", @@ -11726,9 +11726,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.98.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.98.0.tgz", - "integrity": "sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==", + "version": "1.99.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.99.0.tgz", + "integrity": "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==", "license": "MIT", "dependencies": { "chokidar": "^4.0.0", diff --git a/package.json b/package.json index 438923f89fa..6ddc341ff63 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "properties-parser": "0.6.0", "puppeteer": "^24.6.1", "rate-limiter-flexible": "^9.0.1", - "sass": "1.98.0", + "sass": "1.99.0", "semver": "^7.7.1", "sharp": "^0.34.2", "sqlite3": "^5.1.7", From c9f42c47fc13e12ae896848de2913081eff8442e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 08:09:53 +0000 Subject: [PATCH 25/36] Bump typescript from 5.9.3 to 6.0.2 Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.9.3 to 6.0.2. - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Commits](https://github.com/microsoft/TypeScript/compare/v5.9.3...v6.0.2) --- updated-dependencies: - dependency-name: typescript dependency-version: 6.0.2 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 106 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9af01363ac9..fdfddeee926 100644 --- a/package-lock.json +++ b/package-lock.json @@ -87,7 +87,7 @@ "nyc": "18.0.0", "should": "13.2.3", "supertest": "7.2.2", - "typescript": "^5.8.2" + "typescript": "^6.0.2" } }, "api/utils/countly-request": { @@ -2349,14 +2349,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", - "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.1.tgz", + "integrity": "sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.56.1", - "@typescript-eslint/types": "^8.56.1", + "@typescript-eslint/tsconfig-utils": "^8.58.1", + "@typescript-eslint/types": "^8.58.1", "debug": "^4.4.3" }, "engines": { @@ -2367,18 +2367,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", - "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.1.tgz", + "integrity": "sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1" + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/visitor-keys": "8.58.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2389,9 +2389,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", - "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.1.tgz", + "integrity": "sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw==", "dev": true, "license": "MIT", "engines": { @@ -2402,13 +2402,13 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", - "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.1.tgz", + "integrity": "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw==", "dev": true, "license": "MIT", "engines": { @@ -2420,21 +2420,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", - "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.1.tgz", + "integrity": "sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.56.1", - "@typescript-eslint/tsconfig-utils": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", + "@typescript-eslint/project-service": "8.58.1", + "@typescript-eslint/tsconfig-utils": "8.58.1", + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/visitor-keys": "8.58.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.4.0" + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2444,7 +2444,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { @@ -2471,13 +2471,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" @@ -2487,16 +2487,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", - "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.1.tgz", + "integrity": "sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1" + "@typescript-eslint/scope-manager": "8.58.1", + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/typescript-estree": "8.58.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2507,17 +2507,17 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz", - "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.1.tgz", + "integrity": "sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/types": "8.58.1", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -12969,14 +12969,14 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -13036,9 +13036,9 @@ } }, "node_modules/ts-api-utils": { - "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==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { @@ -13157,9 +13157,9 @@ } }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz", + "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", "devOptional": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 6ddc341ff63..6dd9cd425be 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "nyc": "18.0.0", "should": "13.2.3", "supertest": "7.2.2", - "typescript": "^5.8.2" + "typescript": "^6.0.2" }, "dependencies": { "all-the-cities": "3.1.0", From d994963e9dd168fa219ef59ba34cc11994bc28c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:51:09 +0000 Subject: [PATCH 26/36] Bump @faker-js/faker from 10.3.0 to 10.4.0 in /ui-tests Bumps [@faker-js/faker](https://github.com/faker-js/faker) from 10.3.0 to 10.4.0. - [Release notes](https://github.com/faker-js/faker/releases) - [Changelog](https://github.com/faker-js/faker/blob/next/CHANGELOG.md) - [Commits](https://github.com/faker-js/faker/compare/v10.3.0...v10.4.0) --- updated-dependencies: - dependency-name: "@faker-js/faker" dependency-version: 10.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- ui-tests/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui-tests/package-lock.json b/ui-tests/package-lock.json index 2162d8421e9..d2076c02534 100644 --- a/ui-tests/package-lock.json +++ b/ui-tests/package-lock.json @@ -83,9 +83,9 @@ } }, "node_modules/@faker-js/faker": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-10.3.0.tgz", - "integrity": "sha512-It0Sne6P3szg7JIi6CgKbvTZoMjxBZhcv91ZrqrNuaZQfB5WoqYYbzCUOq89YR+VY8juY9M1vDWmDDa2TzfXCw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-10.4.0.tgz", + "integrity": "sha512-sDBWI3yLy8EcDzgobvJTWq1MJYzAkQdpjXuPukga9wXonhpMRvd1Izuo2Qgwey2OiEoRIBr35RMU9HJRoOHzpw==", "funding": [ { "type": "opencollective", From fd276db3cd9cf46bfb4e6a52b4322380f2c2a33f Mon Sep 17 00:00:00 2001 From: Can Angun <39311746+can-angun@users.noreply.github.com> Date: Thu, 9 Apr 2026 11:29:01 +0300 Subject: [PATCH 27/36] Update README.md --- ui-tests/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-tests/README.md b/ui-tests/README.md index a2b03d70864..8cf6f150162 100644 --- a/ui-tests/README.md +++ b/ui-tests/README.md @@ -13,7 +13,7 @@ - Run `npm run cy:open`: Open the Cypress Test Runner - Run `npm run cy:run`: Run Cypress tests to completion -- Run `npm run cy:run:login`: Run Cypress with login feature +- Run `npm run cy:run:login`: Run Cypress with login feature ### Dependencies @@ -65,4 +65,4 @@ Cypress.SelectorPlayground.defaults({ selectorPriority: ['data-test-id', 'id', 'class'] }) -``` \ No newline at end of file +``` From 3e1c352ff23b0be77c4a88d6216e12199a61c8eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:41:57 +0000 Subject: [PATCH 28/36] Bump pdfjs-dist from 5.5.207 to 5.6.205 in /ui-tests Bumps [pdfjs-dist](https://github.com/mozilla/pdf.js) from 5.5.207 to 5.6.205. - [Release notes](https://github.com/mozilla/pdf.js/releases) - [Commits](https://github.com/mozilla/pdf.js/compare/v5.5.207...v5.6.205) --- updated-dependencies: - dependency-name: pdfjs-dist dependency-version: 5.6.205 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- ui-tests/package-lock.json | 102 ++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/ui-tests/package-lock.json b/ui-tests/package-lock.json index 7e17baa89ab..f2cc3fd3f26 100644 --- a/ui-tests/package-lock.json +++ b/ui-tests/package-lock.json @@ -589,9 +589,9 @@ } }, "node_modules/@napi-rs/canvas": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.95.tgz", - "integrity": "sha512-lkg23ge+rgyhgUwXmlbkPEhuhHq/hUi/gXKH+4I7vO+lJrbNfEYcQdJLIGjKyXLQzgFiiyDAwh5vAe/tITAE+w==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.97.tgz", + "integrity": "sha512-8cFniXvrIEnVwuNSRCW9wirRZbHvrD3JVujdS2P5n5xiJZNZMOZcfOvJ1pb66c7jXMKHHglJEDVJGbm8XWFcXQ==", "dev": true, "license": "MIT", "optional": true, @@ -606,23 +606,23 @@ "url": "https://github.com/sponsors/Brooooooklyn" }, "optionalDependencies": { - "@napi-rs/canvas-android-arm64": "0.1.95", - "@napi-rs/canvas-darwin-arm64": "0.1.95", - "@napi-rs/canvas-darwin-x64": "0.1.95", - "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.95", - "@napi-rs/canvas-linux-arm64-gnu": "0.1.95", - "@napi-rs/canvas-linux-arm64-musl": "0.1.95", - "@napi-rs/canvas-linux-riscv64-gnu": "0.1.95", - "@napi-rs/canvas-linux-x64-gnu": "0.1.95", - "@napi-rs/canvas-linux-x64-musl": "0.1.95", - "@napi-rs/canvas-win32-arm64-msvc": "0.1.95", - "@napi-rs/canvas-win32-x64-msvc": "0.1.95" + "@napi-rs/canvas-android-arm64": "0.1.97", + "@napi-rs/canvas-darwin-arm64": "0.1.97", + "@napi-rs/canvas-darwin-x64": "0.1.97", + "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.97", + "@napi-rs/canvas-linux-arm64-gnu": "0.1.97", + "@napi-rs/canvas-linux-arm64-musl": "0.1.97", + "@napi-rs/canvas-linux-riscv64-gnu": "0.1.97", + "@napi-rs/canvas-linux-x64-gnu": "0.1.97", + "@napi-rs/canvas-linux-x64-musl": "0.1.97", + "@napi-rs/canvas-win32-arm64-msvc": "0.1.97", + "@napi-rs/canvas-win32-x64-msvc": "0.1.97" } }, "node_modules/@napi-rs/canvas-android-arm64": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.95.tgz", - "integrity": "sha512-SqTh0wsYbetckMXEvHqmR7HKRJujVf1sYv1xdlhkifg6TlCSysz1opa49LlS3+xWuazcQcfRfmhA07HxxxGsAA==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.97.tgz", + "integrity": "sha512-V1c/WVw+NzH8vk7ZK/O8/nyBSCQimU8sfMsB/9qeSvdkGKNU7+mxy/bIF0gTgeBFmHpj30S4E9WHMSrxXGQuVQ==", "cpu": [ "arm64" ], @@ -641,9 +641,9 @@ } }, "node_modules/@napi-rs/canvas-darwin-arm64": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.95.tgz", - "integrity": "sha512-F7jT0Syu+B9DGBUBcMk3qCRIxAWiDXmvEjamwbYfbZl7asI1pmXZUnCOoIu49Wt0RNooToYfRDxU9omD6t5Xuw==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.97.tgz", + "integrity": "sha512-ok+SCEF4YejcxuJ9Rm+WWunHHpf2HmiPxfz6z1a/NFQECGXtsY7A4B8XocK1LmT1D7P174MzwPF9Wy3AUAwEPw==", "cpu": [ "arm64" ], @@ -662,9 +662,9 @@ } }, "node_modules/@napi-rs/canvas-darwin-x64": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.95.tgz", - "integrity": "sha512-54eb2Ho15RDjYGXO/harjRznBrAvu+j5nQ85Z4Qd6Qg3slR8/Ja+Yvvy9G4yo7rdX6NR9GPkZeSTf2UcKXwaXw==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.97.tgz", + "integrity": "sha512-PUP6e6/UGlclUvAQNnuXCcnkpdUou6VYZfQOQxExLp86epOylmiwLkqXIvpFmjoTEDmPmXrI+coL/9EFU1gKPA==", "cpu": [ "x64" ], @@ -683,9 +683,9 @@ } }, "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.95.tgz", - "integrity": "sha512-hYaLCSLx5bmbnclzQc3ado3PgZ66blJWzjXp0wJmdwpr/kH+Mwhj6vuytJIomgksyJoCdIqIa4N6aiqBGJtJ5Q==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.97.tgz", + "integrity": "sha512-XyXH2L/cic8eTNtbrXCcvqHtMX/nEOxN18+7rMrAM2XtLYC/EB5s0wnO1FsLMWmK+04ZSLN9FBGipo7kpIkcOw==", "cpu": [ "arm" ], @@ -704,9 +704,9 @@ } }, "node_modules/@napi-rs/canvas-linux-arm64-gnu": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.95.tgz", - "integrity": "sha512-J7VipONahKsmScPZsipHVQBqpbZx4favaD8/enWzzlGcjiwycOoymL7f4tNeqdjK0su19bDOUt6mjp9gsPWYlw==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.97.tgz", + "integrity": "sha512-Kuq/M3djq0K8ktgz6nPlK7Ne5d4uWeDxPpyKWOjWDK2RIOhHVtLtyLiJw2fuldw7Vn4mhw05EZXCEr4Q76rs9w==", "cpu": [ "arm64" ], @@ -725,9 +725,9 @@ } }, "node_modules/@napi-rs/canvas-linux-arm64-musl": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.95.tgz", - "integrity": "sha512-PXy0UT1J/8MPG8UAkWp6Fd51ZtIZINFzIjGH909JjQrtCuJf3X6nanHYdz1A+Wq9o4aoPAw1YEUpFS1lelsVlg==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.97.tgz", + "integrity": "sha512-kKmSkQVnWeqg7qdsiXvYxKhAFuHz3tkBjW/zyQv5YKUPhotpaVhpBGv5LqCngzyuRV85SXoe+OFj+Tv0a0QXkQ==", "cpu": [ "arm64" ], @@ -746,9 +746,9 @@ } }, "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.95.tgz", - "integrity": "sha512-2IzCkW2RHRdcgF9W5/plHvYFpc6uikyjMb5SxjqmNxfyDFz9/HB89yhi8YQo0SNqrGRI7yBVDec7Pt+uMyRWsg==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.97.tgz", + "integrity": "sha512-Jc7I3A51jnEOIAXeLsN/M/+Z28LUeakcsXs07FLq9prXc0eYOtVwsDEv913Gr+06IRo34gJJVgT0TXvmz+N2VA==", "cpu": [ "riscv64" ], @@ -767,9 +767,9 @@ } }, "node_modules/@napi-rs/canvas-linux-x64-gnu": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.95.tgz", - "integrity": "sha512-OV/ol/OtcUr4qDhQg8G7SdViZX8XyQeKpPsVv/j3+7U178FGoU4M+yIocdVo1ih/A8GQ63+LjF4jDoEjaVU8Pw==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.97.tgz", + "integrity": "sha512-iDUBe7AilfuBSRbSa8/IGX38Mf+iCSBqoVKLSQ5XaY2JLOaqz1TVyPFEyIck7wT6mRQhQt5sN6ogfjIDfi74tg==", "cpu": [ "x64" ], @@ -788,9 +788,9 @@ } }, "node_modules/@napi-rs/canvas-linux-x64-musl": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.95.tgz", - "integrity": "sha512-Z5KzqBK/XzPz5+SFHKz7yKqClEQ8pOiEDdgk5SlphBLVNb8JFIJkxhtJKSvnJyHh2rjVgiFmvtJzMF0gNwwKyQ==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.97.tgz", + "integrity": "sha512-AKLFd/v0Z5fvgqBDqhvqtAdx+fHMJ5t9JcUNKq4FIZ5WH+iegGm8HPdj00NFlCSnm83Fp3Ln8I2f7uq1aIiWaA==", "cpu": [ "x64" ], @@ -809,9 +809,9 @@ } }, "node_modules/@napi-rs/canvas-win32-arm64-msvc": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.95.tgz", - "integrity": "sha512-aj0YbRpe8qVJ4OzMsK7NfNQePgcf9zkGFzNZ9mSuaxXzhpLHmlF2GivNdCdNOg8WzA/NxV6IU4c5XkXadUMLeA==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.97.tgz", + "integrity": "sha512-u883Yr6A6fO7Vpsy9YE4FVCIxzzo5sO+7pIUjjoDLjS3vQaNMkVzx5bdIpEL+ob+gU88WDK4VcxYMZ6nmnoX9A==", "cpu": [ "arm64" ], @@ -830,9 +830,9 @@ } }, "node_modules/@napi-rs/canvas-win32-x64-msvc": { - "version": "0.1.95", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.95.tgz", - "integrity": "sha512-GA8leTTCfdjuHi8reICTIxU0081PhXvl3lzIniLUjeLACx9GubUiyzkwFb+oyeKLS5IAGZFLKnzAf4wm2epRlA==", + "version": "0.1.97", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.97.tgz", + "integrity": "sha512-sWtD2EE3fV0IzN+iiQUqr/Q1SwqWhs2O1FKItFlxtdDkikpEj5g7DKQpY3x55H/MAOnL8iomnlk3mcEeGiUMoQ==", "cpu": [ "x64" ], @@ -2335,16 +2335,16 @@ } }, "node_modules/pdfjs-dist": { - "version": "5.5.207", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.5.207.tgz", - "integrity": "sha512-WMqqw06w1vUt9ZfT0gOFhMf3wHsWhaCrxGrckGs5Cci6ybDW87IvPaOd2pnBwT6BJuP/CzXDZxjFgmSULLdsdw==", + "version": "5.6.205", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.6.205.tgz", + "integrity": "sha512-tlUj+2IDa7G1SbvBNN74UHRLJybZDWYom+k6p5KIZl7huBvsA4APi6mKL+zCxd3tLjN5hOOEE9Tv7VdzO88pfg==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=20.19.0 || >=22.13.0 || >=24" }, "optionalDependencies": { - "@napi-rs/canvas": "^0.1.95", + "@napi-rs/canvas": "^0.1.96", "node-readable-to-web-readable-stream": "^0.4.2" } }, From 912defd6aa43e501c2f5a76966b70f71a47eb8a5 Mon Sep 17 00:00:00 2001 From: Can Angun <39311746+can-angun@users.noreply.github.com> Date: Thu, 9 Apr 2026 13:17:02 +0300 Subject: [PATCH 29/36] Update README.md --- ui-tests/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-tests/README.md b/ui-tests/README.md index 8cf6f150162..44804e4e020 100644 --- a/ui-tests/README.md +++ b/ui-tests/README.md @@ -13,7 +13,7 @@ - Run `npm run cy:open`: Open the Cypress Test Runner - Run `npm run cy:run`: Run Cypress tests to completion -- Run `npm run cy:run:login`: Run Cypress with login feature +- Run `npm run cy:run:login`: Run Cypress with login feature ### Dependencies From 757cde7e661b0a064741ecde24fe6d5182b7bbb6 Mon Sep 17 00:00:00 2001 From: Cihad Tekin Date: Thu, 9 Apr 2026 14:40:57 +0300 Subject: [PATCH 30/36] [alerts] Convert alert jobs to use app timezone instead of server timezone. App that alert created for is being stored inside the job now. Added debug logs to each module --- plugins/alerts/api/alertModules/cohorts.js | 24 +-- plugins/alerts/api/alertModules/crashes.js | 27 +--- plugins/alerts/api/alertModules/dataPoints.js | 76 +++------- plugins/alerts/api/alertModules/events.js | 37 +---- plugins/alerts/api/alertModules/nps.js | 29 +--- plugins/alerts/api/alertModules/rating.js | 28 +--- plugins/alerts/api/alertModules/revenue.js | 57 +------- plugins/alerts/api/alertModules/sessions.js | 61 +------- plugins/alerts/api/alertModules/survey.js | 30 +--- plugins/alerts/api/alertModules/users.js | 13 +- plugins/alerts/api/alertModules/views.js | 27 +--- plugins/alerts/api/api.js | 137 +++++++++++------- plugins/alerts/api/jobs/monitor.js | 53 +++---- plugins/alerts/api/parts/common-lib.js | 32 ++++ 14 files changed, 210 insertions(+), 421 deletions(-) diff --git a/plugins/alerts/api/alertModules/cohorts.js b/plugins/alerts/api/alertModules/cohorts.js index 62d4f2d1c0d..31150f9f2f4 100644 --- a/plugins/alerts/api/alertModules/cohorts.js +++ b/plugins/alerts/api/alertModules/cohorts.js @@ -6,28 +6,24 @@ const log = require('../../../../api/utils/log.js')('alert:cohorts'); const moment = require('moment-timezone'); const common = require('../../../../api/utils/common.js'); const commonLib = require("../parts/common-lib.js"); -const { ObjectId } = require('mongodb'); - -module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: date }) { - const app = await common.readBatcher.getOne("apps", { _id: new ObjectId(alert.selectedApps[0]) }); - if (!app) { - log.e(`App ${alert.selectedApps[0]} couldn't be found`); - return done(); - } +module.exports.check = async function({ alert, app, done, scheduledTo: date }) { let { period, alertDataSubType2, compareType, compareValue } = alert; compareValue = Number(compareValue); const metricValue = await getCohortMetricByDate(app, alertDataSubType2, date, period) || 0; + log.d(alert._id, "value on", date, "is", metricValue); if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { if (metricValue > compareValue) { + log.d(alert._id, "triggered because", metricValue, "is more than", compareValue); await commonLib.trigger({ alert, app, metricValue, date }, log); } } else { const before = moment(date).subtract(1, commonLib.PERIOD_TO_DATE_COMPONENT_MAP[period]).toDate(); const metricValueBefore = await getCohortMetricByDate(app, alertDataSubType2, before, period); + log.d(alert._id, "value on", before, "is", metricValueBefore); if (!metricValueBefore) { return done(); } @@ -38,6 +34,7 @@ module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: : change <= -compareValue; if (shouldTrigger) { + log.d(alert._id, "triggered because", compareType, String(change) + "%"); await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); } } @@ -83,14 +80,3 @@ async function getCohortMetricByDate(app, cohortId, date, period) { } } -/* -(async function() { - await new Promise(res => setTimeout(res, 2000)); - const app = { _id: ObjectId("65c1f875a12e98a328d5eb9e"), timezone: "Europe/Istanbul" }; - const date = new Date("2024-02-07T12:00:00.000Z"); - const cohort = "3bcc37740d564419586ec26b66ea7c32"; - let monthlyData = await getCohortMetricByDate(app, cohort, date, "monthly"); - let dailyData = await getCohortMetricByDate(app, cohort, date, "daily"); - console.log(monthlyData, dailyData); -})(); -*/ \ No newline at end of file diff --git a/plugins/alerts/api/alertModules/crashes.js b/plugins/alerts/api/alertModules/crashes.js index 8178342e778..b8b0accab69 100644 --- a/plugins/alerts/api/alertModules/crashes.js +++ b/plugins/alerts/api/alertModules/crashes.js @@ -6,7 +6,6 @@ const log = require('../../../../api/utils/log.js')('alert:crashes'); const moment = require('moment-timezone'); const common = require('../../../../api/utils/common.js'); const commonLib = require("../parts/common-lib.js"); -const { ObjectId } = require('mongodb'); const METRIC_TO_PROPERTY_MAP = { "non-fatal crashes/errors per session": "crnfses", @@ -49,26 +48,23 @@ async function triggerByEvent(payload) { } -module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: date }) { - const app = await common.readBatcher.getOne("apps", { _id: new ObjectId(alert.selectedApps[0]) }); - if (!app) { - log.e(`App ${alert.selectedApps[0]} couldn't be found`); - return done(); - } - +module.exports.check = async function({ alert, app, done, scheduledTo: date }) { let { alertDataSubType, period, compareType, compareValue, filterValue } = alert; compareValue = Number(compareValue); const metricValue = await calculateMetricByDate(app, alertDataSubType, date, period, filterValue) || 0; + log.d(alert._id, "value on", date, "is", metricValue); if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { if (metricValue > compareValue) { + log.d(alert._id, "triggered because", metricValue, "is more than", compareValue); await commonLib.trigger({ alert, app, metricValue, date }, log); } } else { const before = moment(date).subtract(1, commonLib.PERIOD_TO_DATE_COMPONENT_MAP[period]).toDate(); const metricValueBefore = await calculateMetricByDate(app, alertDataSubType, before, period, filterValue); + log.d(alert._id, "value on", before, "is", metricValueBefore); if (!metricValueBefore) { return done(); } @@ -79,6 +75,7 @@ module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: : change <= -compareValue; if (shouldTrigger) { + log.d(alert._id, "triggered because", compareType, String(change) + "%"); await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); } } @@ -87,7 +84,7 @@ module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: }; /** - * Abstraction on top of getCrashDataByDate to calculate composite metrics. + * Abstraction on top of getCrashDataByDate to calculate composite metrics. * Possible metricStrings: * - non-fatal crashes/errors per session * - fatal crashes/errors per session @@ -174,15 +171,3 @@ async function getCrashDataByDate(app, metric, date, period, versions) { } return number; } - -/* -(async function() { - await new Promise(res => setTimeout(res, 2000)); - const app = { _id: ObjectId("65c1f875a12e98a328d5eb9e"), timezone: "Europe/Istanbul" }; - const date = new Date("2024-02-07T12:00:00.000Z"); - let monthlyData = await getCrashDataByDate(app, "cr_u", date, "monthly"); - let dailyData = await getCrashDataByDate(app, "cr_u", date, "daily", ["4:02:0", "4:01:2"]); - console.log(monthlyData, dailyData); - console.log(await calculateMetricByDate(app, "# of crashes/errors", date, "daily")); -})(); -*/ \ No newline at end of file diff --git a/plugins/alerts/api/alertModules/dataPoints.js b/plugins/alerts/api/alertModules/dataPoints.js index 2ec9aacefb7..056db54f8f3 100644 --- a/plugins/alerts/api/alertModules/dataPoints.js +++ b/plugins/alerts/api/alertModules/dataPoints.js @@ -6,54 +6,40 @@ const log = require('../../../../api/utils/log.js')('alert:dataPoints'); const moment = require('moment-timezone'); const common = require('../../../../api/utils/common.js'); const commonLib = require("../parts/common-lib.js"); -const { ObjectId } = require('mongodb'); const DATA_POINT_PROPERTY = "dp"; -module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: date }) { - const selectedApp = alert.selectedApps[0]; - let apps; - if (selectedApp === "all") { - apps = await common.readBatcher.getMany("apps", {}); - } - else { - apps = [await common.readBatcher.getOne("apps", { _id: new ObjectId(selectedApp) })]; - } +module.exports.check = async function({ alert, app, done, scheduledTo: date }) { + let { period, compareType, compareValue } = alert; + compareValue = Number(compareValue); - for (let app of apps) { - if (!app) { - log.e(`App ${alert.selectedApps[0]} couldn't be found`); - continue; - } + const metricValue = await getDataPointByDate(app, date, period) || 0; + log.d(alert._id, "value on", date, "is", metricValue); - let { period, compareType, compareValue } = alert; - compareValue = Number(compareValue); - - const metricValue = await getDataPointByDate(app, date, period) || 0; - - if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { - if (metricValue > compareValue) { - await commonLib.trigger({ alert, app, metricValue, date }, log); - } + if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { + if (metricValue > compareValue) { + log.d(alert._id, "triggered because", metricValue, "is more than", compareValue); + await commonLib.trigger({ alert, app, metricValue, date }, log); + } + } + else { + const before = moment(date).subtract(1, commonLib.PERIOD_TO_DATE_COMPONENT_MAP[period]).toDate(); + const metricValueBefore = await getDataPointByDate(app, before, period); + log.d(alert._id, "value on", before, "is", metricValueBefore); + if (!metricValueBefore) { + return done(); } - else { - const before = moment(date).subtract(1, commonLib.PERIOD_TO_DATE_COMPONENT_MAP[period]).toDate(); - const metricValueBefore = await getDataPointByDate(app, before, period); - if (!metricValueBefore) { - continue; - } - const change = (metricValue / metricValueBefore - 1) * 100; - const shouldTrigger = compareType === commonLib.COMPARE_TYPE_ENUM.INCREASED_BY - ? change >= compareValue - : change <= -compareValue; + const change = (metricValue / metricValueBefore - 1) * 100; + const shouldTrigger = compareType === commonLib.COMPARE_TYPE_ENUM.INCREASED_BY + ? change >= compareValue + : change <= -compareValue; - if (shouldTrigger) { - await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); - } + if (shouldTrigger) { + log.d(alert._id, "triggered because", compareType, String(change) + "%"); + await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); } } - done(); }; @@ -117,17 +103,3 @@ function dailySum(dailyData) { } return dailyValue; } -/* -(async function() { - await new Promise(res => setTimeout(res, 2000)); - const app = { _id: ObjectId("65c1f875a12e98a328d5eb9e"), timezone: "Europe/Istanbul" }; - const date1 = new Date("2024-01-07T10:00:00.000Z"); - const date2 = new Date("2024-02-07T10:00:00.000Z"); - const date3 = new Date("2024-03-07T10:00:00.000Z"); - let monthlyData1 = await getDataPointByDate(app, date1, "monthly"); - let monthlyData2 = await getDataPointByDate(app, date2, "monthly"); - let monthlyData3 = await getDataPointByDate(app, date3, "monthly"); - console.log("monthly:", monthlyData1, monthlyData2, monthlyData3); - console.log("all:", monthlyData1 + monthlyData2 + monthlyData3); -})(); -*/ \ No newline at end of file diff --git a/plugins/alerts/api/alertModules/events.js b/plugins/alerts/api/alertModules/events.js index 14f6b57b735..796bfa1842f 100644 --- a/plugins/alerts/api/alertModules/events.js +++ b/plugins/alerts/api/alertModules/events.js @@ -6,7 +6,6 @@ const log = require('../../../../api/utils/log.js')('alert:events'); const moment = require('moment-timezone'); const common = require('../../../../api/utils/common.js'); const commonLib = require("../parts/common-lib.js"); -const { ObjectId } = require('mongodb'); const METRIC_TO_PROPERTY_MAP = { // these are directly being stored in db @@ -20,13 +19,7 @@ const METRIC_TO_PROPERTY_MAP = { const AVERAGE_METRICS = ["average sum", "average duration"]; -module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) => { - const app = await common.readBatcher.getOne("apps", { _id: new ObjectId(alert.selectedApps[0]) }); - if (!app) { - log.e(`App ${alert.selectedApps[0]} couldn't be found`); - return done(); - } - +module.exports.check = async({ alert, app, done, scheduledTo: date }) => { let { alertDataSubType, alertDataSubType2, period, compareType, compareValue, filterKey, filterValue } = alert; const metricProp = METRIC_TO_PROPERTY_MAP[alertDataSubType]; let segments; @@ -45,9 +38,11 @@ module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) = } metricValue /= count; } + log.d(alert._id, "value on", date, "is", metricValue); if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { if (metricValue > compareValue) { + log.d(alert._id, "triggered because", metricValue, "is more than", compareValue); await commonLib.trigger({ alert, app, metricValue, date }, log); } } @@ -67,6 +62,7 @@ module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) = } metricValueBefore /= count; } + log.d(alert._id, "value on", before, "is", metricValueBefore); const change = (metricValue / metricValueBefore - 1) * 100; const shouldTrigger = compareType === commonLib.COMPARE_TYPE_ENUM.INCREASED_BY @@ -74,6 +70,7 @@ module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) = : change <= -compareValue; if (shouldTrigger) { + log.d(alert._id, "triggered because", compareType, String(change) + "%"); await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); } } @@ -155,27 +152,3 @@ async function getEventMetricByDate(app, event, metric, date, period, segments) } return number; } -/* -(async function() { - if (!require("cluster").isPrimary) { - return; - } - await new Promise(res => setTimeout(res, 2000)); - const app = { _id: "67fff00d901abe2f8cc57646", timezone: "Europe/Istanbul" }; - const date = new Date("2025-02-02T12:47:19.247Z"); - const event = "Product Viewed"; - const prop = "c"; - - const hourly = await getEventMetricByDate(app, event, prop, date, "hourly"); - console.assert(hourly === 5, "hourly event data doesn't match"); - - const daily = await getEventMetricByDate(app, event, prop, date2, "daily", { "Delivery Type": "Express" }); - console.assert(daily === 22, "daily segmented event data doesn't match"); - - const monthly = await getEventMetricByDate(app, event, prop, date2, "monthly"); - console.assert(monthly === 5120, "monthly event data doesn't match"); - - const monthlySegmented = await getEventMetricByDate(app, event, prop, date2, "monthly", { "Delivery Type": "Express" }); - console.assert(monthlySegmented === 2535, "monthly segmented event data doesn't match"); -})(); -*/ \ No newline at end of file diff --git a/plugins/alerts/api/alertModules/nps.js b/plugins/alerts/api/alertModules/nps.js index bc59714b57b..0cb28bb525f 100644 --- a/plugins/alerts/api/alertModules/nps.js +++ b/plugins/alerts/api/alertModules/nps.js @@ -6,7 +6,6 @@ const log = require('../../../../api/utils/log.js')('alert:nps'); const moment = require('moment-timezone'); const common = require('../../../../api/utils/common.js'); const commonLib = require("../parts/common-lib.js"); -const { ObjectId } = require('mongodb'); module.exports.triggerByEvent = triggerByEvent; /** @@ -50,26 +49,23 @@ async function triggerByEvent(payload) { } } -module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: date }) { - const app = await common.readBatcher.getOne("apps", { _id: new ObjectId(alert.selectedApps[0]) }); - if (!app) { - log.e(`App ${alert.selectedApps[0]} couldn't be found`); - return done(); - } - +module.exports.check = async function({ alert, app, done, scheduledTo: date }) { let { period, alertDataSubType2, compareType, compareValue, filterValue } = alert; compareValue = Number(compareValue); const metricValue = await getResponsesByDate(app, alertDataSubType2, date, period, filterValue) || 0; + log.d(alert._id, "value on", date, "is", metricValue); if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { if (metricValue > compareValue) { + log.d(alert._id, "triggered because", metricValue, "is more than", compareValue); await commonLib.trigger({ alert, app, metricValue, date }, log); } } else { const before = moment(date).subtract(1, commonLib.PERIOD_TO_DATE_COMPONENT_MAP[period]).toDate(); const metricValueBefore = await getResponsesByDate(app, alertDataSubType2, before, period, filterValue); + log.d(alert._id, "value on", before, "is", metricValueBefore); if (!metricValueBefore) { return done(); } @@ -80,6 +76,7 @@ module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: : change <= -compareValue; if (shouldTrigger) { + log.d(alert._id, "triggered because", compareType, String(change) + "%"); await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); } } @@ -164,19 +161,3 @@ function sumOfAllResponses(scope, nps, score) { return numberOfResponses; } -/* -(async function() { - const app = {name: "test", _id: new ObjectId("6600901a71159e99a3434253"), timezone: "Europe/Istanbul", plugins: null }; - const nps = "6600909ed476e1837317dc52"; - const date = new Date("2024-09-16T12:00:00.000Z"); - - let data = await getResponsesByDate(app, nps, date, "monthly"); - console.log("monthly:", data); - - data = await getResponsesByDate(app, nps, date, "daily"); - console.log("daily:", data); - - data = await getResponsesByDate(app, nps, date, "hourly"); - console.log("hourly:", data); -})(); -*/ \ No newline at end of file diff --git a/plugins/alerts/api/alertModules/rating.js b/plugins/alerts/api/alertModules/rating.js index 41c0159e059..4290885ec67 100644 --- a/plugins/alerts/api/alertModules/rating.js +++ b/plugins/alerts/api/alertModules/rating.js @@ -6,7 +6,6 @@ const log = require('../../../../api/utils/log.js')('alert:rating'); const moment = require('moment-timezone'); const common = require('../../../../api/utils/common.js'); const commonLib = require("../parts/common-lib.js"); -const { ObjectId } = require('mongodb'); const { getEventMetricByDate } = require("./events.js"); module.exports.triggerByEvent = triggerByEvent; @@ -50,13 +49,7 @@ async function triggerByEvent(payload) { } } -module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: date }) { - const app = await common.readBatcher.getOne("apps", { _id: new ObjectId(alert.selectedApps[0]) }); - if (!app) { - log.e(`App ${alert.selectedApps[0]} couldn't be found`); - return done(); - } - +module.exports.check = async function({ alert, app, done, scheduledTo: date }) { let { period, alertDataSubType2, compareType, compareValue, filterValue } = alert; compareValue = Number(compareValue); let ratingsFilter; @@ -71,15 +64,18 @@ module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: } const metricValue = await getRatingResponsesByDate(app, alertDataSubType2, date, period, ratingsFilter) || 0; + log.d(alert._id, "value on", date, "is", metricValue); if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { if (metricValue > compareValue) { + log.d(alert._id, "triggered because", metricValue, "is more than", compareValue); await commonLib.trigger({ alert, app, metricValue, date }, log); } } else { const before = moment(date).subtract(1, commonLib.PERIOD_TO_DATE_COMPONENT_MAP[period]).toDate(); const metricValueBefore = await getRatingResponsesByDate(app, alertDataSubType2, before, period, ratingsFilter); + log.d(alert._id, "value on", before, "is", metricValueBefore); if (!metricValueBefore) { return done(); } @@ -90,6 +86,7 @@ module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: : change <= -compareValue; if (shouldTrigger) { + log.d(alert._id, "triggered because", compareType, String(change) + "%"); await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); } } @@ -149,18 +146,3 @@ async function getRatingResponsesByDate(app, widgetId, date, period, ratings) { return prev; }, undefined); } - -/* -(async function() { - if (!require("cluster").isPrimary) { - return; - } - await new Promise(res => setTimeout(res, 2000)); - const app = { _id: new ObjectId("68ca8d133bded4a5d888bb45"), timezone: "Europe/Istanbul" }; - const date = new Date("2025-09-29T12:47:19.247Z"); - const widgetId = "68ca8d133bded4a5d888bb4a"; - let monthlyData = await getRatingResponsesByDate(app, widgetId, date, "monthly", [1, 2, 3, 4, 5]); - let dailyData = await getRatingResponsesByDate(app, widgetId, date, "daily"); - console.log(monthlyData, dailyData); -})(); -*/ \ No newline at end of file diff --git a/plugins/alerts/api/alertModules/revenue.js b/plugins/alerts/api/alertModules/revenue.js index 467818aabe5..b0a82d481ea 100644 --- a/plugins/alerts/api/alertModules/revenue.js +++ b/plugins/alerts/api/alertModules/revenue.js @@ -5,9 +5,7 @@ const log = require('../../../../api/utils/log.js')('alert:revenue'); const moment = require('moment-timezone'); -const common = require('../../../../api/utils/common.js'); const commonLib = require("../parts/common-lib.js"); -const { ObjectId } = require('mongodb'); const { getEventMetricByDate } = require("./events.js"); const { getUserMetricByDate } = require("./users.js"); @@ -23,26 +21,23 @@ const PAYING_USER_PROP_KEY = "p"; * - average revenue per paying user * - # of paying users */ -module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) => { - const app = await common.readBatcher.getOne("apps", { _id: new ObjectId(alert.selectedApps[0]) }); - if (!app) { - log.e(`App ${alert.selectedApps[0]} couldn't be found`); - return done(); - } - +module.exports.check = async({ alert, app, done, scheduledTo: date }) => { let { alertDataSubType, period, compareType, compareValue } = alert; compareValue = Number(compareValue); const metricValue = await calculateRevenueMetric(app, alertDataSubType, date, period) || 0; + log.d(alert._id, "value on", date, "is", metricValue); if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { if (metricValue > compareValue) { + log.d(alert._id, "triggered because", metricValue, "is more than", compareValue); await commonLib.trigger({ alert, app, metricValue, date }, log); } } else { const before = moment(date).subtract(1, commonLib.PERIOD_TO_DATE_COMPONENT_MAP[period]).toDate(); const metricValueBefore = await calculateRevenueMetric(app, alertDataSubType, before, period); + log.d(alert._id, "value on", before, "is", metricValueBefore); if (!metricValueBefore) { return done(); } @@ -53,6 +48,7 @@ module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) = : change <= -compareValue; if (shouldTrigger) { + log.d(alert._id, "triggered because", compareType, String(change) + "%"); await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); } } @@ -122,46 +118,3 @@ async function getRevenueEventMetricByDate(app, metric, date, period) { return result; } - -/* -(async function() { - await new Promise(res => setTimeout(res, 2000)); - const date = new Date("2024-01-04T12:47:19.247Z"); - const app = { - _id: "65c1f875a12e98a328d5eb9e", - timezone: "Europe/Istanbul", - plugins: { - revenue: { - iap_events: [ 'Checkout' ] - } - } - }; - - const hourlyRevenue = await calculateRevenueMetric(app, "total revenue", date, "hourly"); - const hourlyRevenuePerUser = await calculateRevenueMetric(app, "average revenue per user", date, "hourly"); - const hourlyRevenuePerPayingUser = await calculateRevenueMetric(app, "average revenue per paying user", date, "hourly"); - const hourlyPayingUsers = await calculateRevenueMetric(app, "# of paying users", date, "hourly"); - console.log("hourly total revenue", date, "is", hourlyRevenue); - console.log("hourly revenue per user on", date, "is", hourlyRevenuePerUser); - console.log("hourly revenue per paying user on", date, "is", hourlyRevenuePerPayingUser); - console.log("hourly paying user on", date, "is", hourlyPayingUsers); - - const dailyRevenue = await calculateRevenueMetric(app, "total revenue", date, "daily"); - const dailyRevenuePerUser = await calculateRevenueMetric(app, "average revenue per user", date, "daily"); - const dailyRevenuePerPayingUser = await calculateRevenueMetric(app, "average revenue per paying user", date, "daily"); - const dailyPayingUsers = await calculateRevenueMetric(app, "# of paying users", date, "daily"); - console.log("daily total revenue", date, "is", dailyRevenue); - console.log("daily revenue per user on", date, "is", dailyRevenuePerUser); - console.log("daily revenue per paying user on", date, "is", dailyRevenuePerPayingUser); - console.log("daily paying user on", date, "is", dailyPayingUsers); - - const monthlyRevenue = await calculateRevenueMetric(app, "total revenue", date, "monthly"); - const monthlyRevenuePerUser = await calculateRevenueMetric(app, "average revenue per user", date, "monthly"); - const monthlyRevenuePerPayingUser = await calculateRevenueMetric(app, "average revenue per paying user", date, "monthly"); - const monthlyPayingUsers = await calculateRevenueMetric(app, "# of paying users", date, "monthly"); - console.log("monthly total revenue", date, "is", monthlyRevenue); - console.log("monthly revenue per user on", date, "is", monthlyRevenuePerUser); - console.log("monthly revenue per paying user on", date, "is", monthlyRevenuePerPayingUser); - console.log("monthly paying user on", date, "is", monthlyPayingUsers); -})(); -*/ \ No newline at end of file diff --git a/plugins/alerts/api/alertModules/sessions.js b/plugins/alerts/api/alertModules/sessions.js index fab71862217..258017465d8 100644 --- a/plugins/alerts/api/alertModules/sessions.js +++ b/plugins/alerts/api/alertModules/sessions.js @@ -7,20 +7,13 @@ const log = require('../../../../api/utils/log.js')('alert:sessions'); const moment = require('moment-timezone'); const common = require('../../../../api/utils/common.js'); const commonLib = require("../parts/common-lib.js"); -const { ObjectId } = require('mongodb'); const METRIC_ENUM = { NUM_OF_SESSIONS: "# of sessions", AVG_SESSION_DURATION: "average session duration", }; -module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) => { - const app = await common.readBatcher.getOne("apps", { _id: new ObjectId(alert.selectedApps[0]) }); - if (!app) { - log.e(`App ${alert.selectedApps[0]} couldn't be found`); - return done(); - } - +module.exports.check = async({ alert, app, done, scheduledTo: date }) => { let { alertDataSubType, period, compareType, compareValue } = alert; compareValue = Number(compareValue); @@ -42,9 +35,11 @@ module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) = log.e(`Metric "${alert.alertDataSubType}" couldn't be mapped for alert ${alert._id.toString()}`); return done(); } + log.d(alert._id, "value on", date, "is", metricValue); if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { if (metricValue > compareValue) { + log.d(alert._id, "triggered because", metricValue, "is more than", compareValue); await commonLib.trigger({ alert, app, metricValue, date }, log); } } @@ -67,6 +62,7 @@ module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) = } metricValueBefore = sessionDuration / numberOfSessionsBefore / 60; } + log.d(alert._id, "value on", before, "is", metricValueBefore); if (!metricValueBefore) { return done(); @@ -78,6 +74,7 @@ module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) = : change <= -compareValue; if (shouldTrigger) { + log.d(alert._id, "triggered because", compareType, String(change) + "%"); await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); } } @@ -130,51 +127,3 @@ async function getSessionMetricByDate(app, metric, date, period) { return number; } - -/* -(async function() { - await new Promise(res => setTimeout(res, 2000)); - const app = { - _id: "65c1f875a12e98a328d5eb9e", - timezone: "Europe/Istanbul" - }; - const dates = [ - new Date("2024-02-01"), - new Date("2024-02-02"), - new Date("2024-02-03"), - new Date("2024-02-04"), - new Date("2024-02-05"), - new Date("2024-02-06"), - new Date("2024-02-07"), - new Date("2024-02-09"), - new Date("2024-02-12"), - new Date("2024-02-13"), - new Date("2024-02-16"), - new Date("2024-02-19"), - new Date("2024-02-20"), - ]; - let totalMonthlyValue = 0; - for (let date of dates) { - const dailyValue = await getSessionMetricByDate(app, "t", date, "daily"); - if (typeof dailyValue !== "undefined") { - totalMonthlyValue += dailyValue; - } - } - const monthlyValue = await getSessionMetricByDate(app, "t", new Date("2024-02-01"), "monthly"); - - console.log("sum of daily values", totalMonthlyValue); - console.log("monthly value", monthlyValue); - - const hours = [ - new Date("2024-02-01T00:00:00.000Z"), - ]; - let totalDailyValue = 0; - for (const hour of hours) { - const hourlyValue = await getSessionMetricByDate(app, "t", hour, "hourly"); - if (typeof hourlyValue !== "undefined") { - totalDailyValue += hourlyValue; - } - } - console.log(totalDailyValue); -})(); -*/ \ No newline at end of file diff --git a/plugins/alerts/api/alertModules/survey.js b/plugins/alerts/api/alertModules/survey.js index 3c7a7dfa2fb..76c7d137095 100644 --- a/plugins/alerts/api/alertModules/survey.js +++ b/plugins/alerts/api/alertModules/survey.js @@ -6,7 +6,6 @@ const log = require('../../../../api/utils/log.js')('alert:survey'); const moment = require('moment-timezone'); const common = require('../../../../api/utils/common.js'); const commonLib = require("../parts/common-lib.js"); -const { ObjectId } = require('mongodb'); module.exports.triggerByEvent = triggerByEvent; /** @@ -49,26 +48,23 @@ async function triggerByEvent(payload) { } } -module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: date }) { - const app = await common.readBatcher.getOne("apps", { _id: new ObjectId(alert.selectedApps[0]) }); - if (!app) { - log.e(`App ${alert.selectedApps[0]} couldn't be found`); - return done(); - } - +module.exports.check = async function({ alert, app, done, scheduledTo: date }) { let { period, alertDataSubType2, compareType, compareValue } = alert; compareValue = Number(compareValue); const metricValue = await getResponsesByDate(app, alertDataSubType2, date, period) || 0; + log.d(alert._id, "value on", date, "is", metricValue); if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { if (metricValue > compareValue) { + log.d(alert._id, "triggered because", metricValue, "is more than", compareValue); await commonLib.trigger({ alert, app, metricValue, date }, log); } } else { const before = moment(date).subtract(1, commonLib.PERIOD_TO_DATE_COMPONENT_MAP[period]).toDate(); const metricValueBefore = await getResponsesByDate(app, alertDataSubType2, before, period); + log.d(alert._id, "value on", before, "is", metricValueBefore); if (!metricValueBefore) { return done(); } @@ -79,6 +75,7 @@ module.exports.check = async function({ alertConfigs: alert, done, scheduledTo: : change <= -compareValue; if (shouldTrigger) { + log.d(alert._id, "triggered because", compareType, String(change) + "%"); await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); } } @@ -157,20 +154,3 @@ function sumOfAllResponses(scope, survey) { return numberOfResponses; } - -/* -(async function() { - await new Promise(res => setTimeout(res, 2000)); - const app = { _id: ObjectId("65c1f875a12e98a328d5eb9e"), timezone: "Europe/Istanbul" }; - const widgetId = "65c38401b46a4d172d7c61a5"; - const date = new Date("2024-02-07T12:00:00.000Z"); - let data = await getResponsesByDate(app, widgetId, date, "monthly"); - console.log("monthly:", data); - - data = await getResponsesByDate(app, widgetId, date, "daily"); - console.log("daily:", data); - - data = await getResponsesByDate(app, widgetId, date, "hourly"); - console.log("hourly:", data); -})(); -*/ \ No newline at end of file diff --git a/plugins/alerts/api/alertModules/users.js b/plugins/alerts/api/alertModules/users.js index ed636e8a60a..99e9a50b966 100644 --- a/plugins/alerts/api/alertModules/users.js +++ b/plugins/alerts/api/alertModules/users.js @@ -7,20 +7,13 @@ const log = require('../../../../api/utils/log.js')('alert:users'); const moment = require('moment-timezone'); const common = require('../../../../api/utils/common.js'); const commonLib = require("../parts/common-lib.js"); -const { ObjectId } = require('mongodb'); const METRIC_TO_PROPERTY_MAP = { "# of users": "u", "# of new users": "n", }; -module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) => { - const app = await common.readBatcher.getOne("apps", { _id: new ObjectId(alert.selectedApps[0]) }); - if (!app) { - log.e(`App ${alert.selectedApps[0]} couldn't be found`); - return done(); - } - +module.exports.check = async({ alert, app, done, scheduledTo: date }) => { let { alertDataSubType, period, compareType, compareValue } = alert; const metricProperty = METRIC_TO_PROPERTY_MAP[alertDataSubType]; compareValue = Number(compareValue); @@ -31,15 +24,18 @@ module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) = } const metricValue = await getUserMetricByDate(app, metricProperty, date, period) || 0; + log.d(alert._id, "value on", date, "is", metricValue); if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { if (metricValue > compareValue) { + log.d(alert._id, "triggered because", metricValue, "is more than", compareValue); await commonLib.trigger({ alert, app, metricValue, date }, log); } } else { const before = moment(date).subtract(1, commonLib.PERIOD_TO_DATE_COMPONENT_MAP[period]).toDate(); const metricValueBefore = await getUserMetricByDate(app, metricProperty, before, period); + log.d(alert._id, "value on", before, "is", metricValueBefore); if (!metricValueBefore) { return done(); } @@ -50,6 +46,7 @@ module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) = : change <= -compareValue; if (shouldTrigger) { + log.d(alert._id, "triggered because", compareType, String(change) + "%"); await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); } } diff --git a/plugins/alerts/api/alertModules/views.js b/plugins/alerts/api/alertModules/views.js index 75b6b63890b..be61d8f5490 100644 --- a/plugins/alerts/api/alertModules/views.js +++ b/plugins/alerts/api/alertModules/views.js @@ -15,13 +15,7 @@ const METRIC_TO_PROPERTY_MAP = { "# of page views": "t", }; -module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) => { - const app = await common.readBatcher.getOne("apps", { _id: new ObjectId(alert.selectedApps[0]) }); - if (!app) { - log.e(`App ${alert.selectedApps[0]} couldn't be found`); - return done(); - } - +module.exports.check = async({ alert, app, done, scheduledTo: date }) => { let { alertDataSubType, alertDataSubType2, period, compareType, compareValue } = alert; const metricProperty = METRIC_TO_PROPERTY_MAP[alertDataSubType]; compareValue = Number(compareValue); @@ -32,15 +26,18 @@ module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) = } const metricValue = await getViewMetricByDate(app, metricProperty, alertDataSubType2, date, period) || 0; + log.d(alert._id, "value on", date, "is", metricValue); if (compareType === commonLib.COMPARE_TYPE_ENUM.MORE_THAN) { if (metricValue > compareValue) { + log.d(alert._id, "triggered because", metricValue, "is more than", compareValue); await commonLib.trigger({ alert, app, metricValue, date }, log); } } else { const before = moment(date).subtract(1, commonLib.PERIOD_TO_DATE_COMPONENT_MAP[period]).toDate(); const metricValueBefore = await getViewMetricByDate(app, metricProperty, alertDataSubType2, before, period); + log.d(alert._id, "value on", before, "is", metricValueBefore); if (!metricValueBefore) { return done(); } @@ -51,6 +48,7 @@ module.exports.check = async({ alertConfigs: alert, done, scheduledTo: date }) = : change <= -compareValue; if (shouldTrigger) { + log.d(alert._id, "triggered because", compareType, String(change) + "%"); await commonLib.trigger({ alert, app, date, metricValue, metricValueBefore }, log); } } @@ -92,18 +90,3 @@ async function getViewMetricByDate(app, metric, view, date, period) { } return scope?.[dateKey]?.[metric]; } - -/* -(async function() { - await new Promise(res => setTimeout(res, 2000)); - const app = { _id: "65c1f875a12e98a328d5eb9e", timezone: "Europe/Istanbul" }; - const view = "65c5e7f7c26cadacd1229f3a"; - const date = new Date("2024-02-13T13:47:19.247Z"); - const hourly = await getViewMetricByDate(app, "t", view, date, "hourly"); - console.log("hourly:", hourly); - const daily = await getViewMetricByDate(app, "t", view, date, "daily"); - console.log("daily:", daily); - const monthly = await getViewMetricByDate(app, "t", view, date, "monthly"); - console.log("monthly:", monthly); -})(); -*/ \ No newline at end of file diff --git a/plugins/alerts/api/api.js b/plugins/alerts/api/api.js index 4478311ceaa..5c19c9c29db 100644 --- a/plugins/alerts/api/api.js +++ b/plugins/alerts/api/api.js @@ -3,11 +3,12 @@ const plugins = require('../../pluginManager.js'); const log = require('../../../api/utils/log.js')('alert:api'); var Promise = require("bluebird"); const JOB = require('../../../api/parts/jobs'); -const utils = require('./parts/utils'); +const utils = require('./parts/utils.js'); const _ = require('lodash'); const { validateCreate, validateRead, validateUpdate } = require('../../../api/utils/rights.js'); const FEATURE_NAME = 'alerts'; const commonLib = require("./parts/common-lib.js"); +const moment = require('moment-timezone'); /** * Alerts that can be triggered when an event is received. @@ -23,16 +24,35 @@ const TRIGGER_BY_EVENT = Object.keys(commonLib.TRIGGERED_BY_EVENT).map(name => ( name })); -// FIX THIS: workaround for the job.schedule -const _date = new Date("2024-03-25T23:59:00.000Z"); -const _timeDelta = _date.getTimezoneOffset() / 60; -const _hours = String((23 + _timeDelta) % 24).padStart(2, "0"); - -const PERIOD_TO_TEXT_EXPRESSION_MAPPER = { - "hourly": "every 1 hour on the 59th min", - "daily": "at " + _hours + ":59", - "monthly": "on the last day of the month at " + _hours + ":59", -}; +/** + * Returns the text expression build from period for later.js. + * Takes the timezone offset into account while calculating the trigger time. + * @param {string} period - "hourly"|"daily"|"monthly" + * @param {number} offset - timezone offset in minutes + * @returns {string} schedule text + */ +function getScheduleTextExpression(period, offset) { + if (typeof offset !== "number") { + log.e("Offset is required"); + return; + } + if (period === "hourly") { + return "every 1 hour on the 59th min"; + } + else { + const utcClock = moment("2026-02-01T23:59:00.000Z") + .tz("UTC") + .subtract(offset, "minutes") + .format("HH:mm"); + if (period === "daily") { + return "at " + utcClock; + } + else if (period === "monthly") { + return "on the last day of the month at " + utcClock; + } + } + log.e(`No such period \"${period}\"`); +} (function() { /** @@ -59,12 +79,17 @@ const PERIOD_TO_TEXT_EXPRESSION_MAPPER = { * update alert job * @param {object} alert - alert record data */ - function updateJobForAlert(alert) { + async function updateJobForAlert(alert) { if (alert.enabled) { - const textExpression = PERIOD_TO_TEXT_EXPRESSION_MAPPER[alert.period]; - if (textExpression) { - JOB.job('alerts:monitor', { alertID: alert._id }).replace().schedule(textExpression); - // JOB.job('alerts:monitor', { alertID: alert._id }).replace().schedule("every seconds"); + const apps = await commonLib.loadAlertAppsWithTimezoneOffsets(alert); + for (const app of apps) { + const textExpression = getScheduleTextExpression(alert.period, app.offset); + if (textExpression) { + JOB.job('alerts:monitor', { + alertID: alert._id, + appID: app._id + }).replace().schedule(textExpression); + } } } else { @@ -74,16 +99,17 @@ const PERIOD_TO_TEXT_EXPRESSION_MAPPER = { /** * load job list */ - function loadJobs() { - common.readBatcher.getMany("alerts", {}, function(err, alertsList) { - log.d(alertsList, "get alert configs"); - alertsList && alertsList.forEach(t => { - //period type - if (t.period) { - updateJobForAlert(t); - } - }); + async function loadJobs() { + // delete and then re-create all jobs + await common.db.collection("jobs").deleteMany({ + name: "alerts:monitor" }); + const alerts = await common.readBatcher.getMany("alerts", { + enabled: true, + period: { $exists: true } + }); + log.d("loaded", alerts); + await Promise.all(alerts.map(updateJobForAlert)); } plugins.register("/i", async function(ob) { @@ -124,22 +150,20 @@ const PERIOD_TO_TEXT_EXPRESSION_MAPPER = { }); plugins.register("/master", function() { - loadJobs(); + setTimeout(function() { + plugins.dispatch("/updateAlert", { method: "alertTrigger" }); + }, 10000); }); plugins.register("/updateAlert", function(ob) { - setTimeout(() => { - if (ob && (ob.method === "alertTrigger")) { - if (ob.alert) { - deleteJob(ob.alert, function() { - updateJobForAlert(ob.alert); - }); - } - else { - loadJobs(); - } + if (ob && ob.method === "alertTrigger") { + if (ob.alert) { + updateJobForAlert(ob.alert); + } + else { + loadJobs(); } - }, 2000); + } }); @@ -148,21 +172,18 @@ const PERIOD_TO_TEXT_EXPRESSION_MAPPER = { utils.addAlertCount(ob); }); - setTimeout(function() { - plugins.dispatch("/updateAlert", { method: "alertTrigger" }); - }, 10000); /** - * @api {get} /i/alert/save save new create or updated alert data. - * @apiName saveAlert - * @apiGroup alerts + * @api {get} /i/alert/save save new create or updated alert data. + * @apiName saveAlert + * @apiGroup alerts * - * @apiDescription create or update alert. - * @apiQuery {string} alert_config alert Configuration JSON object string. + * @apiDescription create or update alert. + * @apiQuery {string} alert_config alert Configuration JSON object string. * if contains "_id" will update related alert in DB. - * @apiQuery {String} app_id target app id of the alert. + * @apiQuery {String} app_id target app id of the alert. * * @apiSuccessExample {json} Success-Response: * HTTP/1.1 200 OK @@ -229,7 +250,6 @@ const PERIOD_TO_TEXT_EXPRESSION_MAPPER = { if (result && result.value) { plugins.dispatch("/updateAlert", { method: "alertTrigger", alert: result.value }); } - plugins.dispatch("/updateAlert", { method: "alertTrigger" }); common.returnOutput(params, result && result.value); } @@ -361,14 +381,19 @@ const PERIOD_TO_TEXT_EXPRESSION_MAPPER = { qquery, {}, { $set: { enabled: statusList[alertID] } }, - { new: false, upsert: false } + { new: true, upsert: false } ) ); } - Promise.all(batch).then(function() { - log.d("alert all updated."); + Promise.all(batch).then(function(result) { + let updatedAlerts = []; + if (Array.isArray(result)) { + updatedAlerts = result + .filter(({ ok }) => !!ok) + .map(({ value }) => value); + } common.readBatcher.invalidate("alerts", {}, {}, true); - plugins.dispatch("/updateAlert", { method: "alertTrigger" }); + updatedAlerts.map(alert => plugins.dispatch("/updateAlert", { method: "alertTrigger", alert })); common.returnOutput(params, true); }); }); @@ -376,13 +401,13 @@ const PERIOD_TO_TEXT_EXPRESSION_MAPPER = { }); /** - * @api {post} /i/alert/list get alert list - * @apiName getAlertList - * @apiGroup alerts + * @api {post} /i/alert/list get alert list + * @apiName getAlertList + * @apiGroup alerts * - * @apiDescription get Alert List user can view. + * @apiDescription get Alert List user can view. * - * @apiQuery {String} app_id target app id of the alert. + * @apiQuery {String} app_id target app id of the alert. * * @apiSuccessExample {json} Success-Response: * HTTP/1.1 200 OK diff --git a/plugins/alerts/api/jobs/monitor.js b/plugins/alerts/api/jobs/monitor.js index debe90c19c8..fab1bf99b65 100644 --- a/plugins/alerts/api/jobs/monitor.js +++ b/plugins/alerts/api/jobs/monitor.js @@ -30,40 +30,31 @@ class MonitorJob extends Job { * @param {object} _db - db object * @param {function} done - callback function */ - run(_db, done) { - const alertID = this._json.data.alertID; + async run(_db, done) { + let { alertID, appID } = this._json.data; const scheduledTo = this._json.next; - const self = this; - common.db.collection("alerts").findOne({ - _id: common.db.ObjectID(alertID), - // these are being triggered by the event listener in api.js - alertDataSubType: { $nin: Object.values(TRIGGERED_BY_EVENT) } - }, async function(err, alertConfigs) { - if (err) { - log.e(err); - return; + try { + const alert = await common.db.collection("alerts").findOne({ + _id: common.db.ObjectID(alertID), + // these are being triggered by the event listener in api.js + alertDataSubType: { $nin: Object.values(TRIGGERED_BY_EVENT) } + }); + const app = await common.db.collection("apps").findOne({ + _id: common.db.ObjectID(appID), + }); + log.d("alert job info:", this._json, alert, app); + if (!alert || !app) { + throw new Error("Alert", alertID, "or App", appID, "couldn't be found"); } - if (!alertConfigs) { - return; + if (alert.alertDataType === 'profile_groups') { + alert.alertDataType = 'cohorts'; } - log.d('Runing alerts Monitor Job ....'); - log.d("job info:", self._json, alertConfigs); - if (alertConfigs.alertDataType === 'profile_groups') { - alertConfigs.alertDataType = 'cohorts'; - } - const module = ALERT_MODULES[alertConfigs.alertDataType]; - if (module) { - try { - await module.check({ alertConfigs, done, scheduledTo }); - } - catch (error) { - log.e("Error while running " + alertConfigs.alertDataType + " alert check", error); - } - } - else { - log.e("Alert module " + alertConfigs.alertDataType + " not found"); - } - }); + const module = ALERT_MODULES[alert.alertDataType]; + await module.check({ alert, app, done, scheduledTo }); + } + catch (err) { + log.e(err); + } } } diff --git a/plugins/alerts/api/parts/common-lib.js b/plugins/alerts/api/parts/common-lib.js index 7eda0c8eec7..dea327d1972 100644 --- a/plugins/alerts/api/parts/common-lib.js +++ b/plugins/alerts/api/parts/common-lib.js @@ -28,6 +28,7 @@ * @property {string} name - name identifier * @property {ObjectId} _id - document id * @property {string} timezone - timezone string (e.g. Europe/Istanbul) + * @property {number} offset - timezone offset (e.g. 120 for Europe/Berlin, -240 for US/Eastern) * @property {any} plugins */ @@ -57,6 +58,7 @@ const moment = require('moment-timezone'); const path = require("path"); const fs = require("fs"); const ejs = require("ejs"); +const { ObjectId } = require("mongodb"); const EMAIL_TEMPLATE = ejs.compile( fs.readFileSync( path.resolve(__dirname, '../../frontend/public/templates/email.html'), @@ -92,6 +94,7 @@ module.exports = { determineAudience, compileEmail, trigger, + loadAlertAppsWithTimezoneOffsets, }; /** @@ -257,4 +260,33 @@ async function trigger(result, log) { log.e("Alert e-mail couldn't be send to " + email, err); } } +} + +/** + * Returns all of the app objects from "apps" collection with "offset" + * property populated for the given alert. + * @param {Alert} alert - alert object + * @returns {App[]} App objects with offset property + */ +async function loadAlertAppsWithTimezoneOffsets(alert) { + const selectedApp = alert.selectedApps[0]; + // there can only be a single app selected. + // or all of the apps are selected (only available for data points): + let apps; + if (selectedApp === "all") { + apps = await common.readBatcher.getMany("apps", {}); + } + else { + apps = [ + await common.readBatcher.getOne("apps", { + _id: new ObjectId(selectedApp) + }) + ]; + } + for (const app of apps) { + app.offset = app.timezone + ? moment.tz(app.timezone).utcOffset() + : moment().utcOffset(); // fallback to system timezone + } + return apps; } \ No newline at end of file From 9b8b55853f245338041a0944321c4bff34681a3e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 08:09:47 +0000 Subject: [PATCH 31/36] Bump rate-limiter-flexible from 9.1.1 to 11.0.0 Bumps [rate-limiter-flexible](https://github.com/animir/node-rate-limiter-flexible) from 9.1.1 to 11.0.0. - [Release notes](https://github.com/animir/node-rate-limiter-flexible/releases) - [Commits](https://github.com/animir/node-rate-limiter-flexible/compare/v9.1.1...v11.0.0) --- updated-dependencies: - dependency-name: rate-limiter-flexible dependency-version: 11.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index fdfddeee926..5fa42b873fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,7 +62,7 @@ "offline-geocoder": "git+https://github.com/Countly/offline-geocoder.git", "properties-parser": "0.6.0", "puppeteer": "^24.6.1", - "rate-limiter-flexible": "^9.0.1", + "rate-limiter-flexible": "^11.0.0", "sass": "1.99.0", "semver": "^7.7.1", "sharp": "^0.34.2", @@ -11342,9 +11342,9 @@ } }, "node_modules/rate-limiter-flexible": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-9.1.1.tgz", - "integrity": "sha512-imxFjzPCmvDLMe7d2tsgiSQvs5EI2fI9SNymmslAfOqznZhsZ+PqbIjIYKpuSbd3pKovR1aMG47qfCLIO/adVg==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-11.0.0.tgz", + "integrity": "sha512-UhN3xVeU6Az3y6hAuxMUwFsKcKD1HffhMGK0MknbSxH9vkwslS/p19ovCvJqIVT97pE778nKu2sUgYAcxj4dmQ==", "license": "ISC" }, "node_modules/raw-body": { diff --git a/package.json b/package.json index 6dd9cd425be..a87b89c9e2c 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "offline-geocoder": "git+https://github.com/Countly/offline-geocoder.git", "properties-parser": "0.6.0", "puppeteer": "^24.6.1", - "rate-limiter-flexible": "^9.0.1", + "rate-limiter-flexible": "^11.0.0", "sass": "1.99.0", "semver": "^7.7.1", "sharp": "^0.34.2", From 38eb2dd3d4fbdef0e58fd5601eb324068fac06ff Mon Sep 17 00:00:00 2001 From: Cihad Tekin Date: Thu, 9 Apr 2026 15:18:24 +0300 Subject: [PATCH 32/36] [alerts] codacy fix --- plugins/alerts/api/api.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/alerts/api/api.js b/plugins/alerts/api/api.js index 5c19c9c29db..af39982d58c 100644 --- a/plugins/alerts/api/api.js +++ b/plugins/alerts/api/api.js @@ -29,7 +29,7 @@ const TRIGGER_BY_EVENT = Object.keys(commonLib.TRIGGERED_BY_EVENT).map(name => ( * Takes the timezone offset into account while calculating the trigger time. * @param {string} period - "hourly"|"daily"|"monthly" * @param {number} offset - timezone offset in minutes - * @returns {string} schedule text + * @returns {string|undefined} schedule text */ function getScheduleTextExpression(period, offset) { if (typeof offset !== "number") { @@ -52,6 +52,7 @@ function getScheduleTextExpression(period, offset) { } } log.e(`No such period \"${period}\"`); + return; } (function() { From 685862cc2b376dbfc83b73271c6ce853542157b1 Mon Sep 17 00:00:00 2001 From: Cihad Tekin Date: Thu, 9 Apr 2026 15:21:19 +0300 Subject: [PATCH 33/36] Changelog update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc3270a3112..dd31eda241c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Version 25.03.X Fixes: - [core] Fixed duplicate conditional in form field template +- [alerts] Fixed alert jobs using system's timezone instead of application's Enterprise Fixes: - [data-manager] Fix notification message after editing user property From 59c642f019db3d379e19d8ff046d53d64a7dc6f6 Mon Sep 17 00:00:00 2001 From: Cihad Tekin Date: Thu, 9 Apr 2026 15:37:05 +0300 Subject: [PATCH 34/36] [alerts] codacy fix --- plugins/alerts/api/api.js | 42 ++++++++++---------------- plugins/alerts/api/parts/common-lib.js | 4 +-- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/plugins/alerts/api/api.js b/plugins/alerts/api/api.js index af39982d58c..8c82c3ebff5 100644 --- a/plugins/alerts/api/api.js +++ b/plugins/alerts/api/api.js @@ -29,30 +29,20 @@ const TRIGGER_BY_EVENT = Object.keys(commonLib.TRIGGERED_BY_EVENT).map(name => ( * Takes the timezone offset into account while calculating the trigger time. * @param {string} period - "hourly"|"daily"|"monthly" * @param {number} offset - timezone offset in minutes - * @returns {string|undefined} schedule text + * @returns {string} schedule text */ function getScheduleTextExpression(period, offset) { - if (typeof offset !== "number") { - log.e("Offset is required"); - return; - } if (period === "hourly") { return "every 1 hour on the 59th min"; } - else { - const utcClock = moment("2026-02-01T23:59:00.000Z") - .tz("UTC") - .subtract(offset, "minutes") - .format("HH:mm"); - if (period === "daily") { - return "at " + utcClock; - } - else if (period === "monthly") { - return "on the last day of the month at " + utcClock; - } + const utcClock = moment("2026-02-01T23:59:00.000Z") + .tz("UTC") + .subtract(offset, "minutes") + .format("HH:mm"); + if (period === "daily") { + return "at " + utcClock; } - log.e(`No such period \"${period}\"`); - return; + return "on the last day of the month at " + utcClock; } (function() { @@ -81,7 +71,7 @@ function getScheduleTextExpression(period, offset) { * @param {object} alert - alert record data */ async function updateJobForAlert(alert) { - if (alert.enabled) { + if (alert.enabled && Object.keys(commonLib.PERIOD_TO_DATE_COMPONENT_MAP).includes(alert.period)) { const apps = await commonLib.loadAlertAppsWithTimezoneOffsets(alert); for (const app of apps) { const textExpression = getScheduleTextExpression(alert.period, app.offset); @@ -289,13 +279,13 @@ function getScheduleTextExpression(period, offset) { /** - * @api {get} /i/alert/delete delete alert by alert ID - * @apiName deleteAlert - * @apiGroup alerts + * @api {get} /i/alert/delete delete alert by alert ID + * @apiName deleteAlert + * @apiGroup alerts * * @apiDescription delete alert by id. * @apiQuery {string} alertID target alert id from db. - * @apiQuery {String} app_id target app id of the alert. + * @apiQuery {String} app_id target app id of the alert. * * @apiSuccessExample {json} Success-Response: * HTTP/1.1 200 OK @@ -343,13 +333,13 @@ function getScheduleTextExpression(period, offset) { /** * @api {post} /i/alert/status change alert status - * @apiName changeAlertStatus - * @apiGroup alerts + * @apiName changeAlertStatus + * @apiGroup alerts * * @apiDescription change alerts status by boolean flag. * @apiQuery {string} JSON string of status object for alerts record want to update. * for example: {"626270afbf7392a8bfd8c1f3":false, "42dafbf7392a8bfd8c1e1": true} - * @apiQuery {String} app_id target app id of the alert. + * @apiQuery {String} app_id target app id of the alert. * * @apiSuccessExample {text} Success-Response: * HTTP/1.1 200 OK diff --git a/plugins/alerts/api/parts/common-lib.js b/plugins/alerts/api/parts/common-lib.js index dea327d1972..5840708d1e5 100644 --- a/plugins/alerts/api/parts/common-lib.js +++ b/plugins/alerts/api/parts/common-lib.js @@ -18,7 +18,7 @@ * @property {boolean} enabled - true|false * @property {string} compareDescribe - text to show on lists for this alert * @property {Array} alertValues - audience e.g. for alertBy="email", list of e-mails - * @property {Array} allGroups - + * @property {Array} allGroups - * @property {string} createdBy - creation time */ @@ -209,7 +209,7 @@ async function compileEmail(result) { * Formats the metric value to ensure it maintains its type. * If the value is a number, it rounds to 2 decimal places if necessary. * Otherwise, it returns the value as is. - * + * * @param {number|string} value - The value to be formatted. * @returns {number|string} The formatted value, maintaining the original type. */ From 41187d530b4815025f4eeae8ccdf192b8f3aecf2 Mon Sep 17 00:00:00 2001 From: Cihad Tekin Date: Thu, 9 Apr 2026 16:45:45 +0300 Subject: [PATCH 35/36] Update CHANGELOG.md for 25.03.42 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd31eda241c..7658ae1eef6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## Version 25.03.X +## Version 25.03.42 Fixes: - [core] Fixed duplicate conditional in form field template - [alerts] Fixed alert jobs using system's timezone instead of application's From 141cefc0409a5035e1f00d436e4b7d9aa4edba6d Mon Sep 17 00:00:00 2001 From: Cihad Tekin Date: Thu, 9 Apr 2026 16:49:19 +0300 Subject: [PATCH 36/36] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7658ae1eef6..0f287511c20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## Version 25.03.42 Fixes: -- [core] Fixed duplicate conditional in form field template - [alerts] Fixed alert jobs using system's timezone instead of application's +- [core] Fixed duplicate conditional in form field template Enterprise Fixes: - [data-manager] Fix notification message after editing user property