@zoho_apptics/apptics-js-sdk 1.0.2 → 2.0.0-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/LICENSE +13 -0
- package/README.md +747 -11
- package/dist/apptics.esm.min.js +3 -0
- package/dist/apptics.esm.min.js.map +1 -0
- package/dist/apptics.min.js +3 -0
- package/dist/apptics.min.js.map +1 -0
- package/dist/chunks/batch-BU_mTpm1.min.js +3 -0
- package/dist/chunks/batch-BU_mTpm1.min.js.map +1 -0
- package/dist/chunks/logs-Bea5zUW_.min.js +3 -0
- package/dist/chunks/logs-Bea5zUW_.min.js.map +1 -0
- package/dist/cjs/auto-init.d.ts +8 -0
- package/dist/cjs/auto-init.js +32 -0
- package/dist/cjs/core/attempts.d.ts +28 -0
- package/dist/cjs/core/attempts.js +113 -0
- package/dist/cjs/core/batch.d.ts +32 -0
- package/dist/cjs/core/batch.js +115 -0
- package/dist/cjs/core/callsite.d.ts +28 -0
- package/dist/cjs/core/callsite.js +93 -0
- package/dist/cjs/core/consent.d.ts +23 -0
- package/dist/cjs/core/consent.js +130 -0
- package/dist/cjs/core/constants.d.ts +212 -0
- package/dist/cjs/core/constants.js +299 -0
- package/dist/cjs/core/db.d.ts +40 -0
- package/dist/cjs/core/db.js +334 -0
- package/dist/cjs/core/debug.d.ts +22 -0
- package/dist/cjs/core/debug.js +88 -0
- package/dist/cjs/core/env.d.ts +28 -0
- package/dist/cjs/core/env.js +267 -0
- package/dist/cjs/core/framework-id.d.ts +1 -0
- package/dist/cjs/core/framework-id.js +9 -0
- package/dist/cjs/core/guard.d.ts +2 -0
- package/dist/cjs/core/guard.js +72 -0
- package/dist/cjs/core/hooks.d.ts +41 -0
- package/dist/cjs/core/hooks.js +23 -0
- package/dist/cjs/core/logger.d.ts +16 -0
- package/dist/cjs/core/logger.js +86 -0
- package/dist/cjs/core/state.d.ts +69 -0
- package/dist/cjs/core/state.js +78 -0
- package/dist/cjs/core/storage.d.ts +46 -0
- package/dist/cjs/core/storage.js +229 -0
- package/dist/cjs/core/transport.d.ts +83 -0
- package/dist/cjs/core/transport.js +441 -0
- package/dist/cjs/core/utils.d.ts +26 -0
- package/dist/cjs/core/utils.js +175 -0
- package/dist/cjs/core/validate.d.ts +18 -0
- package/dist/cjs/core/validate.js +233 -0
- package/dist/cjs/device/appversion.d.ts +20 -0
- package/dist/cjs/device/appversion.js +158 -0
- package/dist/cjs/device/index.d.ts +23 -0
- package/dist/cjs/device/index.js +372 -0
- package/dist/cjs/engagement/api-rules.d.ts +84 -0
- package/dist/cjs/engagement/api-rules.js +219 -0
- package/dist/cjs/engagement/auto-api.d.ts +7 -0
- package/dist/cjs/engagement/auto-api.js +200 -0
- package/dist/cjs/engagement/auto-screen.d.ts +16 -0
- package/dist/cjs/engagement/auto-screen.js +241 -0
- package/dist/cjs/engagement/defined-events.d.ts +23 -0
- package/dist/cjs/engagement/defined-events.js +58 -0
- package/dist/cjs/engagement/send.d.ts +6 -0
- package/dist/cjs/engagement/send.js +99 -0
- package/dist/cjs/engagement/session.d.ts +42 -0
- package/dist/cjs/engagement/session.js +327 -0
- package/dist/cjs/engagement/track.d.ts +56 -0
- package/dist/cjs/engagement/track.js +350 -0
- package/dist/cjs/errors/send.d.ts +6 -0
- package/dist/cjs/errors/send.js +73 -0
- package/dist/cjs/errors/track.d.ts +4 -0
- package/dist/cjs/errors/track.js +127 -0
- package/dist/cjs/feedback/controls.d.ts +31 -0
- package/dist/cjs/feedback/controls.js +286 -0
- package/dist/cjs/feedback/index.d.ts +8 -0
- package/dist/cjs/feedback/index.js +37 -0
- package/dist/cjs/feedback/logs.d.ts +40 -0
- package/dist/cjs/feedback/logs.js +202 -0
- package/dist/cjs/feedback/send.d.ts +25 -0
- package/dist/cjs/feedback/send.js +178 -0
- package/dist/cjs/feedback/template.d.ts +2 -0
- package/dist/cjs/feedback/template.js +162 -0
- package/dist/cjs/feedback/ui.d.ts +55 -0
- package/dist/cjs/feedback/ui.js +631 -0
- package/dist/cjs/heatmap/index.d.ts +16 -0
- package/dist/cjs/heatmap/index.js +22 -0
- package/dist/cjs/heatmap/send.d.ts +13 -0
- package/dist/cjs/heatmap/send.js +82 -0
- package/dist/cjs/heatmap/track.d.ts +4 -0
- package/dist/cjs/heatmap/track.js +377 -0
- package/dist/cjs/index.d.ts +68 -0
- package/dist/cjs/index.js +150 -0
- package/dist/cjs/lifecycle.d.ts +14 -0
- package/dist/cjs/lifecycle.js +538 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/remoteconfig/custom.d.ts +10 -0
- package/dist/cjs/remoteconfig/custom.js +78 -0
- package/dist/cjs/remoteconfig/evaluate.d.ts +24 -0
- package/dist/cjs/remoteconfig/evaluate.js +171 -0
- package/dist/cjs/remoteconfig/fetch.d.ts +24 -0
- package/dist/cjs/remoteconfig/fetch.js +214 -0
- package/dist/cjs/remoteconfig/index.d.ts +13 -0
- package/dist/cjs/remoteconfig/index.js +90 -0
- package/dist/cjs/remoteconfig/store.d.ts +18 -0
- package/dist/cjs/remoteconfig/store.js +98 -0
- package/dist/cjs/remotelog/gate.d.ts +11 -0
- package/dist/cjs/remotelog/gate.js +54 -0
- package/dist/cjs/remotelog/index.d.ts +25 -0
- package/dist/cjs/remotelog/index.js +55 -0
- package/dist/cjs/remotelog/logger.d.ts +28 -0
- package/dist/cjs/remotelog/logger.js +139 -0
- package/dist/cjs/remotelog/send.d.ts +13 -0
- package/dist/cjs/remotelog/send.js +153 -0
- package/dist/cjs/scheduler.d.ts +8 -0
- package/dist/cjs/scheduler.js +78 -0
- package/dist/cjs/types.d.ts +312 -0
- package/dist/cjs/user/index.d.ts +33 -0
- package/dist/cjs/user/index.js +178 -0
- package/dist/esm/auto-init.d.ts +8 -0
- package/dist/esm/auto-init.js +29 -0
- package/dist/esm/core/attempts.d.ts +28 -0
- package/dist/esm/core/attempts.js +106 -0
- package/dist/esm/core/batch.d.ts +32 -0
- package/dist/esm/core/batch.js +108 -0
- package/dist/esm/core/callsite.d.ts +28 -0
- package/dist/esm/core/callsite.js +89 -0
- package/dist/esm/core/consent.d.ts +23 -0
- package/dist/esm/core/consent.js +120 -0
- package/dist/esm/core/constants.d.ts +212 -0
- package/dist/esm/core/constants.js +277 -0
- package/dist/esm/core/db.d.ts +40 -0
- package/dist/esm/core/db.js +324 -0
- package/dist/esm/core/debug.d.ts +22 -0
- package/dist/esm/core/debug.js +81 -0
- package/dist/esm/core/env.d.ts +28 -0
- package/dist/esm/core/env.js +251 -0
- package/dist/esm/core/framework-id.d.ts +1 -0
- package/dist/esm/core/framework-id.js +7 -0
- package/dist/esm/core/guard.d.ts +2 -0
- package/dist/esm/core/guard.js +70 -0
- package/dist/esm/core/hooks.d.ts +41 -0
- package/dist/esm/core/hooks.js +21 -0
- package/dist/esm/core/logger.d.ts +16 -0
- package/dist/esm/core/logger.js +82 -0
- package/dist/esm/core/state.d.ts +69 -0
- package/dist/esm/core/state.js +73 -0
- package/dist/esm/core/storage.d.ts +46 -0
- package/dist/esm/core/storage.js +219 -0
- package/dist/esm/core/transport.d.ts +83 -0
- package/dist/esm/core/transport.js +425 -0
- package/dist/esm/core/utils.d.ts +26 -0
- package/dist/esm/core/utils.js +161 -0
- package/dist/esm/core/validate.d.ts +18 -0
- package/dist/esm/core/validate.js +226 -0
- package/dist/esm/device/appversion.d.ts +20 -0
- package/dist/esm/device/appversion.js +153 -0
- package/dist/esm/device/index.d.ts +23 -0
- package/dist/esm/device/index.js +362 -0
- package/dist/esm/engagement/api-rules.d.ts +84 -0
- package/dist/esm/engagement/api-rules.js +211 -0
- package/dist/esm/engagement/auto-api.d.ts +7 -0
- package/dist/esm/engagement/auto-api.js +198 -0
- package/dist/esm/engagement/auto-screen.d.ts +16 -0
- package/dist/esm/engagement/auto-screen.js +238 -0
- package/dist/esm/engagement/defined-events.d.ts +23 -0
- package/dist/esm/engagement/defined-events.js +55 -0
- package/dist/esm/engagement/send.d.ts +6 -0
- package/dist/esm/engagement/send.js +96 -0
- package/dist/esm/engagement/session.d.ts +42 -0
- package/dist/esm/engagement/session.js +315 -0
- package/dist/esm/engagement/track.d.ts +56 -0
- package/dist/esm/engagement/track.js +340 -0
- package/dist/esm/errors/send.d.ts +6 -0
- package/dist/esm/errors/send.js +70 -0
- package/dist/esm/errors/track.d.ts +4 -0
- package/dist/esm/errors/track.js +123 -0
- package/dist/esm/feedback/controls.d.ts +31 -0
- package/dist/esm/feedback/controls.js +280 -0
- package/dist/esm/feedback/index.d.ts +8 -0
- package/dist/esm/feedback/index.js +30 -0
- package/dist/esm/feedback/logs.d.ts +40 -0
- package/dist/esm/feedback/logs.js +188 -0
- package/dist/esm/feedback/send.d.ts +25 -0
- package/dist/esm/feedback/send.js +175 -0
- package/dist/esm/feedback/template.d.ts +2 -0
- package/dist/esm/feedback/template.js +159 -0
- package/dist/esm/feedback/ui.d.ts +55 -0
- package/dist/esm/feedback/ui.js +626 -0
- package/dist/esm/heatmap/index.d.ts +16 -0
- package/dist/esm/heatmap/index.js +17 -0
- package/dist/esm/heatmap/send.d.ts +13 -0
- package/dist/esm/heatmap/send.js +79 -0
- package/dist/esm/heatmap/track.d.ts +4 -0
- package/dist/esm/heatmap/track.js +374 -0
- package/dist/esm/index.d.ts +68 -0
- package/dist/esm/index.js +122 -0
- package/dist/esm/lifecycle.d.ts +14 -0
- package/dist/esm/lifecycle.js +534 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/remoteconfig/custom.d.ts +10 -0
- package/dist/esm/remoteconfig/custom.js +74 -0
- package/dist/esm/remoteconfig/evaluate.d.ts +24 -0
- package/dist/esm/remoteconfig/evaluate.js +166 -0
- package/dist/esm/remoteconfig/fetch.d.ts +24 -0
- package/dist/esm/remoteconfig/fetch.js +210 -0
- package/dist/esm/remoteconfig/index.d.ts +13 -0
- package/dist/esm/remoteconfig/index.js +85 -0
- package/dist/esm/remoteconfig/store.d.ts +18 -0
- package/dist/esm/remoteconfig/store.js +91 -0
- package/dist/esm/remotelog/gate.d.ts +11 -0
- package/dist/esm/remotelog/gate.js +48 -0
- package/dist/esm/remotelog/index.d.ts +25 -0
- package/dist/esm/remotelog/index.js +51 -0
- package/dist/esm/remotelog/logger.d.ts +28 -0
- package/dist/esm/remotelog/logger.js +136 -0
- package/dist/esm/remotelog/send.d.ts +13 -0
- package/dist/esm/remotelog/send.js +149 -0
- package/dist/esm/scheduler.d.ts +8 -0
- package/dist/esm/scheduler.js +74 -0
- package/dist/esm/types.d.ts +312 -0
- package/dist/esm/user/index.d.ts +33 -0
- package/dist/esm/user/index.js +170 -0
- package/dist/feedback.esm.min.js +3 -0
- package/dist/feedback.esm.min.js.map +1 -0
- package/dist/heatmap.esm.min.js +3 -0
- package/dist/heatmap.esm.min.js.map +1 -0
- package/dist/style.css +1 -0
- package/package.json +124 -7
- package/src/appticssdk.js +0 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { type ApConfig } from './constants.js';
|
|
2
|
+
import type { DeviceInfo, Dict, TrackingStatus, UserInfo } from '../types.js';
|
|
3
|
+
/** Runtime state shared by every module (the former `_ZAP` object). */
|
|
4
|
+
export interface State {
|
|
5
|
+
_initialised: boolean;
|
|
6
|
+
/** Start-up finished (storage loaded, session open, timers running). */
|
|
7
|
+
_ready: boolean;
|
|
8
|
+
/** Public calls made after init() and before _ready, replayed in order. */
|
|
9
|
+
_pending: Array<() => void>;
|
|
10
|
+
_readyPromise: Promise<boolean> | null;
|
|
11
|
+
_regDeviceSending: boolean;
|
|
12
|
+
_regDeviceResolve: Array<(value: any) => void>;
|
|
13
|
+
_regDeviceReject: Array<(reason: any) => void>;
|
|
14
|
+
_sending: boolean;
|
|
15
|
+
_deferSendTimer: ReturnType<typeof setTimeout> | null;
|
|
16
|
+
_config: ApConfig;
|
|
17
|
+
_defaultoptions: Dict;
|
|
18
|
+
inactiveduration: number;
|
|
19
|
+
_token: string;
|
|
20
|
+
_frameworkID: number;
|
|
21
|
+
_platform: string;
|
|
22
|
+
_isanonrequired: boolean;
|
|
23
|
+
_devicestatus: TrackingStatus;
|
|
24
|
+
_uuid: string;
|
|
25
|
+
_apid: string;
|
|
26
|
+
_mapid: string;
|
|
27
|
+
_device_info: DeviceInfo;
|
|
28
|
+
_user_info: UserInfo;
|
|
29
|
+
_current_screen: Dict;
|
|
30
|
+
_current_session: Dict;
|
|
31
|
+
_properties: Dict;
|
|
32
|
+
_ignoreDnt: boolean;
|
|
33
|
+
_isGlobalErrorTracking: boolean;
|
|
34
|
+
_shouldTrack: boolean;
|
|
35
|
+
_engagementTracking: boolean;
|
|
36
|
+
_errorTracking: boolean;
|
|
37
|
+
/** getsdkconfig module 18. Heatmap has its own flag in v2; before that it rode engagement. */
|
|
38
|
+
_heatmapTracking: boolean;
|
|
39
|
+
/** getsdkconfig module 17. */
|
|
40
|
+
_remoteLoggerEnabled: boolean;
|
|
41
|
+
/** getsdkconfig's module flag for remote config, which is the authority on whether it runs. */
|
|
42
|
+
_remoteConfigEnabled: boolean;
|
|
43
|
+
/** What the last getupdates answer said, used only to stop asking about a module it reported off. */
|
|
44
|
+
_remoteConfigReported: boolean;
|
|
45
|
+
/** getsdkconfig module 12. */
|
|
46
|
+
_feedbackEnabled: boolean;
|
|
47
|
+
_quartzEnabled: boolean;
|
|
48
|
+
/** Epoch ms getsdkconfig asked us to wait until before asking again. 0 means no answer yet. */
|
|
49
|
+
_nextConfigCheck: number;
|
|
50
|
+
/**
|
|
51
|
+
* When debug mode switches itself off, as a timestamp; 0 while it is not running.
|
|
52
|
+
* Every tracked item pushes it back, so it only arrives after a genuinely idle hour.
|
|
53
|
+
*/
|
|
54
|
+
_debugUntil: number;
|
|
55
|
+
_trackinfo: Dict;
|
|
56
|
+
}
|
|
57
|
+
export declare const _ZAP: State;
|
|
58
|
+
/** Restores every field to its default. The object identity is kept, since modules hold a reference to it. */
|
|
59
|
+
export declare function resetState(): void;
|
|
60
|
+
export declare function getConfig<K extends keyof ApConfig>(key: K): ApConfig[K];
|
|
61
|
+
/** The oldest timestamp still worth keeping: now minus batch_request_timeout days. */
|
|
62
|
+
export declare function oldestKeptTime(): number;
|
|
63
|
+
/**
|
|
64
|
+
* True for an item too old (or dated far enough in the future to be nonsense) to be worth
|
|
65
|
+
* sending. Queues use it to drop such items on the way in, and the sender uses it to drop the
|
|
66
|
+
* ones already stored. A minute of slack absorbs clock differences between tabs and machines,
|
|
67
|
+
* so an item a few milliseconds ahead of this clock is still kept.
|
|
68
|
+
*/
|
|
69
|
+
export declare function isExpired(time: unknown): boolean;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var constants = require('./constants.js');
|
|
5
|
+
var utils = require('./utils.js');
|
|
6
|
+
var frameworkId = require('./framework-id.js');
|
|
7
|
+
|
|
8
|
+
function initialState() {
|
|
9
|
+
return {
|
|
10
|
+
_initialised: false,
|
|
11
|
+
_ready: false,
|
|
12
|
+
_pending: [],
|
|
13
|
+
_readyPromise: null,
|
|
14
|
+
_regDeviceSending: false,
|
|
15
|
+
_regDeviceResolve: [],
|
|
16
|
+
_regDeviceReject: [],
|
|
17
|
+
_sending: false,
|
|
18
|
+
_deferSendTimer: null,
|
|
19
|
+
_config: { ...constants.AP_CONFIG },
|
|
20
|
+
_defaultoptions: {},
|
|
21
|
+
inactiveduration: constants.DEFAULT_INACTIVE_MINUTES,
|
|
22
|
+
_token: '', // no i18n
|
|
23
|
+
// issued by Apptics at pack time; see scripts/register-version.mjs
|
|
24
|
+
_frameworkID: frameworkId.FRAMEWORK_ID,
|
|
25
|
+
_platform: constants.AP_CONSTANTS.BROWSER,
|
|
26
|
+
_isanonrequired: true,
|
|
27
|
+
_devicestatus: constants.AP_TRACKING_STATUS.USAGE_TRACKING_WITHOUT_PII,
|
|
28
|
+
_uuid: '', // no i18n
|
|
29
|
+
_apid: '', // no i18n
|
|
30
|
+
_mapid: '', // no i18n
|
|
31
|
+
_device_info: {},
|
|
32
|
+
_user_info: {},
|
|
33
|
+
_current_screen: {},
|
|
34
|
+
_current_session: {},
|
|
35
|
+
_properties: {},
|
|
36
|
+
_ignoreDnt: false,
|
|
37
|
+
_isGlobalErrorTracking: true,
|
|
38
|
+
_shouldTrack: true,
|
|
39
|
+
_engagementTracking: true,
|
|
40
|
+
_heatmapTracking: true,
|
|
41
|
+
_remoteLoggerEnabled: true,
|
|
42
|
+
_remoteConfigEnabled: true,
|
|
43
|
+
_remoteConfigReported: true,
|
|
44
|
+
_feedbackEnabled: true,
|
|
45
|
+
_nextConfigCheck: 0,
|
|
46
|
+
_debugUntil: 0,
|
|
47
|
+
_errorTracking: true,
|
|
48
|
+
_quartzEnabled: true,
|
|
49
|
+
_trackinfo: {},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const _ZAP = initialState();
|
|
53
|
+
function getConfig(key) {
|
|
54
|
+
return _ZAP._config[key];
|
|
55
|
+
}
|
|
56
|
+
/** The oldest timestamp still worth keeping: now minus batch_request_timeout days. */
|
|
57
|
+
function oldestKeptTime() {
|
|
58
|
+
return utils.nowMs() - getConfig('batch_request_timeout') * 24 * 60 * 60 * 1000; // no i18n
|
|
59
|
+
}
|
|
60
|
+
/** How far ahead of this clock a timestamp may be before it counts as nonsense. */
|
|
61
|
+
const CLOCK_SKEW_MS = 60 * 1000;
|
|
62
|
+
/**
|
|
63
|
+
* True for an item too old (or dated far enough in the future to be nonsense) to be worth
|
|
64
|
+
* sending. Queues use it to drop such items on the way in, and the sender uses it to drop the
|
|
65
|
+
* ones already stored. A minute of slack absorbs clock differences between tabs and machines,
|
|
66
|
+
* so an item a few milliseconds ahead of this clock is still kept.
|
|
67
|
+
*/
|
|
68
|
+
function isExpired(time) {
|
|
69
|
+
if (typeof time !== 'number' || !isFinite(time)) {
|
|
70
|
+
return false; // no usable timestamp: leave it to the caller's own rules
|
|
71
|
+
}
|
|
72
|
+
return time < oldestKeptTime() || time > utils.nowMs() + CLOCK_SKEW_MS;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
exports._ZAP = _ZAP;
|
|
76
|
+
exports.getConfig = getConfig;
|
|
77
|
+
exports.isExpired = isExpired;
|
|
78
|
+
exports.oldestKeptTime = oldestKeptTime;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Backend, type QueueName } from './db.js';
|
|
2
|
+
import type { Dict, QueueItem, TrackingStatus } from '../types.js';
|
|
3
|
+
/** Opens storage, migrates 1.x data and loads settings into memory. Shared by all callers. */
|
|
4
|
+
export declare function storageReady(): Promise<Backend | null>;
|
|
5
|
+
export interface Queue {
|
|
6
|
+
readonly name: QueueName;
|
|
7
|
+
all(): Promise<QueueItem[]>;
|
|
8
|
+
payload(): Promise<QueueItem[]>;
|
|
9
|
+
add(item: QueueItem): Promise<void>;
|
|
10
|
+
update(item: QueueItem): Promise<void>;
|
|
11
|
+
remove(items?: QueueItem[]): Promise<void>;
|
|
12
|
+
clear(): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/** Sessions, screens, events and api calls waiting to be sent. */
|
|
15
|
+
export declare const engagement_transactions: Queue;
|
|
16
|
+
/** Errors waiting to be sent. */
|
|
17
|
+
export declare const error_transactions: Queue;
|
|
18
|
+
/**
|
|
19
|
+
* Feedback log lines and diagnostics entries, from addFeedbackLog() and addDiagnosticsInfo().
|
|
20
|
+
* These are not sent on their own: feedback/logs.ts renders them into the files that
|
|
21
|
+
* feedback/add carries, and removes the ones a submission took with it.
|
|
22
|
+
*/
|
|
23
|
+
export declare const log_transactions: Queue;
|
|
24
|
+
/** Clicks and scrolls waiting for heatmap/add. */
|
|
25
|
+
export declare const heatmap_transactions: Queue;
|
|
26
|
+
/**
|
|
27
|
+
* Remote log lines waiting for console/addlog. Stored rather than sent straight out because the
|
|
28
|
+
* endpoint takes one line per call and counts retries (`attempt`), so a line has to outlive a
|
|
29
|
+
* failed send — and a reload.
|
|
30
|
+
*/
|
|
31
|
+
export declare const consolelog_transactions: Queue;
|
|
32
|
+
/** Token, uuid, appversion, device_info, users, trackinfo. */
|
|
33
|
+
export declare const user_defaults: {
|
|
34
|
+
all(): Dict;
|
|
35
|
+
item(key: string): any;
|
|
36
|
+
add(key: string, value: unknown): void;
|
|
37
|
+
clear(): void;
|
|
38
|
+
};
|
|
39
|
+
/** Opt-in status, stored as the tracking_status setting. */
|
|
40
|
+
export declare const tracking_preference: {
|
|
41
|
+
_tracking_status: string;
|
|
42
|
+
all(): Dict;
|
|
43
|
+
opt_in_status(): TrackingStatus;
|
|
44
|
+
update_status(tracking_status: TrackingStatus): void;
|
|
45
|
+
};
|
|
46
|
+
export declare function getKeyFromDeviceInfo(key: string): any;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var constants = require('./constants.js');
|
|
5
|
+
var state = require('./state.js');
|
|
6
|
+
var logger = require('./logger.js');
|
|
7
|
+
var utils = require('./utils.js');
|
|
8
|
+
var db = require('./db.js');
|
|
9
|
+
|
|
10
|
+
var readyPromise = null;
|
|
11
|
+
var settings = {};
|
|
12
|
+
/** Runs `op` once storage is ready, in call order. Never rejects. */
|
|
13
|
+
function withBackend(label, fallback, op) {
|
|
14
|
+
return storageReady().then(function (b) {
|
|
15
|
+
return b ? op(b) : fallback;
|
|
16
|
+
}).catch(function (err) {
|
|
17
|
+
logger.Console.warn('apptics: storage ' + label + ' failed: ' + String(err)); // no i18n
|
|
18
|
+
return fallback;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function migrateLegacy(b) {
|
|
22
|
+
if (b.kind !== 'indexeddb' || !b.importAll) { // no i18n
|
|
23
|
+
return Promise.resolve();
|
|
24
|
+
}
|
|
25
|
+
var raw;
|
|
26
|
+
try {
|
|
27
|
+
raw = {
|
|
28
|
+
settings: localStorage.getItem(db.LEGACY_KEYS.settings),
|
|
29
|
+
engagements: localStorage.getItem(db.LEGACY_KEYS.engagements),
|
|
30
|
+
errors: localStorage.getItem(db.LEGACY_KEYS.errors),
|
|
31
|
+
logs: localStorage.getItem(db.LEGACY_KEYS.logs),
|
|
32
|
+
consolelogs: localStorage.getItem(db.LEGACY_KEYS.consolelogs),
|
|
33
|
+
// read for completeness of the shape only: 1.x never wrote this key
|
|
34
|
+
heatmaps: null,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
return Promise.resolve();
|
|
39
|
+
}
|
|
40
|
+
if (raw.settings === null && raw.engagements === null && raw.errors === null && raw.logs === null
|
|
41
|
+
&& raw.consolelogs === null) {
|
|
42
|
+
return Promise.resolve();
|
|
43
|
+
}
|
|
44
|
+
var parse = function (text) {
|
|
45
|
+
try {
|
|
46
|
+
return text === null ? null : JSON.parse(text);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var queues = {
|
|
53
|
+
engagements: db.asList(parse(raw.engagements)),
|
|
54
|
+
errors: db.asList(parse(raw.errors)),
|
|
55
|
+
logs: db.asList(parse(raw.logs)),
|
|
56
|
+
consolelogs: db.asList(parse(raw.consolelogs)),
|
|
57
|
+
// nothing to migrate: 1.x had no heatmaps
|
|
58
|
+
heatmaps: [],
|
|
59
|
+
};
|
|
60
|
+
queues.engagements.concat(queues.errors, queues.logs, queues.consolelogs).forEach(function (item) {
|
|
61
|
+
if (!item.id)
|
|
62
|
+
item.id = utils.getNewUUID();
|
|
63
|
+
});
|
|
64
|
+
var importAll = b.importAll.bind(b);
|
|
65
|
+
// Promise.resolve().then(...) turns a synchronous throw inside importAll into a rejection
|
|
66
|
+
return Promise.resolve().then(function () {
|
|
67
|
+
return importAll(db.asDict(parse(raw.settings)), queues);
|
|
68
|
+
}).then(function () {
|
|
69
|
+
Object.values(db.LEGACY_KEYS).forEach(function (key) {
|
|
70
|
+
try {
|
|
71
|
+
localStorage.removeItem(key);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
// keys stay; the import is idempotent
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
logger.Console.log('apptics: moved 1.x data from localStorage to IndexedDB'); // no i18n
|
|
78
|
+
}).catch(function (err) {
|
|
79
|
+
logger.Console.warn('apptics: 1.x data migration failed, will retry next load: ' + String(err)); // no i18n
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/** Opens storage, migrates 1.x data and loads settings into memory. Shared by all callers. */
|
|
83
|
+
function storageReady() {
|
|
84
|
+
if (!readyPromise) {
|
|
85
|
+
readyPromise = db.openBackend().then(function (b) {
|
|
86
|
+
if (!b) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return migrateLegacy(b).then(function () {
|
|
90
|
+
return b.loadSettings();
|
|
91
|
+
}).then(function (loaded) {
|
|
92
|
+
// writes made before loading finished win over stored values
|
|
93
|
+
settings = Object.assign({}, loaded, settings);
|
|
94
|
+
return b;
|
|
95
|
+
});
|
|
96
|
+
}).catch(function (err) {
|
|
97
|
+
logger.Console.warn('apptics: storage unavailable: ' + String(err)); // no i18n
|
|
98
|
+
return null;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return readyPromise;
|
|
102
|
+
}
|
|
103
|
+
/** When an item happened: engagements carry starttime, errors and logs happenedat. */
|
|
104
|
+
function itemTime(item) {
|
|
105
|
+
return item.starttime !== undefined ? item.starttime : item.happenedat;
|
|
106
|
+
}
|
|
107
|
+
/** First batch_size items, capped at 1 MB. */
|
|
108
|
+
function takeBatch(items) {
|
|
109
|
+
const targetSize = 1024 * 1024; // 1 MB in bytes
|
|
110
|
+
let dataSize = 0;
|
|
111
|
+
const result = [];
|
|
112
|
+
for (const item of items.slice(0, state.getConfig('batch_size'))) { // no i18n
|
|
113
|
+
const size = utils.sizeof(JSON.stringify(item));
|
|
114
|
+
if (dataSize + size > targetSize) {
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
result.push(item);
|
|
118
|
+
dataSize += size;
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
function createQueue(name) {
|
|
123
|
+
const queue = {
|
|
124
|
+
name: name,
|
|
125
|
+
all() {
|
|
126
|
+
return withBackend('read ' + name, [], function (b) { return b.queueAll(name); }); // no i18n
|
|
127
|
+
},
|
|
128
|
+
payload() {
|
|
129
|
+
return queue.all().then(takeBatch);
|
|
130
|
+
},
|
|
131
|
+
add(item) {
|
|
132
|
+
if (!item.id) {
|
|
133
|
+
item.id = utils.getNewUUID();
|
|
134
|
+
}
|
|
135
|
+
// a week-old item would only be dropped at send time, so don't store it at all
|
|
136
|
+
if (state.isExpired(itemTime(item))) {
|
|
137
|
+
logger.Console.warn('apptics: dropping a ' + name + ' item older than ' + state.getConfig('batch_request_timeout') + ' days'); // no i18n
|
|
138
|
+
return Promise.resolve();
|
|
139
|
+
}
|
|
140
|
+
return withBackend('add ' + name, undefined, function (b) { return b.queuePut(name, [item]); }); // no i18n
|
|
141
|
+
},
|
|
142
|
+
update(item) {
|
|
143
|
+
return withBackend('update ' + name, undefined, function (b) { return b.queuePut(name, [item]); }); // no i18n
|
|
144
|
+
},
|
|
145
|
+
remove(itemsToRemove) {
|
|
146
|
+
const ids = (itemsToRemove || []).map(function (item) { return String(item.id); });
|
|
147
|
+
return withBackend('remove ' + name, undefined, function (b) { return b.queueDelete(name, ids); }); // no i18n
|
|
148
|
+
},
|
|
149
|
+
clear() {
|
|
150
|
+
return withBackend('clear ' + name, undefined, function (b) { return b.queueClear(name); }); // no i18n
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
return queue;
|
|
154
|
+
}
|
|
155
|
+
/** Sessions, screens, events and api calls waiting to be sent. */
|
|
156
|
+
const engagement_transactions = createQueue('engagements'); // no i18n
|
|
157
|
+
/** Errors waiting to be sent. */
|
|
158
|
+
const error_transactions = createQueue('errors'); // no i18n
|
|
159
|
+
/**
|
|
160
|
+
* Feedback log lines and diagnostics entries, from addFeedbackLog() and addDiagnosticsInfo().
|
|
161
|
+
* These are not sent on their own: feedback/logs.ts renders them into the files that
|
|
162
|
+
* feedback/add carries, and removes the ones a submission took with it.
|
|
163
|
+
*/
|
|
164
|
+
const log_transactions = createQueue('logs'); // no i18n
|
|
165
|
+
/** Clicks and scrolls waiting for heatmap/add. */
|
|
166
|
+
const heatmap_transactions = createQueue('heatmaps'); // no i18n
|
|
167
|
+
/**
|
|
168
|
+
* Remote log lines waiting for console/addlog. Stored rather than sent straight out because the
|
|
169
|
+
* endpoint takes one line per call and counts retries (`attempt`), so a line has to outlive a
|
|
170
|
+
* failed send — and a reload.
|
|
171
|
+
*/
|
|
172
|
+
const consolelog_transactions = createQueue('consolelogs'); // no i18n
|
|
173
|
+
/* ---------------- settings (sync reads, background writes) ---------------- */
|
|
174
|
+
function setSetting(key, value) {
|
|
175
|
+
settings[key] = value === undefined ? undefined : utils.cloneObject(value);
|
|
176
|
+
withBackend('save ' + key, undefined, function (b) { return b.putSetting(key, settings[key]); }); // no i18n
|
|
177
|
+
}
|
|
178
|
+
/** Token, uuid, appversion, device_info, users, trackinfo. */
|
|
179
|
+
const user_defaults = {
|
|
180
|
+
all() {
|
|
181
|
+
return utils.cloneObject(settings);
|
|
182
|
+
},
|
|
183
|
+
item(key) {
|
|
184
|
+
const value = settings[key];
|
|
185
|
+
return value === undefined ? undefined : utils.cloneObject(value);
|
|
186
|
+
},
|
|
187
|
+
add(key, value) {
|
|
188
|
+
setSetting(key, value);
|
|
189
|
+
},
|
|
190
|
+
clear() {
|
|
191
|
+
settings = {};
|
|
192
|
+
withBackend('clear settings', undefined, function (b) { return b.clearSettings(); }); // no i18n
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
/** Opt-in status, stored as the tracking_status setting. */
|
|
196
|
+
const tracking_preference = {
|
|
197
|
+
_tracking_status: 'tracking_status', // no i18n
|
|
198
|
+
all() {
|
|
199
|
+
return user_defaults.all();
|
|
200
|
+
},
|
|
201
|
+
opt_in_status() {
|
|
202
|
+
return (settings[tracking_preference._tracking_status] || constants.AP_TRACKING_STATUS.USAGE_TRACKING_WITHOUT_PII);
|
|
203
|
+
},
|
|
204
|
+
update_status(tracking_status) {
|
|
205
|
+
state._ZAP._devicestatus = tracking_status;
|
|
206
|
+
// Legacy order kept: this reads the status *before* the write below (setTrackingStatus recomputes it after).
|
|
207
|
+
state._ZAP._isanonrequired =
|
|
208
|
+
tracking_preference.opt_in_status() == constants.AP_TRACKING_STATUS.USAGE_TRACKING_WITH_PII ? false : state._ZAP._isanonrequired;
|
|
209
|
+
setSetting(tracking_preference._tracking_status, tracking_status);
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
function getKeyFromDeviceInfo(key) {
|
|
213
|
+
var current_device_info = settings['device_info']; // no i18n
|
|
214
|
+
if (current_device_info !== undefined && current_device_info !== null && current_device_info !== '' &&
|
|
215
|
+
current_device_info[key] !== undefined && current_device_info[key] !== null && current_device_info[key] !== '') {
|
|
216
|
+
return utils.cloneObject(current_device_info[key]);
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
exports.consolelog_transactions = consolelog_transactions;
|
|
222
|
+
exports.engagement_transactions = engagement_transactions;
|
|
223
|
+
exports.error_transactions = error_transactions;
|
|
224
|
+
exports.getKeyFromDeviceInfo = getKeyFromDeviceInfo;
|
|
225
|
+
exports.heatmap_transactions = heatmap_transactions;
|
|
226
|
+
exports.log_transactions = log_transactions;
|
|
227
|
+
exports.storageReady = storageReady;
|
|
228
|
+
exports.tracking_preference = tracking_preference;
|
|
229
|
+
exports.user_defaults = user_defaults;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { DEFAULT_API_PATHS } from './constants.js';
|
|
2
|
+
import type { Dict, ServerResult } from '../types.js';
|
|
3
|
+
export type ApiPath = keyof typeof DEFAULT_API_PATHS;
|
|
4
|
+
export type RequestHeaders = Record<string, string>;
|
|
5
|
+
export type RequestBody = XMLHttpRequestBodyInit | null;
|
|
6
|
+
/**
|
|
7
|
+
* How long a request may take before it counts as failed. Without a limit a request the network
|
|
8
|
+
* never answers keeps its caller waiting for good, and with it the queue it was sending.
|
|
9
|
+
*/
|
|
10
|
+
export declare const REQUEST_TIMEOUT_MS = 30000;
|
|
11
|
+
export declare function makeRequest(url: string, method: string, payload: RequestBody, headers?: RequestHeaders): Promise<string>;
|
|
12
|
+
export declare function getHeaderParams(key: string): string;
|
|
13
|
+
export declare function getParameters(path: ApiPath): string;
|
|
14
|
+
/**
|
|
15
|
+
* `extra` appends params the path needs per call rather than per state, which console/addlog does
|
|
16
|
+
* (happenedtime and module change with every line). Values are encoded; the keys are our own.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getUrlWithParams(path: ApiPath, extra?: Dict): string;
|
|
19
|
+
/** Whether this path should go to its debug twin. */
|
|
20
|
+
export declare function usesDebugApi(path: ApiPath): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Headers for every call made after device registration.
|
|
23
|
+
*
|
|
24
|
+
* apid and mapid are the only two, because they are the only two every url allows: the v2
|
|
25
|
+
* endpoints declare Access-Control-Allow-Headers as exactly "apid,mapid", and a browser drops
|
|
26
|
+
* any header outside that list at the preflight. Asking for the debug twin is done with the url
|
|
27
|
+
* alone, which needs no permission to send.
|
|
28
|
+
*/
|
|
29
|
+
export declare function apiHeaders(): RequestHeaders;
|
|
30
|
+
/**
|
|
31
|
+
* A rejection that carries the server's own answer, so a caller can tell *why* it failed.
|
|
32
|
+
* Without this the reason is flattened into a string and a permanent refusal is indistinguishable
|
|
33
|
+
* from a dropped connection.
|
|
34
|
+
*/
|
|
35
|
+
export interface ServerRejection extends Error {
|
|
36
|
+
serverResult?: ServerResult;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Whether a rejection is the server saying "never": the batch is malformed and keeping it would
|
|
40
|
+
* block every later batch behind it, for good. Anything else — a 5xx, a timeout, no network — is
|
|
41
|
+
* worth retrying and must not be treated this way.
|
|
42
|
+
*/
|
|
43
|
+
export declare function isPermanentRefusal(err: unknown): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Sends one request. Resolves with the parsed response when it reports success; otherwise
|
|
46
|
+
* rejects with an Error carrying the server's answer. Requests are independent of each other:
|
|
47
|
+
* nothing orders one behind another.
|
|
48
|
+
*/
|
|
49
|
+
export declare function postToApptics(path: ApiPath, payload: RequestBody, headers: RequestHeaders, label: string, extra?: Dict): Promise<ServerResult>;
|
|
50
|
+
/**
|
|
51
|
+
* The most a page may have in flight as keepalive bodies at once. Browsers refuse a keepalive
|
|
52
|
+
* request once the bodies still in flight would pass 64 KiB; this stays under that with room for
|
|
53
|
+
* the url and headers.
|
|
54
|
+
*/
|
|
55
|
+
export declare const KEEPALIVE_BUDGET: number;
|
|
56
|
+
/**
|
|
57
|
+
* Sends as the page goes away, where a normal XHR would be cancelled with the document.
|
|
58
|
+
*
|
|
59
|
+
* `keepalive` is what lets the request outlive the page. fetch is used rather than sendBeacon
|
|
60
|
+
* because sendBeacon cannot carry the apid and mapid headers these urls require.
|
|
61
|
+
*
|
|
62
|
+
* The request leaves before this returns, so a caller never has to wait on it to send the next
|
|
63
|
+
* thing. The promise settles when the answer arrives, if the page is still there to see it: a
|
|
64
|
+
* caller removes what it sent only then. Data whose answer never comes stays stored and goes
|
|
65
|
+
* again on the next visit as attempt 2, which `attempt` and `firstattempttime` let the server
|
|
66
|
+
* recognise as a copy rather than store twice.
|
|
67
|
+
*
|
|
68
|
+
* A body that would take the page past the keepalive budget is not sent at all: the browser would
|
|
69
|
+
* refuse it, and it is better kept for the next visit than lost.
|
|
70
|
+
*/
|
|
71
|
+
export declare function postKeepalive(path: ApiPath, payload: RequestBody, headers: RequestHeaders, label: string, extra?: Dict): Promise<ServerResult>;
|
|
72
|
+
/** A labelled rejection for crawlers (the SDK does nothing for them), otherwise null. */
|
|
73
|
+
export declare function rejectIfDisabled(label: string): Promise<never> | null;
|
|
74
|
+
/** A labelled rejection when the browser is offline, otherwise null. */
|
|
75
|
+
export declare function rejectIfOffline(label: string): Promise<never> | null;
|
|
76
|
+
/** Device ids sent alongside every payload. */
|
|
77
|
+
export declare function getMetaObj(): Dict;
|
|
78
|
+
/**
|
|
79
|
+
* Calls made after registration need apid/mapid. Without them this asks device.ts to
|
|
80
|
+
* refresh device info (which registers) and returns a labelled rejection; otherwise null. Shared by sender, user
|
|
81
|
+
* and feedback (P11).
|
|
82
|
+
*/
|
|
83
|
+
export declare function rejectIfNoDeviceIds(label: string): Promise<never> | null;
|