diff --git a/api/lib/countly.common.d.ts b/api/lib/countly.common.d.ts new file mode 100644 index 00000000000..4129ae6d771 --- /dev/null +++ b/api/lib/countly.common.d.ts @@ -0,0 +1,356 @@ +import * as moment from "moment-timezone"; +import * as underscore from "underscore"; + +declare const countlyCommon: { + /** + * Calculate unique users from map + * @param {object} dbObj - database object + * @param {object} uniqueMap - unique map + * @returns {number} unique users + */ + calculateUniqueFromMap: (dbObj: any, uniqueMap: any) => number; + /** + * Get descendant property + * @param {object} obj - object to get property from + * @param {string} desc - descendant property + * @returns {any} property value + */ + getDescendantProp: (obj: any, desc: string) => any; + /** + * Set descendant property + * @param {object} obj - object to set property on + * @param {string} desc - descendant property + * @param {any} value - value to set + */ + setDescendantProp: (obj: any, desc: string, value: any) => void; + /** + * Remove descendant property + * @param {object} obj - object to remove property from + * @param {string} desc - descendant property + */ + removeDescendantProp: (obj: any, desc: string) => void; + /** + * Get time series + * @param {object} dbObj - database object + * @param {string} period - period + * @param {string} timezone - timezone + * @param {string} dateId - date id + * @param {boolean} isUTC - is UTC + * @returns {array} time series + */ + getTimeSeries: ( + dbObj: any, + period: string, + timezone: string, + dateId: string, + isUTC: boolean + ) => any; + /** + * Get period object + * @param {string} period - period + * @param {string} timezone - timezone + * @param {moment} date - date + * @returns {object} period object + */ + getPeriodObject: ( + period: string, + timezone: string, + date: moment.Moment + ) => any; + /** + * Get period name + * @param {string} period - period + * @returns {string} period name + */ + getPeriodName: (period: string) => string; + /** + * Get period start + * @param {string} period - period + * @param {string} timezone - timezone + * @param {moment} date - date + * @returns {number} period start + */ + getPeriodStart: ( + period: string, + timezone: string, + date: moment.Moment + ) => number; + /** + * Get period end + * @param {string} period - period + * @param {string} timezone - timezone + * @param {moment} date - date + * @returns {number} period end + */ + getPeriodEnd: ( + period: string, + timezone: string, + date: moment.Moment + ) => number; + /** + * Get timestamp + * @param {moment} date - date + * @returns {number} timestamp + */ + getTimestamp: (date: moment.Moment) => number; + /** + * Get timestamp string + * @param {moment} date - date + * @returns {string} timestamp string + */ + getTimestampString: (date: moment.Moment) => string; + /** + * Get ISO date + * @param {moment} date - date + * @returns {string} ISO date + */ + getISODate: (date: moment.Moment) => string; + /** + * Get start of current day + * @param {string} timezone - timezone + * @returns {moment} start of current day + */ + getStartOfCurrentDay: (timezone: string) => moment.Moment; + /** + * Get start of today UTC + * @returns {moment} start of today UTC + */ + getStartOfTodayUTC: () => moment.Moment; + /** + * Get start of today + * @param {string} timezone - timezone + * @returns {moment} start of today + */ + getStartOfToday: (timezone: string) => moment.Moment; + /** + * Get start of this week + * @param {string} timezone - timezone + * @returns {moment} start of this week + */ + getStartOfThisWeek: (timezone: string) => moment.Moment; + /** + * Get start of this month + * @param {string} timezone - timezone + * @returns {moment} start of this month + */ + getStartOfThisMonth: (timezone: string) => moment.Moment; + /** + * Get start of this year + * @param {string} timezone - timezone + * @returns {moment} start of this year + */ + getStartOfThisYear: (timezone: string) => moment.Moment; + /** + * Get start of next day + * @param {string} timezone - timezone + * @returns {moment} start of next day + */ + getStartOfNextDay: (timezone: string) => moment.Moment; + /** + * Get start of next week + * @param {string} timezone - timezone + * @returns {moment} start of next week + */ + getStartOfNextWeek: (timezone: string) => moment.Moment; + /** + * Get start of next month + * @param {string} timezone - timezone + * @returns {moment} start of next month + */ + getStartOfNextMonth: (timezone: string) => moment.Moment; + /** + * Get start of next year + * @param {string} timezone - timezone + * @returns {moment} start of next year + */ + getStartOfNextYear: (timezone: string) => moment.Moment; + /** + * Get days in month + * @param {moment} date - date + * @returns {number} days in month + */ + getDaysInMonth: (date: moment.Moment) => number; + /** + * Get months in year + * @returns {number} months in year + */ + getMonthsInYear: () => number; + /** + * Get start of UTC day + * @param {moment} date - date + * @returns {moment} start of UTC day + */ + getStartOfUTCDay: (date: moment.Moment) => moment.Moment; + /** + * Get start of timezone day + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {moment} start of timezone day + */ + getStartOfTimezoneDay: ( + date: moment.Moment, + timezone: string + ) => moment.Moment; + /** + * Get start of timezone week + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {moment} start of timezone week + */ + getStartOfTimezoneWeek: ( + date: moment.Moment, + timezone: string + ) => moment.Moment; + /** + * Get start of timezone month + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {moment} start of timezone month + */ + getStartOfTimezoneMonth: ( + date: moment.Moment, + timezone: string + ) => moment.Moment; + /** + * Get start of timezone year + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {moment} start of timezone year + */ + getStartOfTimezoneYear: ( + date: moment.Moment, + timezone: string + ) => moment.Moment; + /** + * Get start of next timezone day + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {moment} start of next timezone day + */ + getStartOfNextTimezoneDay: ( + date: moment.Moment, + timezone: string + ) => moment.Moment; + /** + * Get start of next timezone week + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {moment} start of next timezone week + */ + getStartOfNextTimezoneWeek: ( + date: moment.Moment, + timezone: string + ) => moment.Moment; + /** + * Get start of next timezone month + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {moment} start of next timezone month + */ + getStartOfNextTimezoneMonth: ( + date: moment.Moment, + timezone: string + ) => moment.Moment; + /** + * Get start of next timezone year + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {moment} start of next timezone year + */ + getStartOfNextTimezoneYear: ( + date: moment.Moment, + timezone: string + ) => moment.Moment; + /** + * Get UTC timestamp + * @param {moment} date - date + * @returns {number} UTC timestamp + */ + getUTCTimestamp: (date: moment.Moment) => number; + /** + * Get timezone timestamp + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {number} timezone timestamp + */ + getTimezoneTimestamp: (date: moment.Moment, timezone: string) => number; + /** + * Get UTC timestamp string + * @param {moment} date - date + * @returns {string} UTC timestamp string + */ + getUTCTimestampString: (date: moment.Moment) => string; + /** + * Get timezone timestamp string + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {string} timezone timestamp string + */ + getTimezoneTimestampString: (date: moment.Moment, timezone: string) => string; + /** + * Get UTC timestamp for filename + * @param {moment} date - date + * @returns {number} UTC timestamp for filename + */ + getUTCTimestampForFilename: (date: moment.Moment) => number; + /** + * Get timezone timestamp for filename + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {number} timezone timestamp for filename + */ + getTimezoneTimestampForFilename: ( + date: moment.Moment, + timezone: string + ) => number; + /** + * Get UTC timestamp for query + * @param {moment} date - date + * @returns {number} UTC timestamp for query + */ + getUTCTimestampForQuery: (date: moment.Moment) => number; + /** + * Get timezone timestamp for query + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {number} timezone timestamp for query + */ + getTimezoneTimestampForQuery: ( + date: moment.Moment, + timezone: string + ) => number; + /** + * Get UTC timestamp for filename query + * @param {moment} date - date + * @returns {number} UTC timestamp for filename query + */ + getUTCTimestampForFilenameQuery: (date: moment.Moment) => number; + /** + * Get timezone timestamp for filename query + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {number} timezone timestamp for filename query + */ + getTimezoneTimestampForFilenameQuery: ( + date: moment.Moment, + timezone: string + ) => number; + /** + * Get UTC timestamp for filename query string + * @param {moment} date - date + * @returns {string} UTC timestamp for filename query string + */ + getUTCTimestampForFilenameQueryString: (date: moment.Moment) => string; + /** + * Get timezone timestamp for filename query string + * @param {moment} date - date + * @param {string} timezone - timezone + * @returns {string} timezone timestamp for filename query string + */ + getTimezoneTimestampForFilenameQueryString: ( + date: moment.Moment, + timezone: string + ) => string; +}; + +export = countlyCommon; diff --git a/api/parts/data/fetch.d.ts b/api/parts/data/fetch.d.ts new file mode 100644 index 00000000000..26decf9a98d --- /dev/null +++ b/api/parts/data/fetch.d.ts @@ -0,0 +1,35 @@ +import { Params } from "../../utils/common"; + +export interface Fetch { + prefetchEventData(collection: string, params: Params): void; + fetchEventData(collection: string, params: Params): void; + fetchEventGroupById(params: Params): void; + fetchEventGroups(params: Params): void; + fetchMergedEventGroups(params: Params): void; + getMergedEventGroups( + params: Params, + event: string, + options: any, + callback: Function + ): void; + fetchMergedEventData(params: Params): void; + getMergedEventData( + params: Params, + events: string[], + options: any, + callback: Function + ): void; + fetchCollection(collection: string, params: Params): void; + fetchTimeData(collection: string, params: Params): void; + fetchDashboard(params: Params): void; + fetchAllApps(params: Params): void; + fetchTotalUsersObj( + collection: string, + params: Params, + callback: Function + ): void; + getPeriodObj(params: Params): void; +} + +declare const fetch: Fetch; +export default fetch; diff --git a/api/parts/data/usage.d.ts b/api/parts/data/usage.d.ts new file mode 100644 index 00000000000..52ba8030e88 --- /dev/null +++ b/api/parts/data/usage.d.ts @@ -0,0 +1,17 @@ +import { Params } from "../../utils/common"; + +export interface Usage { + setLocation(params: Params): Promise; + setUserLocation(params: Params, loc: any): void; + processSessionDuration(params: Params, callback: Function): void; + getPredefinedMetrics(params: Params, userProps: any): any[]; + returnAllProcessedMetrics(params: Params): any; + processSessionDurationRange( + totalSessionDuration: number, + params: Params, + done: Function + ): void; +} + +declare const usage: Usage; +export default usage; diff --git a/api/parts/jobs/handle.d.ts b/api/parts/jobs/handle.d.ts new file mode 100644 index 00000000000..ec4e5ead0cf --- /dev/null +++ b/api/parts/jobs/handle.d.ts @@ -0,0 +1,14 @@ +import { Db } from "mongodb"; +import { IPC } from "./ipc"; +import { Job } from "./job"; + +export class Handle { + static instance: Handle; + db: Db; + classes: { [key: string]: any }; + files: { [key: string]: string }; + job(name: string, data: any): Job; + runTransient(name: string, data: any): Promise; + get ipc(): IPC; + suspendJob(params: any): Promise; +} diff --git a/api/parts/jobs/index.d.ts b/api/parts/jobs/index.d.ts new file mode 100644 index 00000000000..b02fef2c54e --- /dev/null +++ b/api/parts/jobs/index.d.ts @@ -0,0 +1,2 @@ +export * from "./manager"; +export * from "./handle"; diff --git a/api/parts/jobs/manager.d.ts b/api/parts/jobs/manager.d.ts new file mode 100644 index 00000000000..3b4c97c6292 --- /dev/null +++ b/api/parts/jobs/manager.d.ts @@ -0,0 +1,32 @@ +import { Db } from "mongodb"; +import { Job } from "./job"; +import { IPC } from "./ipc"; + +export interface ManagerOptions { + db: Db; +} + +export class Manager { + constructor(); + classes: { [key: string]: any }; + types: string[]; + files: { [key: string]: string }; + processes: { [key: string]: any[] }; + running: { [key: string]: any[] }; + resources: any[]; + db: Db; + collection: any; + checkingAfterDelay: boolean; + job(name: string, data: any): Job; + checkAfterDelay(delay?: number): void; + check(): void; + process(jobs: any[]): Promise; + schedule(job: any): Promise; + start(job: any): Promise; + runIPC(job: any): Promise; + canRun(job: any, count?: number): boolean; + getPool(job: any): any; + getResource(job: any): any; + hasResources(job: any): boolean; + readonly ipc: IPC; +} diff --git a/api/parts/mgmt/app_users.d.ts b/api/parts/mgmt/app_users.d.ts new file mode 100644 index 00000000000..2e6f6b57ac2 --- /dev/null +++ b/api/parts/mgmt/app_users.d.ts @@ -0,0 +1,30 @@ +import { Params } from "../../utils/common"; + +export interface AppUsersApi { + create(app_id: string, doc: any, params: Params, callback: Function): void; + update( + app_id: string, + query: any, + update: any, + params: Params, + callback: Function + ): void; + delete(app_id: string, query: any, params: Params, callback: Function): void; + search( + app_id: string, + query: any, + project: any, + sort: any, + limit: number, + skip: number, + callback: Function + ): void; + count(app_id: string, query: any, callback: Function): void; + getUid(app_id: string, callback: Function): void; + mergeOtherPlugins(options: any, callback: Function): void; + deleteExport(id: string, params: Params, callback: Function): void; + export(app_id: string, query: any, params: Params, taskmanager: any): void; +} + +declare const usersApi: AppUsersApi; +export default usersApi; diff --git a/api/parts/mgmt/apps.d.ts b/api/parts/mgmt/apps.d.ts new file mode 100644 index 00000000000..5deb135a26c --- /dev/null +++ b/api/parts/mgmt/apps.d.ts @@ -0,0 +1,16 @@ +import { Params } from "../../utils/common"; + +export interface AppsApi { + getAllApps(params: Params): boolean; + getCurrentUserApps(params: Params): boolean; + getAppsDetails(params: Params): boolean; + createApp(params: Params): Promise; + updateApp(params: Params): boolean; + deleteApp(params: Params): boolean; + resetApp(params: Params): boolean; + getAppPlugins(params: Params): Promise; + updateAppPlugins(params: Params): boolean; +} + +declare const appsApi: AppsApi; +export default appsApi; diff --git a/api/parts/mgmt/cms.d.ts b/api/parts/mgmt/cms.d.ts new file mode 100644 index 00000000000..b7316b7ece6 --- /dev/null +++ b/api/parts/mgmt/cms.d.ts @@ -0,0 +1,11 @@ +import { Params } from "../../utils/common"; + +export interface CmsApi { + getEntriesWithUpdate(params: Params): boolean; + getEntries(params: Params): boolean; + saveEntries(params: Params): void; + clearCache(params: Params): void; +} + +declare const cmsApi: CmsApi; +export default cmsApi; diff --git a/api/parts/mgmt/date_presets.d.ts b/api/parts/mgmt/date_presets.d.ts new file mode 100644 index 00000000000..a2e8ea986c1 --- /dev/null +++ b/api/parts/mgmt/date_presets.d.ts @@ -0,0 +1,12 @@ +import { Params } from "../../utils/common"; + +export interface DatePresetsApi { + getAll(params: Params): boolean; + getById(params: Params): boolean; + create(params: Params): boolean; + update(params: Params): boolean; + delete(params: Params): boolean; +} + +declare const datePresetsApi: DatePresetsApi; +export default datePresetsApi; diff --git a/api/parts/mgmt/event_groups.d.ts b/api/parts/mgmt/event_groups.d.ts new file mode 100644 index 00000000000..00cd574b121 --- /dev/null +++ b/api/parts/mgmt/event_groups.d.ts @@ -0,0 +1,10 @@ +import { Params } from "../../utils/common"; + +export interface EventGroupsApi { + create(params: Params): void; + update(params: Params): void; + remove(params: Params): void; +} + +declare const eventGroupsApi: EventGroupsApi; +export default eventGroupsApi; diff --git a/api/parts/mgmt/users.d.ts b/api/parts/mgmt/users.d.ts new file mode 100644 index 00000000000..4340b88ea3d --- /dev/null +++ b/api/parts/mgmt/users.d.ts @@ -0,0 +1,19 @@ +import { Params } from "../../utils/common"; + +export interface UsersApi { + getCurrentUser(params: Params): boolean; + getUserById(params: Params): boolean; + getAllUsers(params: Params): boolean; + resetTimeBan(params: Params): boolean; + createUser(params: Params): Promise; + updateUser(params: Params): Promise; + deleteUser(params: Params): Promise; + deleteOwnAccount(params: Params): Promise; + updateHomeSettings(params: Params): boolean; + saveNote(params: Params): void; + deleteNote(params: Params): void; + ackNotification(params: Params): void; +} + +declare const usersApi: UsersApi; +export default usersApi; diff --git a/api/utils/authorizer.d.ts b/api/utils/authorizer.d.ts new file mode 100644 index 00000000000..1e40de3cda6 --- /dev/null +++ b/api/utils/authorizer.d.ts @@ -0,0 +1,113 @@ +import { Db } from "mongodb"; + +/** + * Module providing one time authentication + * @module api/utils/authorizer + */ +export interface AuthorizerOptions { + db: Db; + token: string; + qstring?: any; + req_path?: string; + callback: (valid: any, expires_after?: number) => void; + return_data?: boolean; + ttl?: number; + multi?: boolean; + owner?: string; + app?: string | string[]; + endpoint?: string | string[]; + purpose?: string; + temporary?: boolean; + tryReuse?: boolean; +} + +export interface Authorizer { + /** + * Store token for later authentication + * @function save + * @name module:api/utils/authorizer.save + * @param {object} options - options for the task + * @param {object} options.db - database connection + * @param {number} options.ttl - amount of seconds for token to work, 0 works indefinately + * @param {bool} [options.multi=false] - if true, can be used many times until expired + * @param {string} options.token - token to store, if not provided, will be generated + * @param {string} options.owner - id of the user who created this token + * @param {string} options.app - list of the apps for which token was created + * @param {string} options.endpoint - regexp of endpoint(any string - is used as substring,to mach exact ^{yourpath}$) + * @param {string} options.tryReuse - if true - tries to find not expired token with same parameters. If not founds cretes new token. If found - updates token expiration time to new one and returns token. + * @param {bool} [options.temporary=false] - If logged in with temporary token. Doesn't kill other sessions on logout. + * @param {function} options.callback - function called when saving was completed or errored, providing error object as first param and token string as second + */ + save(options: AuthorizerOptions): void; + /** + * Get whole token information from database + * @function read + * @name module:api/utils/authorizer.read + * @param {object} options - options for the task + * @param {object} options.db - database connection + * @param {string} options.token - token to read + * @param {function} options.callback - function called when reading was completed or errored, providing error object as first param and token object from database as second + */ + read(options: AuthorizerOptions): void; + clearExpiredTokens(options: { db: Db }): void; + /** + * Checks if token is not expired yet + * @function check_if_expired + * @name module:api/utils/authorizer.check_if_expired + * @param {object} options - options for the task + * @param {object} options.db - database connection + * @param {string} options.token - token to rvalidate + * @param {function} options.callback - function called when reading was completed or errored, providing error object as first param, true or false if expired as second, seconds till expiration as third.(-1 if never expires, 0 - if expired) + */ + check_if_expired(options: AuthorizerOptions): void; + /** + * extent token life spas + * @function extend_token + * @name module:api/utils/authorizer.extend_token + * @param {object} options - options for the task + * @param {object} options.db - database connection + * @param {string} options.token - token to extend + * @param {string} options.extendBy - extend token by given time(in ms)(optional) You have to provide extedBy or extendTill. extendBy==0 makes it never die + * @param {string} options.extendTill - extend till given timestamp. (optional) You have to provide extedBy or extendTill + * @param {function} options.callback - function called when reading was completed or errored, providing error object as first param and true as second if extending successful + */ + extend_token(options: AuthorizerOptions): void; + /** + * Verify token and expire it + * @function verify + * @name module:api/utils/authorizer.verify + * @param {object} options - options for the task + * @param {object} options.db - database connection + * @param {string} options.token - token to verify + * @param {string} options.qstring - params.qstring. If not passed and there is limitation for this token on params - token will not be valid + * @param {string} options.req_path - current request path + * @param {function} options.callback - function called when verifying was completed, providing 1 argument, true if could verify token and false if couldn't + */ + verify(options: AuthorizerOptions): void; + /** + * Similar to authorizer.verify. Only difference - return token owner if valid. + * @function verify_return + * @name module:api/utils/authorizer.verify_return + * @param {object} options - options for the task + * @param {object} options.db - database connection + * @param {string} options.token - token to verify + * @param {string} options.qstring - params.qstring. If not passed and there is limitation for this token on params - token will not be valid + * @param {string} options.req_path - current request path + * @param {function} options.callback - function called when verifying was completed, providing 1 argument, true if could verify token and false if couldn't + */ + verify_return(options: AuthorizerOptions): void; + getToken(): string; + /** + * Clean all expired tokens + * @function clean + * @name module:api/utils/authorizer.clean + * @param {object} options - options for the task + * @param {object} options.db - database connection + * @param {function} options.callback - function called when cleaning completed + */ + clean(options: { db: Db; callback: (err: any, result: any) => void }): void; +} + +declare const authorizer: Authorizer; + +export default authorizer; diff --git a/api/utils/common/crypto-utils.d.ts b/api/utils/common/crypto-utils.d.ts new file mode 100644 index 00000000000..d7130a70d26 --- /dev/null +++ b/api/utils/common/crypto-utils.d.ts @@ -0,0 +1,67 @@ +/** + * Module for cryptography and security utility functions + * @module api/utils/common/crypto-utils + */ + +declare module "api/utils/common/crypto-utils" { + import { BinaryToTextEncoding } from "crypto"; + + /** + * Create HMAC sha1 hash from provided value and optional salt + * @param {string} str - value to hash + * @param {string=} addSalt - optional salt, uses ms timestamp by default + * @returns {string} HMAC sha1 hash + */ + export function sha1Hash(str: string, addSalt?: string): string; + + /** + * Create HMAC sha512 hash from provided value and optional salt + * @param {string} str - value to hash + * @param {string=} addSalt - optional salt, uses ms timestamp by default + * @returns {string} HMAC sha1 hash + */ + export function sha512Hash(str: string, addSalt?: string): string; + + /** + * Create argon2 hash string + * @param {string} str - string to hash + * @returns {promise} hash promise + **/ + export function argon2Hash(str: string): Promise; + + /** + * Create MD5 hash from provided value + * @param {string} str - value to hash + * @returns {string} MD5 hash + */ + export function md5Hash(str: string): string; + + /** + * Shuffle string using getRandomValues + * @param {string} text - text to be shuffled + * @returns {string} shuffled password + */ + export function shuffleString(text: string): string; + + /** + * Gets a random string from given character set string with given length + * @param {string} charSet - charSet string + * @param {number} length - length of the random string. default 1 + * @returns {string} random string from charset + */ + export function getRandomValue(charSet: string, length?: number): string; + + /** + * Generate random password + * @param {number} length - length of the password + * @param {boolean} no_special - do not include special characters + * @returns {string} password + * @example + * //outputs 4UBHvRBG1v + * generatePassword(10, true); + */ + export function generatePassword( + length: number, + no_special?: boolean + ): string; +} diff --git a/api/utils/common/date-utils.d.ts b/api/utils/common/date-utils.d.ts new file mode 100644 index 00000000000..8f247aebdba --- /dev/null +++ b/api/utils/common/date-utils.d.ts @@ -0,0 +1,117 @@ +/** + * Module for date and time utility functions + * @module api/utils/common/date-utils + */ + +declare module "api/utils/common/date-utils" { + import moment from "moment-timezone"; + + /** + * @typedef timeObject + * @type {object} + * @global + * @property {momentjs} now - momentjs instance for request's time in app's timezone + * @property {momentjs} nowUTC - momentjs instance for request's time in UTC + * @property {momentjs} nowWithoutTimestamp - momentjs instance for current time in app's timezone + * @property {number} timestamp - request's seconds timestamp + * @property {number} mstimestamp - request's miliseconds timestamp + * @property {string} yearly - year of request time in app's timezone in YYYY format + * @property {string} monthly - month of request time in app's timezone in YYYY.M format + * @property {string} daily - date of request time in app's timezone in YYYY.M.D format + * @property {string} hourly - hour of request time in app's timezone in YYYY.M.D.H format + * @property {number} weekly - week of request time in app's timezone as result day of the year, divided by 7 + * @property {string} month - month of request time in app's timezone in format M + * @property {string} day - day of request time in app's timezone in format D + * @property {string} hour - hour of request time in app's timezone in format H + */ + type timeObject = { + now: moment.Moment; + nowUTC: moment.Moment; + nowWithoutTimestamp: moment.Moment; + timestamp: number; + mstimestamp: number; + yearly: string; + monthly: string; + daily: string; + hourly: string; + weekly: number; + weeklyISO: number; + month: string; + day: string; + hour: string; + }; + + /** + * Creates a time object from request's milisecond or second timestamp in provided app's timezone + * @param {string} appTimezone - app's timezone + * @param {number} reqTimestamp - timestamp in the request + * @returns {timeObject} Time object for current request + */ + export function initTimeObj( + appTimezone: string, + reqTimestamp: number + ): timeObject; + + /** + * Creates a Date object from provided seconds timestamp in provided timezone + * @param {number} timestamp - unix timestamp in seconds + * @param {string} timezone - name of the timezone + * @returns {moment} moment object for provided time + */ + export function getDate(timestamp: number, timezone: string): moment.Moment; + + /** + * Returns day of the year from provided seconds timestamp in provided timezone + * @param {number} timestamp - unix timestamp in seconds + * @param {string} timezone - name of the timezone + * @returns {number} current day of the year + */ + export function getDOY(timestamp: number, timezone: string): number; + + /** + * Returns amount of days in provided year + * @param {number} year - year to check for days + * @returns {number} number of days in provided year + */ + export function getDaysInYear(year: number): number; + + /** + * Returns amount of iso weeks in provided year + * @param {number} year - year to check for days + * @returns {number} number of iso weeks in provided year + */ + export function getISOWeeksInYear(year: number): number; + + /** + * Get diference between 2 momentjs instances in specific measurement + * @param {moment} moment1 - momentjs with start date + * @param {moment} moment2 - momentjs with end date + * @param {string} measure - units of difference, can be minutes, hours, days, weeks + * @returns {number} difference in provided units + */ + export function getDiff( + moment1: moment.Moment, + moment2: moment.Moment, + measure: string + ): number; + + /** + * Adjust timestamp with app's timezone for timestamp queries that should equal bucket results + * @param {number} ts - miliseconds timestamp + * @param {string} tz - timezone + * @returns {number} adjusted timestamp for timezone + */ + export function adjustTimestampByTimezone(ts: number, tz: string): number; + + /** + * Checks if provided value could be converted to a number, + * even if current type is other, as string, as example value "42" + * @param {any} n - value to check if it can be converted to number + * @returns {boolean} true if can be a number, false if can't be a number + * @example + * isNumber(1) //outputs true + * isNumber("2") //outputs true + * isNumber("test") //outputs false + */ + export function isNumber(n: any): boolean; +} diff --git a/api/utils/common/db-maps.d.ts b/api/utils/common/db-maps.d.ts new file mode 100644 index 00000000000..119f69e950e --- /dev/null +++ b/api/utils/common/db-maps.d.ts @@ -0,0 +1,130 @@ +/** + * Module for database mapping constants + * @module api/utils/common/db-maps + */ + +declare module "api/utils/common/db-maps" { + /** + * Mapping some common property names from longer understandable to shorter representation stored in database + * @type {object} + */ + export const dbMap: { + events: string; + total: string; + new: string; + unique: string; + duration: string; + durations: string; + frequency: string; + loyalty: string; + sum: string; + dur: string; + count: string; + }; + + /** + * Mapping some common user property names from longer understandable to shorter representation stored in database + * @type {object} + */ + export const dbUserMap: { + device_id: string; + user_id: string; + first_seen: string; + last_seen: string; + last_payment: string; + session_duration: string; + total_session_duration: string; + session_count: string; + device: string; + device_type: string; + manufacturer: string; + carrier: string; + city: string; + region: string; + country_code: string; + platform: string; + platform_version: string; + app_version: string; + last_begin_session_timestamp: string; + last_end_session_timestamp: string; + has_ongoing_session: string; + previous_events: string; + resolution: string; + has_hinge: string; + }; + + /** + * Mapping for unique identifiers + * @type {object} + */ + export const dbUniqueMap: { + "*": string[]; + users: string[]; + }; + + /** + * Mapping some common event property names from longer understandable to shorter representation stored in database + * @type {object} + */ + export const dbEventMap: { + user_properties: string; + timestamp: string; + segmentations: string; + count: string; + sum: string; + duration: string; + previous_events: string; + }; + + /** + * Operating syste/platform mappings from what can be passed in metrics to shorter representations + * stored in db as prefix to OS segmented values + * @type {object} + */ + export const os_mapping: { + webos: string; + brew: string; + unknown: string; + undefined: string; + tvos: string; + "apple tv": string; + watchos: string; + "unity editor": string; + qnx: string; + "os/2": string; + "amazon fire tv": string; + amazon: string; + web: string; + windows: string; + "open bsd": string; + searchbot: string; + "sun os": string; + solaris: string; + beos: string; + "mac osx": string; + macos: string; + mac: string; + osx: string; + linux: string; + unix: string; + ios: string; + android: string; + blackberry: string; + "windows phone": string; + wp: string; + roku: string; + symbian: string; + chrome: string; + debian: string; + nokia: string; + firefox: string; + tizen: string; + arch: string; + }; + + /** + * Whole base64 alphabet for fetching splitted documents + * @type {object} + */ + export const base64: string[]; +} diff --git a/api/utils/common/db-utils.d.ts b/api/utils/common/db-utils.d.ts new file mode 100644 index 00000000000..e4c12fd99d7 --- /dev/null +++ b/api/utils/common/db-utils.d.ts @@ -0,0 +1,90 @@ +/** + * Module for database utility functions + * @module api/utils/common/db-utils + */ + +declare module "api/utils/common/db-utils" { + import { Moment } from "moment-timezone"; + import { Collection } from "mongodb"; + + /** + * Promise wrapper for database operations + * @param {varies} arguments - collection name, operation and operation parameters + * @returns {Promise} promise for database operation + */ + export function dbPromise(...args: any[]): Promise; + + /** + * Modifies provided object filling properties used in zero documents in the format object["2012.7.20.property"] = increment. + * Usualy used when filling up Countly metric model zero document + * @param {params} params - {@link params} object + * @param {object} object - object to fill + * @param {string} property - meric value or segment or property to fill/increment + * @param {number=} increment - by how much to increments, default is 1 + * @param {boolean=} isUnique - if property is unique + * @returns {void} void + */ + export function fillTimeObjectZero( + params: any, + object: any, + property: string | string[], + increment?: number, + isUnique?: boolean + ): boolean; + + /** + * Modifies provided object filling properties used in monthly documents in the format object["2012.7.20.property"] = increment. + * Usualy used when filling up Countly metric model monthly document + * @param {params} params - {@link params} object + * @param {object} object - object to fill + * @param {string} property - meric value or segment or property to fill/increment + * @param {number=} increment - by how much to increments, default is 1 + * @param {boolean=} forceHour - force recording hour information too, dfault is false + * @returns {void} void + */ + export function fillTimeObjectMonth( + params: any, + object: any, + property: string | string[], + increment?: number, + forceHour?: boolean + ): boolean; + + /** + * Modifies provided object in the format object["2012.7.20.property"] = increment. + * Usualy used when filling up Countly metric model data + * @param {params} params - {@link params} object + * @param {object} object - object to fill + * @param {string} property - meric value or segment or property to fill/increment + * @param {number=} increment - by how much to increments, default is 1 + * @returns {void} void + */ + export function fillTimeObject( + params: any, + object: any, + property: string, + increment?: number + ): boolean; + + /** + * Get object of date ids that should be used in fetching standard metric model documents + * @param {params} params - {@link params} object + * @returns {object} with date ids, as {zero:"2017:0", month:"2017:2"} + */ + export function getDateIds(params: any): { zero: string; month: string }; + + /** + * Clear clashing query operations + * @param {object} query - MongoDB query object + * @returns {object} cleaned query + */ + export function clearClashingQueryOperations(query: any): any; + + /** + * Merge 2 mongodb update queries + * @param {object} ob1 - existing database update query + * @param {object} ob2 - addition to database update query + * @returns {object} merged database update query + */ + export function mergeQuery(ob1: any, ob2: any): any; +} diff --git a/api/utils/common/format-utils.d.ts b/api/utils/common/format-utils.d.ts new file mode 100644 index 00000000000..b76d857746c --- /dev/null +++ b/api/utils/common/format-utils.d.ts @@ -0,0 +1,27 @@ +/** + * Module for formatting utility functions + * @module api/utils/common/format-utils + */ + +declare module "api/utils/common/format-utils" { + /** + * Standard number formatter, taken from frontend's countly.common.js + * + * @memberof countlyCommon + * @param {number} x - number to format + * @returns {string} formatted number + * @example + * //outputs 1,234,567 + * formatNumber(1234567); + */ + export function formatNumber(x: number): string; + + /** + * Second formatter + * + * @memberof countlyCommon + * @param {number} number - number of seconds to format + * @returns {string} formatted seconds + */ + export function formatSecond(number: number): string; +} diff --git a/api/utils/common/html-utils.d.ts b/api/utils/common/html-utils.d.ts new file mode 100644 index 00000000000..707cf82c7c9 --- /dev/null +++ b/api/utils/common/html-utils.d.ts @@ -0,0 +1,77 @@ +/** + * Module for HTML and string manipulation utilities + * @module api/utils/common/html-utils + */ + +declare module "api/utils/common/html-utils" { + /** + * Escape special characters in the given string of html. + * @param {string} string - The string to escape for inserting into HTML + * @param {bool} more - if false, escapes only tags, if true escapes also quotes and ampersands + * @returns {string} escaped string + **/ + export function escape_html(string: string, more?: boolean): string; + + /** + * Function to escape unicode characters + * @param {string} str - string for which to escape + * @returns {string} escaped string + */ + export function encodeCharacters(str: string): string; + + /** + * Decode escaped html + * @param {string} string - The string to decode + * @returns {string} escaped string + **/ + export function decode_html(string: string): 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 + **/ + export function getJSON(val: string): { valid: boolean; data?: any }; + + /** + * Escape special characters in the given value, may be nested object + * @param {string} key - key of the value + * @param {vary} value - value to escape + * @param {bool} more - if false, escapes only tags, if true escapes also quotes and ampersands + * @returns {vary} escaped value + **/ + export function escape_html_entities( + key: string, + value: any, + more?: boolean + ): any; + + /** + * Sanitizes a filename to prevent directory traversals and such. + * @param {string} filename - filename to sanitize + * @param {string} replacement - string to replace characters to be removed + * @returns {string} sanitizedFilename - sanitized filename + */ + export function sanitizeFilename( + filename: string, + replacement?: string + ): string; + + /** + * Sanitizes html content by allowing only safe tags + * @param {string} html - html content to sanitize + * @param {object} extendedWhitelist - extended whitelist of tags to allow + * @returns {string} sanitizedHTML - sanitized html content + */ + export function sanitizeHTML( + html: string, + extendedWhitelist?: object + ): string; + + /** + * Remove spaces, tabs, and newlines from the start and end from all levels of a nested object + * @param {any} value - Arbitrary value + * @returns {any} Trimmed value + */ + export function trimWhitespaceStartEnd(value: any): any; +} diff --git a/api/utils/common/http-utils.d.ts b/api/utils/common/http-utils.d.ts new file mode 100644 index 00000000000..c31a350c582 --- /dev/null +++ b/api/utils/common/http-utils.d.ts @@ -0,0 +1,84 @@ +/** + * Module for HTTP request/response utility functions + * @module api/utils/common/http-utils + */ + +declare module "api/utils/common/http-utils" { + import { IncomingMessage, ServerResponse } from "http"; + + /** + * Custom API response handler callback + * @typedef APICallback + * @callback APICallback + * @type {function} + * @global + * @param {bool} error - true if there was problem processing request, and false if request was processed successfully + * @param {string} responseMessage - what API returns + * @param {object} headers - what API would have returned to HTTP request + * @param {number} returnCode - HTTP code, what API would have returned to HTTP request + * @param {params} params - request context that was passed to requestProcessor, modified during request processing + */ + export type APICallback = ( + error: boolean, + responseMessage: string, + headers: { [key: string]: string } | undefined, + returnCode: number, + params: any + ) => void; + + /** + * Block {@link module:api/utils/common.returnMessage} and {@link module:api/utils/common.returnOutput} from ouputting anything + * @param {params} params - params object + */ + export function blockResponses(params: any): void; + + /** + * Unblock/allow {@link module:api/utils/common.returnMessage} and {@link module:api/utils/common.returnOutput} ouputting anything + * @param {params} params - params object + */ + export function unblockResponses(params: any): void; + + /** + * Return raw headers and body + * @param {params} params - params object + * @param {number} returnCode - http code to use + * @param {string} body - raw data to output + * @param {object} heads - headers to add to the output + */ + export function returnRaw( + params: any, + returnCode: number, + body: string, + heads?: { [key: string]: string } + ): void; + + /** + * Output message as request response with provided http code + * @param {params} params - params object + * @param {number} returnCode - http code to use + * @param {string|object} message - Message to output, will be encapsulated in JSON object under result property + * @param {object} heads - headers to add to the output + * @param {boolean} noResult - skip wrapping message object into stupid {result: } + */ + export function returnMessage( + params: any, + returnCode: number, + message: string | object, + heads?: { [key: string]: string }, + noResult?: boolean + ): void; + + /** + * Output message as request response with provided http code + * @param {params} params - params object + * @param {output} output - object to stringify and output + * @param {string} noescape - prevent escaping HTML entities + * @param {object} heads - headers to add to the output + */ + export function returnOutput( + params: any, + output: any, + noescape?: string, + heads?: { [key: string]: string } + ): void; +} diff --git a/api/utils/common/ip-utils.d.ts b/api/utils/common/ip-utils.d.ts new file mode 100644 index 00000000000..21979d71dac --- /dev/null +++ b/api/utils/common/ip-utils.d.ts @@ -0,0 +1,22 @@ +/** + * Module for IP address utility functions + * @module api/utils/common/ip-utils + */ + +declare module "api/utils/common/ip-utils" { + import { IncomingMessage } from "http"; + + /** + * Get IP address from request object + * @param {req} req - nodejs request object + * @returns {string} ip address + */ + export function getIpAddress(req: IncomingMessage): string; + + /** + * This function takes ipv4 or ipv6 with possible port, removes port information and returns plain ip address + * @param {string} ip - ip address to check for port and return plain ip + * @returns {string} plain ip address + */ + export function stripPort(ip: string): string; +} diff --git a/api/utils/common/misc-utils.d.ts b/api/utils/common/misc-utils.d.ts new file mode 100644 index 00000000000..603b4d4e5e8 --- /dev/null +++ b/api/utils/common/misc-utils.d.ts @@ -0,0 +1,51 @@ +/** + * Module for miscellaneous utility functions + * @module api/utils/common/misc-utils + */ + +declare module "api/utils/common/misc-utils" { + /** + * Create promise for function which result should be checked periodically + * @param {function} func - function to run when verifying result, should return true if success + * @param {number} count - how many times to run the func before giving up, if result is always negative + * @param {number} interval - how often to retest function on negative result in miliseconds + * @returns {Promise} promise for checking task + */ + export function checkPromise( + func: () => boolean, + count: number, + interval: number + ): Promise; + + /** + * Update carrier from metrics to convert mnc/mcc code to carrier name + * @param {object} metrics - metrics object from SDK request + */ + export function processCarrier(metrics: any): void; + + /** + * Parse Sequence + * @param {number} num - sequence number for id + * @returns {string} converted to base 62 number + */ + export function parseSequence(num: number): string; + + /** + * Sync license check results to request (and session if present) + * + * @param {object} req request + * @param {object|undefined} check check results + */ + export function licenseAssign(req: any, check: any): void; + + /** + * Check db host match for both of API and Frontend config + * @param {object} apiConfig - mongodb object from API config + * @param {object} frontendConfig - mongodb object from Frontend config + * @returns {boolean} isMatched - is config correct? + */ + export function checkDatabaseConfigMatch( + apiConfig: any, + frontendConfig: any + ): boolean; +} diff --git a/api/utils/common/mongodb-ext.d.ts b/api/utils/common/mongodb-ext.d.ts new file mode 100644 index 00000000000..a1783b7b916 --- /dev/null +++ b/api/utils/common/mongodb-ext.d.ts @@ -0,0 +1,59 @@ +/** + * Module for MongoDB extension utilities + * @module api/utils/common/mongodb-ext + */ + +declare module "api/utils/common/mongodb-ext" { + import { ObjectId } from "mongodb"; + + /** + * DB-related extensions / functions + */ + export const dbext: { + /** + * Wrapper for MongoDB ObjectID + * @param {string} id - ID to convert to ObjectID + * @returns {ObjectID} MongoDB ObjectID + */ + ObjectID(id: string): ObjectId | string; + + /** + * MongoDB ObjectId reference + */ + ObjectId: typeof ObjectId; + + /** + * Check if passed value is an ObjectId + * + * @param {any} id value + * @returns {boolean} true if id is instance of ObjectId + */ + isoid(id: any): boolean; + + /** + * Decode string to ObjectID if needed + * + * @param {String|ObjectID|null|undefined} id string or object id, empty string is invalid input + * @returns {ObjectID} id + */ + oid(id: string | ObjectId | null | undefined): ObjectId | undefined | null; + + /** + * Create ObjectID with given timestamp. Uses current ObjectID random/server parts, meaning the + * object id returned still has same uniquness guarantees as random ones. + * + * @param {Date|number} date Date object or timestamp in seconds, current date by default + * @returns {ObjectID} with given timestamp + */ + oidWithDate(date?: Date | number): ObjectId; + + /** + * Create blank ObjectID with given timestamp. Everything except for date part is zeroed. + * For use in queries like {_id: {$gt: oidBlankWithDate()}} + * + * @param {Date|number} date Date object or timestamp in seconds, current date by default + * @returns {ObjectID} with given timestamp and zeroes in the rest of the bytes + */ + oidBlankWithDate(date?: Date | number): ObjectId; + }; +} diff --git a/api/utils/common/object-utils.d.ts b/api/utils/common/object-utils.d.ts new file mode 100644 index 00000000000..3802b2a0222 --- /dev/null +++ b/api/utils/common/object-utils.d.ts @@ -0,0 +1,166 @@ +/** + * Module for object and data manipulation utilities + * @module api/utils/common/object-utils + */ + +declare module "api/utils/common/object-utils" { + /** + * Fetches nested property values from an obj. + * @param {object} obj - standard countly metric object + * @param {string} desc - dot separate path to fetch from object + * @returns {object} fetched object from provided path + * @example + * //outputs {"u":20,"t":20,"n":5} + * getDescendantProp({"2017":{"1":{"2":{"u":20,"t":20,"n":5}}}}, "2017.1.2"); + */ + export function getDescendantProp(obj: object, desc: string): any; + + /** + * Checks if provided value could be converted to a number, + * even if current type is other, as string, as example value "42" + * @param {any} n - value to check if it can be converted to number + * @returns {boolean} true if can be a number, false if can't be a number + * @example + * isNumber(1) //outputs true + * isNumber("2") //outputs true + * isNumber("test") //outputs false + */ + export function isNumber(n: any): boolean; + + /** + * This default Countly behavior of type conversion for storing proeprties accepted through API requests + * dealing with numbers as strings and too long numbers + * @param {any} value - value to convert to usable type + * @param {boolean} preventParsingToNumber - do not change value to number (e.g. "1", ["1"]); + * @returns {varies} converted value + * @example + * convertToType(1) //outputs 1 + * convertToType("2") //outputs 2 + * convertToType("test") //outputs "test" + * convertToType("12345678901234567890") //outputs "12345678901234567890" + */ + export function convertToType( + value: any, + preventParsingToNumber?: boolean + ): any; + + /** + * Safe division between numbers providing 0 as result in cases when dividing by 0 + * @param {number} dividend - number which to divide + * @param {number} divisor - number by which to divide + * @returns {number} result of division + * @example + * //outputs 0 + * safeDivision(100, 0); + */ + export function safeDivision(dividend: number, divisor: number): number; + + /** + * Pad number with specified character from left to specified length + * @param {number} number - number to pad + * @param {number} width - pad to what length in symbols + * @returns {string} padded number + * @example + * //outputs 0012 + * zeroFill(12, 4, "0"); + */ + export function zeroFill(number: number, width: number): string; + + /** + * Add item or array to existing array only if values are not already in original array + * @param {array} arr - original array where to add unique elements + * @param {string|number|array} item - item to add or array to merge + */ + export function arrayAddUniq(arr: any[], item: string | number | any[]): void; + + /** + * Fix event keys before storing in database by removing dots and $ from the string, removing other prefixes and limiting length + * @param {string} eventKey - key value to fix + * @returns {string|false} escaped key or false if not possible to use key at all + */ + export function fixEventKey(eventKey: string): string | false; + + /** + * Getter/setter for dot notatons: + * @param {object} obj - object to use + * @param {string} is - path of properties to get + * @param {varies} value - value to set + * @returns {varies} value at provided path + * @example + * dot({a: {b: {c: 'string'}}}, 'a.b.c') === 'string' + * dot({a: {b: {c: 'string'}}}, ['a', 'b', 'c']) === 'string' + * dot({a: {b: {c: 'string'}}}, 'a.b.c', 5) === 5 + * dot({a: {b: {c: 'string'}}}, 'a.b.c') === 5 + */ + export function dot(obj: object, is: string | string[], value?: any): any; + + /** + * Not deep object and primitive type comparison function + * + * @param {Any} a object to compare + * @param {Any} b object to compare + * @param {Boolean} checkFromA true if check should be performed agains keys of a, resulting in true even if b has more keys + * @return {Boolean} true if objects are equal, false if different types or not equal + */ + export function equal(a: any, b: any, checkFromA?: boolean): boolean; + + /** + * Returns plain object with key set to value + * @param {varies} arguments - every odd value will be used as key and every event value as value for odd key + * @returns {object} new object with set key/value properties + */ + export function o(...args: any[]): object; + + /** + * Return index of array with objects where property = value + * @param {array} array - array where to search value + * @param {string} property - property where to look for value + * @param {varies} value - value you are searching for + * @returns {number} index of the array + */ + export function indexOf(array: any[], property: string, value: any): number; + + /** + * Optionally load module if it exists + * @param {string} module - module name + * @param {object} options - additional opeitons + * @param {boolean} options.rethrow - throw exception if there is some other error + * @param {varies} value - value you are searching for + * @returns {number} index of the array + */ + export function optional( + module: string, + options?: { rethrow?: boolean } + ): any; + + /** + * Compares two version strings with : as delimiter (which we used to escape dots in app versions) + * @param {string} v1 - first version + * @param {string} v2 - second version + * @param {object} options - providing additional options + * @param {string} options.delimiter - delimiter between version, subversion, etc, defaults : + * @returns {number} 0 if they are both the same, 1 if first one is higher and -1 is second one is higher + */ + export function versionCompare( + v1: string, + v2: string, + options?: { delimiter?: string } + ): number; + + /** + * Promise that tries to catch errors + * @param {function} f function which is usually passed to Promise constructor + * @return {Promise} Promise with constructor catching errors by rejecting the promise + */ + export function p( + f: (resolve: (value: any) => void, reject: (reason?: any) => void) => void + ): Promise; + + /** + * Revive json encoded data, as for example, regular expressions + * @param {string} key - key of json object + * @param {vary} value - value of json object + * @returns {vary} modified value, if it had revivable data + */ + export function reviver(key: string, value: any): any; +} diff --git a/api/utils/common/validation-utils.d.ts b/api/utils/common/validation-utils.d.ts new file mode 100644 index 00000000000..85da0ad9b24 --- /dev/null +++ b/api/utils/common/validation-utils.d.ts @@ -0,0 +1,30 @@ +/** + * Module for validation utility functions + * @module api/utils/common/validation-utils + */ + +declare module "api/utils/common/validation-utils" { + import { ObjectId } from "mongodb"; + + /** + * Validates provided arguments + * @param {object} args - arguments to validate + * @param {object} 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 + * @param {string} argProperties.min-length - property should not be shorter than provided value + * @param {string} argProperties.exclude-from-ret-obj - should property be present in returned validated args object + * @param {string} argProperties.has-number - should string property has any number in it + * @param {string} argProperties.has-char - should string property has any latin character in it + * @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 + */ + export function validateArgs( + args: any, + argProperties: any, + returnErrors?: boolean + ): any; +} diff --git a/api/utils/countly-request/index.d.ts b/api/utils/countly-request/index.d.ts new file mode 100644 index 00000000000..9e348fe5de1 --- /dev/null +++ b/api/utils/countly-request/index.d.ts @@ -0,0 +1,198 @@ +/** + * @module api/utils/countly-request + */ + +import * as got from "got"; +import { FormData } from "form-data"; +import { HttpsProxyAgent, HttpProxyAgent } from "hpagent"; + +/** + * Configuration for Countly request + */ +export interface CountlyConfig { + /** + * Proxy hostname + */ + proxy_hostname?: string; + + /** + * Proxy port + */ + proxy_port?: number; + + /** + * Proxy username + */ + proxy_username?: string; + + /** + * Proxy password + */ + proxy_password?: string; +} + +/** + * File data for uploading + */ +export interface FileData { + /** + * Name of the field to upload file as + */ + fileField: string; + + /** + * File stream to upload + */ + fileStream: any; +} + +/** + * Request options + */ +export interface RequestOptions { + /** + * URL to make the request to + */ + url?: string; + + /** + * URI to make the request to (alias for url) + */ + uri?: string; + + /** + * Query string parameters + */ + qs?: Record; + + /** + * Whether to verify SSL certificates + */ + strictSSL?: boolean; + + /** + * Whether to decompress the response + */ + gzip?: boolean; + + /** + * Cookie jar + */ + jar?: any; + + /** + * Base URL + */ + baseUrl?: string; + + /** + * Request body + */ + body?: any; + + /** + * JSON body + */ + json?: boolean | any; + + /** + * Form data + */ + form?: Record & { + fileStream?: any; + fileField?: string; + }; + + /** + * Agent options + */ + agent?: { + https?: HttpsProxyAgent | HttpProxyAgent; + }; + + /** + * Any other options + */ + [key: string]: any; +} + +/** + * Callback function for HTTP requests + */ +export type RequestCallback = ( + error: Error | null, + response?: any, + body?: any +) => void; + +/** + * Request function + */ +export interface RequestFunction { + /** + * Make an HTTP request + * @param uri - URI to make the request to or options object + * @param options - Request options + * @param callback - Callback function + * @param config - Countly configuration + */ + ( + uri: string | RequestOptions, + options?: RequestOptions | RequestCallback, + callback?: RequestCallback, + config?: CountlyConfig + ): void; + + /** + * Make a GET request + * @param uri - URI to make the request to or options object + * @param options - Request options + * @param callback - Callback function + * @param config - Countly configuration + */ + get( + uri: string | RequestOptions, + options?: RequestOptions | RequestCallback, + callback?: RequestCallback, + config?: CountlyConfig + ): void; + + /** + * Make a POST request + * @param uri - URI to make the request to or options object + * @param options - Request options + * @param callback - Callback function + * @param config - Countly configuration + */ + post( + uri: string | RequestOptions, + options?: RequestOptions | RequestCallback, + callback?: RequestCallback, + config?: CountlyConfig + ): void; + + /** + * Convert request options to got options + * @param options - Request options + * @returns Got options + */ + convertOptionsToGot(options: RequestOptions): Record | null; +} + +/** + * Convert request options to got options + * @param options - Request options + * @returns Got options + */ +export function convertOptionsToGot( + options: RequestOptions +): Record | null; + +/** + * Factory function to initialize with config + * @param countlyConfig - Countly configuration + * @returns Request function + */ +declare function requestFactory(countlyConfig?: CountlyConfig): RequestFunction; + +export = requestFactory; diff --git a/api/utils/countly-root/index.d.ts b/api/utils/countly-root/index.d.ts new file mode 100644 index 00000000000..cedf222bb29 --- /dev/null +++ b/api/utils/countly-root/index.d.ts @@ -0,0 +1,10 @@ +import * as path from "path"; + +/** + * Resolves the given relative path to absolute from Countly repository root path. + * @param relativePath The path relative to Countly root directory. + * @returns The absolute path resolved for the given relative path. + */ +declare function fromCountlyRoot(relativePath: string): string; + +export = fromCountlyRoot; diff --git a/api/utils/countlyFs.d.ts b/api/utils/countlyFs.d.ts new file mode 100644 index 00000000000..32ed76b4ecb --- /dev/null +++ b/api/utils/countlyFs.d.ts @@ -0,0 +1,259 @@ +import { Db, GridFSBucket, ObjectId } from "mongodb"; +import { Readable } from "stream"; + +/** + * Module to abstract storing files on hard drive or in a shared system between multiple countly instances, currently based on GridFS + * @module api/utils/countlyFs + */ +export interface CountlyFsOptions { + id?: string; + writeMode?: "overwrite" | "version"; + chunkSizeBytes?: number; + metadata?: any; + contentType?: string; + aliases?: string[]; + forceClean?: boolean; +} + +export interface CountlyFs { + gridfs: { + /** + * Generic save function for data in gridfs + * @param category - collection where to store data + * @param dest - filename + * @param readStream - stream where to get file content + * @param options - additional options for saving file + * @param options.id - custom id for the file + * @param callback - function called when we have result, providing error object as first param and id as second + */ + saveData( + category: string, + dest: string, + data: string, + options: CountlyFsOptions, + callback: (err: any, result: any) => void + ): void; + /** + * Generic save function for data in gridfs + * @param category - collection where to store data + * @param dest - filename + * @param readStream - stream where to get file content + * @param options - additional options for saving file + * @param options.id - custom id for the file + * @param callback - function called when we have result, providing error object as first param and id as second + */ + saveStream( + category: string, + dest: string, + readStream: Readable, + options: CountlyFsOptions, + callback: (err: any, result: any) => void + ): void; + /** + * Generic save function for data in gridfs + * @param category - collection where to store data + * @param dest - filename + * @param options - additional options for saving file + * @param options.id - custom id for the file + * @param callback - function called when we have result, providing error object as first param and stream as second + */ + getStream( + category: string, + dest: string, + options: CountlyFsOptions, + callback: (err: any, stream: Readable) => void + ): void; + /** + * Generic save function for data in gridfs + * @param category - collection where to store data + * @param id - file id + * @param callback - function called when we have result, providing error object as first param and stream as second + */ + getStreamById( + category: string, + id: string, + callback: (err: any, stream: Readable) => void + ): void; + /** + * Generic save function for data in gridfs + * @param category - collection where to store data + * @param dest - filename + * @param options - additional options for saving file + * @param options.id - custom id for the file + * @param callback - function called when we have result, providing error object as first param and size as second + */ + getSize( + category: string, + dest: string, + options: CountlyFsOptions, + callback: (err: any, size: number) => void + ): void; + /** + * Generic save function for data in gridfs + * @param category - collection where to store data + * @param id - file id + * @param callback - function called when we have result, providing error object as first param + */ + deleteFileById( + category: string, + id: string, + callback: (err: any) => void + ): void; + /** + * Generic save function for data in gridfs + * @param category - collection where to store data + * @param id - file id + * @param updateFields - fields to update + * @param callback - function called when updating was completed or errored, providing error object as first param and result as second + */ + updateFileById( + category: string, + id: string, + updateFields: any, + callback: (err: any, result: any) => void + ): void; + }; + /** + * Get file's id + * @param category - collection where to store data + * @param filename - filename + * @param callback - function called when we have result, providing error object as first param and id as second + */ + getId( + category: string, + filename: string, + callback: (err: any, id: string | false) => void + ): void; + /** + * Check if file exists + * @param category - collection where to store data + * @param dest - file's destination + * @param options - additional options for saving file + * @param options.id - custom id for the file + * @param callback - function called when we have result, providing error object as first param and boolean as second to indicate if file exists + */ + exists( + category: string, + dest: string, + options: CountlyFsOptions, + callback: (err: any, exists: boolean) => void + ): void; + /** + * Save file in shared system + * @param category - collection where to store data + * @param dest - file's destination + * @param source - source file + * @param options - additional options for saving file + * @param options.id - custom id for the file + * @param options.writeMode - write mode, by default errors on existing file, possible values "overwrite" deleting previous file, or "version", will not work with provided custom id + * @param options.chunkSizeBytes - Optional overwrite this bucket's chunkSizeBytes for this file + * @param options.metadata - Optional object to store in the file document's metadata field + * @param contentType - Optional string to store in the file document's contentType field + * @param aliases - Optional array of strings to store in the file document's aliases field + * @param callback - function called when saving was completed or errored, providing error object as first param + */ + saveFile( + category: string, + dest: string, + source: string, + options: CountlyFsOptions, + callback: (err: any) => void + ): void; + /** + * Save string data in shared system + * @param category - collection where to store data + * @param dest - file's destination + * @param data - data to save + * @param options - additional options for saving file + * @param options.id - custom id for the file + * @param options.writeMode - write mode, by default errors on existing file, possible values "overwrite" deleting previous file, or "version", will not work with provided custom id + * @param options.chunkSizeBytes - Optional overwrite this bucket's chunkSizeBytes for this file + * @param options.metadata - Optional object to store in the file document's metadata field + * @param contentType - Optional string to store in the file document's contentType field + * @param aliases - Optional array of strings to store in the file document's aliases field + * @param callback - function called when saving was completed or errored, providing error object as first param + */ + saveData( + category: string, + dest: string, + data: string, + options: CountlyFsOptions, + callback: (err: any) => void + ): void; + /** + * Save file from stream in shared system + * @param category - collection where to store data + * @param dest - file's destination + * @param readStream - stream where to get file content + * @param options - additional options for saving file + * @param options.id - custom id for the file + * @param options.writeMode - write mode, by default errors on existing file, possible values "overwrite" deleting previous file, or "version", will not work with provided custom id + * @param options.chunkSizeBytes - Optional overwrite this bucket's chunkSizeBytes for this file + * @param options.metadata - Optional object to store in the file document's metadata field + * @param contentType - Optional string to store in the file document's contentType field + * @param aliases - Optional array of strings to store in the file document's aliases field + * @param callback - function called when saving was completed or errored, providing error object as first param + */ + saveStream( + category: string, + dest: string, + readStream: Readable, + options: CountlyFsOptions, + callback: (err: any) => void + ): void; + /** + * Rename existing file + * @param category - collection where to store data + * @param dest - file's destination + * @param source - source file + * @param options - additional options for saving file + * @param options.id - custom id for the file + * @param callback - function called when renaming was completed or errored, providing error object as first param + */ + rename( + category: string, + dest: string, + source: string, + options: CountlyFsOptions, + callback: (err: any) => void + ): Promise; + /** + * Delete file from shared system + * @param category - collection where to store data + * @param dest - file's destination + * @param options - additional options for saving file + * @param options.id - custom id for the file + * @param callback - function called when deleting was completed or errored, providing error object as first param + */ + deleteFile( + category: string, + dest: string, + options: CountlyFsOptions, + callback: (err: any) => void + ): void; + /** + * Delete all files from collection/category + * @param category - collection of files to delete + * @param dest - directory destination + * @param callback - function called when deleting was completed or errored, providing error object as first param + */ + deleteAll( + category: string, + dest: string, + callback: (err: any) => void + ): Promise; + /** + * Force clean file if there were errors inserting or deleting previously + * @param category - collection where to store data + * @param filename - filename + * @param callback - function called when deleting was completed or errored, providing error object as first param + */ + clearFile( + category: string, + filename: string, + callback: (err: any) => void + ): void; +} + +declare const countlyFs: CountlyFs; +export default countlyFs; diff --git a/api/utils/localization.d.ts b/api/utils/localization.d.ts new file mode 100644 index 00000000000..8f643b6a2b3 --- /dev/null +++ b/api/utils/localization.d.ts @@ -0,0 +1,80 @@ +/** + * Module for server side localization. Uses minimized localization files at frontend/express/public/localization/min/ + * @module api/utils/localization + */ + +import * as fs from "fs"; +import * as path from "path"; +import { Logger } from "./log"; +import * as common from "./common"; + +/** + * Properties object containing localized strings + */ +export interface LocalizationProperties { + [key: string]: string; +} + +/** + * Localization module + */ +interface Locale { + /** + * Replaces placeholders in localized string with provided values + * @param value - localized value with placeholders to be replaced + * @param var_args - other arguments to be inserted in localized string's placeholder places {} + * @returns localized string with placeholders replaced by provided var_args values + * @example + * localize.getProperties(member.lang, function(err, properties){ + * var message = localize.format(properties["mail.new-member"], mail.getUserFirstName(member), host, member.username, memberPassword); + * mail.sendMessage(member.email, properties["mail.new-member-subject"], message); + * }); + */ + format(value: string, ...args: any[]): string; + + /** + * Replaces placeholders in localized string with provided values (array version) + * @param value - localized value with placeholders to be replaced + * @param args - array of arguments to be inserted in localized string's placeholder places {} + * @returns localized string with placeholders replaced by provided args values + */ + format(value: string, args: any[]): string; + + /** + * Fetches single localized string by property name for provided language + * @param lang - 2 symbol code for localization file to be fetched, for example, "en" + * @param name - name of the localized property to fetch + * @param callback - function to be called when localized property files was fetched, receiving first param as error and second as localized string + * @example + * localize.getProperty(member.lang, "mail.new-member-subject", function(err, subject){ + * mail.sendMessage(member.email, subject); + * }); + */ + getProperty( + lang: string, + name: string, + callback: (err: Error | null, value: string) => void + ): void; + + /** + * Fetches whole localized object with property names as key and localized strings as values for provided language + * @param lang - 2 symbol code for localization file to be fetched, for example, "en" + * @param callback - function to be called when localized property files was fetched, receiving first param as error and second as properties object + * @example + * localize.getProperties(member.lang, function(err, properties){ + * var message = localize.format(properties["mail.new-member"], mail.getUserFirstName(member), host, member.username, memberPassword); + * mail.sendMessage(member.email, properties["mail.new-member-subject"], message); + * }); + */ + getProperties( + lang: string, + callback: (err: Error | null, properties: LocalizationProperties) => void + ): void; +} + +/** + * Localization module instance + */ +declare const locale: Locale; + +export = locale; diff --git a/api/utils/log.d.ts b/api/utils/log.d.ts new file mode 100644 index 00000000000..80a1d89c438 --- /dev/null +++ b/api/utils/log.d.ts @@ -0,0 +1,19 @@ +export interface Logger { + id(): string; + d(...args: any[]): void; + i(...args: any[]): void; + w(...args: any[]): void; + e(...args: any[]): void; + f( + l: string, + fn: (log: (...args: any[]) => void) => void, + fl?: string, + ...fargs: any[] + ): boolean; + callback(next?: Function): Function; + logdb(opname: string, next?: Function, nextError?: Function): Function; + sub(subname: string): Logger; +} + +declare function createLogger(name: string): Logger; +export default createLogger; diff --git a/api/utils/models.d.ts b/api/utils/models.d.ts new file mode 100644 index 00000000000..7834ad3ee39 --- /dev/null +++ b/api/utils/models.d.ts @@ -0,0 +1,269 @@ +import { ObjectId } from "mongodb"; +import { ValidateArgsProperties, ValidateArgsReturn } from "./common"; + +/** + * Base class for data classes for json getter + * + * @see push/api/data/* for examples + */ +export class Jsonable { + /** + * Internal data storage + */ + protected _data: Record; + + /** + * Constructor + * + * @param data data object + */ + constructor(data?: Record); + + /** + * Set data doing any decoding / transformations along the way + * + * @param data data to set + */ + setData(data: Record): void; + + /** + * Update internal data doing any decoding / transformations along the way + * + * @param update data update + */ + updateData(update: Record): void; + + /** + * Get new object containing all fields ready for sending to client side + */ + get json(): Record; + + /** + * Compatibility layer for cache & standard node.js functions IPC + * + * @returns json string + */ + toJSON(): Record; +} + +/** + * Validation class + * + * @see push/api/data/* for examples + */ +export class Validatable extends Jsonable { + /** + * Class scheme + */ + static get scheme(): Record; + + /** + * Class schema per given data, allows schema variativity for given data (validates according to subclasses schemas using a discriminator field) + * @see push/api/data/trigger.js + * + * @returns class schema by default + */ + static discriminator( + data?: Record + ): Record; + + /** + * Override Jsonable logic allowing only valid data to be saved + */ + get json(): Record; + + /** + * Validate data + * + * @param data data to validate + * @param scheme optional scheme override + * @returns common.validateArgs object with replaced by class instance: {errors: [], result: true, obj: Validatable} + */ + static validate( + data: Record, + scheme?: Record + ): ValidateArgsReturn; + + /** + * Validate data + * + * @returns array of string errors or undefined if validation passed + */ + validate(): string[] | undefined; +} + +/** + * Batch insert interface for MongoDB operations + */ +export interface BatchInsert { + /** + * Get current batch buffer length + */ + readonly length: number; + + /** + * Get current batch total count + */ + readonly total: number; + + /** + * Async push, that is if we're ok with a promise per insert + * + * @param record document to insert + */ + pushAsync(record: Record): Promise; + + /** + * Sync push, that is if we're NOT ok with a promise per insert + * + * @param record document to insert + * @returns true if buffer needs to be flush()ed + */ + pushSync(record: Record): boolean; + + /** + * Flush the buffer by inserting documents into collection + * + * @param ignore_codes error codes to ignore + */ + flush(ignore_codes?: number[]): Promise>; +} + +/** + * Base class for MongoDB-backed instances + * + * @see push/api/data/* for examples + */ +export class Mongoable extends Validatable { + /** + * Must be overridden in subclasses to return collection name + */ + static get collection(): string; + + /** + * Getter for id as a string + */ + get id(): string | undefined; + + /** + * Getter for id as is + */ + get _id(): ObjectId | undefined; + + /** + * Setter for _id + * + * @param id ObjectID value + */ + set _id(id: ObjectId | null | undefined); + + /** + * Find a record in db and map it to instance of this class + * + * @param query query for findOne + * @returns instance of this class if the record is found in database, null otherwise + */ + static findOne( + this: new (...args: any[]) => T, + query: Record | string | ObjectId + ): Promise; + + /** + * Refresh current instance with data from the database + * + * @returns this instance of this class if the record is found in database, false otherwise + */ + refresh(): Promise; + + /** + * Find multiple records in db and map them to instances of this class + * + * @param query query for find + * @returns array of instances of this class if the records are found in the database, empty array otherwise + */ + static findMany( + this: new (...args: any[]) => T, + query: Record + ): Promise; + + /** + * Count records in collection + * + * @param query query for count + * @returns count of records in collection satisfying the query + */ + static count(query: Record): Promise; + + /** + * Delete record from collection + * + * @param query query for count + * @returns count of records in collection satisfying the query + */ + static deleteOne(query: Record): Promise; + + /** + * Pass current data to mongo's save + */ + save(): Promise; + + /** + * Run an update operation modifying this's _data + * + * @param update query for an update + * @param op op to run to modify state of this in case of success + */ + update( + update: Record, + op: (instance: T) => any + ): Promise; + + /** + * Run an atomic update operation against `filter` with modifications in `update`, updating instance data with latest version in case of success + * + * @param filter filter for an update + * @param update modify for a findAndModify + * @returns true in case of success, false otherwise + */ + static findOneAndUpdate( + this: new (...args: any[]) => T, + filter: Record, + update: Record + ): Promise; + + /** + * Run an atomic update operation against `filter` with modifications in `update`, updating instance data with latest version in case of success + * + * @param filter filter for an update + * @param update modify for a findAndModify + * @returns true in case of success, false otherwise + */ + updateAtomically( + filter: Record, + update: Record + ): Promise; + + /** + * Simple batch insert object: + * + * let batch = Model.batchInsert(3); + * await batch.pushAsync({a: 1}); + * await batch.pushAsync({a: 2}); + * await batch.pushAsync({a: 3}); // <- insertMany here + * await batch.pushAsync({a: 4}); + * ... + * await batch.flush(); // flush the rest + * + * --- or --- + * + * for (let n of [1, 2, 3]) { + * if (batch.pushSync({a: 1})) { + * await batch.flush(); + * } + * } + * + * @param batch batch size + * @returns with 2 async methods: push(record) and flush() + */ + static batchInsert(batch?: number): BatchInsert; +} diff --git a/api/utils/pdf.d.ts b/api/utils/pdf.d.ts new file mode 100644 index 00000000000..234075064ff --- /dev/null +++ b/api/utils/pdf.d.ts @@ -0,0 +1,115 @@ +/** + * Module for pdf export + * @module api/utils/pdf + */ + +import { Logger } from "./log"; +import * as puppeteer from "puppeteer"; + +/** + * PDF generation options for Puppeteer + */ +export interface PDFOptions { + /** + * Scale of the webpage rendering. Defaults to 1. Scale amount must be between 0.1 and 2. + */ + scale?: number; + /** + * Display header and footer. Defaults to false. + */ + displayHeaderFooter?: boolean; + /** + * HTML template for the print header. Should be valid HTML markup with following classes used to inject printing values into them: + * - date: formatted print date + * - title: document title + * - url: document location + * - pageNumber: current page number + * - totalPages: total pages in the document + */ + headerTemplate?: string; + /** + * HTML template for the print footer. Should use the same format as the headerTemplate. + */ + footerTemplate?: string; + /** + * Print background graphics. Defaults to false. + */ + printBackground?: boolean; + /** + * Paper orientation. Defaults to false. + */ + landscape?: boolean; + /** + * Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means print all pages. + */ + pageRanges?: string; + /** + * Paper format. If set, takes priority over width or height options. Defaults to 'Letter'. + */ + format?: + | "Letter" + | "Legal" + | "Tabloid" + | "Ledger" + | "A0" + | "A1" + | "A2" + | "A3" + | "A4" + | "A5" + | "A6"; + /** + * Paper width, accepts values labeled with units. + */ + width?: string | number; + /** + * Paper height, accepts values labeled with units. + */ + height?: string | number; + /** + * Paper margins, defaults to none. + */ + margin?: { + /** + * Top margin, accepts values labeled with units. + */ + top?: string | number; + /** + * Right margin, accepts values labeled with units. + */ + right?: string | number; + /** + * Bottom margin, accepts values labeled with units. + */ + bottom?: string | number; + /** + * Left margin, accepts values labeled with units. + */ + left?: string | number; + }; + /** + * Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means print all pages. + */ + preferCSSPageSize?: boolean; + /** + * Give any CSS @page size declared in the page priority over what is declared in width and height or format options. + * Defaults to false, which will scale the content to fit the paper size. + */ + path?: string; +} + +/** + * Function to generate pdf from html + * @param html - html text to be converted to html + * @param callback - callback function after pdf is generated + * @param options - pdf options, default null + * @param puppeteerArgs - pupeteer arguments, default null + * @param remoteContent - if it is set base64 string of html content buffer is set as pdf content, default true + */ +export function renderPDF( + html: string, + callback: (buffer: Buffer) => void, + options?: PDFOptions | null, + puppeteerArgs?: puppeteer.LaunchOptions | null, + remoteContent?: boolean +): Promise; diff --git a/api/utils/random-sfc32.d.ts b/api/utils/random-sfc32.d.ts new file mode 100644 index 00000000000..c57e7263a53 --- /dev/null +++ b/api/utils/random-sfc32.d.ts @@ -0,0 +1,25 @@ +/** + * Module for 32-bit Random Number Generation between [0, 1) + * @module api/utils/random-sfc32 + */ + +import * as crypto from "crypto"; + +/** + * Random number generator function that returns a number between 0 and 1 + */ +export type RandomNumberGenerator = () => number; + +/** + * Seed scramble function used internally + */ +export type SeedScrambleFunction = () => number; + +/** + * Function that returns random number generator + * @param key - Seed value for the RNG. If not provided, a random key will be generated using crypto.randomBytes + * @returns Returns prng instance that generates random numbers between 0 and 1 + */ +declare function random(key?: string): RandomNumberGenerator; + +export = random; diff --git a/api/utils/render.d.ts b/api/utils/render.d.ts new file mode 100644 index 00000000000..905416441c8 --- /dev/null +++ b/api/utils/render.d.ts @@ -0,0 +1,124 @@ +/** + * Module rendering views as images + * @module api/utils/render + */ + +import * as puppeteer from "puppeteer"; +import { Logger } from "./log"; +import * as countlyFs from "./countlyFs"; + +/** + * Dimensions for the screenshot + */ +export interface RenderDimensions { + /** + * The width of the screenshot + */ + width?: number; + + /** + * The height of the screenshot + */ + height?: number; + + /** + * The padding value to subtract from the height of the screenshot + */ + padding?: number; + + /** + * The scale(ppi) value of the screenshot + */ + scale?: number; +} + +/** + * Options for rendering a view + */ +export interface RenderViewOptions { + /** + * The hostname + */ + host?: string; + + /** + * The login token value + */ + token: string; + + /** + * The view to open + */ + view: string; + + /** + * The id of the block to capture screenshot of + */ + id?: string; + + /** + * Path where to save the screenshot + */ + savePath?: string; + + /** + * Function called after opening the view + */ + cbFn?: (options: RenderViewOptions) => void; + + /** + * Function called just before capturing the screenshot + */ + beforeScrnCbFn?: (options: RenderViewOptions) => void; + + /** + * The dimensions of the screenshot + */ + dimensions?: RenderDimensions; + + /** + * Source identifier for the screenshot + */ + source?: string; + + /** + * Timeout in milliseconds + */ + timeout?: number; + + /** + * Regular expression to wait for in response URLs + */ + waitForRegex?: RegExp; + + /** + * Whether to wait for regex after callback function + */ + waitForRegexAfterCbfn?: boolean; +} + +/** + * Image data returned after rendering + */ +export interface ImageData { + /** + * The image buffer + */ + image: Buffer; + + /** + * The path where the image was saved + */ + path: string; +} + +/** + * Function to render views as images + * @param options - options required for rendering + * @param cb - callback function called with the error value or the image data + * @return void + */ +export function renderView( + options: RenderViewOptions, + cb: (error: Error | null, imageData?: ImageData) => void +): void; diff --git a/api/utils/requestProcessor.d.ts b/api/utils/requestProcessor.d.ts new file mode 100644 index 00000000000..a08aa76f428 --- /dev/null +++ b/api/utils/requestProcessor.d.ts @@ -0,0 +1,831 @@ +import { Params } from "./common"; +import { ObjectId } from "mongodb"; +import { Logger } from "./log"; +import { IncomingMessage, ServerResponse } from "http"; +import { Moment } from "moment"; +import { pluginManager } from "../../plugins/pluginManager"; + +/** + * Callback for API responses + * @callback APICallback + * @param {Error|null} err - Error object if there was an error, null otherwise + * @param {any} data - Response data + * @param {Record} headers - Response headers + * @param {number} returnCode - HTTP status code + * @param {Params} params - Request parameters + */ +export type APICallback = ( + err: Error | null, + data: any, + headers: Record, + returnCode: number, + params: RequestParams +) => void; + +/** + * Interface for the Countly API structure + */ +export interface CountlyApi { + /** Data-related API endpoints */ + data: { + /** Usage-related endpoints */ + usage: { + /** + * Processes a write API request + * @param params - Request parameters + */ + processRequest: (params: Params) => void; + }; + /** Data fetching endpoints */ + fetch: { + /** + * Fetches data based on request parameters + * @param params - Request parameters + */ + fetchData: (params: Params) => void; + /** + * Fetches time data + * @param params - Request parameters + */ + fetchTimeData: (params: Params) => void; + /** + * Fetches collection data + * @param params - Request parameters + */ + fetchCollection: (params: Params) => void; + }; + /** Event-related endpoints */ + events: { + /** + * Fetches events + * @param params - Request parameters + */ + fetchEvents: (params: Params) => void; + /** + * Fetches event overview + * @param params - Request parameters + */ + fetchOverview: (params: Params) => void; + /** + * Fetches event details + * @param params - Request parameters + */ + fetchEventDetails: (params: Params) => void; + }; + /** Export-related endpoints */ + exports: { + /** + * Exports data + * @param params - Request parameters + */ + exportData: (params: Params) => void; + }; + /** Geo data-related endpoints */ + geoData: { + /** + * Fetches geo data + * @param params - Request parameters + */ + fetchGeoData: (params: Params) => void; + }; + }; + /** Management-related API endpoints */ + mgmt: { + /** User management endpoints */ + users: { + /** + * Creates a new user + * @param params - Request parameters + */ + createUser: (params: Params) => void; + /** + * Updates an existing user + * @param params - Request parameters + */ + updateUser: (params: Params) => void; + /** + * Deletes a user + * @param params - Request parameters + */ + deleteUser: (params: Params) => void; + /** + * Deletes the user's own account + * @param params - Request parameters + */ + deleteOwnAccount: (params: Params) => void; + /** + * Updates home settings for a user + * @param params - Request parameters + */ + updateHomeSettings: (params: Params) => void; + /** + * Acknowledges a notification + * @param params - Request parameters + */ + ackNotification: (params: Params) => void; + /** + * Saves a note + * @param params - Request parameters + */ + saveNote: (params: Params) => void; + /** + * Deletes a note + * @param params - Request parameters + */ + deleteNote: (params: Params) => void; + }; + /** App management endpoints */ + apps: { + /** + * Creates a new app + * @param params - Request parameters + */ + createApp: (params: Params) => void; + /** + * Updates an existing app + * @param params - Request parameters + */ + updateApp: (params: Params) => void; + /** + * Deletes an app + * @param params - Request parameters + */ + deleteApp: (params: Params) => void; + /** + * Resets an app + * @param params - Request parameters + */ + resetApp: (params: Params) => void; + }; + /** App user management endpoints */ + appUsers: { + /** + * Creates a new app user + * @param appId - App ID + * @param data - User data + * @param params - Request parameters + * @param callback - Callback function + */ + create: ( + appId: string, + data: Record, + params: Params, + callback: (err: Error | string | null, result?: any) => void + ) => void; + }; + /** Event group management endpoints */ + eventGroups: { + /** + * Creates a new event group + * @param params - Request parameters + */ + createEventGroup: (params: Params) => void; + /** + * Updates an existing event group + * @param params - Request parameters + */ + updateEventGroup: (params: Params) => void; + /** + * Deletes an event group + * @param params - Request parameters + */ + deleteEventGroup: (params: Params) => void; + }; + /** CMS management endpoints */ + cms: { + /** + * Creates a new CMS entry + * @param params - Request parameters + */ + createCMS: (params: Params) => void; + /** + * Updates an existing CMS entry + * @param params - Request parameters + */ + updateCMS: (params: Params) => void; + /** + * Deletes a CMS entry + * @param params - Request parameters + */ + deleteCMS: (params: Params) => void; + }; + /** Date preset management endpoints */ + datePresets: { + /** + * Creates a new date preset + * @param params - Request parameters + */ + createDatePreset: (params: Params) => void; + /** + * Updates an existing date preset + * @param params - Request parameters + */ + updateDatePreset: (params: Params) => void; + /** + * Deletes a date preset + * @param params - Request parameters + */ + deleteDatePreset: (params: Params) => void; + }; + }; +} + +/** + * Options for DataTable + */ +export interface Options { + /** Order of columns */ + columnOrder?: string[]; + /** Default sorting configuration */ + defaultSorting?: Record; + /** Fields that can be searched */ + searchableFields?: string[]; + /** Search strategy to use */ + searchStrategy?: "regex" | "hard"; + /** Projection for output */ + outputProjection?: Record; + /** Default output format */ + defaultOutputFormat?: "full" | "rows"; + /** Unique key for the data */ + uniqueKey?: string; + /** Whether to disable unique sorting */ + disableUniqueSorting?: boolean; +} + +/** + * DataTable class for handling tabular data + */ +export class DataTable { + /** + * Creates a new DataTable instance + * @param queryString - Query string parameters + * @param options - DataTable options + */ + constructor(queryString: Record, options?: Options); + + /** + * Gets the aggregation pipeline for MongoDB + * @param options - Pipeline options + * @returns MongoDB aggregation pipeline + */ + getAggregationPipeline(options?: { + /** Initial pipeline stages */ + initialPipeline?: Record[]; + /** Filtered pipeline stages */ + filteredPipeline?: Record[]; + /** Custom facets */ + customFacets?: Record; + }): Record[]; + + /** + * Processes the query result + * @param queryResult - Result from MongoDB query + * @param processFn - Function to process rows + * @returns Processed result + */ + getProcessedResult( + queryResult: any, + processFn?: (rows: any[]) => any + ): Record; + + /** + * Gets the search field + * @private + * @returns Search field configuration + */ + private _getSearchField(): Record; +} + +/** + * Extensions to MongoDB for Countly + */ +export interface CommonDbExt { + /** + * Creates a MongoDB ObjectID from a string + * @param id - ID string + * @returns MongoDB ObjectID + */ + ObjectID(id: string): ObjectId; + + /** MongoDB ObjectId constructor */ + ObjectId: typeof ObjectId; + + /** + * Checks if a value is a valid MongoDB ObjectID + * @param id - Value to check + * @returns Whether the value is a valid ObjectID + */ + isoid(id: any): boolean; + + /** + * Converts a value to a MongoDB ObjectID if possible + * @param id - Value to convert + * @returns MongoDB ObjectID or the original value + */ + oid( + id: string | ObjectId | null | undefined + ): ObjectId | string | null | undefined; + + /** + * Creates a MongoDB ObjectID with a specific date + * @param date - Date to use + * @returns MongoDB ObjectID + */ + oidWithDate(date?: Date | number): ObjectId; + + /** + * Creates a MongoDB ObjectID with a specific date and blank identifier + * @param date - Date to use + * @returns MongoDB ObjectID + */ + oidBlankWithDate(date?: Date | number): ObjectId; +} + +/** + * Function to process a request + */ +export interface ProcessRequest { + /** + * Processes a request + * @param params - Request parameters + */ + (params: RequestParams): void; +} + +/** + * Function to validate an app for write API + */ +export interface ValidateAppForWriteAPI { + /** + * Validates an app for write API + * @param params - Request parameters + * @param done - Callback function + * @param try_times - Number of retry attempts + */ + (params: RequestParams, done: () => void, try_times?: number): void; +} + +/** + * Function to restart a request + */ +export interface RestartRequest { + /** + * Restarts a request + * @param params - Request parameters + * @param initiator - Validation function + * @param done - Callback function + * @param try_times - Number of retry attempts + * @param fail - Failure callback + */ + ( + params: RequestParams, + initiator: ValidateAppForWriteAPI, + done: () => void, + try_times: number, + fail: (reason: string) => void + ): void; +} + +/** + * Function to process a user + */ +export interface ProcessUser { + /** + * Processes a user + * @param params - Request parameters + * @param initiator - Validation function + * @param done - Callback function + * @param try_times - Number of retry attempts + * @returns Promise + */ + ( + params: RequestParams, + initiator: ValidateAppForWriteAPI, + done: () => void, + try_times: number + ): Promise; +} + +/** + * Function to validate an app for fetch API + */ +export interface ValidateAppForFetchAPI { + /** + * Validates an app for fetch API + * @param params - Request parameters + * @param done - Callback function + * @param try_times - Number of retry attempts + */ + (params: RequestParams, done: () => void, try_times?: number): void; +} + +/** + * Function to process a bulk request + */ +export interface ProcessBulkRequest { + /** + * Processes a bulk request + * @param i - Current request index + * @param requests - Array of requests + * @param params - Request parameters + */ + (i: number, requests: any[], params: RequestParams): void; +} + +/** + * Function to process request data + */ +export interface ProcessRequestData { + /** + * Processes request data + * @param params - Request parameters + * @param app - App object + * @param done - Callback function + */ + (params: RequestParams, app: Record, done: () => void): void; +} + +/** + * Function to process a fetch request + */ +export interface ProcessFetchRequest { + /** + * Processes a fetch request + * @param params - Request parameters + * @param app - App object + * @param done - Callback function + */ + (params: RequestParams, app: Record, done: () => void): void; +} + +/** + * Function to verify checksum salt + */ +export interface ChecksumSaltVerification { + /** + * Verifies checksum salt + * @param params - Request parameters + * @returns Whether verification passed + */ + (params: RequestParams): boolean; +} + +/** + * Function to validate redirect + */ +export interface ValidateRedirect { + /** + * Validates a redirect + * @param ob - Object to validate + * @returns Validation result + */ + (ob: Record): boolean; +} + +/** + * Function to fetch an app user + */ +export interface FetchAppUser { + /** + * Fetches an app user + * @param params - Request parameters + * @returns Promise + */ + (params: RequestParams): Promise; +} + +/** + * Function to ignore possible devices + */ +export interface IgnorePossibleDevices { + /** + * Ignores possible devices + * @param params - Request parameters + * @returns Whether devices should be ignored + */ + (params: RequestParams): boolean; +} + +/** + * Function to reload configuration + */ +export interface ReloadConfig { + /** + * Reloads configuration + * @returns Promise + */ + (): Promise; +} + +/** Process request function */ + +/** + * Time object for request processing + */ +export interface TimeObject { + /** momentjs instance for request's time in app's timezone */ + now: Moment; + /** momentjs instance for request's time in UTC */ + nowUTC: Moment; + /** momentjs instance for current time in app's timezone */ + nowWithoutTimestamp: Moment; + /** request's seconds timestamp */ + timestamp: number; + /** Request timestamp in milliseconds */ + mstimestamp: number; + /** year of request time in app's timezone in YYYY format */ + yearly: string; + /** month of request time in app's timezone in YYYY.M format */ + monthly: string; + /** date of request time in app's timezone in YYYY.M.D format */ + daily: string; + /** hour of request time in app's timezone in YYYY.M.D.H format */ + hourly: string; + /** week of request time in app's timezone as result day of the year, divided by 7 */ + weekly: number; + /** Other time-related properties */ + [key: string]: any; +} + +/** + * Main request processing object containing all information shared through all the parts of the same request + */ +export interface RequestParams extends Params { + /** Full URL href */ + href: string; + /** The HTTP response object */ + res: ServerResponse; + /** The HTTP request object */ + req: IncomingMessage & { + /** Request body */ + body?: any; + /** Request URL */ + url?: string; + /** Request method */ + method?: string; + /** Request headers */ + headers?: Record; + /** Request socket */ + socket?: any; + /** Request connection */ + connection?: any; + }; + /** API output handler. Which should handle API response */ + APICallback?: APICallback; + /** All the passed fields either through query string in GET requests or body and query string for POST requests */ + qstring: Record; + /** Two top level url path, for example /i/analytics, first two segments from the fullPath */ + apiPath: string; + /** Full url path, for example /i/analytics/dashboards */ + fullPath: string; + /** Object with uploaded files, available in POST requests which upload files */ + files?: { + /** Uploaded app image file */ + app_image?: { + /** The temporary path of the uploaded app image file */ + path: string; + /** The original name of the uploaded app image file */ + name: string; + /** The MIME type of the uploaded app image file */ + type: string; + /** The size (in bytes) of the uploaded app image file */ + size: number; + }; + [key: string]: any; + }; + /** Used for skipping SDK requests, if contains true, then request should be ignored and not processed */ + cancelRequest?: string; + /** Flag to block responses from being sent */ + blockResponses?: boolean; + /** Flag to force processing request timeout */ + forceProcessingRequestTimeout?: boolean; + /** True if this SDK request is processed from the bulk method */ + bulk?: boolean; + /** Array of the promises by different events. When all promises are fulfilled, request counts as processed */ + promises?: Promise[]; + /** IP address of the device submitted request, exists in all SDK requests */ + ip_address?: string; + /** Data with some user info, like country geolocation, etc from the request, exists in all SDK requests */ + user: { + /** User's country */ + country?: string; + /** User's city */ + city?: string; + /** User's timezone offset (in minutes) */ + tz?: number; + [key: string]: any; + }; + /** Document from the app_users collection for current user, exists in all SDK requests after validation */ + app_user?: { + /** Application user ID */ + uid?: string; + /** Device ID */ + did?: string; + /** User's country */ + country?: string; + /** User's city */ + city?: string; + /** User's timezone offset (in minutes) */ + tz?: number; + /** Custom properties for the application user */ + custom?: Record; + /** Last session timestamp of the app user */ + ls?: any; + /** Flag indicating if the user has an ongoing session */ + has_ongoing_session?: boolean; + /** Timestamp of the user's last request */ + last_req?: number | string; + [key: string]: any; + }; + /** ID of app_users document for the user, exists in all SDK requests after validation */ + app_user_id?: string; + /** Document for the app sending request, exists in all SDK requests after validation */ + app?: Record; + /** ObjectID of the app document, available after validation */ + app_id?: string; + /** Selected app country, available after validation */ + app_cc?: string; + /** Name of the app */ + app_name?: string; + /** Selected app timezone, available after validation */ + appTimezone?: string; + /** Time object for the request */ + time: TimeObject; + /** Parsed URL parts */ + urlParts?: any; + /** The URL path split into segments */ + paths?: string[]; +} + +declare const processRequest: ProcessRequest; + +/** Process user function */ +declare const processUserFunction: ProcessUser; + +/** Process request data function */ +declare const processRequestData: ProcessRequestData; + +/** Process fetch request function */ +declare const processFetchRequest: ProcessFetchRequest; + +/** Process bulk request function */ +declare const processBulkRequest: ProcessBulkRequest; + +/** Checksum salt verification function */ +declare const checksumSaltVerification: ChecksumSaltVerification; + +/** Validate redirect function */ +declare const validateRedirect: ValidateRedirect; + +/** Validate app for write API function */ +declare const validateAppForWriteAPI: ValidateAppForWriteAPI; + +/** Validate app for fetch API function */ +declare const validateAppForFetchAPI: ValidateAppForFetchAPI; + +/** Restart request function */ +declare const restartRequest: RestartRequest; + +/** Fetch app user function */ +declare const fetchAppUser: FetchAppUser; + +/** Ignore possible devices function */ +declare const ignorePossibleDevices: IgnorePossibleDevices; + +/** Reload config function */ +declare const reloadConfig: ReloadConfig; + +/** Logger instance */ +declare const log: Logger; + +/** + * Function to validate user for write API + */ +export interface ValidateUserForWriteAPI { + /** + * Validates a user for write API + * @param params - Request parameters or callback function + * @param callback - Callback function (optional if params is a function) + */ + (params: RequestParams | Function, callback?: Function): void; +} + +/** + * Function to validate user for data read API + */ +export interface ValidateUserForDataReadAPI { + /** + * Validates a user for data read API + * @param params - Request parameters or callback function + * @param feature - Feature to validate for + * @param callback - Callback function (optional if params is a function) + */ + ( + params: RequestParams | Function, + feature: string, + callback?: Function + ): void; +} + +/** + * Function to validate user for data write API + */ +export interface ValidateUserForDataWriteAPI { + /** + * Validates a user for data write API + * @param params - Request parameters or callback function + * @param callback - Callback function (optional if params is a function) + */ + (params: RequestParams | Function, callback?: Function): void; +} + +/** + * Function to validate user for global admin + */ +export interface ValidateUserForGlobalAdmin { + /** + * Validates a user for global admin + * @param params - Request parameters or callback function + * @param callback - Callback function (optional if params is a function) + */ + (params: RequestParams | Function, callback?: Function): void; +} + +/** + * Function to validate user for management read API + */ +export interface ValidateUserForMgmtReadAPI { + /** + * Validates a user for management read API + * @param params - Request parameters or callback function + * @param callback - Callback function (optional if params is a function) + */ + (params: RequestParams | Function, callback?: Function): void; +} + +/** + * Function to load version marks from filesystem + */ +export interface LoadFsVersionMarks { + /** + * Loads version marks from filesystem + * @param callback - Callback function + */ + (callback: (err: Error | null, data: any[]) => void): void; +} + +/** + * Function to load version marks from database + */ +export interface LoadDbVersionMarks { + (callback: (err: Error | null, data: any[]) => void): void; +} + +/** Validate user for write API function */ +declare const validateUserForWriteAPI: ValidateUserForWriteAPI; + +/** Validate user for data read API function */ +declare const validateUserForDataReadAPI: ValidateUserForDataReadAPI; + +/** Validate user for data write API function */ +declare const validateUserForDataWriteAPI: ValidateUserForDataWriteAPI; + +/** Validate user for global admin function */ +declare const validateUserForGlobalAdmin: ValidateUserForGlobalAdmin; + +/** Validate user for management read API function */ +declare const validateUserForMgmtReadAPI: ValidateUserForMgmtReadAPI; + +/** Load filesystem version marks function */ +declare const loadFsVersionMarks: LoadFsVersionMarks; + +/** Load database version marks function */ +declare const loadDbVersionMarks: LoadDbVersionMarks; + +/** Countly API object */ +declare const countlyApi: CountlyApi; + +export { + processRequest, + processUserFunction as processUser, + processRequestData, + processFetchRequest, + processBulkRequest, + checksumSaltVerification, + validateRedirect, + validateAppForWriteAPI, + validateAppForFetchAPI, + restartRequest, + fetchAppUser, + ignorePossibleDevices, + reloadConfig, + loadFsVersionMarks, + loadDbVersionMarks, + validateUserForWriteAPI, + validateUserForDataReadAPI, + validateUserForDataWriteAPI, + validateUserForGlobalAdmin, + validateUserForMgmtReadAPI, + log, + countlyApi, +}; diff --git a/api/utils/rights.d.ts b/api/utils/rights.d.ts new file mode 100644 index 00000000000..dab7d737d5c --- /dev/null +++ b/api/utils/rights.d.ts @@ -0,0 +1,51 @@ +import { Params } from "./common"; +import { Db } from "mongodb"; + +export interface ValidateUserForRead { + (params: Params, callback: Function, callbackParam?: any): Promise; +} + +export interface ValidateGlobalAdmin { + (params: Params, callback: Function, callbackParam?: any): Promise; +} + +export interface ValidateAppAdmin { + (params: Params, callback: Function, callbackParam?: any): Promise; +} + +export interface ValidateUser { + (params: Params, callback: Function, callbackParam?: any): Promise; +} + +export declare const validateUserForRead: ValidateUserForRead; +export declare const validateUserForWrite: ValidateUserForRead; +export declare const validateGlobalAdmin: ValidateGlobalAdmin; +export declare const validateAppAdmin: ValidateAppAdmin; +export declare const validateUser: ValidateUser; +export declare function dbUserHasAccessToCollection( + params: Params, + collection: string, + callback: (hasAccess: boolean) => void +): void; +export declare function getBaseAppFilter( + member: any, + db: string, + collection: string +): any; +export declare function hasAdminAccess(member: any, appId: string): boolean; +export declare function getUserApps(member: any): string[]; +export declare function validateUpdate( + params: Params, + feature: string, + callback: () => void +): void; +export declare function validateDelete( + params: Params, + feature: string, + callback: () => void +): void; +export declare function validateCreate( + params: Params, + feature: string, + callback: () => void +): void; diff --git a/api/utils/taskmanager.d.ts b/api/utils/taskmanager.d.ts new file mode 100644 index 00000000000..b6bacaea024 --- /dev/null +++ b/api/utils/taskmanager.d.ts @@ -0,0 +1,93 @@ +import { Db } from "mongodb"; +import { Params } from "./common"; + +export interface TaskManagerOptions { + db: Db; + params: Params; + threshold: number; + force: boolean; + type: string; + meta: any; + name: string; + report_name: string; + report_desc: string; + period_desc: string; + view: string; + app_id: string; + processData: ( + err: any, + res: any, + callback: (err: any, res: any) => void + ) => void; + outputData: (err: any, data: any) => void; + creator?: string; + global?: boolean; + autoRefresh?: boolean; + r_hour?: number; + forceCreateTask?: boolean; + gridfs?: boolean; + binary?: boolean; + id?: string; + start?: number; + errored?: boolean; + errormsg?: any; + request?: any; + subtask?: string; + subtask_key?: string; + linked_to?: string; +} + +export interface TaskManager { + longtask(options: TaskManagerOptions): (err: any, res: any) => void; + getId(): string; + createTask( + options: TaskManagerOptions, + callback?: (err: any, result: any) => void + ): void; + saveResult( + options: TaskManagerOptions, + data: any, + callback?: (err: any, result: any) => void + ): void; + nameResult( + options: { db: Db; id: string; name: string }, + data: any, + callback?: (err: any, result: any) => void + ): void; + checkIfRunning( + options: { db: Db; params: Params }, + callback: (taskId: string) => void + ): void; + getResult( + options: { db: Db; id: string; subtask_key?: string }, + callback: (err: any, result: any) => void + ): void; + getResults( + options: { db: Db; query: any }, + callback: (err: any, result: any) => void + ): void; + getCounts( + options: { db: Db; query: any }, + callback: (err: any, result: any) => void + ): void; + editTask( + options: { db: Db; id: string; data: any }, + callback: (err: any, result: any) => void + ): void; + deleteResult( + options: { db: Db; id: string }, + callback: (err: any, task: any) => void + ): void; + getTableQueryResult( + options: { db: Db; query: any; page: any; sort: any; keyword: any }, + callback: (err: any, result: any) => void + ): void; + markReportsDirtyBasedOnRule( + options: { db: Db; rules: any }, + callback: () => void + ): void; +} + +declare const taskmanager: TaskManager; + +export default taskmanager; diff --git a/api/utils/timezones.d.ts b/api/utils/timezones.d.ts new file mode 100644 index 00000000000..d7a869b6257 --- /dev/null +++ b/api/utils/timezones.d.ts @@ -0,0 +1,45 @@ +/** + * Timezone information for a specific timezone in a country + */ +export interface TimezoneInfo { + /** + * Object with a single key-value pair where the key is the timezone display name (e.g., "(GMT+01:00) Andorra") + * and the value is the timezone identifier (e.g., "Europe/Andorra") + */ + [displayName: string]: string; +} + +/** + * Country timezone information + */ +export interface CountryTimezoneInfo { + /** + * Country name + */ + n: string; + + /** + * Array of timezone information for the country + */ + z: TimezoneInfo[]; +} + +/** + * Object containing timezone data organized by country code + */ +export interface TimeZones { + /** + * Country code as key (e.g., "US", "GB", "JP") with country timezone information as value + */ + [countryCode: string]: CountryTimezoneInfo; +} + +/** + * Object containing timezone data organized by country code + */ +export const getTimeZones: TimeZones; + +/** + * Array of valid timezone identifiers (e.g., "Europe/London", "America/New_York") + */ +export const timezoneValidation: string[]; diff --git a/api/utils/utils.d.ts b/api/utils/utils.d.ts new file mode 100644 index 00000000000..54046ab3d6b --- /dev/null +++ b/api/utils/utils.d.ts @@ -0,0 +1,64 @@ +/** + * Module for some common utility functions that needs to be separated from {@link module:api/utils/common} either due to circular references or other reasons + * @module api/utils/utils + */ + +import * as crypto from "crypto"; +import { countlyConfig } from "./../config"; + +/** + * Encrypt provided value + * @param {string} text - value to encrypt + * @param {string=} key - key used for encryption and decryption + * @param {string=} iv - initialization vector to make encryption more secure + * @param {string=} algorithm - name of the algorithm to use for encryption. The algorithm is dependent on OpenSSL, examples are 'aes192', etc. On recent OpenSSL releases, openssl list-cipher-algorithms will display the available cipher algorithms. Default value is aes-256-cbc + * @param {string=} input_encoding - how encryption input is encoded. Used as output for decrypting. Default utf-8. + * @param {string=} output_encoding - how encryption output is encoded. Used as input for decrypting. Default hex. + * @returns {string} encrypted value + */ +export function encrypt( + text: string, + key?: string, + iv?: Buffer, + algorithm?: string, + input_encoding?: BufferEncoding, + output_encoding?: crypto.BinaryToTextEncoding +): string; + +/** + * Decrypt provided value + * @param {string} crypted - value to decrypt + * @param {string=} key - key used for encryption and decryption + * @param {string=} iv - initialization vector used in encryption + * @param {string=} algorithm - name of the algorithm used in encryption. The algorithm is dependent on OpenSSL, examples are 'aes192', etc. On recent OpenSSL releases, openssl list-cipher-algorithms will display the available cipher algorithms. Default value is aes-256-cbc + * @param {string=} input_encoding - how decryption input is encoded. Default hex. + * @param {string=} output_encoding - how decryption output is encoded. Default utf-8. + * @returns {string} decrypted value + */ +export function decrypt( + crypted: string, + key?: string, + iv?: Buffer, + algorithm?: string, + input_encoding?: crypto.BinaryToTextEncoding, + output_encoding?: BufferEncoding +): string; + +/** + * Old deprecated decrypt function, needed for old stored values + * @param {string} crypted - value to decrypt + * @param {string=} key - key used for encryption and decryption + * @param {string=} iv - initialization vector used in encryption + * @param {string=} algorithm - name of the algorithm used in encryption. The algorithm is dependent on OpenSSL, examples are 'aes192', etc. On recent OpenSSL releases, openssl list-cipher-algorithms will display the available cipher algorithms. Default value is aes-256-cbc + * @param {string=} input_encoding - how decryption input is encoded. Default hex. + * @param {string=} output_encoding - how decryption output is encoded. Default utf-8. + * @returns {string} decrypted value + */ +export function decrypt_old( + crypted: string, + key?: string, + iv?: Buffer, + algorithm?: string, + input_encoding?: crypto.BinaryToTextEncoding, + output_encoding?: BufferEncoding +): string; diff --git a/frontend/express/version.info.d.ts b/frontend/express/version.info.d.ts new file mode 100644 index 00000000000..89fb50727f5 --- /dev/null +++ b/frontend/express/version.info.d.ts @@ -0,0 +1,7 @@ +declare module "core/frontend/express/version.info" { + const versionInfo: { + version: string; + type: string; + }; + export = versionInfo; +} diff --git a/lib/countly.common.d.ts b/lib/countly.common.d.ts new file mode 100644 index 00000000000..c851695e367 --- /dev/null +++ b/lib/countly.common.d.ts @@ -0,0 +1,3 @@ +export function getPeriodObj(params: any): void; +export function getTimestampRangeQuery(params: any, isStart: boolean): any; +export function formatNumber(x: number): string; diff --git a/plugins/pluginManager.d.ts b/plugins/pluginManager.d.ts new file mode 100644 index 00000000000..a6bd4e24277 --- /dev/null +++ b/plugins/pluginManager.d.ts @@ -0,0 +1,30 @@ +declare const pluginManager: { + init: () => void; + loadConfigs: (db: any, callback: () => void) => void; + setConfigs: ( + namespace: string, + conf: any, + exclude: boolean, + onchange: () => void + ) => void; + getConfig: (namespace: string, userSettings?: any, override?: boolean) => any; + getAllConfigs: () => any; + getUserConfigs: (userSettings?: any) => any; + dispatch: (event: string, data: any) => any; + getPlugins: () => string[]; + processPluginInstall: ( + db: any, + pluginName: string, + callback: () => void + ) => void; + connectToAllDatabases: () => Promise; + addCollectionToExpireList: (collection: string) => void; + getExpireList: () => string[]; + setUserConfigs: (namespace: string, conf: any) => void; + loadDependencyMap: () => void; + installMissingPlugins: (db: any, callback?: () => void) => void; + reloadEnabledPluginList: (db: any, callback?: () => void) => void; + fetchMaskingConf: (options: any) => void; +}; + +export = pluginManager;