From 04119e5b3e41fa0c6499fbaca3994eb0e4356fa3 Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 20:41:47 +0200 Subject: [PATCH 01/14] replacing "params" with "Params" type --- api/parts/data/fetch.js | 68 +++++++++++++++++++++------------------- api/utils/taskmanager.js | 6 +++- plugins/sdk/api/api.js | 6 +++- 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/api/parts/data/fetch.js b/api/parts/data/fetch.js index 2b679e22e75..30dfb4942e2 100644 --- a/api/parts/data/fetch.js +++ b/api/parts/data/fetch.js @@ -3,6 +3,10 @@ * @module api/parts/data/fetch */ +/** + * @typedef {import('../../../types/requestProcessor').Params} Params + */ + const { getAdminApps, getUserApps } = require('../../utils/rights.js'); /** @lends module:api/parts/data/fetch */ @@ -69,7 +73,7 @@ fetch.fetchFromGranularData = async function(queryData, callback) { /** * Prefetch event data, either by provided key or first event all events * @param {string} collection - event key -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.prefetchEventData = async function(collection, params) { if (!params.qstring.event) { @@ -151,7 +155,7 @@ fetch.prefetchEventData = async function(collection, params) { /** * Fetch specific event data and output to browser * @param {string} collection - event key -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchEventData = function(collection, params) { var fetchFields = {}; @@ -230,7 +234,7 @@ fetch.fetchMergedEventGroups = function(params) { /** * The return the merged event data for event groups. -* @param {params} params - params object with app_id and date +* @param {Params} params - params object with app_id and date * @param {string} event - id of event group * @param {object=} options - additional optional settings * @param {object=} options.db - database connection to use, by default will try to use common.db @@ -260,7 +264,7 @@ fetch.getMergedEventGroups = function(params, event, options, callback) { /** * Get merged data from multiple events in standard data model and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchMergedEventData = function(params) { fetch.getMergedEventData(params, params.qstring.events, {}, function(result) { @@ -270,7 +274,7 @@ fetch.fetchMergedEventData = function(params) { /** * Get merged data from multiple events in standard data model -* @param {params} params - params object with app_id and date +* @param {Params} params - params object with app_id and date * @param {array} events - array with event keys * @param {object=} options - additional optional settings * @param {object=} options.db - database connection to use, by default will try to use common.db @@ -430,7 +434,7 @@ fetch.getMergedEventData = function(params, events, options, callback) { /** * Get collection data for specific app and output to browser * @param {string} collection - collection name -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchCollection = function(collection, params) { common.db.collection(collection).findOne({ '_id': params.app_id }, function(err, result) { @@ -466,7 +470,7 @@ fetch.fetchCollection = function(collection, params) { /** * Get time data for specific metric by collection and output to browser * @param {string} collection - collection name -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchTimeData = function(collection, params) { @@ -493,7 +497,7 @@ fetch.fetchTimeData = function(collection, params) { /** * Get data for dashboard api and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchDashboard = function(params) { params.qstring.period = params.qstring.period || "30days"; @@ -569,7 +573,7 @@ fetch.fetchDashboard = function(params) { /** * Get data for old all apps api and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchAllApps = function(params) { var filter = {}; @@ -709,7 +713,7 @@ fetch.fetchAllApps = function(params) { /** * Calls aggregation query to calculate top three values based on 't' in given collection -* @param {params} params - params object +* @param {Params} params - params object * @param {string} collection - collection name * @param {function} callback - callback function **/ @@ -805,7 +809,7 @@ function getDataforTops(params, collection, callback) { /** * Get data for tops api and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchTop = function(params) { var obj = {}; @@ -845,7 +849,7 @@ fetch.fetchTop = function(params) { /** * Get data for tops api and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchTops = function(params) { if (params.qstring.metric || params.qstring.metrics) { @@ -877,7 +881,7 @@ fetch.fetchTops = function(params) { /** * Get data for countries api and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchCountries = function(params) { params.qstring.period = "30days"; @@ -934,7 +938,7 @@ fetch.fetchCountries = function(params) { /** * Get session data and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchSessions = function(params) { fetchTimeObj('users', params, false, function(usersDoc) { @@ -949,7 +953,7 @@ fetch.fetchSessions = function(params) { /** * Get loyalty ranges data and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchLoyalty = function(params) { fetchTimeObj("users", params, false, function(doc) { @@ -967,7 +971,7 @@ fetch.fetchLoyalty = function(params) { /** * Get frequency ranges data and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchFrequency = function(params) { fetchTimeObj("users", params, false, function(doc) { @@ -985,7 +989,7 @@ fetch.fetchFrequency = function(params) { /** * Get durations ranges data and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchDurations = function(params) { fetchTimeObj("users", params, false, function(doc) { @@ -1003,7 +1007,7 @@ fetch.fetchDurations = function(params) { /** * Get metric segment data from database, merging year and month and splitted docments together and breaking down data by segment -* @param {params} params - params object with app_id and date +* @param {Params} params - params object with app_id and date * @param {string} metric - name of the collection where to get data from * @param {object} totalUsersMetric - data from total users api request to correct unique user values * @param {function} callback - callback to retrieve the data, receiving only one param which is output @@ -1031,7 +1035,7 @@ fetch.getMetric = function(params, metric, totalUsersMetric, callback) { /** * Get metric segment data from database with options, merging year and month and splitted docments together and breaking down data by segment -* @param {params} params - params object with app_id and date +* @param {Params} params - params object with app_id and date * @param {string} metric - name of the collection where to get data from * @param {object} totalUsersMetric - data from total users api request to correct unique user values * @param {object=} fetchTimeOptions - additional optional settings @@ -1191,7 +1195,7 @@ fetch.metricToProperty = function(metric) { /** * Get metric data for metric api and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchMetric = function(params) { var output = function(data) { @@ -1213,7 +1217,7 @@ fetch.fetchMetric = function(params) { /** * Get events overview data for overview api and output to browser -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchDataEventsOverview = function(params) { var ob = { @@ -1295,7 +1299,7 @@ fetch.fetchDataEventsOverview = function(params) { /** * Get top events data -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.fetchDataTopEvents = function(params) { @@ -1362,7 +1366,7 @@ fetch.fetchDataTopEvents = function(params) { /** * Get events data for events pi output to browser -* @param {params} params - params object +* @param {Params} params - params object * @returns {void} void **/ fetch.fetchEvents = function(params) { @@ -1430,7 +1434,7 @@ fetch.fetchEvents = function(params) { /** * Get Countly standard data model from database for segments or single level data as users, merging year and month and splitted docments together and output to browser * @param {string} collection - name of the collection where to get data from -* @param {params} params - params object with app_id and date +* @param {Params} params - params object with app_id and date * @param {boolean} isCustomEvent - if value we are fetching for custom event or standard metric * @param {object=} options - additional optional settings * @param {object=} options.db - database connection to use, by default will try to use common.db @@ -1471,7 +1475,7 @@ fetch.fetchTimeObj = function(collection, params, isCustomEvent, options) { /** * Get Countly standard data model from database for segments or single level data as users, merging year and month and splitted docments together * @param {string} collection - name of the collection where to get data from -* @param {params} params - params object with app_id and date +* @param {Params} params - params object with app_id and date * @param {object=} options - additional optional settings * @param {object=} options.db - database connection to use, by default will try to use common.db * @param {string=} options.unique - name of the metric to treat as unique, default "u" from common.dbMap.unique @@ -1488,7 +1492,7 @@ fetch.getTimeObj = function(collection, params, options, callback) { /** * Get Countly standard data model from database for events, merging year and month and splitted docments together * @param {string} collection - name of the collection where to get data from -* @param {params} params - params object with app_id and date +* @param {Params} params - params object with app_id and date * @param {object=} options - additional optional settings * @param {object=} options.db - database connection to use, by default will try to use common.db * @param {string=} options.unique - name of the metric to treat as unique, default "u" from common.dbMap.unique @@ -1517,7 +1521,7 @@ fetch.getTimeObjForEvents = function(collection, params, options, callback) { /** * Get data for estimating total users count if period contains today and output to browser * @param {string} metric - name of the collection where to get data from -* @param {params} params - params object with app_id and date +* @param {Params} params - params object with app_id and date */ fetch.fetchTotalUsersObj = function(metric, params) { fetch.getTotalUsersObj(metric, params, function(output) { @@ -1528,7 +1532,7 @@ fetch.fetchTotalUsersObj = function(metric, params) { /** * Get data for estimating total users count if period contains today * @param {string} metric - name of the collection where to get data from -* @param {params} params - params object with app_id and date +* @param {Params} params - params object with app_id and date * @param {function} callback - callback to retrieve the data, receiving only one param which is output */ fetch.getTotalUsersObj = function(metric, params, callback) { @@ -1538,7 +1542,7 @@ fetch.getTotalUsersObj = function(metric, params, callback) { /** * Get data for estimating total users count allowing plugins to add their own data * @param {string} metric - name of the collection where to get data from -* @param {params} params - params object with app_id and date +* @param {Params} params - params object with app_id and date * @param {object=} options - additional optional settings * @param {object=} options.db - database connection to use, by default will try to use common.db * @param {function} callback - callback to retrieve the data, receiving only one param which is output @@ -1804,7 +1808,7 @@ async function fetchFromGranular(collection, params, options, callback) { /** * Fetch db data in standard format * @param {string} collection - from which collection to fetch -* @param {params} params - params object +* @param {Params} params - params object * @param {boolean} isCustomEvent - if we are fetching custom event or not * @param {object=} options - additional optional settings * @param {object=} options.db - database connection to use, by default will try to use common.db @@ -2192,7 +2196,7 @@ function fetchTimeObj(collection, params, isCustomEvent, options, callback) { /** * Get period and out it to browser * @param {string} coll - collection, this is not used, but more for compliance with validation functions -* @param {params} params - params object +* @param {Params} params - params object **/ fetch.getPeriodObj = function(coll, params) { common.returnOutput(params, countlyCommon.getPeriodObj(params, "30days")); @@ -2224,7 +2228,7 @@ function union(x, y) { /** * Fetch data for tops - * @param {params} params - params object + * @param {Params} params - params object * @param {Array} allMetrics - All metrics array * @param {String} metric - metric to fetch data for * @param {Function} cb - callback function diff --git a/api/utils/taskmanager.js b/api/utils/taskmanager.js index 67b3820a090..9cf5a476205 100644 --- a/api/utils/taskmanager.js +++ b/api/utils/taskmanager.js @@ -3,6 +3,10 @@ * @module api/utils/taskmanager */ +/** + * @typedef {import('../../types/requestProcessor').Params} Params + */ + /** @lends module:api/utils/taskmanager */ var taskmanager = {}; var common = require("./common.js"); @@ -18,7 +22,7 @@ const log = require('./log.js')('core:taskmanager'); * Monitors DB query or some other potentially long task and switches to long task manager if it exceeds threshold * @param {object} options - options for the task * @param {object} options.db - database connection -* @param {params} options.params - params object +* @param {Params} options.params - params object * @param {number} options.threshold - amount of seconds to wait before switching to long running task * @param {number} options.force - force to use taskmanager, ignoring threshold * @param {string} options.type - type of data, as which module or plugin uses this data diff --git a/plugins/sdk/api/api.js b/plugins/sdk/api/api.js index 1c66763df4a..4ef47a23462 100644 --- a/plugins/sdk/api/api.js +++ b/plugins/sdk/api/api.js @@ -4,6 +4,10 @@ var fetch = require('../../../api/parts/data/fetch.js'); var countlyModel = require('../../../api/lib/countly.model.js'); var {validateRead, validateUpdate} = require('../../../api/utils/rights.js'); +/** + * @typedef {import('../../../types/requestProcessor').Params} Params + */ + const FEATURE_NAME = 'sdk'; const validOptions = [ "tracking", @@ -448,7 +452,7 @@ plugins.register("/permissions/features", function(ob) { /** * Updates SDK config (used internally when configuration is changed in the dashboard) - * @param {params} params - request params + * @param {Params} params - request params * @returns {void} */ function updateParameter(params) { From 708fdf66bfb319f8112ec888c7174a19a477510c Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 20:44:54 +0200 Subject: [PATCH 02/14] replacing more "params" with "Params" --- api/ingestor/usage.js | 2 +- api/lib/countly.common.js | 4 ++-- api/parts/data/events.js | 4 ++-- api/parts/data/exports.js | 10 ++++----- api/parts/data/usage.js | 12 +++++------ api/parts/mgmt/app_users.js | 6 +++--- api/parts/mgmt/apps.js | 28 ++++++++++++------------- api/parts/mgmt/cms.js | 12 +++++------ api/parts/mgmt/date_presets.js | 8 +++---- api/parts/mgmt/users.js | 26 +++++++++++------------ api/tcp_example.js | 2 +- api/utils/common.js | 2 +- api/utils/rights.js | 22 +++++++++---------- plugins/server-stats/api/parts/stats.js | 2 +- plugins/views/api/ingestor.js | 4 ++-- 15 files changed, 72 insertions(+), 72 deletions(-) diff --git a/api/ingestor/usage.js b/api/ingestor/usage.js index 81cf17bcc40..d7f21f7fea0 100644 --- a/api/ingestor/usage.js +++ b/api/ingestor/usage.js @@ -8,7 +8,7 @@ var usage = {}, /** * Get location either from coordinate to populate country and city, or from country and city to get coordinates -* @param {params} params - params object +* @param {Params} params - params object * @param {object} loc - location object * @param {number} loc.lat - lattitude * @param {number} loc.lon - longitude diff --git a/api/lib/countly.common.js b/api/lib/countly.common.js index f181f4a01f0..4cc64928c0f 100644 --- a/api/lib/countly.common.js +++ b/api/lib/countly.common.js @@ -2581,7 +2581,7 @@ countlyCommon.getDashboardData = function(data, properties, unique, totalUserOve /** * Get timestamp query range based on request data using period and app's timezone -* @param {params} params - params object +* @param {Params} params - params object * @param {boolean} inSeconds - if true will output result in seconds, else in miliseconds * @returns {object} mongodb query object with preset ts field to be queried * @example @@ -2758,7 +2758,7 @@ countlyCommon.decode = function(str) { * Get period object in atomic way from params, * getting params.qstring.period for period * and params.appTimezone for timezone -* @param {params} params - params object with app timezone and period +* @param {Params} params - params object with app timezone and period * @param {(string|string[]|number[])} defaultPeriod - default period value in case it's not supplied in the params * @returns {module:api/lib/countly.common.periodObj} period object */ diff --git a/api/parts/data/events.js b/api/parts/data/events.js index 79382165fa6..529b350e54b 100644 --- a/api/parts/data/events.js +++ b/api/parts/data/events.js @@ -16,7 +16,7 @@ var countlyEvents = {}, /** * Process JSON decoded events data from request -* @param {params} params - params object +* @param {Params} params - params object * @returns {Promise} resolved when procesing finished **/ countlyEvents.processEvents = function(params) { @@ -201,7 +201,7 @@ countlyEvents.processEvents = function(params) { * @param {array} appEvents - aray with existing event keys * @param {object} appSegments - object with event key as key, and segments as array value * @param {object} appSgValues - object in format [collection][document_id][segment] and array of values as value for inserting in database -* @param {params} params - params object +* @param {Params} params - params object * @param {array} omitted_segments - array of segments to omit * @param {array} whitelisted_segments - array of segments to keep * @param {function} done - callback function to call when done processing diff --git a/api/parts/data/exports.js b/api/parts/data/exports.js index dff4d9361d8..b4573a2f1d7 100644 --- a/api/parts/data/exports.js +++ b/api/parts/data/exports.js @@ -194,7 +194,7 @@ exports.getType = function(key) { }; /** * Output data as response -* @param {params} params - params object +* @param {Params} params - params object * @param {string} data - data to output * @param {string} filename - name of the file to output to browser * @param {string} type - type to be used in content type @@ -331,7 +331,7 @@ function getValues(values, valuesMap, paramList, doc, options) { } /** * Stream data as response -* @param {params} params - params object +* @param {Params} params - params object * @param {Stream} stream - cursor object. Need to call stream on it. * @param {string} options - options object options.filename - name of the file to output to browser @@ -470,7 +470,7 @@ function isObjectId(id) { * Export data from database * @param {object} options - options for the export * @param {object} options.db - database connection -* @param {params} options.params - params object +* @param {Params} options.params - params object * @param {string} options.collection - name of the collection to export * @param {object} [options.query={}] - database query which data to filter * @param {object} [options.projection={}] - database projections which fields to return @@ -568,7 +568,7 @@ exports.fromDatabase = function(options) { /** * Export data from response of request * @param {object} options - options for the export -* @param {params} options.params - params object +* @param {Params} options.params - params object * @param {object} options.path - path for api endpoint * @param {object} options.data - json data to use as post or query string * @param {object} options.prop - which property to export, tries to export whole response if not provided @@ -734,7 +734,7 @@ exports.fromRequestQuery = function(options) { * Create export from provided data * @param {string|array} data - data to format * @param {object} options - options for the export -* @param {params} options.params - params object +* @param {Params} options.params - params object * @param {string} [options.type=json] - type of data to output * @param {string} [options.filename] - name of the file to output, by default auto generated * @param {function} options.output - callback function where to pass data, by default outputs as file based on type diff --git a/api/parts/data/usage.js b/api/parts/data/usage.js index 7452b04e0aa..5fa8dafd94b 100644 --- a/api/parts/data/usage.js +++ b/api/parts/data/usage.js @@ -16,7 +16,7 @@ var usage = {}, /** * Get location either from coordinate to populate country and city, or from country and city to get coordinates -* @param {params} params - params object +* @param {Params} params - params object * @param {object} loc - location object * @param {number} loc.lat - lattitude * @param {number} loc.lon - longitude @@ -172,7 +172,7 @@ usage.setUserLocation = function(params, loc) { /** * Process session_duration calls -* @param {params} params - params object +* @param {Params} params - params object * @param {function} callback - callback when done **/ usage.processSessionDuration = function(params, callback) { @@ -215,7 +215,7 @@ usage.processSessionDuration = function(params, callback) { /** * Gets metrics to collect from plugins -* @param {params} params - params object +* @param {Params} params - params object * @param {object} userProps - object where to populate with user properties to set to user document * @returns {array} collected metrics **/ @@ -413,7 +413,7 @@ usage.returnAllProcessedMetrics = function(params) { /** * Process session duration ranges for Session duration metric * @param {number} totalSessionDuration - duration of session -* @param {params} params - params object +* @param {Params} params - params object * @param {function} done - callback when done **/ usage.processSessionDurationRange = function(totalSessionDuration, params, done) { @@ -465,7 +465,7 @@ usage.processSessionDurationRange = function(totalSessionDuration, params, done) /** * Process ending user session and calculate loyalty and frequency range metrics * @param {object} dbAppUser - user's document -* @param {params} params - params object +* @param {Params} params - params object * @param {function} done - callback when done * @returns {void} void **/ @@ -642,7 +642,7 @@ function processUserSession(dbAppUser, params, done) { * @param {object} user - user's document * @param {array} uniqueLevelsZero - unique properties of zero document * @param {array} uniqueLevelsMonth - unique properties of month document -* @param {params} params - params object +* @param {Params} params - params object * @param {function} done - callback when done * @returns {boolean} true **/ diff --git a/api/parts/mgmt/app_users.js b/api/parts/mgmt/app_users.js index 6ad4dd89cf1..b1712a6ec0b 100644 --- a/api/parts/mgmt/app_users.js +++ b/api/parts/mgmt/app_users.js @@ -30,7 +30,7 @@ catch (ex) { * Create new app_user document. Creates uid if one is not provided * @param {string} app_id - _id of the app * @param {object} doc - document to insert -* @param {params} params - to determine who makes modification, should have member property with user who makes modification, and req for request object to determine ip address +* @param {Params} params - to determine who makes modification, should have member property with user who makes modification, and req for request object to determine ip address * @param {function} callback - called when finished providing error (if any) as first param and insert result as second */ usersApi.create = function(app_id, doc, params, callback) { @@ -186,7 +186,7 @@ usersApi.createUserDocument = function(params, done) { * @param {string} app_id - _id of the app * @param {object} query - mongodb query to select which app users to update * @param {object} update - mongodb update object -* @param {params} params - to determine who makes modification, should have member property with user who makes modification, and req for request object to determine ip address +* @param {Params} params - to determine who makes modification, should have member property with user who makes modification, and req for request object to determine ip address * @param {function} callback - called when finished providing error (if any) as first param and updated user document as second */ usersApi.update = function(app_id, query, update, params, callback) { @@ -233,7 +233,7 @@ usersApi.update = function(app_id, query, update, params, callback) { * Delete existing app_users documents, deletes also all plugin data * @param {string} app_id - _id of the app * @param {object} query - mongodb query to select which app users to delete -* @param {params} params - to determine who makes modification, should have member property with user who makes modification, and req for request object to determine ip address +* @param {Params} params - to determine who makes modification, should have member property with user who makes modification, and req for request object to determine ip address * @param {function} callback - called when finished providing error (if any) as first param and array with uids of removed users as second */ usersApi.delete = function(app_id, query, params, callback) { diff --git a/api/parts/mgmt/apps.js b/api/parts/mgmt/apps.js index ef6799678c1..97dfb67deb3 100644 --- a/api/parts/mgmt/apps.js +++ b/api/parts/mgmt/apps.js @@ -19,7 +19,7 @@ const {timezoneValidation} = require('../../utils/timezones.js'); const FEATURE_NAME = 'global_applications'; /** * Get all apps and outputs to browser, requires global admin permission -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if got data from db, false if did not **/ appsApi.getAllApps = function(params) { @@ -46,7 +46,7 @@ appsApi.getAllApps = function(params) { /** * Get only apps that current user has access to and outputs to browser -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if got data from db, false if did not **/ appsApi.getCurrentUserApps = function(params) { @@ -72,7 +72,7 @@ appsApi.getCurrentUserApps = function(params) { /** * Gets app details for specific app and outputs to browser -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if got data from db, false if did not **/ appsApi.getAppsDetails = function(params) { @@ -167,7 +167,7 @@ appsApi.getAppsDetails = function(params) { }; /** * upload app icon function -* @param {params} params - params object with args to create app +* @param {Params} params - params object with args to create app * @return {object} return promise object; **/ const iconUpload = async function(params) { @@ -200,7 +200,7 @@ const iconUpload = async function(params) { /** * Creates new app, and outputs result to browser -* @param {params} params - params object with args to create app +* @param {Params} params - params object with args to create app * @returns {boolean} true if operation successful **/ appsApi.createApp = async function(params) { @@ -306,7 +306,7 @@ appsApi.createApp = async function(params) { /** * Updates existing app, and outputs result to browser -* @param {params} params - params object with args to update app with +* @param {Params} params - params object with args to update app with * @returns {boolean} true if operation successful **/ appsApi.updateApp = function(params) { @@ -421,7 +421,7 @@ appsApi.updateApp = function(params) { /** * Returns application level configurations - * @param {params} params - params object with query parameters appId and name(optional parameter) + * @param {Params} params - params object with query parameters appId and name(optional parameter) * @returns {boolean} returns true; */ appsApi.getAppPlugins = async function(params) { @@ -461,7 +461,7 @@ appsApi.getAppPlugins = async function(params) { /** * Updates existing app's configurations and outputs result to browser -* @param {params} params - params object with args to update app with +* @param {Params} params - params object with args to update app with * @returns {boolean} true if operation successful **/ appsApi.updateAppPlugins = function(params) { @@ -600,7 +600,7 @@ appsApi.updateAppPlugins = function(params) { /** * Deletes existing app's and outputs result to browser -* @param {params} params - params object with app_id to delete +* @param {Params} params - params object with app_id to delete * @returns {boolean} true if operation successful **/ appsApi.deleteApp = function(params) { @@ -740,7 +740,7 @@ appsApi.deleteApp = function(params) { /** * Resets app to clean state -* @param {params} params - params object with app_id to reset +* @param {Params} params - params object with app_id to reset * @returns {boolean} true if operation successful **/ appsApi.resetApp = function(params) { @@ -792,7 +792,7 @@ appsApi.resetApp = function(params) { * Deletes app's data, either all or for specific period, as well as can reset data to clean state * @param {string} appId - id of the app for which to delete data * @param {boolean} fromAppDelete - true if all document will also be deleted -* @param {params} params - params object +* @param {Params} params - params object * @param {object} app - app document **/ function deleteAppData(appId, fromAppDelete, params, app) { @@ -820,7 +820,7 @@ function deleteAppLongTasks(appId) { * Deletes all app's data or resets data to clean state * @param {string} appId - id of the app for which to delete data * @param {boolean} fromAppDelete - true if all document will also be deleted -* @param {params} params - params object +* @param {Params} params - params object * @param {object} app - app document **/ function deleteAllAppData(appId, fromAppDelete, params, app) { @@ -886,7 +886,7 @@ function deleteAllAppData(appId, fromAppDelete, params, app) { * Deletes app's data for specific period * @param {string} appId - id of the app for which to delete data * @param {boolean} fromAppDelete - true if all document will also be deleted -* @param {params} params - params object +* @param {Params} params - params object * @param {object} app - app document **/ function deletePeriodAppData(appId, fromAppDelete, params, app) { @@ -1101,7 +1101,7 @@ function isValidCountry(country) { /** * Check if APP KEY is unique before updating app -* @param {params} params - params object +* @param {Params} params - params object * @param {function} callback - callback to update app * @param {boolean} update - true when updating app, false when creating new app **/ diff --git a/api/parts/mgmt/cms.js b/api/parts/mgmt/cms.js index facb6470e38..8b60553f4b9 100644 --- a/api/parts/mgmt/cms.js +++ b/api/parts/mgmt/cms.js @@ -19,7 +19,7 @@ const AVAILABLE_API_IDS = ["server-guides", "server-consents", "server-intro-vid /** * Get entries for a given API ID from Countly CMS -* @param {params} params - params object +* @param {Params} params - params object * @param {function} callback - callback function **/ function fetchFromCMS(params, callback) { @@ -73,7 +73,7 @@ function fetchFromCMS(params, callback) { /** * Transform and store CMS entries in DB -* @param {params} params - params object +* @param {Params} params - params object * @param {object} err - error object * @param {array} data - data array * @param {function} callback - callback function @@ -138,7 +138,7 @@ function transformAndStoreData(params, err, data, callback) { /** * Get entries for a given API ID from Countly CMS -* @param {params} params - params object +* @param {Params} params - params object **/ function syncCMSDataToDB(params) { // Check if there is a process running @@ -186,7 +186,7 @@ cmsApi.saveEntries = function(params) { /** * Get entries for a given API ID * Will request from CMS if entries are stale or not found -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true **/ cmsApi.getEntriesWithUpdate = function(params) { @@ -270,7 +270,7 @@ cmsApi.getEntriesWithUpdate = function(params) { /** * Get entries for a given API ID -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true **/ cmsApi.getEntries = function(params) { @@ -330,7 +330,7 @@ cmsApi.getEntries = function(params) { /** * Clear cache for all API IDs -* @param {params} params - params object +* @param {Params} params - params object **/ cmsApi.clearCache = function(params) { var query = {}; diff --git a/api/parts/mgmt/date_presets.js b/api/parts/mgmt/date_presets.js index d1a87c391b6..bae57fe0ca7 100755 --- a/api/parts/mgmt/date_presets.js +++ b/api/parts/mgmt/date_presets.js @@ -9,7 +9,7 @@ var presetsApi = {}, /** * Get presets -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if successful **/ presetsApi.getAll = async function(params) { @@ -155,7 +155,7 @@ presetsApi.getAll = async function(params) { /** * Add new preset -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if successful **/ presetsApi.create = function(params) { @@ -322,7 +322,7 @@ presetsApi.create = function(params) { /** * Update preset -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if successful **/ presetsApi.update = function(params) { @@ -577,7 +577,7 @@ presetsApi.update = function(params) { /** * Get presets -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if successful **/ presetsApi.delete = function(params) { diff --git a/api/parts/mgmt/users.js b/api/parts/mgmt/users.js index 5937363cedd..94083a399ee 100644 --- a/api/parts/mgmt/users.js +++ b/api/parts/mgmt/users.js @@ -20,7 +20,7 @@ var argon2 = require('argon2'); var crypto = require('crypto'); /** * Get data about current user and output to browser -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true **/ usersApi.getCurrentUser = function(params) { @@ -32,7 +32,7 @@ usersApi.getCurrentUser = function(params) { /** * Get data about specific user by user id, and outputs to browser -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if fetched data from db **/ usersApi.getUserById = function(params) { @@ -67,7 +67,7 @@ usersApi.getUserById = function(params) { /** * Get list of all users, for global admins only, and outputs to browser -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if fetched data from db **/ usersApi.getAllUsers = function(params) { @@ -123,7 +123,7 @@ usersApi.getAllUsers = function(params) { /** * Reset timeban for user and output result to browser -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if timeban reseted **/ usersApi.resetTimeBan = function(params) { @@ -142,7 +142,7 @@ usersApi.resetTimeBan = function(params) { /** * Create new dashboard user and output result to browser -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if user created **/ usersApi.createUser = async function(params) { @@ -410,7 +410,7 @@ async function depCheck(params) { /** * Updates dashboard user's data and output result to browser -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if user was updated **/ usersApi.updateUser = async function(params) { @@ -580,7 +580,7 @@ usersApi.updateUser = async function(params) { /** * Deletes dashboard user and output result to browser -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true if user was deleted **/ usersApi.deleteUser = async function(params) { @@ -844,7 +844,7 @@ usersApi.deleteOwnAccount = function(params) { module.exports = usersApi; /** * Check update or delete note permission. - * @param {params} params - params object + * @param {Params} params - params object * @returns {boolean} true */ usersApi.checkNoteEditPermission = async function(params) { @@ -881,7 +881,7 @@ usersApi.checkNoteEditPermission = async function(params) { /** * Create or update note -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true **/ usersApi.saveNote = async function(params) { @@ -971,7 +971,7 @@ usersApi.saveNote = async function(params) { /** * Delete Note -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true **/ usersApi.deleteNote = async function(params) { @@ -997,7 +997,7 @@ usersApi.deleteNote = async function(params) { /** * Delete deleted user note -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true **/ usersApi.deleteUserNotes = async function(params) { @@ -1013,7 +1013,7 @@ usersApi.deleteUserNotes = async function(params) { }; /** * fetch apps id for those user can access; -* @param {params} params - params object +* @param {Params} params - params object * @returns {array} app id array */ usersApi.fetchUserAppIds = async function(params) { @@ -1043,7 +1043,7 @@ usersApi.fetchUserAppIds = async function(params) { }; /** * fetch Notes -* @param {params} params - params object +* @param {Params} params - params object * @returns {boolean} true **/ usersApi.fetchNotes = async function(params) { diff --git a/api/tcp_example.js b/api/tcp_example.js index 387ff224850..024309fc7f5 100644 --- a/api/tcp_example.js +++ b/api/tcp_example.js @@ -58,7 +58,7 @@ plugins.dbConnection(countlyConfig).then(function(db) { * @param {string} message - response string that was usually returned by API * @param {object} headers - HTTP headers that would usually be returned by API * @param {number} returnCode - HTTP response code that would usually be returned by API - * @param {params} paramsOb - params object for processed request + * @param {Params} paramsOb - params object for processed request **/ function respond(message, headers, returnCode, paramsOb) { console.log(message, headers, returnCode, paramsOb); diff --git a/api/utils/common.js b/api/utils/common.js index ce844854a99..74ee135cfe0 100644 --- a/api/utils/common.js +++ b/api/utils/common.js @@ -2379,7 +2379,7 @@ common.clearClashingQueryOperations = function(query) { /** * Single method to update app_users document for specific user for SDK requests -* @param {params} params - params object +* @param {Params} params - params object * @param {object} update - update query for mongodb, should contain operators on highest level, as $set or $unset * @param {boolean} no_meta - if true, won't update some auto meta data, like first api call, last api call, etc. * @param {function} callback - function to run when update is done or failes, passing error and result as arguments diff --git a/api/utils/rights.js b/api/utils/rights.js index 70a68d19b2a..06f19d8f632 100644 --- a/api/utils/rights.js +++ b/api/utils/rights.js @@ -53,7 +53,7 @@ function validate_token_if_exists(params) { * User must exist, must not be locked, must pass plugin validation (if any) and have at least user access to the provided app (which also must exist). * If user does not pass validation, it outputs error to request. In case validation passes, provided callback is called. * Additionally populates params with member information and app information. -* @param {params} params - {@link params} object +* @param {Params} params - {@link params} object * @param {function} callback - function to call only if validation passes * @param {any=} callbackParam - parameter to pass to callback function (params is automatically passed to callback function, no need to include that) * @returns {Promise} promise @@ -149,7 +149,7 @@ exports.validateUserForRead = function(params, callback, callbackParam) { * User must exist, must not be locked, must pass plugin validation (if any) and have at least admin access to the provided app (which also must exist). * If user does not pass validation, it outputs error to request. In case validation passes, provided callback is called. * Additionally populates params with member information and app information. -* @param {params} params - {@link params} object +* @param {Params} params - {@link params} object * @param {function} callback - function to call only if validation passes * @param {any=} callbackParam - parameter to pass to callback function (params is automatically passed to callback function, no need to include that) * @returns {Promise} promise @@ -238,7 +238,7 @@ exports.validateUserForWrite = function(params, callback, callbackParam) { * User must exist, must not be locked, must pass plugin validation (if any) and have global admin access. * If user does not pass validation, it outputs error to request. In case validation passes, provided callback is called. * Additionally populates params with member information. -* @param {params} params - {@link params} object +* @param {Params} params - {@link params} object * @param {function} callback - function to call only if validation passes * @param {any=} callbackParam - parameter to pass to callback function (params is automatically passed to callback function, no need to include that) * @returns {Promise} promise @@ -309,7 +309,7 @@ exports.validateGlobalAdmin = function(params, callback, callbackParam) { * User must exist, must not be locked, must pass plugin validation (if any). * If user does not pass validation, it outputs error to request. In case validation passes, provided callback is called. * Additionally populates params with member information. -* @param {params} params - {@link params} object +* @param {Params} params - {@link params} object * @param {function} callback - function to call only if validation passes * @param {any=} callbackParam - parameter to pass to callback function (params is automatically passed to callback function, no need to include that) * @returns {Promise} promise @@ -387,7 +387,7 @@ exports.validateAppAdmin = function(params, callback, callbackParam) { * User must exist, must not be locked and must pass plugin validation (if any). * If user does not pass validation, it outputs error to request. In case validation passes, provided callback is called. * Additionally populates params with member information. -* @param {params} params - {@link params} object +* @param {Params} params - {@link params} object * @param {function} callback - function to call only if validation passes * @param {any=} callbackParam - parameter to pass to callback function (params is automatically passed to callback function, no need to include that) * @returns {Promise} promise @@ -456,7 +456,7 @@ exports.validateUser = function(params, callback, callbackParam) { }; /** * Wrap callback using promise -* @param {params} params - {@link params} object +* @param {Params} params - {@link params} object * @param {function} callback - function to call only if validation passes * @param {any=} callbackParam - parameter to pass to callback function * @param {function} func - promise function @@ -791,7 +791,7 @@ exports.dbUserHasAccessToCollection = function(params, collection, app_id, callb * User must exist, must not be locked, must pass plugin validation (if any) and have at least read access to the provided app (which also must exist). * If user does not pass validation, it outputs error to request. In case validation passes, provided callback is called. * Additionally populates params with member information and app information. -* @param {params} params - {@link params} object +* @param {Params} params - {@link params} object * @param {string} feature - feature that trying to access * @param {function} callback - function to call only if validation passes * @param {any=} callbackParam - parameter to pass to callback function (params is automatically passed to callback function, no need to include that) @@ -943,7 +943,7 @@ exports.validateRead = function(params, feature, callback, callbackParam) { * User must exist, must not be locked, must pass plugin validation (if any) and have accessType that passed as accessType parameter to the provided app (which also must exist). * If user does not pass validation, it outputs error to request. In case validation passes, provided callback is called. * Additionally populates params with member information and app information. -* @param {params} params - {@link params} object +* @param {Params} params - {@link params} object * @param {string} feature - feature that trying to access * @param {string} accessType - required access type for related request (c: create, u: update and d: delete) * @param {function} callback - function to call only if validation passes @@ -1111,7 +1111,7 @@ exports.getBaseAppFilter = function(member, dbName, collectionName) { }; /** * Validate user for create access by api_key for provided app_id (both required parameters for the request). -* @param {params} params - {@link params} object +* @param {Params} params - {@link params} object * @param {string} feature - feature that trying to access * @param {function} callback - function to call only if validation passes * @param {any=} callbackParam - parameter to pass to callback function (params is automatically passed to callback function, no need to include that) @@ -1122,7 +1122,7 @@ exports.validateCreate = function(params, feature, callback, callbackParam) { /** * Validate user for update access by api_key for provided app_id (both required parameters for the request). -* @param {params} params - {@link params} object +* @param {Params} params - {@link params} object * @param {string} feature - feature that trying to access * @param {function} callback - function to call only if validation passes * @param {any=} callbackParam - parameter to pass to callback function (params is automatically passed to callback function, no need to include that) @@ -1133,7 +1133,7 @@ exports.validateUpdate = function(params, feature, callback, callbackParam) { /** * Validate user for delete access by api_key for provided app_id (both required parameters for the request). -* @param {params} params - {@link params} object +* @param {Params} params - {@link params} object * @param {string} feature - feature that trying to access * @param {function} callback - function to call only if validation passes * @param {any=} callbackParam - parameter to pass to callback function (params is automatically passed to callback function, no need to include that) diff --git a/plugins/server-stats/api/parts/stats.js b/plugins/server-stats/api/parts/stats.js index 96db3e06aee..e483ef85af9 100644 --- a/plugins/server-stats/api/parts/stats.js +++ b/plugins/server-stats/api/parts/stats.js @@ -90,7 +90,7 @@ function updateDataPoints(writeBatcher, appId, sessionCount, eventCount, consoli /** * Check if data should be counted as consolidated - * @param {params} params - params object + * @param {Params} params - params object * @returns {boolean} true if consolidated */ function isConsolidated(params) { diff --git a/plugins/views/api/ingestor.js b/plugins/views/api/ingestor.js index f08c986e3cc..ea6c5b402b5 100644 --- a/plugins/views/api/ingestor.js +++ b/plugins/views/api/ingestor.js @@ -10,8 +10,8 @@ var pluginOb = {}, * @param {object} options - Options to update * @param {boolean} options.bounce - if bounce * @param {boolean} options.exit - if exit - * @param {params} params - params object - * @param {params} callback - when done + * @param {Params} params - params object + * @param {Params} callback - when done **/ /*const updateViewParams = async function(id, options, params) { var updateObj = {}; From b2d432bb8ed5d8cdc21859f5886cc3a4cab00f23 Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 20:46:26 +0200 Subject: [PATCH 03/14] more params --- api/parts/data/usage.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/parts/data/usage.js b/api/parts/data/usage.js index 5fa8dafd94b..501f27a34b0 100644 --- a/api/parts/data/usage.js +++ b/api/parts/data/usage.js @@ -100,7 +100,7 @@ function locFromGeoip(loc, ip_address) { /** * Set Location information in params but donot update it in users document - * @param {params} params - params object + * @param {Params} params - params object * @returns {Promise} promise which resolves upon completeing processing */ usage.setLocation = function(params) { @@ -160,7 +160,7 @@ usage.setLocation = function(params) { /** * Set user location in params - * @param {params} params - params object + * @param {Params} params - params object * @param {object} loc - location info */ usage.setUserLocation = function(params, loc) { @@ -370,7 +370,7 @@ usage.getPredefinedMetrics = function(params, userProps) { /** * Process all metrics and return - * @param {params} params - params object + * @param {Params} params - params object * @returns {object} params */ usage.returnAllProcessedMetrics = function(params) { From 22703b30f238b64ad1cb403e4f95db1cfb0173b8 Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 20:46:44 +0200 Subject: [PATCH 04/14] more --- api/ingestor/usage.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/ingestor/usage.js b/api/ingestor/usage.js index d7f21f7fea0..f0ef2e9028f 100644 --- a/api/ingestor/usage.js +++ b/api/ingestor/usage.js @@ -92,7 +92,7 @@ function locFromGeoip(loc, ip_address) { /** * Set Location information in params but donot update it in users document - * @param {params} params - params object + * @param {Params} params - params object * @returns {Promise} promise which resolves upon completeing processing */ usage.setLocation = function(params) { @@ -152,7 +152,7 @@ usage.setLocation = function(params) { /** * Set user location in params - * @param {params} params - params object + * @param {Params} params - params object * @param {object} loc - location info */ usage.setUserLocation = function(params, loc) { @@ -274,7 +274,7 @@ usage; /** * Process all metrics and return - * @param {params} params - params object + * @param {Params} params - params object * @returns {object} params */ usage.returnRequestMetrics = function(params) { From da5521fdf092fc719a2ca9a2d6fd175fd185f002 Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 20:57:36 +0200 Subject: [PATCH 05/14] Fixing array type issues --- api/parts/data/fetch.js | 46 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/api/parts/data/fetch.js b/api/parts/data/fetch.js index 30dfb4942e2..dbe47de0b45 100644 --- a/api/parts/data/fetch.js +++ b/api/parts/data/fetch.js @@ -241,8 +241,8 @@ fetch.fetchMergedEventGroups = function(params) { * @param {string=} options.unique - name of the metric to treat as unique, default "u" from common.dbMap.unique * @param {string=} options.id - id to use as prefix from documents, by default will use params.app_id * @param {object=} options.levels - describes which metrics to expect on which levels -* @param {array=} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] -* @param {array=} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] +* @param {string[]} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] +* @param {string[]} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] * @param {function} callback - callback to retrieve the data, receiving only one param which is output */ fetch.getMergedEventGroups = function(params, event, options, callback) { @@ -275,14 +275,14 @@ fetch.fetchMergedEventData = function(params) { /** * Get merged data from multiple events in standard data model * @param {Params} params - params object with app_id and date -* @param {array} events - array with event keys +* @param {string[]} events - array with event keys * @param {object=} options - additional optional settings * @param {object=} options.db - database connection to use, by default will try to use common.db * @param {string=} options.unique - name of the metric to treat as unique, default "u" from common.dbMap.unique * @param {string=} options.id - id to use as prefix from documents, by default will use params.app_id * @param {object=} options.levels - describes which metrics to expect on which levels -* @param {array=} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] -* @param {array=} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] +* @param {string[]} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] +* @param {string[]} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] * @param {function} callback - callback to retrieve the data, receiving only one param which is output */ fetch.getMergedEventData = function(params, events, options, callback) { @@ -1043,8 +1043,8 @@ fetch.getMetric = function(params, metric, totalUsersMetric, callback) { * @param {string=} fetchTimeOptions.unique - name of the metric to treat as unique, default "u" from common.dbMap.unique * @param {string=} fetchTimeOptions.id - id to use as prefix from documents, by default will use params.app_id * @param {object=} fetchTimeOptions.levels - describes which metrics to expect on which levels -* @param {array=} fetchTimeOptions.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] -* @param {array=} fetchTimeOptions.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] +* @param {string[]} fetchTimeOptions.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] +* @param {string[]} fetchTimeOptions.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] * @param {function} callback - callback to retrieve the data, receiving only one param which is output * @example Retrieved data * [ @@ -1123,7 +1123,7 @@ fetch.getMetricWithOptions = function(params, metric, totalUsersMetric, fetchTim /** * Get collection and metric name from metric string * @param {string} metric - metric/segment name -* @return {Array} array with collection, metric, model object +* @return {Array} array with collection, metric, model object **/ fetch.metricToCollection = function(metric) { switch (metric) { @@ -1441,8 +1441,8 @@ fetch.fetchEvents = function(params) { * @param {string=} options.unique - name of the metric to treat as unique, default "u" from common.dbMap.unique * @param {string=} options.id - id to use as prefix from documents, by default will use params.app_id * @param {object=} options.levels - describes which metrics to expect on which levels -* @param {array=} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] -* @param {array=} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] +* @param {string[]} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] +* @param {string[]} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] */ fetch.fetchTimeObj = function(collection, params, isCustomEvent, options) { fetchTimeObj(collection, params, isCustomEvent, options, function(output) { @@ -1481,8 +1481,8 @@ fetch.fetchTimeObj = function(collection, params, isCustomEvent, options) { * @param {string=} options.unique - name of the metric to treat as unique, default "u" from common.dbMap.unique * @param {string=} options.id - id to use as prefix from documents, by default will use params.app_id * @param {object=} options.levels - describes which metrics to expect on which levels -* @param {array=} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] -* @param {array=} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] +* @param {string[]} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] +* @param {string[]} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] * @param {function} callback - callback to retrieve the data, receiving only one param which is output */ fetch.getTimeObj = function(collection, params, options, callback) { @@ -1498,8 +1498,8 @@ fetch.getTimeObj = function(collection, params, options, callback) { * @param {string=} options.unique - name of the metric to treat as unique, default "u" from common.dbMap.unique * @param {string=} options.id - id to use as prefix from documents, by default will use params.app_id * @param {object=} options.levels - describes which metrics to expect on which levels -* @param {array=} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] -* @param {array=} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] +* @param {string[]} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] +* @param {string[]} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] * @param {function} callback - callback to retrieve the data, receiving only one param which is output */ fetch.getTimeObjForEvents = function(collection, params, options, callback) { @@ -1815,8 +1815,8 @@ async function fetchFromGranular(collection, params, options, callback) { * @param {string=} options.unique - name of the metric to treat as unique, default "u" from common.dbMap.unique * @param {string=} options.id - id to use as prefix from documents, by default will use params.app_id * @param {object=} options.levels - describes which metrics to expect on which levels -* @param {array=} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] -* @param {array=} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] +* @param {string[]} options.levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] +* @param {string[]} options.levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] * @param {function} callback - to call when fetch done **/ function fetchTimeObj(collection, params, isCustomEvent, options, callback) { @@ -2032,11 +2032,11 @@ function fetchTimeObj(collection, params, isCustomEvent, options, callback) { /** * Merge multiple db documents into one - * @param {array} dataObjects - array with db documents + * @param {object[]} dataObjects - array with db documents * @param {boolean} isRefresh - is it refresh data only for today * @param {object=} levels - describes which metrics to expect on which levels - * @param {array=} levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] - * @param {array=} levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] + * @param {string[]} levels.daily - which metrics to expect on daily level, default ["t", "n", "c", "s", "dur"] + * @param {string[]} levels.monthly - which metrics to expect on monthly level, default ["t", "n", "d", "e", "c", "s", "dur"] * @param {boolean} truncateEventValuesList - if true, then will limit returned segment value count in meta. * @returns {object} merged object **/ @@ -2204,9 +2204,9 @@ fetch.getPeriodObj = function(coll, params) { /** * Returns the union of two arrays -* @param {array} x - array 1 -* @param {array} y - array 2 -* @returns {array} merged array +* @param {any[]} x - array 1 +* @param {any[]} y - array 2 +* @returns {any[]} merged array **/ function union(x, y) { var obj = {}; @@ -2229,7 +2229,7 @@ function union(x, y) { /** * Fetch data for tops * @param {Params} params - params object - * @param {Array} allMetrics - All metrics array + * @param {object[]} allMetrics - All metrics array * @param {String} metric - metric to fetch data for * @param {Function} cb - callback function */ From b322c7a6f2eb3783d2c409c118a77660bd7960bd Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 21:01:18 +0200 Subject: [PATCH 06/14] ppparams --- api/parts/data/fetch.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/parts/data/fetch.js b/api/parts/data/fetch.js index dbe47de0b45..239dcf914de 100644 --- a/api/parts/data/fetch.js +++ b/api/parts/data/fetch.js @@ -186,7 +186,7 @@ fetch.fetchEventData = function(collection, params) { /** * The return the event groups data by _id. -* @param {Object} params - params object +* @param {Params} params - params object * @param {string} params._id - The id of the event group id. **/ fetch.fetchEventGroupById = function(params) { @@ -203,7 +203,7 @@ fetch.fetchEventGroupById = function(params) { /** * The return the event groups data by app_id. -* @param {Object} params - params object +* @param {Params} params - params object * @param {string} params.app_id - The id of the event group of application id. **/ fetch.fetchEventGroups = function(params) { @@ -220,7 +220,7 @@ fetch.fetchEventGroups = function(params) { /** * The return the merged event data for event groups. -* @param {Object} params - params object +* @param {Params} params - params object **/ fetch.fetchMergedEventGroups = function(params) { const { qstring: { event } } = params; @@ -1741,7 +1741,7 @@ fetch.formatTotalUsersObj = function(obj, forMetric, prev) { /** * Caluclates model data from granural data * @param {string} collection - collection name - * @param {object} params - request parameters + * @param {Params} params - request parameters * @param {object} options - options of query * @param {funtyion} callback - callback function with result */ From 19444aee9ba7e638663443980be08dcf8c67730b Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 21:21:00 +0200 Subject: [PATCH 07/14] typing --- api/utils/common.js | 3 ++- types/common.d.ts | 51 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/api/utils/common.js b/api/utils/common.js index 74ee135cfe0..1fdb6cc6acb 100644 --- a/api/utils/common.js +++ b/api/utils/common.js @@ -198,7 +198,8 @@ common.dbMap = { 'loyalty': 'l', 'sum': 's', 'dur': 'dur', - 'count': 'c' + 'count': 'c', + 'paying': 'p' }; common.dbUserMap = { diff --git a/types/common.d.ts b/types/common.d.ts index 3debb3c4a1a..608b20e8587 100644 --- a/types/common.d.ts +++ b/types/common.d.ts @@ -263,6 +263,13 @@ export interface Common { **/ decode_html: (string: string) => string; + /** + * Encode string for database storage by escaping $ and . + * @param {string} str - string to encode + * @returns {string} encoded string + **/ + dbEncode: (str: string) => string; + /** * Check if string is a valid json * @param {string} val - string that might be json encoded @@ -660,6 +667,17 @@ export interface Common { */ recordMetric: (params: Params, props: CustomMetricProps) => void; + /** + * Alias for internal recordMetric function - records specific metric + * @param {Params} params - params object + * @param {string} metric - metric to record + * @param {object} props - properties of a metric defining how to record it + * @param {object} tmpSet - object with already set meta properties + * @param {object} updateUsersZero - object with already set update for zero docs + * @param {object} updateUsersMonth - object with already set update for months docs + */ + collectMetric: (params: Params, metric: string, props: any, tmpSet: any, updateUsersZero: any, updateUsersMonth: any) => void; + /** * Get object of date ids that should be used in fetching standard metric model documents * @param {Params} params - {@link params} object @@ -973,7 +991,40 @@ export interface Common { */ trimWhitespaceStartEnd: (value: any) => any; + /** + * Apply unique estimation on model data + * @param {any} model - model object to apply unique data to + * @param {any} uniqueData - unique estimation data + * @param {string} prop - property name to apply unique data for + * @param {string} segment - segment name if applying for segment + */ + applyUniqueOnModel: (model: any, uniqueData: any, prop: string, segment?: string) => void; + /** + * Shift hourly data by timezone offset + * @param {any} data - data object to shift + * @param {number} offset - timezone offset in hours + * @param {string} field - field name to use for shifting, defaults to "_id" + * @returns {any} shifted data + */ + shiftHourlyData: (data: any, offset: number, field?: string) => any; + + /** + * Convert model object to array format + * @param {any} model - model object to convert + * @param {boolean} segmented - if model is segmented + * @returns {any[]} converted array + */ + convertModelToArray: (model: any, segmented?: boolean) => any[]; + + /** + * Convert array to model object format + * @param {any[]} arr - array to convert + * @param {boolean} segmented - if array is segmented + * @param {string[]} props - properties to include in model + * @returns {any} converted model object + */ + convertArrayToModel: (arr: any[], segmented?: boolean, props?: string[]) => any; /** DataTable class for server-side processing */ DataTable: any; From 16381167f638e527a574a6e11a8ffa75f2f91a4e Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 21:29:47 +0200 Subject: [PATCH 08/14] minor changes --- api/utils/common.js | 2 +- types/common.d.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/utils/common.js b/api/utils/common.js index 1fdb6cc6acb..f6b1cd74e39 100644 --- a/api/utils/common.js +++ b/api/utils/common.js @@ -116,7 +116,7 @@ common.decode_html = function(string) { /** * Check if string is a valid json * @param {string} val - string that might be json encoded - * @returns {object} with property data for parsed data and property valid to check if it was valid json encoded string or not + * @returns {{valid: boolean, data?: any}} with property data for parsed data and property valid to check if it was valid json encoded string or not **/ function getJSON(val) { var ret = {valid: false}; diff --git a/types/common.d.ts b/types/common.d.ts index 608b20e8587..7c9a134e2ab 100644 --- a/types/common.d.ts +++ b/types/common.d.ts @@ -450,7 +450,7 @@ export interface Common { * '2017.2.23.8.u': 1, * '2017.w8.u': 1 } */ - fillTimeObject: (params: Params, object: any, property: string | string[], increment?: number) => void; + fillTimeObject: (params: Params, object: any, property: string, increment?: number) => void; /** * Creates a time object from request's milisecond or second timestamp in provided app's timezone @@ -578,7 +578,7 @@ export interface Common { * //outputs * { 'd.u': 1, 'd.2.u': 1, 'd.w8.u': 1 } */ - fillTimeObjectZero: (params: Params, object: any, property: string | string[], increment?: number, isUnique?: boolean) => boolean; + fillTimeObjectZero: (params: Params, object: any, property: string, increment?: number, isUnique?: boolean) => boolean; /** * Modifies provided object filling properties used in monthly documents in the format object["2012.7.20.property"] = increment. @@ -596,7 +596,7 @@ export interface Common { * //outputs * { 'd.23.u': 1, 'd.23.12.u': 1 } */ - fillTimeObjectMonth: (params: Params, object: any, property: string | string[], increment?: number, forceHour?: boolean) => boolean; + fillTimeObjectMonth: (params: Params, object: any, property: string, increment?: number, forceHour?: boolean) => boolean; /** * Record data in Countly standard metric model From 2f8b642ce2c545d116e2b0175c78ff918195c96f Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 21:55:47 +0200 Subject: [PATCH 09/14] Fixing --- api/utils/common.js | 6 ++++-- types/common.d.ts | 20 +++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/api/utils/common.js b/api/utils/common.js index f6b1cd74e39..f1bcd5db7cc 100644 --- a/api/utils/common.js +++ b/api/utils/common.js @@ -5,6 +5,7 @@ /** * @typedef {import('../../types/requestProcessor').Params} Params * @typedef {import('../../types/common').TimeObject} TimeObject + * @typedef {import('../../types/common').JSONParseResult} JSONParseResult * @typedef {import('mongodb').ObjectId} ObjectId * @typedef {import('moment-timezone').Moment} MomentTimezone */ @@ -116,10 +117,11 @@ common.decode_html = function(string) { /** * Check if string is a valid json * @param {string} val - string that might be json encoded - * @returns {{valid: boolean, data?: any}} with property data for parsed data and property valid to check if it was valid json encoded string or not + * @returns {JSONParseResult} with property data for parsed data and property valid to check if it was valid json encoded string or not **/ function getJSON(val) { - var ret = {valid: false}; + /** @type {JSONParseResult} */ + var ret = {/** @type {boolean} */ valid: false}; try { ret.data = JSON.parse(val); if (ret.data && typeof ret.data === "object") { diff --git a/types/common.d.ts b/types/common.d.ts index 7c9a134e2ab..4f0c70a0075 100644 --- a/types/common.d.ts +++ b/types/common.d.ts @@ -174,6 +174,12 @@ export interface ValidationResult { obj?: Record; } +/** Result of JSON parsing attempt */ +export interface JSONParseResult { + valid: boolean; + data?: object | undefined; +} + /** Date IDs */ export interface DateIds { zero: string; @@ -273,9 +279,9 @@ export interface Common { /** * Check if string is a valid json * @param {string} val - string that might be json encoded - * @returns {object} with property data for parsed data and property valid to check if it was valid json encoded string or not + * @returns {JSONParseResult} with property data for parsed data and property valid to check if it was valid json encoded string or not **/ - getJSON: (val: string) => { valid: boolean; data?: any }; + getJSON: (val: string) => JSONParseResult; /** * Logger object for creating module-specific logging @@ -492,8 +498,8 @@ export interface Common { /** * Validates provided arguments - * @param {object} args - arguments to validate - * @param {object} argProperties - rules for validating each argument + * @param {Record} args - arguments to validate + * @param {ValidationArgProperties} argProperties - rules for validating each argument * @param {boolean} argProperties.required - should property be present in args * @param {string} argProperties.type - what type should property be, possible values: String, Array, Number, URL, Boolean, Object, Email * @param {string} argProperties.max-length - property should not be longer than provided value @@ -504,9 +510,9 @@ export interface Common { * @param {string} argProperties.has-upchar - should string property has any upper cased latin character in it * @param {string} argProperties.has-special - should string property has any none latin character in it * @param {boolean} returnErrors - return error details as array or only boolean result - * @returns {object} validated args in obj property, or false as result property if args do not pass validation and errors array + * @returns {ValidationResult | Record | boolean} validated args in obj property, or false as result property if args do not pass validation and errors array */ - validateArgs: (args: object, argProperties: ValidationArgProperties, returnErrors: boolean) => ValidationResult | any; + validateArgs: (args: Record, argProperties: ValidationArgProperties, returnErrors?: boolean) => ValidationResult | Record | boolean; /** * Fix event keys before storing in database by removing dots and $ from the string, removing other prefixes and limiting length @@ -553,7 +559,7 @@ export interface Common { * @param {string} noescape - prevent escaping HTML entities * @param {object} heads - headers to add to the output */ - returnOutput: (params: Params, output: output, noescape: string, heads: object) => void; + returnOutput: (params: Params, output: output, noescape?: string, heads?: object) => void; /** * Get IP address from request object From 12d768797c1c89eff0f2c2e7762d4f37df8dd461 Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 22:40:16 +0200 Subject: [PATCH 10/14] Adding GeoData types --- api/parts/data/geoData.js | 17 ++++++++++++++- tsconfig.json | 3 ++- types/common.d.ts | 6 +++--- types/geoData.d.ts | 44 +++++++++++++++++++++++++++++++++++++++ types/log.d.ts | 2 +- 5 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 types/geoData.d.ts diff --git a/api/parts/data/geoData.js b/api/parts/data/geoData.js index a5f0e97030a..39d9699a7b7 100644 --- a/api/parts/data/geoData.js +++ b/api/parts/data/geoData.js @@ -1,3 +1,13 @@ +/** + * Module for geographic data operations + * @module api/parts/data/geoData + */ + +/** + * @typedef {import('../../../types/geoData').LoadCityCoordinatesOptions} LoadCityCoordinatesOptions + * @typedef {import('../../../types/geoData').LoadCityCoordinatesCallback} LoadCityCoordinatesCallback + * @typedef {import('../../../types/geoData').CityCoordinate} CityCoordinate + */ var geoData = {}; const log = require('../../utils/log.js')("core:geo"); @@ -6,6 +16,11 @@ const common = require('../../utils/common.js'); //City fields //country(code), +/** + * Load city coordinates from the database + * @param {LoadCityCoordinatesOptions} options - Options for loading city coordinates + * @param {LoadCityCoordinatesCallback} callback - Callback function receiving error and cities array + */ geoData.loadCityCoordiantes = function(options, callback) { options.db = options.db || common.db; options.query = options.query || {}; @@ -29,7 +44,7 @@ geoData.loadCityCoordiantes = function(options, callback) { pipeline = [{"$match": options.query}, {"$project": options.projection}]; - options.db.collection("cityCoordinates").aggregate(pipeline).toArray(function(err, cities) { + options.db.collection("cityCoordinates").aggregate(pipeline).toArray(function(/** @type {Error | null} */ err, /** @type {CityCoordinate[]} */ cities) { if (err) { log.e(err); } diff --git a/tsconfig.json b/tsconfig.json index e66fc84288c..468ef56ed1c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,8 @@ "api/utils/common.js", "api/utils/localization.js", "api/lib/countly.common.js", - "api/utils/requestProcessor.js" + "api/utils/requestProcessor.js", + "api/parts/data/geoData.js" ], "exclude": [ "node_modules" diff --git a/types/common.d.ts b/types/common.d.ts index 4f0c70a0075..50864b91123 100644 --- a/types/common.d.ts +++ b/types/common.d.ts @@ -2,7 +2,7 @@ import { Moment } from "moment-timezone"; import { Collection, Db, ObjectId } from "mongodb"; import { Params } from "./requestProcessor"; import { PluginManager, Database } from "./pluginManager"; -import { Logger } from "./log"; +import { Logger, LogModule } from "./log"; import { CountlyAPIConfig } from "./config"; import { ClickHouseQueryService } from "../plugins/clickhouse/types/clickhouseQueryService"; @@ -285,12 +285,12 @@ export interface Common { /** * Logger object for creating module-specific logging - * @type {function(string): Logger} + * @type {LogModule} * @example * const log = common.log('myplugin:api'); * log.i('myPlugin got a request: %j', params.qstring); */ - log: (module: string) => Logger; + log: LogModule; /** * Mapping some common property names from longer understandable to shorter representation stored in database diff --git a/types/geoData.d.ts b/types/geoData.d.ts new file mode 100644 index 00000000000..76ebb9523bb --- /dev/null +++ b/types/geoData.d.ts @@ -0,0 +1,44 @@ +import { Database } from "./pluginManager"; +import { Logger } from "./log"; + +/** Options for loading city coordinates */ +export interface LoadCityCoordinatesOptions { + /** Database connection to use, defaults to common.db */ + db?: Database; + /** MongoDB query object to filter cities */ + query?: Record; + /** MongoDB projection object for fields to return */ + projection?: Record; + /** Country code to filter by */ + country?: string; +} + +/** City coordinate data returned from database */ +export interface CityCoordinate { + /** Country code */ + country?: string; + /** Location coordinates [longitude, latitude] */ + loc?: [number, number]; + /** City name */ + name?: string; + /** MongoDB ObjectId */ + _id?: any; +} + +/** Callback for loadCityCoordinates */ +export type LoadCityCoordinatesCallback = (err: Error | null, cities: CityCoordinate[]) => void; + +/** + * GeoData module for geographic data operations + */ +export interface GeoData { + /** + * Load city coordinates from the database + * @param options - Options for loading city coordinates + * @param callback - Callback function receiving error and cities array + */ + loadCityCoordiantes: (options: LoadCityCoordinatesOptions, callback: LoadCityCoordinatesCallback) => void; +} + +declare const geoData: GeoData; +export default geoData; diff --git a/types/log.d.ts b/types/log.d.ts index 16ae86b5b00..30a08a3f0ef 100644 --- a/types/log.d.ts +++ b/types/log.d.ts @@ -4,7 +4,7 @@ export type LogLevelShort = 'd' | 'i' | 'w' | 'e'; /** Logging configuration structure */ export interface LoggingConfig { - [level: string]: string[] | string; + [level: string]: string[] | string | LogLevel | undefined; default?: LogLevel; } From 88077e290ea1521e7163c9fbbc67128a55144bab Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 23:38:49 +0200 Subject: [PATCH 11/14] types --- api/lib/countly.common.js | 75 +++--- types/countly.common.d.ts | 525 ++++++++++++++++++++++++++++++++++++++ types/geoData.d.ts | 8 +- 3 files changed, 575 insertions(+), 33 deletions(-) create mode 100644 types/countly.common.d.ts diff --git a/api/lib/countly.common.js b/api/lib/countly.common.js index 4cc64928c0f..16ce8d82eb3 100644 --- a/api/lib/countly.common.js +++ b/api/lib/countly.common.js @@ -5,8 +5,24 @@ /** * @typedef {import('moment-timezone').Moment} MomentTimezone + * @typedef {import('../../types/countly.common').PeriodObject} PeriodObject + * @typedef {import('../../types/countly.common').CountlyCommon} CountlyCommonType + * @typedef {import('../../types/countly.common').PercentChange} PercentChange + * @typedef {import('../../types/countly.common').DashboardData} DashboardData + * @typedef {import('../../types/countly.common').DataProperty} DataProperty + * @typedef {import('../../types/countly.common').ChartDataPoint} ChartDataPoint + * @typedef {import('../../types/countly.common').ExtractedChartData} ExtractedChartData + * @typedef {import('../../types/countly.common').ExtractedTwoLevelData} ExtractedTwoLevelData + * @typedef {import('../../types/countly.common').BarDataItem} BarDataItem + * @typedef {import('../../types/countly.common').PeriodRangeQuery} PeriodRangeQuery + * @typedef {import('../../types/countly.common').TimestampRangeQuery} TimestampRangeQuery + * @typedef {import('../../types/countly.common').ClearFunction} ClearFunction + * @typedef {import('../../types/countly.common').FixBarSegmentDataFunction} FixBarSegmentDataFunction + * @typedef {import('../../types/countly.common').FetchFunction} FetchFunction + * @typedef {import('../../types/requestProcessor').Params} Params */ +/** @type {CountlyCommonType} */ /** @lends module:api/lib/countly.common */ var countlyCommon = {}, /** @@ -24,8 +40,8 @@ var _period = "hour", /** * Calculates unique values from a hierarchical map structure - * @param {Object} dbObj - Database object containing hierarchical data (years, months, weeks, days) - * @param {Object} uniqueMap - Map with hierarchical structure (years, months, weeks, days) used to calculate unique values + * @param {Record} dbObj - Database object containing hierarchical data (years, months, weeks, days) + * @param {Record} uniqueMap - Map with hierarchical structure (years, months, weeks, days) used to calculate unique values * @returns {number} - Count of unique items */ countlyCommon.calculateUniqueFromMap = function(dbObj, uniqueMap) { @@ -316,12 +332,13 @@ function fixTimestampToMilliseconds(ts) { /** * Returns a period object used by all time related data calculation functions -* @param {string|any} prmPeriod period to be calculated (optional) todo:figure this type out -* @param {string} bucket - daily or monthly. If bucket is set, period will be modified to fit full months or days -* @returns {timeObject} time object +* @param {string|Array|Record} prmPeriod - period to be calculated (optional) +* @param {string} [bucket] - daily or monthly. If bucket is set, period will be modified to fit full months or days +* @returns {PeriodObject} period object **/ function getPeriodObject(prmPeriod, bucket) { var startTimestamp, endTimestamp, periodObject, cycleDuration; + /** @type {PeriodObject} */ periodObject = { start: 0, end: 0, @@ -856,7 +873,7 @@ countlyCommon.getTimezone = function(params) { * @param {object} period - common period in Countly * @param {string} timezone - app timezone (optional. Pass if not using offset) * @param {number} offset - offset in minutes - * @returns {object} - describes period range + * @returns {PeriodRangeQuery} - describes period range */ countlyCommon.getPeriodRange = function(period, timezone, offset) { //Gets start and end points of period for querying in drill @@ -1157,10 +1174,10 @@ countlyCommon.extractRangeData = function(db, propertyName, rangeArray, explainR /** * Extract single level data without metrics/segments, like total user data from users collection * @param {object} db - countly standard metric data object -* @param {function} clearFunction - function to prefill all expected properties as u, t, n, etc with 0, so you would not have null in the result which won't work when drawing graphs -* @param {object} chartData - prefill chart data with labels, colors, etc -* @param {object} dataProperties - describing which properties and how to extract -* @returns {object} object to use in timeline graph with {"chartDP":chartData, "chartData":_.compact(tableData), "keyEvents":keyEvents} +* @param {ClearFunction} clearFunction - function to prefill all expected properties as u, t, n, etc with 0, so you would not have null in the result which won't work when drawing graphs +* @param {Array} chartData - prefill chart data with labels, colors, etc +* @param {Array} dataProperties - describing which properties and how to extract +* @returns {ExtractedChartData} object to use in timeline graph with {"chartDP":chartData, "chartData":_.compact(tableData), "keyEvents":keyEvents} * @example Extracting total users data from users collection * countlyCommon.extractChartData(_sessionDb, countlySession.clearObject, [ * { data:[], label:"Total Users" } @@ -1532,8 +1549,8 @@ countlyCommon.extractStackedBarData = function(db, clearFunction, chartData, dat * @param {object} data - countly metric model data * @param {object} props - object where key is output property name and value could be string as key from data object or function to create new value based on existing ones * @param {function} clearObject - function to prefill all expected properties as u, t, n, etc with 0, so you would not have null in the result which won't work when drawing graphs -* @param {object} periodObject - period object override -* @returns {object} object with sparkleline data for each property +* @param {PeriodObject} periodObject - period object override +* @returns {Object} object with sparkleline data for each property * @example * var sparkLines = countlyCommon.getSparklineData(countlySession.getDb(), { * "total-sessions": "t", @@ -1605,12 +1622,12 @@ countlyCommon.getSparklineData = function(data, props, clearObject, periodObject /** * Extract two level data with metrics/segments, like total user data from carriers collection * @param {object} db - countly standard metric data object -* @param {object} rangeArray - array of all metrics/segments to extract (usually what is contained in meta) -* @param {function} clearFunction - function to prefill all expected properties as u, t, n, etc with 0, so you would not have null in the result which won't work when drawing graphs -* @param {object} dataProperties - describing which properties and how to extract +* @param {Array} rangeArray - array of all metrics/segments to extract (usually what is contained in meta) +* @param {ClearFunction} clearFunction - function to prefill all expected properties as u, t, n, etc with 0, so you would not have null in the result which won't work when drawing graphs +* @param {Array} dataProperties - describing which properties and how to extract * @param {object=} totalUserOverrideObj - data from total users api request to correct unique user values -* @param {string=} period - period to override -* @returns {object} object to use in bar and pie charts with {"chartData":_.compact(tableData)} +* @param {PeriodObject=} period - period to override +* @returns {ExtractedTwoLevelData} object to use in bar and pie charts with {"chartData":_.compact(tableData)} * @example Extracting carriers data from carriers collection * var chartData = countlyCommon.extractTwoLevelData(_carrierDb, ["At&t", "Verizon"], countlyCarrier.clearObject, [ * { @@ -1832,15 +1849,15 @@ countlyCommon.extractTwoLevelData = function(db, rangeArray, clearFunction, data /** * Extracts top three items (from rangeArray) that have the biggest total session counts from the db object. * @param {object} db - countly standard metric data object -* @param {object} rangeArray - array of all metrics/segments to extract (usually what is contained in meta) -* @param {function} clearFunction - function to prefill all expected properties as u, t, n, etc with 0, so you would not have null in the result which won't work when drawing graphs -* @param {function} fetchFunction - function to fetch property, default used is function (rangeArr, dataObj) {return rangeArr;} +* @param {Array} rangeArray - array of all metrics/segments to extract (usually what is contained in meta) +* @param {ClearFunction} clearFunction - function to prefill all expected properties as u, t, n, etc with 0, so you would not have null in the result which won't work when drawing graphs +* @param {FetchFunction} fetchFunction - function to fetch property, default used is function (rangeArr, dataObj) {return rangeArr;} * @param {number} maxItems - amount of items to return, default 3, if -1 return all * @param {string=} metric - metric to output and use in sorting, default "t" * @param {object=} totalUserOverrideObj - data from total users api request to correct unique user values -* @param {function} fixBarSegmentData - function to make any adjustments to the extracted data based on segment -* @param {string} period - period to extract data from -* @returns {array} array with top 3 values +* @param {FixBarSegmentDataFunction} fixBarSegmentData - function to make any adjustments to the extracted data based on segment +* @param {PeriodObject} period - period to extract data from +* @returns {Array} array with top 3 values * @example Return data * [ * {"name":"iOS","percent":35}, @@ -2379,12 +2396,12 @@ countlyCommon.timeString = function(timespent) { /** * Get calculated totals for each property, usualy used as main dashboard data timeline data without metric segments * @param {object} data - countly metric model data -* @param {array} properties - array of all properties to extract -* @param {array} unique - array of all properties that are unique from properties array. We need to apply estimation to them +* @param {Array} properties - array of all properties to extract +* @param {Array} unique - array of all properties that are unique from properties array. We need to apply estimation to them * @param {object} totalUserOverrideObj - using unique property as key and total_users estimation property as value for all unique metrics that we want to have total user estimation overridden * @param {object} prevTotalUserOverrideObj - using unique property as key and total_users estimation property as value for all unique metrics that we want to have total user estimation overridden for previous period -* @param {object} periodObject period object override for calculation -* @returns {object} dashboard data object +* @param {PeriodObject} periodObject period object override for calculation +* @returns {DashboardData} dashboard data object * @example * countlyCommon.getDashboardData(countlySession.getDb(), ["t", "n", "u", "d", "e", "p", "m"], ["u", "p", "m"], {u:"users"}); * //outputs @@ -2583,7 +2600,7 @@ countlyCommon.getDashboardData = function(data, properties, unique, totalUserOve * Get timestamp query range based on request data using period and app's timezone * @param {Params} params - params object * @param {boolean} inSeconds - if true will output result in seconds, else in miliseconds -* @returns {object} mongodb query object with preset ts field to be queried +* @returns {TimestampRangeQuery} mongodb query object with preset ts field to be queried * @example * countlyCommon.getTimestampRangeQuery(params, true) * //outputs @@ -2760,7 +2777,7 @@ countlyCommon.decode = function(str) { * and params.appTimezone for timezone * @param {Params} params - params object with app timezone and period * @param {(string|string[]|number[])} defaultPeriod - default period value in case it's not supplied in the params -* @returns {module:api/lib/countly.common.periodObj} period object +* @returns {PeriodObject} period object */ countlyCommon.getPeriodObj = function(params, defaultPeriod = "30days") { let appTimezone = params.appTimezone || (params.app && params.app.timezone); diff --git a/types/countly.common.d.ts b/types/countly.common.d.ts new file mode 100644 index 00000000000..b90d4c5796b --- /dev/null +++ b/types/countly.common.d.ts @@ -0,0 +1,525 @@ +import { Moment } from "moment-timezone"; +import { Params } from "./requestProcessor"; + +/** + * Period object containing all period-related information for data extraction + */ +export interface PeriodObject { + /** Period start timestamp in milliseconds */ + start: number; + /** Period end timestamp in milliseconds */ + end: number; + /** Array with ticks for current period (available only for special periods), example ["2016.12.22","2016.12.23","2016.12.24", ...] */ + currentPeriodArr: string[]; + /** Array with ticks for previous period (available only for special periods), example ["2016.12.22","2016.12.23","2016.12.24", ...] */ + previousPeriodArr: string[]; + /** Date format to use when outputting date in graphs, example "D MMM, YYYY" */ + dateString: string; + /** True if current period is special period, false if it is not */ + isSpecialPeriod: boolean; + /** Amount of full days in selected period, example 30 */ + daysInPeriod: number; + /** True if period contains today, false if not */ + periodContainsToday: boolean; + /** Array with ticks for current period which contains data for unique values, like unique users */ + uniquePeriodArr: string[]; + /** Array with ticks for higher buckets to current period unique value estimation */ + uniquePeriodCheckArr: string[]; + /** Array with ticks for previous period which contains data for unique values */ + previousUniquePeriodArr: string[]; + /** Array with ticks for higher buckets to previous period unique value estimation */ + previousUniquePeriodCheckArr: string[]; + /** Period name formatted in dateString (available in non-special periods) */ + activePeriod: string | number; + /** Previous period name formatted in dateString (available in non-special periods) */ + previousPeriod: string | number; + /** Max value of current period tick (available in non-special periods) */ + periodMax: number | string; + /** Min value of current period tick (available in non-special periods) */ + periodMin: number | string; + /** Metric model month document ids to query for this period */ + reqMonthDbDateIds: string[]; + /** Metric model year document ids to query for this period */ + reqZeroDbDateIds: string[]; + /** Map structure for unique value calculation in current period */ + uniqueMap?: Record; + /** Map structure for unique value calculation in previous period */ + uniquePrevMap?: Record; +} + +/** + * Percent change result object + */ +export interface PercentChange { + /** Percentage change as string with % sign */ + percent: string; + /** Trend direction: "u" for upward, "d" for downward */ + trend: "u" | "d"; +} + +/** + * Dashboard data item for a single property + */ +export interface DashboardDataItem { + /** Total value for current period */ + total: number; + /** Total value for previous period */ + "prev-total": number; + /** Percent change as string */ + change: string; + /** Trend direction */ + trend: "u" | "d"; + /** Whether the value is estimated (for unique metrics) */ + is_estimate?: boolean; +} + +/** + * Dashboard data object containing metrics + */ +export interface DashboardData { + [property: string]: DashboardDataItem; +} + +/** + * Data property definition for extraction functions + */ +export interface DataProperty { + /** Property name */ + name: string; + /** Optional function to transform the value */ + func?: (dataObj: any) => any; + /** Period to use: "previous" or "current" */ + period?: "previous" | "current" | "previousThisMonth"; +} + +/** + * Chart data point structure + */ +export interface ChartDataPoint { + /** Data array of [index, value] pairs */ + data: Array<[number, number]>; + /** Label for the data series */ + label?: string; + /** Color for the data series */ + color?: string; + /** Mode for rendering */ + mode?: string; +} + +/** + * Key events for chart data + */ +export interface KeyEvent { + /** Minimum value */ + min: number; + /** Maximum value */ + max: number; +} + +/** + * Extracted chart data result + */ +export interface ExtractedChartData { + /** Chart data points */ + chartDP: ChartDataPoint[]; + /** Table data array */ + chartData: Array>; + /** Key events for min/max values */ + keyEvents: KeyEvent[]; +} + +/** + * Extracted two level data result + */ +export interface ExtractedTwoLevelData { + /** Chart data array */ + chartData: Array>; +} + +/** + * Bar data item + */ +export interface BarDataItem { + /** Name/label of the bar */ + name: string; + /** Value of the bar */ + value: number; + /** Percentage of total */ + percent: number; +} + +/** + * Period range query object for MongoDB + */ +export interface PeriodRangeQuery { + $gt: number; + $lt: number; + $gte: number; + $lte: number; +} + +/** + * Timestamp range query object for MongoDB + */ +export interface TimestampRangeQuery { + $gte: number; + $lt: number; +} + +/** + * Clear function type for data extraction + */ +export type ClearFunction = (obj: any) => any; + +/** + * Fetch function type for bar data extraction + */ +export type FetchFunction = (rangeArr: string, dataObj?: any) => string; + +/** + * Fix bar segment data function type + */ +export type FixBarSegmentDataFunction = (rangeData: ExtractedTwoLevelData) => ExtractedTwoLevelData; + +/** + * CountlyCommon module interface + */ +export interface CountlyCommon { + /** + * Currently selected period object + */ + periodObj: PeriodObject; + + /** + * Calculates unique values from a hierarchical map structure + * @param dbObj - Database object containing hierarchical data + * @param uniqueMap - Map with hierarchical structure used to calculate unique values + * @returns Count of unique items + */ + calculateUniqueFromMap(dbObj: Record, uniqueMap: Record): number; + + /** + * Checks if the period parameter is valid + * @param period - Period parameter + * @returns True if period is valid + */ + isValidPeriodParam(period: string | string[] | Record): boolean; + + /** + * Gets timezone from params + * @param params - Params object + * @returns Timezone string + */ + getTimezone(params: Params): string; + + /** + * Returns query range for querying in drill data with data shifted based on timezone OR offset + * @param period - Common period in Countly + * @param timezone - App timezone (optional) + * @param offset - Offset in minutes + * @returns Period range query object + */ + getPeriodRange(period: string | string[], timezone?: string, offset?: number): PeriodRangeQuery; + + /** + * Change timezone of internal Date object + * @param appTimezone - Name of the timezone + */ + setTimezone(appTimezone: string): void; + + /** + * Change currently selected period + * @param period - New period + */ + setPeriod(period: string | number[]): void; + + /** + * Calculates the percent change between previous and current values + * @param previous - Data for previous period + * @param current - Data for current period + * @returns Percent change object + */ + getPercentChange(previous: number, current: number): PercentChange; + + /** + * Fetches nested property values from an object + * @param obj - Standard countly metric object + * @param desc - Dot separated path to fetch from object + * @returns Fetched object from provided path + */ + getDescendantProp(obj: Record, desc: string): any; + + /** + * Extract range data from standard countly metric data model + * @param db - Countly standard metric data object + * @param propertyName - Name of the property to extract + * @param rangeArray - Array of all metrics/segments to extract + * @param explainRange - Function to convert range/bucket index to meaningful label + * @returns Array containing extracted ranged data + */ + extractRangeData( + db: Record, + propertyName: string, + rangeArray: string[], + explainRange?: (range: string) => string + ): Array>; + + /** + * Extract single level data without metrics/segments + * @param db - Countly standard metric data object + * @param clearFunction - Function to prefill all expected properties + * @param chartData - Prefill chart data with labels, colors, etc + * @param dataProperties - Describing which properties and how to extract + * @returns Object to use in timeline graph + */ + extractChartData( + db: Record, + clearFunction: ClearFunction, + chartData: ChartDataPoint[], + dataProperties: DataProperty[] + ): ExtractedChartData; + + /** + * Extract single level data for stacked bar charts + * @param db - Countly standard metric data object + * @param clearFunction - Function to prefill all expected properties + * @param chartData - Prefill chart data with labels, colors, etc + * @param dataProperties - Describing which properties and how to extract + * @param metric - Metric to select + * @param disableHours - Disable hourly data for graphs + * @returns Object to use in timeline graph + */ + extractStackedBarData( + db: Record, + clearFunction: ClearFunction, + chartData: ChartDataPoint[], + dataProperties: DataProperty[], + metric?: string, + disableHours?: boolean + ): ExtractedChartData; + + /** + * Get total data for period's each time bucket as comma separated string + * @param data - Countly metric model data + * @param props - Object where key is output property name and value is key or function + * @param clearObject - Function to prefill all expected properties + * @param periodObject - Period object override + * @returns Object with sparkline data for each property + */ + getSparklineData( + data: Record, + props: Record number)>, + clearObject: ClearFunction, + periodObject?: PeriodObject + ): Record; + + /** + * Extract two level data with metrics/segments + * @param db - Countly standard metric data object + * @param rangeArray - Array of all metrics/segments to extract + * @param clearFunction - Function to prefill all expected properties + * @param dataProperties - Describing which properties and how to extract + * @param totalUserOverrideObj - Data from total users api request + * @param period - Period to extract data from + * @returns Object to use in bar and pie charts + */ + extractTwoLevelData( + db: Record, + rangeArray: string[], + clearFunction: ClearFunction, + dataProperties: DataProperty[], + totalUserOverrideObj?: Record, + period?: PeriodObject + ): ExtractedTwoLevelData; + + /** + * Extracts top items that have the biggest total session counts + * @param db - Countly standard metric data object + * @param rangeArray - Array of all metrics/segments to extract + * @param clearFunction - Function to prefill all expected properties + * @param fetchFunction - Function to fetch property + * @param maxItems - Amount of items to return, default 3 + * @param metric - Metric to output and use in sorting + * @param totalUserOverrideObj - Data from total users api request + * @param fixBarSegmentData - Function to make adjustments to the extracted data + * @param period - Period to extract data from + * @returns Array with top values + */ + extractBarData( + db: Record, + rangeArray: string[], + clearFunction: ClearFunction, + fetchFunction?: FetchFunction, + maxItems?: number, + metric?: string, + totalUserOverrideObj?: Record, + fixBarSegmentData?: FixBarSegmentDataFunction, + period?: PeriodObject + ): BarDataItem[]; + + /** + * Shortens the given number by adding K or M postfix + * @param number - Number to shorten + * @returns Shorter representation of number + */ + getShortNumber(number: number): string; + + /** + * Getting the date range shown on the dashboard + * @returns String with formatted date range + */ + getDateRange(): string; + + /** + * Extract single level data without metrics/segments + * @param db - Countly standard metric data object + * @param clearFunction - Function to prefill all expected properties + * @param dataProperties - Describing which properties and how to extract + * @param periodObject - Period object override + * @returns Array of extracted data + */ + extractData( + db: Record, + clearFunction: ClearFunction, + dataProperties: DataProperty[], + periodObject?: PeriodObject + ): Array>; + + /** + * Extract metrics data break down by segments + * @param db - Countly standard metric data object + * @param rangeArray - Array of all metrics/segments to extract + * @param clearFunction - Function to prefill all expected properties + * @param dataProperties - Describing which properties and how to extract + * @param totalUserOverrideObj - Data from total users api request + * @returns Array of extracted metric data + */ + extractMetric( + db: Record, + rangeArray: string[], + clearFunction: ClearFunction, + dataProperties: DataProperty[], + totalUserOverrideObj?: Record + ): Array>; + + /** + * Format duration into highest unit of how much time have passed + * @param timespent - Amount in seconds or milliseconds + * @returns Formatted time string + */ + timeString(timespent: number): string; + + /** + * Get calculated totals for each property + * @param data - Countly metric model data + * @param properties - Array of all properties to extract + * @param unique - Array of all properties that are unique + * @param totalUserOverrideObj - Override object for unique metrics + * @param prevTotalUserOverrideObj - Override object for previous period + * @param periodObject - Period object override + * @returns Dashboard data object + */ + getDashboardData( + data: Record, + properties: string[], + unique: string[], + totalUserOverrideObj?: Record, + prevTotalUserOverrideObj?: Record, + periodObject?: PeriodObject + ): DashboardData; + + /** + * Get timestamp query range based on request data + * @param params - Params object + * @param inSeconds - If true will output result in seconds + * @returns MongoDB query object + */ + getTimestampRangeQuery(params: Params, inSeconds?: boolean): TimestampRangeQuery; + + /** + * Merge metric data in chartData by metric name + * @param chartData - Chart data array + * @param metric - Metric name to merge + * @returns Merged chart data + */ + mergeMetricsByName(chartData: Array>, metric: string): Array>; + + /** + * Join 2 arrays into one removing all duplicated values + * @param x - First array + * @param y - Second array + * @returns Array with unique values + */ + union(x: any[], y: any[]): any[]; + + /** + * Encode value to be passed to db as key + * @param str - Value to encode + * @returns Encoded string + */ + encode(str: string): string; + + /** + * Decode value from db + * @param str - Value to decode + * @returns Decoded string + */ + decode(str: string): string; + + /** + * Get period object in atomic way from params + * @param params - Params object with app timezone and period + * @param defaultPeriod - Default period value + * @returns Period object + */ + getPeriodObj(params: Params, defaultPeriod?: string | string[]): PeriodObject; + + /** + * Validate email address + * @param email - Email address to validate + * @returns True if valid + */ + validateEmail(email: string): boolean; + + /** + * Round to provided number of digits + * @param num - Number to round + * @param digits - Amount of digits to round to + * @returns Rounded number + */ + round(num: number, digits?: number): number; + + /** + * Function to fix percentage difference + * @param items - All items + * @param totalPercent - Total percentage so far + * @returns Fixed items array + */ + fixPercentageDelta(items: BarDataItem[], totalPercent: number): BarDataItem[]; + + /** + * Calculate period function + * @param period - Given period + * @param bucket - Bucket for period - monthly or daily + * @returns Period object + */ + calculatePeriodObject(period?: string | string[] | Record, bucket?: "monthly" | "daily"): PeriodObject; + + /** + * Function that increments strings alphabetically + * @param str - String that next character will be calculated + * @returns Calculated string + */ + stringIncrement(str: string): string; + + /** + * Format timestamp to readable date/time string + * @param timestamp - Timestamp in seconds or milliseconds + * @param format - Format to use + * @returns Formatted time and date + */ + formatTime(timestamp: number, format?: string): string; +} + +declare const countlyCommon: CountlyCommon; +export default countlyCommon; diff --git a/types/geoData.d.ts b/types/geoData.d.ts index 76ebb9523bb..376396fb978 100644 --- a/types/geoData.d.ts +++ b/types/geoData.d.ts @@ -4,13 +4,13 @@ import { Logger } from "./log"; /** Options for loading city coordinates */ export interface LoadCityCoordinatesOptions { /** Database connection to use, defaults to common.db */ - db?: Database; + db: Database; /** MongoDB query object to filter cities */ - query?: Record; + query: Record; /** MongoDB projection object for fields to return */ - projection?: Record; + projection: Record; /** Country code to filter by */ - country?: string; + country: string; } /** City coordinate data returned from database */ From ce21dce380b1edcb3ef26520c3bea381dd74ae6e Mon Sep 17 00:00:00 2001 From: ArtursK Date: Wed, 21 Jan 2026 23:53:18 +0200 Subject: [PATCH 12/14] type fixes --- api/lib/countly.common.js | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/api/lib/countly.common.js b/api/lib/countly.common.js index 16ce8d82eb3..ca96274c790 100644 --- a/api/lib/countly.common.js +++ b/api/lib/countly.common.js @@ -332,7 +332,7 @@ function fixTimestampToMilliseconds(ts) { /** * Returns a period object used by all time related data calculation functions -* @param {string|Array|Record} prmPeriod - period to be calculated (optional) +* @param {string|Array|Record} [prmPeriod] - period to be calculated (optional) * @param {string} [bucket] - daily or monthly. If bucket is set, period will be modified to fit full months or days * @returns {PeriodObject} period object **/ @@ -1720,6 +1720,7 @@ countlyCommon.extractTwoLevelData = function(db, rangeArray, clearFunction, data for (let j = 0; j < rangeArray.length; j++) { + /** @type {{[key: string]: any}} */ let tmpPropertyObj = {}, tmp_x = {}; @@ -2237,8 +2238,9 @@ countlyCommon.extractMetric = function(db, rangeArray, clearFunction, dataProper for (let j = 0; j < rangeArray.length; j++) { - let tmpPropertyObj = {}, - tmp_x = {}; + /** @type {{[key: string]: any}} */ + let tmpPropertyObj = {}; + let tmp_x = {}; for (let i = periodMin; i < periodMax; i++) { dataObj = countlyCommon.getDescendantProp(db, countlyCommon.periodObj.currentPeriodArr[i] + "." + rangeArray[j]); @@ -2439,16 +2441,27 @@ countlyCommon.getDashboardData = function(data, properties, unique, totalUserOve return obj; } + /** @type {{[key: string]: any}} */ var _periodObj = periodObject || countlyCommon.periodObj, + /** @type {{[key: string]: any}} */ dataArr = {}, + /** @type {{[key: string]: any}} */ tmp_x, + /** @type {{[key: string]: any}} */ tmp_y, + /** @type {{[key: string]: any}} */ tmpUniqObj, + /** @type {{[key: string]: any}} */ tmpPrevUniqObj, + /** @type {{[key: string]: any}} */ current = {}, + /** @type {{[key: string]: any}} */ previous = {}, + /** @type {{[key: string]: any}} */ currentCheck = {}, + /** @type {{[key: string]: any}} */ previousCheck = {}, + /** @type {{[key: string]: any}} */ change = {}, isEstimate = false; @@ -2720,9 +2733,9 @@ countlyCommon.mergeMetricsByName = function(chartData, metric) { /** * Joined 2 arrays into one removing all duplicated values -* @param {array} x - first array -* @param {array} y - second array -* @returns {array} new array with only unique values from x and y +* @param {Array} x - first array +* @param {Array} y - second array +* @returns {Array} new array with only unique values from x and y * @example * //outputs [1,2,3] * countlyCommon.union([1,2],[2,3]); @@ -2838,9 +2851,9 @@ countlyCommon.round = function(num, digits) { /** * Function to fix percentage difference - * @param {Array} items - All items + * @param {Array} items - All items * @param {Number} totalPercent - Total percentage so far - * @returns {Array} items + * @returns {Array} items */ countlyCommon.fixPercentageDelta = function(items, totalPercent) { if (!items.length) { From 52aa46895d0d8f7ff233ef2ac98b97881582cb84 Mon Sep 17 00:00:00 2001 From: ArtursK Date: Fri, 23 Jan 2026 17:33:54 +0200 Subject: [PATCH 13/14] Moving "geoData" functions into object --- api/parts/data/geoData.js | 61 +++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/api/parts/data/geoData.js b/api/parts/data/geoData.js index 39d9699a7b7..72f746d3dbd 100644 --- a/api/parts/data/geoData.js +++ b/api/parts/data/geoData.js @@ -9,48 +9,41 @@ * @typedef {import('../../../types/geoData').CityCoordinate} CityCoordinate */ -var geoData = {}; const log = require('../../utils/log.js')("core:geo"); const common = require('../../utils/common.js'); - -//City fields -//country(code), -/** - * Load city coordinates from the database - * @param {LoadCityCoordinatesOptions} options - Options for loading city coordinates - * @param {LoadCityCoordinatesCallback} callback - Callback function receiving error and cities array - */ -geoData.loadCityCoordiantes = function(options, callback) { - options.db = options.db || common.db; - options.query = options.query || {}; - options.projection = options.projection || {"country": 1, "loc": 1, "name": 1}; - - var pipeline = []; - if (options.query) { - try { - options.query = JSON.parse(options.query); +/** @type {import('../../../types/geoData').GeoData} */ +var geoData = { + loadCityCoordiantes: function(options, callback) { + options.db = options.db || common.db; + options.query = options.query || {}; + options.projection = options.projection || {"country": 1, "loc": 1, "name": 1}; + + var pipeline = []; + if (options.query) { + try { + options.query = JSON.parse(options.query); + } + catch (SyntaxError) { + log.e("Can't parse city query"); + options.query = {}; + } } - catch (SyntaxError) { - log.e("Can't parse city query"); - options.query = {}; - } - } - if (options.country) { - options.query.country = options.country; - } + if (options.country) { + options.query.country = options.country; + } - pipeline = [{"$match": options.query}, {"$project": options.projection}]; + pipeline = [{"$match": options.query}, {"$project": options.projection}]; - options.db.collection("cityCoordinates").aggregate(pipeline).toArray(function(/** @type {Error | null} */ err, /** @type {CityCoordinate[]} */ cities) { - if (err) { - log.e(err); - } - callback(err, cities || []); - }); + options.db.collection("cityCoordinates").aggregate(pipeline).toArray(function(/** @type {Error | null} */ err, /** @type {CityCoordinate[]} */ cities) { + if (err) { + log.e(err); + } + callback(err, cities || []); + }); + } }; - module.exports = geoData; \ No newline at end of file From f6c455ffb787ca8e9ec2c87c3552e79cf4a68464 Mon Sep 17 00:00:00 2001 From: ArtursK Date: Fri, 23 Jan 2026 23:31:52 +0200 Subject: [PATCH 14/14] Moving locale functions into the object --- api/utils/localization.js | 112 +++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/api/utils/localization.js b/api/utils/localization.js index 926ec610524..a8369fc970b 100644 --- a/api/utils/localization.js +++ b/api/utils/localization.js @@ -3,9 +3,7 @@ * @module api/utils/localization */ -/** @type {import('../../types/localization').Locale} */ -var locale = {}, - fs = require('fs'), +var fs = require('fs'), path = require('path'), parser = require('properties-parser'), log = require('./log')('api:localization'), @@ -27,69 +25,71 @@ catch (ex) { orig = {}; } -locale.format = function(value /* Add parameters as function arguments as necessary */) { - var re, list; - try { - if (arguments[1] && Array.isArray(arguments[1])) { - list = arguments[1]; +/** @type {import('../../types/localization').Locale} */ +var locale = { + format: function(value /* Add parameters as function arguments as necessary */) { + var re, list; + try { + if (arguments[1] && Array.isArray(arguments[1])) { + list = arguments[1]; + } + else { + list = Array.prototype.slice.call(arguments).slice(1, arguments.length); + } + + for (var i = 0; i < list.length; i++) { + re = new RegExp('\\{' + i + '\\}', "g"); + value = value.replace(re, list[i]); + } + return value; } - else { - list = Array.prototype.slice.call(arguments).slice(1, arguments.length); + catch (e) { + log.e('format() error for value "%s" list %j:', value, list, e); + return ''; } + }, - for (var i = 0; i < list.length; i++) { - re = new RegExp('\\{' + i + '\\}', "g"); - value = value.replace(re, list[i]); + getProperty: function(lang, name, callback) { + if (lang === default_lang) { + callback(null, orig[name] || "[" + name + "]"); } - return value; - } - catch (e) { - log.e('format() error for value "%s" list %j:', value, list, e); - return ''; - } -}; - -locale.getProperty = function(lang, name, callback) { - if (lang === default_lang) { - callback(null, orig[name] || "[" + name + "]"); - } - else if (!localized[lang]) { - localized[lang] = JSON.parse(JSON.stringify(orig)); - fs.readFile(dir + '/' + common.sanitizeFilename(file) + '_' + common.sanitizeFilename(lang) + '.properties', 'utf8', function(err, local_properties) { - if (!err && local_properties) { - local_properties = parser.parse(local_properties); - for (var i in local_properties) { - localized[lang][i] = local_properties[i]; + else if (!localized[lang]) { + localized[lang] = JSON.parse(JSON.stringify(orig)); + fs.readFile(dir + '/' + common.sanitizeFilename(file) + '_' + common.sanitizeFilename(lang) + '.properties', 'utf8', function(err, local_properties) { + if (!err && local_properties) { + local_properties = parser.parse(local_properties); + for (var i in local_properties) { + localized[lang][i] = local_properties[i]; + } } - } + callback(null, localized[lang][name] || "[" + name + "]"); + }); + } + else { callback(null, localized[lang][name] || "[" + name + "]"); - }); - } - else { - callback(null, localized[lang][name] || "[" + name + "]"); - } -}; + } + }, -locale.getProperties = function(lang, callback) { - if (lang === default_lang) { - callback(null, JSON.parse(JSON.stringify(orig || {}))); - } - else if (!localized[lang]) { - localized[lang] = JSON.parse(JSON.stringify(orig)); - fs.readFile(dir + '/' + common.sanitizeFilename(file) + '_' + common.sanitizeFilename(lang) + '.properties', 'utf8', function(err, local_properties) { - if (!err && local_properties) { - local_properties = parser.parse(local_properties); - for (var i in local_properties) { - localized[lang][i] = local_properties[i]; + getProperties: function(lang, callback) { + if (lang === default_lang) { + callback(null, JSON.parse(JSON.stringify(orig || {}))); + } + else if (!localized[lang]) { + localized[lang] = JSON.parse(JSON.stringify(orig)); + fs.readFile(dir + '/' + common.sanitizeFilename(file) + '_' + common.sanitizeFilename(lang) + '.properties', 'utf8', function(err, local_properties) { + if (!err && local_properties) { + local_properties = parser.parse(local_properties); + for (var i in local_properties) { + localized[lang][i] = local_properties[i]; + } } - } + callback(null, JSON.parse(JSON.stringify(localized[lang] || {}))); + }); + } + else { callback(null, JSON.parse(JSON.stringify(localized[lang] || {}))); - }); - } - else { - callback(null, JSON.parse(JSON.stringify(localized[lang] || {}))); + } } }; -/** @type {import('../../types/localization').Locale} */ module.exports = locale; \ No newline at end of file