@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.
Files changed (243) hide show
  1. package/CHANGELOG.md +193 -0
  2. package/LICENSE +13 -0
  3. package/README.md +846 -11
  4. package/dist/apptics.esm.min.js +3 -0
  5. package/dist/apptics.esm.min.js.map +1 -0
  6. package/dist/apptics.min.js +3 -0
  7. package/dist/apptics.min.js.map +1 -0
  8. package/dist/chunks/lifecycle-VYr43KcB.min.js +3 -0
  9. package/dist/chunks/lifecycle-VYr43KcB.min.js.map +1 -0
  10. package/dist/cjs/auto-init.d.ts +8 -0
  11. package/dist/cjs/auto-init.js +32 -0
  12. package/dist/cjs/core/attempts.d.ts +28 -0
  13. package/dist/cjs/core/attempts.js +113 -0
  14. package/dist/cjs/core/batch.d.ts +32 -0
  15. package/dist/cjs/core/batch.js +116 -0
  16. package/dist/cjs/core/callsite.d.ts +34 -0
  17. package/dist/cjs/core/callsite.js +115 -0
  18. package/dist/cjs/core/consent.d.ts +27 -0
  19. package/dist/cjs/core/consent.js +132 -0
  20. package/dist/cjs/core/constants.d.ts +237 -0
  21. package/dist/cjs/core/constants.js +315 -0
  22. package/dist/cjs/core/db.d.ts +48 -0
  23. package/dist/cjs/core/db.js +467 -0
  24. package/dist/cjs/core/debug.d.ts +22 -0
  25. package/dist/cjs/core/debug.js +88 -0
  26. package/dist/cjs/core/env.d.ts +28 -0
  27. package/dist/cjs/core/env.js +267 -0
  28. package/dist/cjs/core/framework-id.d.ts +1 -0
  29. package/dist/cjs/core/framework-id.js +9 -0
  30. package/dist/cjs/core/guard.d.ts +11 -0
  31. package/dist/cjs/core/guard.js +86 -0
  32. package/dist/cjs/core/hooks.d.ts +39 -0
  33. package/dist/cjs/core/hooks.js +22 -0
  34. package/dist/cjs/core/locks.d.ts +9 -0
  35. package/dist/cjs/core/locks.js +22 -0
  36. package/dist/cjs/core/logger.d.ts +15 -0
  37. package/dist/cjs/core/logger.js +50 -0
  38. package/dist/cjs/core/state.d.ts +70 -0
  39. package/dist/cjs/core/state.js +78 -0
  40. package/dist/cjs/core/storage.d.ts +61 -0
  41. package/dist/cjs/core/storage.js +327 -0
  42. package/dist/cjs/core/stylesheet.d.ts +8 -0
  43. package/dist/cjs/core/stylesheet.js +29 -0
  44. package/dist/cjs/core/transport.d.ts +85 -0
  45. package/dist/cjs/core/transport.js +456 -0
  46. package/dist/cjs/core/utils.d.ts +26 -0
  47. package/dist/cjs/core/utils.js +175 -0
  48. package/dist/cjs/core/validate.d.ts +18 -0
  49. package/dist/cjs/core/validate.js +233 -0
  50. package/dist/cjs/device/appversion.d.ts +15 -0
  51. package/dist/cjs/device/appversion.js +170 -0
  52. package/dist/cjs/device/index.d.ts +34 -0
  53. package/dist/cjs/device/index.js +472 -0
  54. package/dist/cjs/engagement/api-rules.d.ts +49 -0
  55. package/dist/cjs/engagement/api-rules.js +206 -0
  56. package/dist/cjs/engagement/auto-api.d.ts +7 -0
  57. package/dist/cjs/engagement/auto-api.js +200 -0
  58. package/dist/cjs/engagement/auto-screen.d.ts +18 -0
  59. package/dist/cjs/engagement/auto-screen.js +305 -0
  60. package/dist/cjs/engagement/defined-events.d.ts +23 -0
  61. package/dist/cjs/engagement/defined-events.js +58 -0
  62. package/dist/cjs/engagement/send.d.ts +6 -0
  63. package/dist/cjs/engagement/send.js +104 -0
  64. package/dist/cjs/engagement/session.d.ts +51 -0
  65. package/dist/cjs/engagement/session.js +463 -0
  66. package/dist/cjs/engagement/track.d.ts +56 -0
  67. package/dist/cjs/engagement/track.js +375 -0
  68. package/dist/cjs/errors/send.d.ts +6 -0
  69. package/dist/cjs/errors/send.js +73 -0
  70. package/dist/cjs/errors/track.d.ts +4 -0
  71. package/dist/cjs/errors/track.js +167 -0
  72. package/dist/cjs/feedback/controls.d.ts +37 -0
  73. package/dist/cjs/feedback/controls.js +316 -0
  74. package/dist/cjs/feedback/index.d.ts +9 -0
  75. package/dist/cjs/feedback/index.js +56 -0
  76. package/dist/cjs/feedback/logs.d.ts +45 -0
  77. package/dist/cjs/feedback/logs.js +241 -0
  78. package/dist/cjs/feedback/quartz.d.ts +18 -0
  79. package/dist/cjs/feedback/quartz.js +105 -0
  80. package/dist/cjs/feedback/send.d.ts +28 -0
  81. package/dist/cjs/feedback/send.js +203 -0
  82. package/dist/cjs/feedback/styles.d.ts +10 -0
  83. package/dist/cjs/feedback/styles.js +8 -0
  84. package/dist/cjs/feedback/template.d.ts +2 -0
  85. package/dist/cjs/feedback/template.js +162 -0
  86. package/dist/cjs/feedback/ui.d.ts +63 -0
  87. package/dist/cjs/feedback/ui.js +709 -0
  88. package/dist/cjs/heatmap/send.d.ts +13 -0
  89. package/dist/cjs/heatmap/send.js +82 -0
  90. package/dist/cjs/heatmap/track.d.ts +4 -0
  91. package/dist/cjs/heatmap/track.js +448 -0
  92. package/dist/cjs/index.d.ts +22 -0
  93. package/dist/cjs/index.js +162 -0
  94. package/dist/cjs/lifecycle.d.ts +21 -0
  95. package/dist/cjs/lifecycle.js +734 -0
  96. package/dist/cjs/package.json +3 -0
  97. package/dist/cjs/remoteconfig/country.d.ts +4 -0
  98. package/dist/cjs/remoteconfig/country.js +73 -0
  99. package/dist/cjs/remoteconfig/custom.d.ts +10 -0
  100. package/dist/cjs/remoteconfig/custom.js +58 -0
  101. package/dist/cjs/remoteconfig/evaluate.d.ts +24 -0
  102. package/dist/cjs/remoteconfig/evaluate.js +184 -0
  103. package/dist/cjs/remoteconfig/fetch.d.ts +24 -0
  104. package/dist/cjs/remoteconfig/fetch.js +200 -0
  105. package/dist/cjs/remoteconfig/index.d.ts +15 -0
  106. package/dist/cjs/remoteconfig/index.js +116 -0
  107. package/dist/cjs/remoteconfig/store.d.ts +18 -0
  108. package/dist/cjs/remoteconfig/store.js +98 -0
  109. package/dist/cjs/remoteconfig/tz-countries.d.ts +8 -0
  110. package/dist/cjs/remoteconfig/tz-countries.js +13 -0
  111. package/dist/cjs/remotelog/gate.d.ts +2 -0
  112. package/dist/cjs/remotelog/gate.js +28 -0
  113. package/dist/cjs/remotelog/index.d.ts +8 -0
  114. package/dist/cjs/remotelog/logger.d.ts +22 -0
  115. package/dist/cjs/remotelog/logger.js +111 -0
  116. package/dist/cjs/remotelog/send.d.ts +13 -0
  117. package/dist/cjs/remotelog/send.js +153 -0
  118. package/dist/cjs/remotelogger/index.d.ts +12 -0
  119. package/dist/cjs/remotelogger/index.js +18 -0
  120. package/dist/cjs/scheduler.d.ts +8 -0
  121. package/dist/cjs/scheduler.js +78 -0
  122. package/dist/cjs/types.d.ts +385 -0
  123. package/dist/cjs/user/index.d.ts +33 -0
  124. package/dist/cjs/user/index.js +183 -0
  125. package/dist/esm/auto-init.d.ts +8 -0
  126. package/dist/esm/auto-init.js +29 -0
  127. package/dist/esm/core/attempts.d.ts +28 -0
  128. package/dist/esm/core/attempts.js +106 -0
  129. package/dist/esm/core/batch.d.ts +32 -0
  130. package/dist/esm/core/batch.js +109 -0
  131. package/dist/esm/core/callsite.d.ts +34 -0
  132. package/dist/esm/core/callsite.js +110 -0
  133. package/dist/esm/core/consent.d.ts +27 -0
  134. package/dist/esm/core/consent.js +122 -0
  135. package/dist/esm/core/constants.d.ts +237 -0
  136. package/dist/esm/core/constants.js +292 -0
  137. package/dist/esm/core/db.d.ts +48 -0
  138. package/dist/esm/core/db.js +453 -0
  139. package/dist/esm/core/debug.d.ts +22 -0
  140. package/dist/esm/core/debug.js +81 -0
  141. package/dist/esm/core/env.d.ts +28 -0
  142. package/dist/esm/core/env.js +251 -0
  143. package/dist/esm/core/framework-id.d.ts +1 -0
  144. package/dist/esm/core/framework-id.js +7 -0
  145. package/dist/esm/core/guard.d.ts +11 -0
  146. package/dist/esm/core/guard.js +83 -0
  147. package/dist/esm/core/hooks.d.ts +39 -0
  148. package/dist/esm/core/hooks.js +20 -0
  149. package/dist/esm/core/locks.d.ts +9 -0
  150. package/dist/esm/core/locks.js +20 -0
  151. package/dist/esm/core/logger.d.ts +15 -0
  152. package/dist/esm/core/logger.js +46 -0
  153. package/dist/esm/core/state.d.ts +70 -0
  154. package/dist/esm/core/state.js +73 -0
  155. package/dist/esm/core/storage.d.ts +61 -0
  156. package/dist/esm/core/storage.js +314 -0
  157. package/dist/esm/core/stylesheet.d.ts +8 -0
  158. package/dist/esm/core/stylesheet.js +27 -0
  159. package/dist/esm/core/transport.d.ts +85 -0
  160. package/dist/esm/core/transport.js +439 -0
  161. package/dist/esm/core/utils.d.ts +26 -0
  162. package/dist/esm/core/utils.js +161 -0
  163. package/dist/esm/core/validate.d.ts +18 -0
  164. package/dist/esm/core/validate.js +226 -0
  165. package/dist/esm/device/appversion.d.ts +15 -0
  166. package/dist/esm/device/appversion.js +164 -0
  167. package/dist/esm/device/index.d.ts +34 -0
  168. package/dist/esm/device/index.js +461 -0
  169. package/dist/esm/engagement/api-rules.d.ts +49 -0
  170. package/dist/esm/engagement/api-rules.js +199 -0
  171. package/dist/esm/engagement/auto-api.d.ts +7 -0
  172. package/dist/esm/engagement/auto-api.js +198 -0
  173. package/dist/esm/engagement/auto-screen.d.ts +18 -0
  174. package/dist/esm/engagement/auto-screen.js +301 -0
  175. package/dist/esm/engagement/defined-events.d.ts +23 -0
  176. package/dist/esm/engagement/defined-events.js +55 -0
  177. package/dist/esm/engagement/send.d.ts +6 -0
  178. package/dist/esm/engagement/send.js +101 -0
  179. package/dist/esm/engagement/session.d.ts +51 -0
  180. package/dist/esm/engagement/session.js +448 -0
  181. package/dist/esm/engagement/track.d.ts +56 -0
  182. package/dist/esm/engagement/track.js +365 -0
  183. package/dist/esm/errors/send.d.ts +6 -0
  184. package/dist/esm/errors/send.js +70 -0
  185. package/dist/esm/errors/track.d.ts +4 -0
  186. package/dist/esm/errors/track.js +163 -0
  187. package/dist/esm/feedback/controls.d.ts +37 -0
  188. package/dist/esm/feedback/controls.js +309 -0
  189. package/dist/esm/feedback/index.d.ts +9 -0
  190. package/dist/esm/feedback/index.js +51 -0
  191. package/dist/esm/feedback/logs.d.ts +45 -0
  192. package/dist/esm/feedback/logs.js +227 -0
  193. package/dist/esm/feedback/quartz.d.ts +18 -0
  194. package/dist/esm/feedback/quartz.js +99 -0
  195. package/dist/esm/feedback/send.d.ts +28 -0
  196. package/dist/esm/feedback/send.js +198 -0
  197. package/dist/esm/feedback/styles.d.ts +10 -0
  198. package/dist/esm/feedback/styles.js +4 -0
  199. package/dist/esm/feedback/template.d.ts +2 -0
  200. package/dist/esm/feedback/template.js +159 -0
  201. package/dist/esm/feedback/ui.d.ts +63 -0
  202. package/dist/esm/feedback/ui.js +703 -0
  203. package/dist/esm/heatmap/send.d.ts +13 -0
  204. package/dist/esm/heatmap/send.js +79 -0
  205. package/dist/esm/heatmap/track.d.ts +4 -0
  206. package/dist/esm/heatmap/track.js +445 -0
  207. package/dist/esm/index.d.ts +22 -0
  208. package/dist/esm/index.js +150 -0
  209. package/dist/esm/lifecycle.d.ts +21 -0
  210. package/dist/esm/lifecycle.js +729 -0
  211. package/dist/esm/package.json +3 -0
  212. package/dist/esm/remoteconfig/country.d.ts +4 -0
  213. package/dist/esm/remoteconfig/country.js +70 -0
  214. package/dist/esm/remoteconfig/custom.d.ts +10 -0
  215. package/dist/esm/remoteconfig/custom.js +54 -0
  216. package/dist/esm/remoteconfig/evaluate.d.ts +24 -0
  217. package/dist/esm/remoteconfig/evaluate.js +179 -0
  218. package/dist/esm/remoteconfig/fetch.d.ts +24 -0
  219. package/dist/esm/remoteconfig/fetch.js +196 -0
  220. package/dist/esm/remoteconfig/index.d.ts +15 -0
  221. package/dist/esm/remoteconfig/index.js +111 -0
  222. package/dist/esm/remoteconfig/store.d.ts +18 -0
  223. package/dist/esm/remoteconfig/store.js +91 -0
  224. package/dist/esm/remoteconfig/tz-countries.d.ts +8 -0
  225. package/dist/esm/remoteconfig/tz-countries.js +11 -0
  226. package/dist/esm/remotelog/gate.d.ts +2 -0
  227. package/dist/esm/remotelog/gate.js +26 -0
  228. package/dist/esm/remotelog/index.d.ts +8 -0
  229. package/dist/esm/remotelog/logger.d.ts +22 -0
  230. package/dist/esm/remotelog/logger.js +108 -0
  231. package/dist/esm/remotelog/send.d.ts +13 -0
  232. package/dist/esm/remotelog/send.js +149 -0
  233. package/dist/esm/remotelogger/index.d.ts +12 -0
  234. package/dist/esm/remotelogger/index.js +13 -0
  235. package/dist/esm/scheduler.d.ts +8 -0
  236. package/dist/esm/scheduler.js +74 -0
  237. package/dist/esm/types.d.ts +385 -0
  238. package/dist/esm/user/index.d.ts +33 -0
  239. package/dist/esm/user/index.js +176 -0
  240. package/dist/feedback.esm.min.js +3 -0
  241. package/dist/feedback.esm.min.js.map +1 -0
  242. package/package.json +122 -7
  243. package/src/appticssdk.js +0 -1
@@ -0,0 +1,78 @@
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 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
+ _quartz: { enabled: false, workspace: '', department: '', domain: '', cdnUrl: '' }, // no i18n
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,61 @@
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 feedbacklog_transactions: Queue;
24
+ /** Clicks and scrolls waiting for heatmap/add. */
25
+ export declare const heatmap_transactions: Queue;
26
+ /**
27
+ * Remote log lines waiting for log/add. 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 remotelog_transactions: Queue;
32
+ /**
33
+ * Sets one key of the stored device_info, and of this tab's copy: the uuid the device is
34
+ * registered under, whether it has had a session. Its other keys stay as they are.
35
+ */
36
+ export declare function setDeviceInfoKey(key: string, value: unknown): void;
37
+ /** device_info (uuid included), app_version_info, trackinfo (tracking_status included), users, user_info, and the rest. */
38
+ export declare const user_defaults: {
39
+ all(): Dict;
40
+ item(key: string): any;
41
+ add(key: string, value: unknown): void;
42
+ /** As add(), and resolves once the value is in storage, where other tabs can read it. */
43
+ save(key: string, value: unknown): Promise<void>;
44
+ clear(): void;
45
+ };
46
+ /**
47
+ * Re-reads `keys` from storage. Settings are loaded into memory once, when a tab starts, so a value
48
+ * another tab of this site wrote since then — the device ids it registered — is only in storage.
49
+ * A key storage doesn't hold keeps this tab's value.
50
+ */
51
+ export declare function reloadSettings(keys: string[]): Promise<void>;
52
+ /** The visitor's tracking status, stored in trackinfo as tracking_status. */
53
+ export declare function storedTrackingStatus(): TrackingStatus | undefined;
54
+ /** Opt-in status, stored in the trackinfo setting as tracking_status. */
55
+ export declare const tracking_preference: {
56
+ _tracking_status: string;
57
+ all(): Dict;
58
+ opt_in_status(): TrackingStatus;
59
+ update_status(tracking_status: TrackingStatus): void;
60
+ };
61
+ export declare function getKeyFromDeviceInfo(key: string): any;
@@ -0,0 +1,327 @@
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
+ 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
+ };
34
+ }
35
+ catch (err) {
36
+ return Promise.resolve();
37
+ }
38
+ if (raw.settings === null && raw.engagements === null && raw.errors === null && raw.logs === null
39
+ && raw.consolelogs === null) {
40
+ return Promise.resolve();
41
+ }
42
+ var parse = function (text) {
43
+ try {
44
+ return text === null ? null : JSON.parse(text);
45
+ }
46
+ catch (err) {
47
+ return null;
48
+ }
49
+ };
50
+ // 1.x's keys are logs and consolelogs; they are feedbacklogs and remotelogs now, and a
51
+ // feedback entry's type is feedbacklog or feedbackdiagnostics instead of log or diagnostics
52
+ var queues = {
53
+ engagements: db.asList(parse(raw.engagements)),
54
+ errors: db.asList(parse(raw.errors)),
55
+ feedbacklogs: db.asList(parse(raw.logs)).map(db.renameFeedbackType),
56
+ remotelogs: db.asList(parse(raw.consolelogs)),
57
+ // nothing to migrate: 1.x had no heatmaps
58
+ heatmaps: [],
59
+ };
60
+ queues.engagements.concat(queues.errors, queues.feedbacklogs, queues.remotelogs).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
+ moveRetiredSettings();
95
+ return b;
96
+ });
97
+ }).catch(function (err) {
98
+ logger.Console.warn('apptics: storage unavailable: ' + String(err)); // no i18n
99
+ return null;
100
+ });
101
+ }
102
+ return readyPromise;
103
+ }
104
+ /** When an item happened: engagements carry starttime, errors and logs happenedat. */
105
+ function itemTime(item) {
106
+ return item.starttime !== undefined ? item.starttime : item.happenedat;
107
+ }
108
+ /** First batch_size items, capped at 1 MB. */
109
+ function takeBatch(items) {
110
+ const targetSize = 1024 * 1024; // 1 MB in bytes
111
+ let dataSize = 0;
112
+ const result = [];
113
+ for (const item of items.slice(0, state.getConfig('batch_size'))) { // no i18n
114
+ const size = utils.sizeof(JSON.stringify(item));
115
+ if (dataSize + size > targetSize) {
116
+ break;
117
+ }
118
+ result.push(item);
119
+ dataSize += size;
120
+ }
121
+ return result;
122
+ }
123
+ function createQueue(name) {
124
+ const queue = {
125
+ name: name,
126
+ all() {
127
+ return withBackend('read ' + name, [], function (b) { return b.queueAll(name); }); // no i18n
128
+ },
129
+ payload() {
130
+ return queue.all().then(takeBatch);
131
+ },
132
+ add(item) {
133
+ if (!item.id) {
134
+ item.id = utils.getNewUUID();
135
+ }
136
+ // a week-old item would only be dropped at send time, so don't store it at all
137
+ if (state.isExpired(itemTime(item))) {
138
+ logger.Console.warn('apptics: dropping a ' + name + ' item older than ' + state.getConfig('batch_request_timeout') + ' days'); // no i18n
139
+ return Promise.resolve();
140
+ }
141
+ return withBackend('add ' + name, undefined, function (b) { return b.queuePut(name, [item]); }); // no i18n
142
+ },
143
+ update(item) {
144
+ return withBackend('update ' + name, undefined, function (b) { return b.queuePut(name, [item]); }); // no i18n
145
+ },
146
+ remove(itemsToRemove) {
147
+ const ids = (itemsToRemove || []).map(function (item) { return String(item.id); });
148
+ return withBackend('remove ' + name, undefined, function (b) { return b.queueDelete(name, ids); }); // no i18n
149
+ },
150
+ clear() {
151
+ return withBackend('clear ' + name, undefined, function (b) { return b.queueClear(name); }); // no i18n
152
+ },
153
+ };
154
+ return queue;
155
+ }
156
+ /** Sessions, screens, events and api calls waiting to be sent. */
157
+ const engagement_transactions = createQueue('engagements'); // no i18n
158
+ /** Errors waiting to be sent. */
159
+ const error_transactions = createQueue('errors'); // no i18n
160
+ /**
161
+ * Feedback log lines and diagnostics entries, from addFeedbackLog() and addDiagnosticsInfo().
162
+ * These are not sent on their own: feedback/logs.ts renders them into the files that
163
+ * feedback/add carries, and removes the ones a submission took with it.
164
+ */
165
+ const feedbacklog_transactions = createQueue('feedbacklogs'); // no i18n
166
+ /** Clicks and scrolls waiting for heatmap/add. */
167
+ const heatmap_transactions = createQueue('heatmaps'); // no i18n
168
+ /**
169
+ * Remote log lines waiting for log/add. Stored rather than sent straight out because the
170
+ * endpoint takes one line per call and counts retries (`attempt`), so a line has to outlive a
171
+ * failed send — and a reload.
172
+ */
173
+ const remotelog_transactions = createQueue('remotelogs'); // no i18n
174
+ /* ---------------- settings (sync reads, background writes) ---------------- */
175
+ /** Writes `key`, or removes it from storage altogether when `value` is undefined. */
176
+ function writeSetting(b, key) {
177
+ return settings[key] === undefined ? b.deleteSetting(key) : b.putSetting(key, settings[key]);
178
+ }
179
+ function setSetting(key, value) {
180
+ if (value === undefined) {
181
+ delete settings[key];
182
+ }
183
+ else {
184
+ settings[key] = utils.cloneObject(value);
185
+ }
186
+ withBackend('save ' + key, undefined, function (b) { return writeSetting(b, key); }); // no i18n
187
+ }
188
+ /**
189
+ * Settings 2.0.0-beta kept as keys of their own, now kept inside device_info and trackinfo.
190
+ * Moved once, on the first load after an upgrade, before anything reads them: the uuid is the one
191
+ * the device is registered under, and the tracking status is the visitor's own choice, so losing
192
+ * either would register a new device or forget a consent. token was never read, and goes.
193
+ * appkey and appversion are read and removed by init(), which compares them with this visit's app.
194
+ */
195
+ function moveRetiredSettings() {
196
+ var device = settings.device_info && typeof settings.device_info === 'object' ? settings.device_info : null; // no i18n
197
+ if (settings.uuid !== undefined || settings.hadsession !== undefined) {
198
+ device = Object.assign({}, device || {});
199
+ if (utils.isEmpty(device.uuid) && !utils.isEmpty(settings.uuid)) {
200
+ device.uuid = settings.uuid;
201
+ }
202
+ if (settings.hadsession === true) {
203
+ device.hadsession = true;
204
+ }
205
+ setSetting('device_info', device); // no i18n
206
+ setSetting('uuid', undefined); // no i18n
207
+ setSetting('hadsession', undefined); // no i18n
208
+ }
209
+ if (settings.tracking_status !== undefined) {
210
+ var track = Object.assign({}, settings.trackinfo && typeof settings.trackinfo === 'object' ? settings.trackinfo : {}); // no i18n
211
+ if (track.tracking_status === undefined) {
212
+ track.tracking_status = settings.tracking_status;
213
+ }
214
+ setSetting('trackinfo', track); // no i18n
215
+ setSetting('tracking_status', undefined); // no i18n
216
+ }
217
+ if (settings.token !== undefined) {
218
+ setSetting('token', undefined); // no i18n
219
+ }
220
+ }
221
+ /**
222
+ * Sets one key of the stored device_info, and of this tab's copy: the uuid the device is
223
+ * registered under, whether it has had a session. Its other keys stay as they are.
224
+ */
225
+ function setDeviceInfoKey(key, value) {
226
+ var device = Object.assign({}, settings.device_info && typeof settings.device_info === 'object' ? settings.device_info : {}); // no i18n
227
+ device[key] = value;
228
+ if (state._ZAP._device_info && typeof state._ZAP._device_info === 'object') { // no i18n
229
+ state._ZAP._device_info[key] = value;
230
+ }
231
+ setSetting('device_info', device); // no i18n
232
+ }
233
+ /** device_info (uuid included), app_version_info, trackinfo (tracking_status included), users, user_info, and the rest. */
234
+ const user_defaults = {
235
+ all() {
236
+ return utils.cloneObject(settings);
237
+ },
238
+ item(key) {
239
+ const value = settings[key];
240
+ return value === undefined ? undefined : utils.cloneObject(value);
241
+ },
242
+ add(key, value) {
243
+ setSetting(key, value);
244
+ },
245
+ /** As add(), and resolves once the value is in storage, where other tabs can read it. */
246
+ save(key, value) {
247
+ if (value === undefined) {
248
+ delete settings[key];
249
+ }
250
+ else {
251
+ settings[key] = utils.cloneObject(value);
252
+ }
253
+ return withBackend('save ' + key, undefined, function (b) { return writeSetting(b, key); }); // no i18n
254
+ },
255
+ clear() {
256
+ settings = {};
257
+ withBackend('clear settings', undefined, function (b) { return b.clearSettings(); }); // no i18n
258
+ },
259
+ };
260
+ /**
261
+ * Re-reads `keys` from storage. Settings are loaded into memory once, when a tab starts, so a value
262
+ * another tab of this site wrote since then — the device ids it registered — is only in storage.
263
+ * A key storage doesn't hold keeps this tab's value.
264
+ */
265
+ function reloadSettings(keys) {
266
+ return withBackend('reload settings', undefined, function (b) {
267
+ return b.loadSettings().then(function (loaded) {
268
+ keys.forEach(function (key) {
269
+ if (loaded[key] !== undefined) {
270
+ settings[key] = loaded[key];
271
+ }
272
+ });
273
+ });
274
+ });
275
+ }
276
+ /** The visitor's tracking status, stored in trackinfo as tracking_status. */
277
+ function storedTrackingStatus() {
278
+ var track = settings.trackinfo;
279
+ var status = track && typeof track === 'object' ? track.tracking_status : undefined; // no i18n
280
+ // a status only: getsdkconfig's own answer uses the same key for its per-module flags, and
281
+ // one stored by mistake must not read as a consent and stop all tracking
282
+ return status === constants.AP_TRACKING_STATUS.USAGE_TRACKING_WITH_PII || status === constants.AP_TRACKING_STATUS.USAGE_TRACKING_WITHOUT_PII
283
+ || status === constants.AP_TRACKING_STATUS.NO_TRACKING ? status : undefined;
284
+ }
285
+ /** Opt-in status, stored in the trackinfo setting as tracking_status. */
286
+ const tracking_preference = {
287
+ _tracking_status: 'tracking_status', // no i18n
288
+ all() {
289
+ return user_defaults.all();
290
+ },
291
+ opt_in_status() {
292
+ return (storedTrackingStatus() || constants.AP_TRACKING_STATUS.USAGE_TRACKING_WITHOUT_PII);
293
+ },
294
+ update_status(tracking_status) {
295
+ state._ZAP._devicestatus = tracking_status;
296
+ // Legacy order kept: this reads the status *before* the write below (setTrackingStatus recomputes it after).
297
+ state._ZAP._isanonrequired =
298
+ tracking_preference.opt_in_status() == constants.AP_TRACKING_STATUS.USAGE_TRACKING_WITH_PII ? false : state._ZAP._isanonrequired;
299
+ var track = Object.assign({}, settings.trackinfo && typeof settings.trackinfo === 'object' ? settings.trackinfo : {}); // no i18n
300
+ track.tracking_status = tracking_status;
301
+ if (state._ZAP._trackinfo && typeof state._ZAP._trackinfo === 'object') { // no i18n
302
+ state._ZAP._trackinfo.tracking_status = tracking_status;
303
+ }
304
+ setSetting('trackinfo', track); // no i18n
305
+ },
306
+ };
307
+ function getKeyFromDeviceInfo(key) {
308
+ var current_device_info = settings['device_info']; // no i18n
309
+ if (current_device_info !== undefined && current_device_info !== null && current_device_info !== '' &&
310
+ current_device_info[key] !== undefined && current_device_info[key] !== null && current_device_info[key] !== '') {
311
+ return utils.cloneObject(current_device_info[key]);
312
+ }
313
+ return null;
314
+ }
315
+
316
+ exports.engagement_transactions = engagement_transactions;
317
+ exports.error_transactions = error_transactions;
318
+ exports.feedbacklog_transactions = feedbacklog_transactions;
319
+ exports.getKeyFromDeviceInfo = getKeyFromDeviceInfo;
320
+ exports.heatmap_transactions = heatmap_transactions;
321
+ exports.reloadSettings = reloadSettings;
322
+ exports.remotelog_transactions = remotelog_transactions;
323
+ exports.setDeviceInfoKey = setDeviceInfoKey;
324
+ exports.storageReady = storageReady;
325
+ exports.storedTrackingStatus = storedTrackingStatus;
326
+ exports.tracking_preference = tracking_preference;
327
+ exports.user_defaults = user_defaults;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Adds the feedback form's styles to the page, once, as a <style> element, so no app imports or
3
+ * links a stylesheet: the css is carried in the JavaScript, for npm and the CDN builds alike.
4
+ *
5
+ * Nothing happens when `css` is empty (running from source, as the tests do) or when the page
6
+ * already has the styles (the element is marked data-apptics="style"). Never throws.
7
+ */
8
+ export declare function injectStylesheet(css: string): void;
@@ -0,0 +1,29 @@
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
+ 'use strict';
3
+
4
+ /**
5
+ * Adds the feedback form's styles to the page, once, as a <style> element, so no app imports or
6
+ * links a stylesheet: the css is carried in the JavaScript, for npm and the CDN builds alike.
7
+ *
8
+ * Nothing happens when `css` is empty (running from source, as the tests do) or when the page
9
+ * already has the styles (the element is marked data-apptics="style"). Never throws.
10
+ */
11
+ function injectStylesheet(css) {
12
+ try {
13
+ if (!css || typeof document === 'undefined') { // no i18n
14
+ return;
15
+ }
16
+ if (document.querySelector('[data-apptics="style"]')) { // no i18n
17
+ return;
18
+ }
19
+ var style = document.createElement('style'); // no i18n
20
+ style.setAttribute('data-apptics', 'style'); // no i18n
21
+ style.textContent = css;
22
+ (document.head || document.documentElement).appendChild(style);
23
+ }
24
+ catch (err) {
25
+ // the form still works unstyled; the app must not break over a stylesheet
26
+ }
27
+ }
28
+
29
+ exports.injectStylesheet = injectStylesheet;
@@ -0,0 +1,85 @@
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;
84
+ /** Whether device/add has given this browser its deviceid. */
85
+ export declare function hasDeviceId(): boolean;