@zoho_apptics/apptics-js-sdk 1.0.2 → 2.0.0-beta.1
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 +193 -0
- package/LICENSE +13 -0
- package/README.md +846 -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/lifecycle-VYr43KcB.min.js +3 -0
- package/dist/chunks/lifecycle-VYr43KcB.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 +116 -0
- package/dist/cjs/core/callsite.d.ts +34 -0
- package/dist/cjs/core/callsite.js +115 -0
- package/dist/cjs/core/consent.d.ts +27 -0
- package/dist/cjs/core/consent.js +132 -0
- package/dist/cjs/core/constants.d.ts +237 -0
- package/dist/cjs/core/constants.js +315 -0
- package/dist/cjs/core/db.d.ts +48 -0
- package/dist/cjs/core/db.js +467 -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 +11 -0
- package/dist/cjs/core/guard.js +86 -0
- package/dist/cjs/core/hooks.d.ts +39 -0
- package/dist/cjs/core/hooks.js +22 -0
- package/dist/cjs/core/locks.d.ts +9 -0
- package/dist/cjs/core/locks.js +22 -0
- package/dist/cjs/core/logger.d.ts +15 -0
- package/dist/cjs/core/logger.js +50 -0
- package/dist/cjs/core/state.d.ts +70 -0
- package/dist/cjs/core/state.js +78 -0
- package/dist/cjs/core/storage.d.ts +61 -0
- package/dist/cjs/core/storage.js +327 -0
- package/dist/cjs/core/stylesheet.d.ts +8 -0
- package/dist/cjs/core/stylesheet.js +29 -0
- package/dist/cjs/core/transport.d.ts +85 -0
- package/dist/cjs/core/transport.js +456 -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 +15 -0
- package/dist/cjs/device/appversion.js +170 -0
- package/dist/cjs/device/index.d.ts +34 -0
- package/dist/cjs/device/index.js +472 -0
- package/dist/cjs/engagement/api-rules.d.ts +49 -0
- package/dist/cjs/engagement/api-rules.js +206 -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 +18 -0
- package/dist/cjs/engagement/auto-screen.js +305 -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 +104 -0
- package/dist/cjs/engagement/session.d.ts +51 -0
- package/dist/cjs/engagement/session.js +463 -0
- package/dist/cjs/engagement/track.d.ts +56 -0
- package/dist/cjs/engagement/track.js +375 -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 +167 -0
- package/dist/cjs/feedback/controls.d.ts +37 -0
- package/dist/cjs/feedback/controls.js +316 -0
- package/dist/cjs/feedback/index.d.ts +9 -0
- package/dist/cjs/feedback/index.js +56 -0
- package/dist/cjs/feedback/logs.d.ts +45 -0
- package/dist/cjs/feedback/logs.js +241 -0
- package/dist/cjs/feedback/quartz.d.ts +18 -0
- package/dist/cjs/feedback/quartz.js +105 -0
- package/dist/cjs/feedback/send.d.ts +28 -0
- package/dist/cjs/feedback/send.js +203 -0
- package/dist/cjs/feedback/styles.d.ts +10 -0
- package/dist/cjs/feedback/styles.js +8 -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 +63 -0
- package/dist/cjs/feedback/ui.js +709 -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 +448 -0
- package/dist/cjs/index.d.ts +22 -0
- package/dist/cjs/index.js +162 -0
- package/dist/cjs/lifecycle.d.ts +21 -0
- package/dist/cjs/lifecycle.js +734 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/remoteconfig/country.d.ts +4 -0
- package/dist/cjs/remoteconfig/country.js +73 -0
- package/dist/cjs/remoteconfig/custom.d.ts +10 -0
- package/dist/cjs/remoteconfig/custom.js +58 -0
- package/dist/cjs/remoteconfig/evaluate.d.ts +24 -0
- package/dist/cjs/remoteconfig/evaluate.js +184 -0
- package/dist/cjs/remoteconfig/fetch.d.ts +24 -0
- package/dist/cjs/remoteconfig/fetch.js +200 -0
- package/dist/cjs/remoteconfig/index.d.ts +15 -0
- package/dist/cjs/remoteconfig/index.js +116 -0
- package/dist/cjs/remoteconfig/store.d.ts +18 -0
- package/dist/cjs/remoteconfig/store.js +98 -0
- package/dist/cjs/remoteconfig/tz-countries.d.ts +8 -0
- package/dist/cjs/remoteconfig/tz-countries.js +13 -0
- package/dist/cjs/remotelog/gate.d.ts +2 -0
- package/dist/cjs/remotelog/gate.js +28 -0
- package/dist/cjs/remotelog/index.d.ts +8 -0
- package/dist/cjs/remotelog/logger.d.ts +22 -0
- package/dist/cjs/remotelog/logger.js +111 -0
- package/dist/cjs/remotelog/send.d.ts +13 -0
- package/dist/cjs/remotelog/send.js +153 -0
- package/dist/cjs/remotelogger/index.d.ts +12 -0
- package/dist/cjs/remotelogger/index.js +18 -0
- package/dist/cjs/scheduler.d.ts +8 -0
- package/dist/cjs/scheduler.js +78 -0
- package/dist/cjs/types.d.ts +385 -0
- package/dist/cjs/user/index.d.ts +33 -0
- package/dist/cjs/user/index.js +183 -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 +109 -0
- package/dist/esm/core/callsite.d.ts +34 -0
- package/dist/esm/core/callsite.js +110 -0
- package/dist/esm/core/consent.d.ts +27 -0
- package/dist/esm/core/consent.js +122 -0
- package/dist/esm/core/constants.d.ts +237 -0
- package/dist/esm/core/constants.js +292 -0
- package/dist/esm/core/db.d.ts +48 -0
- package/dist/esm/core/db.js +453 -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 +11 -0
- package/dist/esm/core/guard.js +83 -0
- package/dist/esm/core/hooks.d.ts +39 -0
- package/dist/esm/core/hooks.js +20 -0
- package/dist/esm/core/locks.d.ts +9 -0
- package/dist/esm/core/locks.js +20 -0
- package/dist/esm/core/logger.d.ts +15 -0
- package/dist/esm/core/logger.js +46 -0
- package/dist/esm/core/state.d.ts +70 -0
- package/dist/esm/core/state.js +73 -0
- package/dist/esm/core/storage.d.ts +61 -0
- package/dist/esm/core/storage.js +314 -0
- package/dist/esm/core/stylesheet.d.ts +8 -0
- package/dist/esm/core/stylesheet.js +27 -0
- package/dist/esm/core/transport.d.ts +85 -0
- package/dist/esm/core/transport.js +439 -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 +15 -0
- package/dist/esm/device/appversion.js +164 -0
- package/dist/esm/device/index.d.ts +34 -0
- package/dist/esm/device/index.js +461 -0
- package/dist/esm/engagement/api-rules.d.ts +49 -0
- package/dist/esm/engagement/api-rules.js +199 -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 +18 -0
- package/dist/esm/engagement/auto-screen.js +301 -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 +101 -0
- package/dist/esm/engagement/session.d.ts +51 -0
- package/dist/esm/engagement/session.js +448 -0
- package/dist/esm/engagement/track.d.ts +56 -0
- package/dist/esm/engagement/track.js +365 -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 +163 -0
- package/dist/esm/feedback/controls.d.ts +37 -0
- package/dist/esm/feedback/controls.js +309 -0
- package/dist/esm/feedback/index.d.ts +9 -0
- package/dist/esm/feedback/index.js +51 -0
- package/dist/esm/feedback/logs.d.ts +45 -0
- package/dist/esm/feedback/logs.js +227 -0
- package/dist/esm/feedback/quartz.d.ts +18 -0
- package/dist/esm/feedback/quartz.js +99 -0
- package/dist/esm/feedback/send.d.ts +28 -0
- package/dist/esm/feedback/send.js +198 -0
- package/dist/esm/feedback/styles.d.ts +10 -0
- package/dist/esm/feedback/styles.js +4 -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 +63 -0
- package/dist/esm/feedback/ui.js +703 -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 +445 -0
- package/dist/esm/index.d.ts +22 -0
- package/dist/esm/index.js +150 -0
- package/dist/esm/lifecycle.d.ts +21 -0
- package/dist/esm/lifecycle.js +729 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/remoteconfig/country.d.ts +4 -0
- package/dist/esm/remoteconfig/country.js +70 -0
- package/dist/esm/remoteconfig/custom.d.ts +10 -0
- package/dist/esm/remoteconfig/custom.js +54 -0
- package/dist/esm/remoteconfig/evaluate.d.ts +24 -0
- package/dist/esm/remoteconfig/evaluate.js +179 -0
- package/dist/esm/remoteconfig/fetch.d.ts +24 -0
- package/dist/esm/remoteconfig/fetch.js +196 -0
- package/dist/esm/remoteconfig/index.d.ts +15 -0
- package/dist/esm/remoteconfig/index.js +111 -0
- package/dist/esm/remoteconfig/store.d.ts +18 -0
- package/dist/esm/remoteconfig/store.js +91 -0
- package/dist/esm/remoteconfig/tz-countries.d.ts +8 -0
- package/dist/esm/remoteconfig/tz-countries.js +11 -0
- package/dist/esm/remotelog/gate.d.ts +2 -0
- package/dist/esm/remotelog/gate.js +26 -0
- package/dist/esm/remotelog/index.d.ts +8 -0
- package/dist/esm/remotelog/logger.d.ts +22 -0
- package/dist/esm/remotelog/logger.js +108 -0
- package/dist/esm/remotelog/send.d.ts +13 -0
- package/dist/esm/remotelog/send.js +149 -0
- package/dist/esm/remotelogger/index.d.ts +12 -0
- package/dist/esm/remotelogger/index.js +13 -0
- package/dist/esm/scheduler.d.ts +8 -0
- package/dist/esm/scheduler.js +74 -0
- package/dist/esm/types.d.ts +385 -0
- package/dist/esm/user/index.d.ts +33 -0
- package/dist/esm/user/index.js +176 -0
- package/dist/feedback.esm.min.js +3 -0
- package/dist/feedback.esm.min.js.map +1 -0
- package/package.json +122 -7
- package/src/appticssdk.js +0 -1
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var logger = require('./logger.js');
|
|
5
|
+
var utils = require('./utils.js');
|
|
6
|
+
|
|
7
|
+
const DB_NAME = 'apptics'; // no i18n
|
|
8
|
+
// 3 added the heatmaps store. 4 renamed: each record's order key `seq` to `queue`, the logs store
|
|
9
|
+
// to feedbacklogs and consolelogs to remotelogs. Every upgrade keeps what is already queued.
|
|
10
|
+
const DB_VERSION = 4;
|
|
11
|
+
const OPEN_TIMEOUT_MS = 3000;
|
|
12
|
+
const QUEUES = ['engagements', 'errors', 'feedbacklogs', 'remotelogs', 'heatmaps']; // no i18n
|
|
13
|
+
/** The field, and the index on it, that keeps a queue's records in the order they were added. */
|
|
14
|
+
const QUEUE_KEY = 'queue'; // no i18n
|
|
15
|
+
/** Version 3's names, which the version 4 upgrade moves to the ones above. */
|
|
16
|
+
const OLD_QUEUE_KEY = 'seq'; // no i18n
|
|
17
|
+
const RENAMED_STORES = [['logs', 'feedbacklogs'], ['consolelogs', 'remotelogs']]; // no i18n
|
|
18
|
+
/** The types a feedback entry is stored under: an addFeedbackLog() line, an addDiagnosticsInfo() entry. */
|
|
19
|
+
const FEEDBACK_LOG = 'feedbacklog'; // no i18n
|
|
20
|
+
const FEEDBACK_DIAGNOSTICS = 'feedbackdiagnostics'; // no i18n
|
|
21
|
+
const OLD_FEEDBACK_TYPES = Object.freeze({
|
|
22
|
+
log: FEEDBACK_LOG, // no i18n
|
|
23
|
+
diagnostics: FEEDBACK_DIAGNOSTICS, // no i18n
|
|
24
|
+
});
|
|
25
|
+
/** A feedback entry from 1.x or 2.0.0-beta, with the type it is stored under now. */
|
|
26
|
+
function renameFeedbackType(item) {
|
|
27
|
+
var renamed = item && typeof item.type === 'string' ? OLD_FEEDBACK_TYPES[item.type] : undefined; // no i18n
|
|
28
|
+
return renamed ? { ...item, type: renamed } : item;
|
|
29
|
+
}
|
|
30
|
+
/** 1.x localStorage keys, read once to bring 1.x data into IndexedDB (see migrateLegacy). */
|
|
31
|
+
const LEGACY_KEYS = Object.freeze({
|
|
32
|
+
settings: 'apptics-device-info', // no i18n
|
|
33
|
+
engagements: 'apptics-engagements-transactions', // no i18n
|
|
34
|
+
errors: 'apptics-errors-transactions', // no i18n
|
|
35
|
+
logs: 'apptics-log-transactions', // no i18n
|
|
36
|
+
consolelogs: 'apptics-consolelog-transactions', // no i18n
|
|
37
|
+
});
|
|
38
|
+
/** The localStorage backend's layout, for a browser where IndexedDB will not open. */
|
|
39
|
+
const LOCAL_KEYS = Object.freeze({
|
|
40
|
+
settings: LEGACY_KEYS.settings,
|
|
41
|
+
engagements: LEGACY_KEYS.engagements,
|
|
42
|
+
errors: LEGACY_KEYS.errors,
|
|
43
|
+
feedbacklogs: 'apptics-feedbacklog-transactions', // no i18n
|
|
44
|
+
remotelogs: 'apptics-remotelog-transactions', // no i18n
|
|
45
|
+
heatmaps: 'apptics-heatmap-transactions', // no i18n
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* The localStorage backend once kept these two under the 1.x keys. Moved to the new ones on first
|
|
49
|
+
* use, feedback types renamed on the way, unless something is already there.
|
|
50
|
+
*/
|
|
51
|
+
function moveRenamedLocalKeys() {
|
|
52
|
+
[[LEGACY_KEYS.logs, LOCAL_KEYS.feedbacklogs], [LEGACY_KEYS.consolelogs, LOCAL_KEYS.remotelogs]].forEach(function (pair) {
|
|
53
|
+
try {
|
|
54
|
+
var from = pair[0];
|
|
55
|
+
var to = pair[1];
|
|
56
|
+
var old = localStorage.getItem(from);
|
|
57
|
+
if (old === null) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (localStorage.getItem(to) === null) {
|
|
61
|
+
var items = asList(JSON.parse(old));
|
|
62
|
+
localStorage.setItem(to, JSON.stringify(to === LOCAL_KEYS.feedbacklogs ? items.map(renameFeedbackType) : items));
|
|
63
|
+
}
|
|
64
|
+
localStorage.removeItem(from);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
// left where it is; the next load tries again
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/** Shape guards shared by both backends and the 1.x migration. */
|
|
72
|
+
function asList(value) {
|
|
73
|
+
return Array.isArray(value) ? value : [];
|
|
74
|
+
}
|
|
75
|
+
function asDict(value) {
|
|
76
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
77
|
+
}
|
|
78
|
+
/* ---------------- localStorage backend ---------------- */
|
|
79
|
+
function readJSON(key) {
|
|
80
|
+
try {
|
|
81
|
+
const raw = localStorage.getItem(key);
|
|
82
|
+
return raw === null || raw === '' ? null : JSON.parse(raw); // no i18n
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
logger.Console.warn('apptics: could not read ' + key + ', treating it as empty'); // no i18n
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function writeJSON(key, value) {
|
|
90
|
+
try {
|
|
91
|
+
localStorage.setItem(key, JSON.stringify(value));
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
logger.Console.warn('apptics: could not write ' + key + ': ' + String(err)); // no i18n
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function createLocalStorageBackend() {
|
|
98
|
+
moveRenamedLocalKeys();
|
|
99
|
+
return {
|
|
100
|
+
kind: 'localstorage', // no i18n
|
|
101
|
+
loadSettings() {
|
|
102
|
+
return Promise.resolve(asDict(readJSON(LOCAL_KEYS.settings)));
|
|
103
|
+
},
|
|
104
|
+
putSetting(key, value) {
|
|
105
|
+
const all = asDict(readJSON(LOCAL_KEYS.settings));
|
|
106
|
+
all[key] = value;
|
|
107
|
+
writeJSON(LOCAL_KEYS.settings, all);
|
|
108
|
+
return Promise.resolve();
|
|
109
|
+
},
|
|
110
|
+
deleteSetting(key) {
|
|
111
|
+
const all = asDict(readJSON(LOCAL_KEYS.settings));
|
|
112
|
+
delete all[key];
|
|
113
|
+
writeJSON(LOCAL_KEYS.settings, all);
|
|
114
|
+
return Promise.resolve();
|
|
115
|
+
},
|
|
116
|
+
clearSettings() {
|
|
117
|
+
writeJSON(LOCAL_KEYS.settings, {});
|
|
118
|
+
return Promise.resolve();
|
|
119
|
+
},
|
|
120
|
+
queueAll(store) {
|
|
121
|
+
return Promise.resolve(asList(readJSON(LOCAL_KEYS[store])));
|
|
122
|
+
},
|
|
123
|
+
queuePut(store, items) {
|
|
124
|
+
const list = asList(readJSON(LOCAL_KEYS[store]));
|
|
125
|
+
items.forEach(function (item) {
|
|
126
|
+
const index = list.findIndex(function (existing) { return existing.id === item.id; });
|
|
127
|
+
if (index === -1) {
|
|
128
|
+
list.push(item);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
list[index] = item;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
writeJSON(LOCAL_KEYS[store], list);
|
|
135
|
+
return Promise.resolve();
|
|
136
|
+
},
|
|
137
|
+
queueDelete(store, ids) {
|
|
138
|
+
const remaining = asList(readJSON(LOCAL_KEYS[store])).filter(function (item) {
|
|
139
|
+
return ids.indexOf(item.id) === -1;
|
|
140
|
+
});
|
|
141
|
+
writeJSON(LOCAL_KEYS[store], remaining);
|
|
142
|
+
return Promise.resolve();
|
|
143
|
+
},
|
|
144
|
+
queueClear(store) {
|
|
145
|
+
writeJSON(LOCAL_KEYS[store], []);
|
|
146
|
+
return Promise.resolve();
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
let lastQueue = 0;
|
|
151
|
+
/**
|
|
152
|
+
* Strictly increasing, and time-based so tabs interleave in roughly the right order.
|
|
153
|
+
* Counting up from the last value rather than a counter that wraps keeps insertion order
|
|
154
|
+
* even when a chatty caller adds more than a thousand items inside one millisecond.
|
|
155
|
+
*/
|
|
156
|
+
function nextQueue() {
|
|
157
|
+
const base = utils.nowMs() * 1000;
|
|
158
|
+
lastQueue = base > lastQueue ? base : lastQueue + 1;
|
|
159
|
+
return lastQueue;
|
|
160
|
+
}
|
|
161
|
+
function request(req) {
|
|
162
|
+
return new Promise(function (resolve, reject) {
|
|
163
|
+
req.onsuccess = function () { resolve(req.result); };
|
|
164
|
+
req.onerror = function () { reject(req.error); };
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function completed(tx) {
|
|
168
|
+
return new Promise(function (resolve, reject) {
|
|
169
|
+
tx.oncomplete = function () { resolve(); };
|
|
170
|
+
tx.onerror = function () { reject(tx.error); };
|
|
171
|
+
tx.onabort = function () { reject(tx.error); };
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The record's `type` for an item with none of its own: heatmap records carry no type, since
|
|
176
|
+
* their payload is the item itself and the server takes no extra field. Never undefined.
|
|
177
|
+
*/
|
|
178
|
+
const STORE_TYPES = Object.freeze({
|
|
179
|
+
engagements: 'engagement', // no i18n
|
|
180
|
+
errors: 'error', // no i18n
|
|
181
|
+
feedbacklogs: FEEDBACK_LOG,
|
|
182
|
+
remotelogs: 'remotelog', // no i18n
|
|
183
|
+
heatmaps: 'heatmap', // no i18n
|
|
184
|
+
});
|
|
185
|
+
function recordType(storeName, item) {
|
|
186
|
+
return item && typeof item.type === 'string' && item.type !== '' ? item.type : (STORE_TYPES[storeName] || storeName); // no i18n
|
|
187
|
+
}
|
|
188
|
+
/** Puts `item` unless it exists (keepExisting) or replaces it keeping its place. Runs inside `store`'s transaction. */
|
|
189
|
+
function putRecord(store, item, keepExisting) {
|
|
190
|
+
const id = String(item.id);
|
|
191
|
+
const lookup = store.get(id);
|
|
192
|
+
lookup.onsuccess = function () {
|
|
193
|
+
const existing = lookup.result;
|
|
194
|
+
if (existing && keepExisting) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
store.put({ id: id, queue: existing ? existing.queue : nextQueue(), type: recordType(store.name, item), item: item });
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/** Our stores, as created by onupgradeneeded. */
|
|
201
|
+
function hasAllStores(db) {
|
|
202
|
+
return db.objectStoreNames.contains('settings') && QUEUES.every(function (name) {
|
|
203
|
+
return db.objectStoreNames.contains(name);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
function deleteDatabase(factory) {
|
|
207
|
+
return new Promise(function (resolve) {
|
|
208
|
+
var req = factory.deleteDatabase(DB_NAME);
|
|
209
|
+
req.onsuccess = function () { resolve(); };
|
|
210
|
+
req.onerror = function () { resolve(); };
|
|
211
|
+
req.onblocked = function () { resolve(); };
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Opens the database, and repairs it once if something else created an "apptics" database
|
|
216
|
+
* without our stores (then onupgradeneeded never fires and every read would fail).
|
|
217
|
+
*/
|
|
218
|
+
function openIndexedDB(factory = indexedDB, timeoutMs = OPEN_TIMEOUT_MS) {
|
|
219
|
+
return openOnce(factory, timeoutMs).then(function (db) {
|
|
220
|
+
if (hasAllStores(db)) {
|
|
221
|
+
return db;
|
|
222
|
+
}
|
|
223
|
+
logger.Console.warn('apptics: the "' + DB_NAME + '" database is missing its stores, recreating it'); // no i18n
|
|
224
|
+
db.close();
|
|
225
|
+
return deleteDatabase(factory).then(function () {
|
|
226
|
+
return openOnce(factory, timeoutMs);
|
|
227
|
+
}).then(function (fresh) {
|
|
228
|
+
if (!hasAllStores(fresh)) {
|
|
229
|
+
fresh.close();
|
|
230
|
+
throw new Error('indexedDB: stores could not be created'); // no i18n
|
|
231
|
+
}
|
|
232
|
+
return fresh;
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function openOnce(factory, timeoutMs) {
|
|
237
|
+
return new Promise(function (resolve, reject) {
|
|
238
|
+
let settled = false;
|
|
239
|
+
const fail = function (reason) {
|
|
240
|
+
if (!settled) {
|
|
241
|
+
settled = true;
|
|
242
|
+
clearTimeout(timer);
|
|
243
|
+
reject(reason);
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
const timer = setTimeout(function () {
|
|
247
|
+
fail(new Error('indexedDB open timed out')); // no i18n
|
|
248
|
+
}, timeoutMs);
|
|
249
|
+
let req;
|
|
250
|
+
try {
|
|
251
|
+
req = factory.open(DB_NAME, DB_VERSION);
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
fail(err);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
req.onupgradeneeded = function () {
|
|
258
|
+
upgrade(req.result, req.transaction);
|
|
259
|
+
};
|
|
260
|
+
req.onsuccess = function () {
|
|
261
|
+
if (settled) {
|
|
262
|
+
req.result.close(); // we already gave up (timeout or blocked)
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
settled = true;
|
|
266
|
+
clearTimeout(timer);
|
|
267
|
+
// Another tab running a newer build needs to upgrade the schema, and cannot while this
|
|
268
|
+
// connection is open. Letting go is the only cooperative answer: holding on blocks that
|
|
269
|
+
// tab's upgrade until this one is closed, and it spends the whole time with no storage.
|
|
270
|
+
// This tab keeps working from memory and picks the new schema up on its next load.
|
|
271
|
+
req.result.onversionchange = function () {
|
|
272
|
+
logger.Console.warn('apptics: another tab is upgrading the database, closing this connection'); // no i18n
|
|
273
|
+
req.result.close();
|
|
274
|
+
};
|
|
275
|
+
resolve(req.result);
|
|
276
|
+
};
|
|
277
|
+
req.onerror = function () {
|
|
278
|
+
fail(req.error);
|
|
279
|
+
};
|
|
280
|
+
req.onblocked = function () {
|
|
281
|
+
// Another tab is holding an older version open. A build that sets onversionchange
|
|
282
|
+
// (above) lets go by itself, so this resolves on its own in a moment; the open is left
|
|
283
|
+
// to run until the timeout rather than abandoned, because giving up here would mean
|
|
284
|
+
// running with no storage for the rest of the visit.
|
|
285
|
+
logger.Console.warn('apptics: waiting for another tab to release the database'); // no i18n
|
|
286
|
+
};
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Creates what is missing and moves version 3's data to version 4's names, inside the upgrade's
|
|
291
|
+
* own transaction: either the whole upgrade lands, or the database stays at the old version with
|
|
292
|
+
* everything still in it.
|
|
293
|
+
*/
|
|
294
|
+
function upgrade(db, tx) {
|
|
295
|
+
if (!db.objectStoreNames.contains('settings')) { // no i18n
|
|
296
|
+
db.createObjectStore('settings'); // no i18n
|
|
297
|
+
}
|
|
298
|
+
QUEUES.forEach(function (name) {
|
|
299
|
+
if (!db.objectStoreNames.contains(name)) {
|
|
300
|
+
db.createObjectStore(name, { keyPath: 'id' }).createIndex(QUEUE_KEY, QUEUE_KEY); // no i18n
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
// kept stores: the order key is renamed on every record, and the index with it
|
|
304
|
+
QUEUES.forEach(function (name) {
|
|
305
|
+
const store = tx.objectStore(name);
|
|
306
|
+
if (!store.indexNames.contains(OLD_QUEUE_KEY)) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
store.deleteIndex(OLD_QUEUE_KEY);
|
|
310
|
+
if (!store.indexNames.contains(QUEUE_KEY)) {
|
|
311
|
+
store.createIndex(QUEUE_KEY, QUEUE_KEY);
|
|
312
|
+
}
|
|
313
|
+
eachRecord(store, function (record, cursor) {
|
|
314
|
+
cursor.update(renamedRecord(record, false, name));
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
// renamed stores: every record moves to its new store, then the old store goes
|
|
318
|
+
RENAMED_STORES.forEach(function (pair) {
|
|
319
|
+
const from = pair[0];
|
|
320
|
+
const to = pair[1];
|
|
321
|
+
if (!db.objectStoreNames.contains(from)) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
const source = tx.objectStore(from);
|
|
325
|
+
const target = tx.objectStore(to);
|
|
326
|
+
eachRecord(source, function (record) {
|
|
327
|
+
target.put(renamedRecord(record, to === 'feedbacklogs', to)); // no i18n
|
|
328
|
+
}, function () {
|
|
329
|
+
db.deleteObjectStore(from);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
/** Calls `each` for every record of `store`, then `done`, inside the transaction `store` is in. */
|
|
334
|
+
function eachRecord(store, each, done) {
|
|
335
|
+
const req = store.openCursor();
|
|
336
|
+
req.onsuccess = function () {
|
|
337
|
+
const cursor = req.result;
|
|
338
|
+
if (!cursor) {
|
|
339
|
+
if (done)
|
|
340
|
+
done();
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
each(cursor.value, cursor);
|
|
344
|
+
cursor.continue();
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
/** A version 3 record under version 4's names: `queue` for `seq`, and the feedback types renamed. */
|
|
348
|
+
function renamedRecord(record, feedback, storeName) {
|
|
349
|
+
const queue = typeof record[QUEUE_KEY] === 'number' ? record[QUEUE_KEY] : (typeof record[OLD_QUEUE_KEY] === 'number' ? record[OLD_QUEUE_KEY] : nextQueue()); // no i18n
|
|
350
|
+
const item = (feedback ? renameFeedbackType(record.item) : record.item);
|
|
351
|
+
return { id: String(record.id), queue: queue, type: recordType(storeName, item), item: item };
|
|
352
|
+
}
|
|
353
|
+
function createIndexedDBBackend(db) {
|
|
354
|
+
return {
|
|
355
|
+
kind: 'indexeddb', // no i18n
|
|
356
|
+
loadSettings() {
|
|
357
|
+
const store = db.transaction('settings', 'readonly').objectStore('settings'); // no i18n
|
|
358
|
+
return Promise.all([request(store.getAllKeys()), request(store.getAll())]).then(function ([keys, values]) {
|
|
359
|
+
const out = {};
|
|
360
|
+
keys.forEach(function (key, i) {
|
|
361
|
+
out[String(key)] = values[i];
|
|
362
|
+
});
|
|
363
|
+
return out;
|
|
364
|
+
});
|
|
365
|
+
},
|
|
366
|
+
putSetting(key, value) {
|
|
367
|
+
const tx = db.transaction('settings', 'readwrite'); // no i18n
|
|
368
|
+
tx.objectStore('settings').put(value, key); // no i18n
|
|
369
|
+
return completed(tx);
|
|
370
|
+
},
|
|
371
|
+
deleteSetting(key) {
|
|
372
|
+
const tx = db.transaction('settings', 'readwrite'); // no i18n
|
|
373
|
+
tx.objectStore('settings').delete(key); // no i18n
|
|
374
|
+
return completed(tx);
|
|
375
|
+
},
|
|
376
|
+
clearSettings() {
|
|
377
|
+
const tx = db.transaction('settings', 'readwrite'); // no i18n
|
|
378
|
+
tx.objectStore('settings').clear(); // no i18n
|
|
379
|
+
return completed(tx);
|
|
380
|
+
},
|
|
381
|
+
queueAll(store) {
|
|
382
|
+
const index = db.transaction(store, 'readonly').objectStore(store).index(QUEUE_KEY);
|
|
383
|
+
return request(index.getAll()).then(function (records) {
|
|
384
|
+
return records.map(function (record) { return record.item; });
|
|
385
|
+
});
|
|
386
|
+
},
|
|
387
|
+
queuePut(store, items) {
|
|
388
|
+
const tx = db.transaction(store, 'readwrite'); // no i18n
|
|
389
|
+
const objectStore = tx.objectStore(store);
|
|
390
|
+
items.forEach(function (item) { putRecord(objectStore, item, false); });
|
|
391
|
+
return completed(tx);
|
|
392
|
+
},
|
|
393
|
+
queueDelete(store, ids) {
|
|
394
|
+
const tx = db.transaction(store, 'readwrite'); // no i18n
|
|
395
|
+
const objectStore = tx.objectStore(store);
|
|
396
|
+
ids.forEach(function (id) { objectStore.delete(id); });
|
|
397
|
+
return completed(tx);
|
|
398
|
+
},
|
|
399
|
+
queueClear(store) {
|
|
400
|
+
const tx = db.transaction(store, 'readwrite'); // no i18n
|
|
401
|
+
tx.objectStore(store).clear();
|
|
402
|
+
return completed(tx);
|
|
403
|
+
},
|
|
404
|
+
importAll(settings, queues) {
|
|
405
|
+
// scope derived from QUEUES, not repeated: the loop below opens every one of them,
|
|
406
|
+
// and a store left out of the scope throws NotFoundError the moment it is reached
|
|
407
|
+
const tx = db.transaction(['settings'].concat(QUEUES), 'readwrite'); // no i18n
|
|
408
|
+
const settingsStore = tx.objectStore('settings'); // no i18n
|
|
409
|
+
Object.keys(settings).forEach(function (key) {
|
|
410
|
+
const lookup = settingsStore.get(key);
|
|
411
|
+
lookup.onsuccess = function () {
|
|
412
|
+
if (lookup.result === undefined) {
|
|
413
|
+
settingsStore.put(settings[key], key);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
});
|
|
417
|
+
QUEUES.forEach(function (name) {
|
|
418
|
+
const objectStore = tx.objectStore(name);
|
|
419
|
+
queues[name].forEach(function (item) { putRecord(objectStore, item, true); });
|
|
420
|
+
});
|
|
421
|
+
return completed(tx);
|
|
422
|
+
},
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
function localStorageUsable() {
|
|
426
|
+
try {
|
|
427
|
+
const probe = '__apptics_probe__'; // no i18n
|
|
428
|
+
localStorage.setItem(probe, '1');
|
|
429
|
+
localStorage.removeItem(probe);
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
catch (err) {
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
/** IndexedDB when it opens, otherwise localStorage, otherwise null. Never rejects. */
|
|
437
|
+
function openBackend() {
|
|
438
|
+
const fallback = function (reason) {
|
|
439
|
+
logger.Console.warn('apptics: IndexedDB unavailable (' + String(reason) + '), using localStorage'); // no i18n
|
|
440
|
+
return localStorageUsable() ? createLocalStorageBackend() : null;
|
|
441
|
+
};
|
|
442
|
+
let factory;
|
|
443
|
+
try {
|
|
444
|
+
factory = typeof indexedDB !== 'undefined' ? indexedDB : undefined; // no i18n
|
|
445
|
+
}
|
|
446
|
+
catch (err) {
|
|
447
|
+
factory = undefined; // access can throw in sandboxed frames
|
|
448
|
+
}
|
|
449
|
+
if (!factory) {
|
|
450
|
+
return Promise.resolve(fallback('not supported')); // no i18n
|
|
451
|
+
}
|
|
452
|
+
return openIndexedDB(factory).then(createIndexedDBBackend, fallback);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
exports.DB_NAME = DB_NAME;
|
|
456
|
+
exports.DB_VERSION = DB_VERSION;
|
|
457
|
+
exports.FEEDBACK_DIAGNOSTICS = FEEDBACK_DIAGNOSTICS;
|
|
458
|
+
exports.FEEDBACK_LOG = FEEDBACK_LOG;
|
|
459
|
+
exports.LEGACY_KEYS = LEGACY_KEYS;
|
|
460
|
+
exports.LOCAL_KEYS = LOCAL_KEYS;
|
|
461
|
+
exports.asDict = asDict;
|
|
462
|
+
exports.asList = asList;
|
|
463
|
+
exports.createIndexedDBBackend = createIndexedDBBackend;
|
|
464
|
+
exports.createLocalStorageBackend = createLocalStorageBackend;
|
|
465
|
+
exports.openBackend = openBackend;
|
|
466
|
+
exports.openIndexedDB = openIndexedDB;
|
|
467
|
+
exports.renameFeedbackType = renameFeedbackType;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Whether debug mode is on right now, idle hour included. */
|
|
2
|
+
export declare function debugEnabled(): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Pushes the idle hour out. Called wherever something is actually tracked, which is the only
|
|
5
|
+
* evidence the SDK has that a person is still looking — there is no event for "watching".
|
|
6
|
+
*/
|
|
7
|
+
export declare function noteDebugActivity(): void;
|
|
8
|
+
/**
|
|
9
|
+
* Turns debug mode off if its hour has run out. Called from the flush timer, which ticks whether
|
|
10
|
+
* or not anything is happening — a check that only ran on the way into a request would never
|
|
11
|
+
* fire, because an idle SDK makes no requests.
|
|
12
|
+
*/
|
|
13
|
+
export declare function expireDebugIfIdle(): void;
|
|
14
|
+
/**
|
|
15
|
+
* Turns debug mode on, at any time: before init(), during start-up or while the SDK runs. The
|
|
16
|
+
* choice holds over `debug` in init() for the rest of the page's life.
|
|
17
|
+
*/
|
|
18
|
+
export declare function enableDebug(): void;
|
|
19
|
+
/** Turns debug mode off, at any time, with the same hold over `debug` as enableDebug(). */
|
|
20
|
+
export declare function disableDebug(): void;
|
|
21
|
+
/** What init() applies for `debug`: the config's value, unless the app has already chosen. */
|
|
22
|
+
export declare function applyDebugConfig(configured: boolean): void;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (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
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The switch for debug mode, and the hour that closes it.
|
|
11
|
+
*
|
|
12
|
+
* Debug mode is not free on either side: every engagement, exception and log call goes to its
|
|
13
|
+
* `debug/` twin instead of the ordinary endpoint, which makes the server keep a traceable
|
|
14
|
+
* record of the request. That is worth it while someone is watching, and pure
|
|
15
|
+
* cost once they have walked away — and walking away is the normal way a debugging session ends,
|
|
16
|
+
* not a deliberate switch-off. So the SDK closes it: an hour with nothing tracked turns debug
|
|
17
|
+
* back off by itself, and anything tracked pushes that hour out again.
|
|
18
|
+
*
|
|
19
|
+
* It lives in core because every send asks it: `debug: true` in init(), or enableDebug(), is
|
|
20
|
+
* enough to turn the twins on, and that alone must expire.
|
|
21
|
+
*/
|
|
22
|
+
/** Whether debug mode is on right now, idle hour included. */
|
|
23
|
+
function debugEnabled() {
|
|
24
|
+
return state._ZAP._config.debug_api === true && !debugIdle();
|
|
25
|
+
}
|
|
26
|
+
/** True once the idle hour has run out on a debug session nobody is watching. */
|
|
27
|
+
function debugIdle() {
|
|
28
|
+
return state._ZAP._debugUntil > 0 && utils.nowMs() > state._ZAP._debugUntil;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Pushes the idle hour out. Called wherever something is actually tracked, which is the only
|
|
32
|
+
* evidence the SDK has that a person is still looking — there is no event for "watching".
|
|
33
|
+
*/
|
|
34
|
+
function noteDebugActivity() {
|
|
35
|
+
if (state._ZAP._config.debug_api !== true) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
state._ZAP._debugUntil = utils.nowMs() + constants.DEBUG_IDLE_MS;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Turns debug mode off if its hour has run out. Called from the flush timer, which ticks whether
|
|
42
|
+
* or not anything is happening — a check that only ran on the way into a request would never
|
|
43
|
+
* fire, because an idle SDK makes no requests.
|
|
44
|
+
*/
|
|
45
|
+
function expireDebugIfIdle() {
|
|
46
|
+
if (!debugIdle()) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
logger.Console.log('apptics: debug mode has been idle for an hour, switching it off'); // no i18n
|
|
50
|
+
setDebug(false);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The app's own choice, from enableDebug() or disableDebug(). It wins over `debug` in init(),
|
|
54
|
+
* so debug mode can be switched on or off with one call, before init() runs or while the SDK is
|
|
55
|
+
* running, and an init() or reset() that comes after doesn't switch it back. null until the app
|
|
56
|
+
* has chosen.
|
|
57
|
+
*/
|
|
58
|
+
var chosen = null;
|
|
59
|
+
/** Turning it on starts the idle hour; turning it off clears it, so the next on gets a whole hour. */
|
|
60
|
+
function setDebug(on) {
|
|
61
|
+
state._ZAP._config.debug_api = on;
|
|
62
|
+
state._ZAP._debugUntil = on ? utils.nowMs() + constants.DEBUG_IDLE_MS : 0;
|
|
63
|
+
logger.Console.log('apptics: debug mode ' + (on ? 'on' : 'off')); // no i18n
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Turns debug mode on, at any time: before init(), during start-up or while the SDK runs. The
|
|
67
|
+
* choice holds over `debug` in init() for the rest of the page's life.
|
|
68
|
+
*/
|
|
69
|
+
function enableDebug() {
|
|
70
|
+
chosen = true;
|
|
71
|
+
setDebug(true);
|
|
72
|
+
}
|
|
73
|
+
/** Turns debug mode off, at any time, with the same hold over `debug` as enableDebug(). */
|
|
74
|
+
function disableDebug() {
|
|
75
|
+
chosen = false;
|
|
76
|
+
setDebug(false);
|
|
77
|
+
}
|
|
78
|
+
/** What init() applies for `debug`: the config's value, unless the app has already chosen. */
|
|
79
|
+
function applyDebugConfig(configured) {
|
|
80
|
+
setDebug(chosen !== null ? chosen : configured);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
exports.applyDebugConfig = applyDebugConfig;
|
|
84
|
+
exports.debugEnabled = debugEnabled;
|
|
85
|
+
exports.disableDebug = disableDebug;
|
|
86
|
+
exports.enableDebug = enableDebug;
|
|
87
|
+
exports.expireDebugIfIdle = expireDebugIfIdle;
|
|
88
|
+
exports.noteDebugActivity = noteDebugActivity;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AppticsConfig } from '../types.js';
|
|
2
|
+
export declare function isBlockedWS(ua: string): boolean;
|
|
3
|
+
/** Device RAM as the API wants it ("4 GB"). Chromium only; empty elsewhere. */
|
|
4
|
+
export declare function getRam(): string;
|
|
5
|
+
export declare function getConnectionType(): string;
|
|
6
|
+
export declare function getNetworkStatus(): number;
|
|
7
|
+
/**
|
|
8
|
+
* The battery as a whole percentage, or null where the browser will not say.
|
|
9
|
+
*
|
|
10
|
+
* feedbackWebSDK types `battery` as an int and the console shows it next to a report, which is
|
|
11
|
+
* what makes "it died while I was filling this in" legible. The Battery Status API is behind a
|
|
12
|
+
* promise and is absent in Firefox and Safari entirely, so this answers null rather than 0 -
|
|
13
|
+
* a real 0% and "no answer" are different things, and only one of them belongs in a report.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getBatteryPercent(): Promise<number | null>;
|
|
16
|
+
export declare function getOrientation(): number;
|
|
17
|
+
export declare function getDevice(): string;
|
|
18
|
+
export declare function getOS(): string;
|
|
19
|
+
export declare function getBrowser(): string;
|
|
20
|
+
export declare function getBrowserVersion(): number | string;
|
|
21
|
+
export declare function getReferringURL(): string;
|
|
22
|
+
export declare function getTimeZone(): string;
|
|
23
|
+
/** True for crawlers and non-browser environments; the SDK does nothing for them. */
|
|
24
|
+
export declare function is_apptics_disabled(): boolean;
|
|
25
|
+
/** Pure DNT check (no side effects). consent.hasDoNotTrackEnabled() applies NO_TRACKING. */
|
|
26
|
+
export declare function isDntOn(): boolean;
|
|
27
|
+
/** The console snippet's config (window.appticssettings._defaultoptions), if the page defines one. */
|
|
28
|
+
export declare function getSnippetOptions(): AppticsConfig | undefined;
|