@zoho_apptics/apptics-js-sdk 1.0.1 → 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.
Files changed (226) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +13 -0
  3. package/README.md +747 -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/batch-BU_mTpm1.min.js +3 -0
  9. package/dist/chunks/batch-BU_mTpm1.min.js.map +1 -0
  10. package/dist/chunks/logs-Bea5zUW_.min.js +3 -0
  11. package/dist/chunks/logs-Bea5zUW_.min.js.map +1 -0
  12. package/dist/cjs/auto-init.d.ts +8 -0
  13. package/dist/cjs/auto-init.js +32 -0
  14. package/dist/cjs/core/attempts.d.ts +28 -0
  15. package/dist/cjs/core/attempts.js +113 -0
  16. package/dist/cjs/core/batch.d.ts +32 -0
  17. package/dist/cjs/core/batch.js +115 -0
  18. package/dist/cjs/core/callsite.d.ts +28 -0
  19. package/dist/cjs/core/callsite.js +93 -0
  20. package/dist/cjs/core/consent.d.ts +23 -0
  21. package/dist/cjs/core/consent.js +130 -0
  22. package/dist/cjs/core/constants.d.ts +212 -0
  23. package/dist/cjs/core/constants.js +299 -0
  24. package/dist/cjs/core/db.d.ts +40 -0
  25. package/dist/cjs/core/db.js +334 -0
  26. package/dist/cjs/core/debug.d.ts +22 -0
  27. package/dist/cjs/core/debug.js +88 -0
  28. package/dist/cjs/core/env.d.ts +28 -0
  29. package/dist/cjs/core/env.js +267 -0
  30. package/dist/cjs/core/framework-id.d.ts +1 -0
  31. package/dist/cjs/core/framework-id.js +9 -0
  32. package/dist/cjs/core/guard.d.ts +2 -0
  33. package/dist/cjs/core/guard.js +72 -0
  34. package/dist/cjs/core/hooks.d.ts +41 -0
  35. package/dist/cjs/core/hooks.js +23 -0
  36. package/dist/cjs/core/logger.d.ts +16 -0
  37. package/dist/cjs/core/logger.js +86 -0
  38. package/dist/cjs/core/state.d.ts +69 -0
  39. package/dist/cjs/core/state.js +78 -0
  40. package/dist/cjs/core/storage.d.ts +46 -0
  41. package/dist/cjs/core/storage.js +229 -0
  42. package/dist/cjs/core/transport.d.ts +83 -0
  43. package/dist/cjs/core/transport.js +441 -0
  44. package/dist/cjs/core/utils.d.ts +26 -0
  45. package/dist/cjs/core/utils.js +175 -0
  46. package/dist/cjs/core/validate.d.ts +18 -0
  47. package/dist/cjs/core/validate.js +233 -0
  48. package/dist/cjs/device/appversion.d.ts +20 -0
  49. package/dist/cjs/device/appversion.js +158 -0
  50. package/dist/cjs/device/index.d.ts +23 -0
  51. package/dist/cjs/device/index.js +372 -0
  52. package/dist/cjs/engagement/api-rules.d.ts +84 -0
  53. package/dist/cjs/engagement/api-rules.js +219 -0
  54. package/dist/cjs/engagement/auto-api.d.ts +7 -0
  55. package/dist/cjs/engagement/auto-api.js +200 -0
  56. package/dist/cjs/engagement/auto-screen.d.ts +16 -0
  57. package/dist/cjs/engagement/auto-screen.js +241 -0
  58. package/dist/cjs/engagement/defined-events.d.ts +23 -0
  59. package/dist/cjs/engagement/defined-events.js +58 -0
  60. package/dist/cjs/engagement/send.d.ts +6 -0
  61. package/dist/cjs/engagement/send.js +99 -0
  62. package/dist/cjs/engagement/session.d.ts +42 -0
  63. package/dist/cjs/engagement/session.js +327 -0
  64. package/dist/cjs/engagement/track.d.ts +56 -0
  65. package/dist/cjs/engagement/track.js +350 -0
  66. package/dist/cjs/errors/send.d.ts +6 -0
  67. package/dist/cjs/errors/send.js +73 -0
  68. package/dist/cjs/errors/track.d.ts +4 -0
  69. package/dist/cjs/errors/track.js +127 -0
  70. package/dist/cjs/feedback/controls.d.ts +31 -0
  71. package/dist/cjs/feedback/controls.js +286 -0
  72. package/dist/cjs/feedback/index.d.ts +8 -0
  73. package/dist/cjs/feedback/index.js +37 -0
  74. package/dist/cjs/feedback/logs.d.ts +40 -0
  75. package/dist/cjs/feedback/logs.js +202 -0
  76. package/dist/cjs/feedback/send.d.ts +25 -0
  77. package/dist/cjs/feedback/send.js +178 -0
  78. package/dist/cjs/feedback/template.d.ts +2 -0
  79. package/dist/cjs/feedback/template.js +162 -0
  80. package/dist/cjs/feedback/ui.d.ts +55 -0
  81. package/dist/cjs/feedback/ui.js +631 -0
  82. package/dist/cjs/heatmap/index.d.ts +16 -0
  83. package/dist/cjs/heatmap/index.js +22 -0
  84. package/dist/cjs/heatmap/send.d.ts +13 -0
  85. package/dist/cjs/heatmap/send.js +82 -0
  86. package/dist/cjs/heatmap/track.d.ts +4 -0
  87. package/dist/cjs/heatmap/track.js +377 -0
  88. package/dist/cjs/index.d.ts +68 -0
  89. package/dist/cjs/index.js +150 -0
  90. package/dist/cjs/lifecycle.d.ts +14 -0
  91. package/dist/cjs/lifecycle.js +538 -0
  92. package/dist/cjs/package.json +3 -0
  93. package/dist/cjs/remoteconfig/custom.d.ts +10 -0
  94. package/dist/cjs/remoteconfig/custom.js +78 -0
  95. package/dist/cjs/remoteconfig/evaluate.d.ts +24 -0
  96. package/dist/cjs/remoteconfig/evaluate.js +171 -0
  97. package/dist/cjs/remoteconfig/fetch.d.ts +24 -0
  98. package/dist/cjs/remoteconfig/fetch.js +214 -0
  99. package/dist/cjs/remoteconfig/index.d.ts +13 -0
  100. package/dist/cjs/remoteconfig/index.js +90 -0
  101. package/dist/cjs/remoteconfig/store.d.ts +18 -0
  102. package/dist/cjs/remoteconfig/store.js +98 -0
  103. package/dist/cjs/remotelog/gate.d.ts +11 -0
  104. package/dist/cjs/remotelog/gate.js +54 -0
  105. package/dist/cjs/remotelog/index.d.ts +25 -0
  106. package/dist/cjs/remotelog/index.js +55 -0
  107. package/dist/cjs/remotelog/logger.d.ts +28 -0
  108. package/dist/cjs/remotelog/logger.js +139 -0
  109. package/dist/cjs/remotelog/send.d.ts +13 -0
  110. package/dist/cjs/remotelog/send.js +153 -0
  111. package/dist/cjs/scheduler.d.ts +8 -0
  112. package/dist/cjs/scheduler.js +78 -0
  113. package/dist/cjs/types.d.ts +312 -0
  114. package/dist/cjs/user/index.d.ts +33 -0
  115. package/dist/cjs/user/index.js +178 -0
  116. package/dist/esm/auto-init.d.ts +8 -0
  117. package/dist/esm/auto-init.js +29 -0
  118. package/dist/esm/core/attempts.d.ts +28 -0
  119. package/dist/esm/core/attempts.js +106 -0
  120. package/dist/esm/core/batch.d.ts +32 -0
  121. package/dist/esm/core/batch.js +108 -0
  122. package/dist/esm/core/callsite.d.ts +28 -0
  123. package/dist/esm/core/callsite.js +89 -0
  124. package/dist/esm/core/consent.d.ts +23 -0
  125. package/dist/esm/core/consent.js +120 -0
  126. package/dist/esm/core/constants.d.ts +212 -0
  127. package/dist/esm/core/constants.js +277 -0
  128. package/dist/esm/core/db.d.ts +40 -0
  129. package/dist/esm/core/db.js +324 -0
  130. package/dist/esm/core/debug.d.ts +22 -0
  131. package/dist/esm/core/debug.js +81 -0
  132. package/dist/esm/core/env.d.ts +28 -0
  133. package/dist/esm/core/env.js +251 -0
  134. package/dist/esm/core/framework-id.d.ts +1 -0
  135. package/dist/esm/core/framework-id.js +7 -0
  136. package/dist/esm/core/guard.d.ts +2 -0
  137. package/dist/esm/core/guard.js +70 -0
  138. package/dist/esm/core/hooks.d.ts +41 -0
  139. package/dist/esm/core/hooks.js +21 -0
  140. package/dist/esm/core/logger.d.ts +16 -0
  141. package/dist/esm/core/logger.js +82 -0
  142. package/dist/esm/core/state.d.ts +69 -0
  143. package/dist/esm/core/state.js +73 -0
  144. package/dist/esm/core/storage.d.ts +46 -0
  145. package/dist/esm/core/storage.js +219 -0
  146. package/dist/esm/core/transport.d.ts +83 -0
  147. package/dist/esm/core/transport.js +425 -0
  148. package/dist/esm/core/utils.d.ts +26 -0
  149. package/dist/esm/core/utils.js +161 -0
  150. package/dist/esm/core/validate.d.ts +18 -0
  151. package/dist/esm/core/validate.js +226 -0
  152. package/dist/esm/device/appversion.d.ts +20 -0
  153. package/dist/esm/device/appversion.js +153 -0
  154. package/dist/esm/device/index.d.ts +23 -0
  155. package/dist/esm/device/index.js +362 -0
  156. package/dist/esm/engagement/api-rules.d.ts +84 -0
  157. package/dist/esm/engagement/api-rules.js +211 -0
  158. package/dist/esm/engagement/auto-api.d.ts +7 -0
  159. package/dist/esm/engagement/auto-api.js +198 -0
  160. package/dist/esm/engagement/auto-screen.d.ts +16 -0
  161. package/dist/esm/engagement/auto-screen.js +238 -0
  162. package/dist/esm/engagement/defined-events.d.ts +23 -0
  163. package/dist/esm/engagement/defined-events.js +55 -0
  164. package/dist/esm/engagement/send.d.ts +6 -0
  165. package/dist/esm/engagement/send.js +96 -0
  166. package/dist/esm/engagement/session.d.ts +42 -0
  167. package/dist/esm/engagement/session.js +315 -0
  168. package/dist/esm/engagement/track.d.ts +56 -0
  169. package/dist/esm/engagement/track.js +340 -0
  170. package/dist/esm/errors/send.d.ts +6 -0
  171. package/dist/esm/errors/send.js +70 -0
  172. package/dist/esm/errors/track.d.ts +4 -0
  173. package/dist/esm/errors/track.js +123 -0
  174. package/dist/esm/feedback/controls.d.ts +31 -0
  175. package/dist/esm/feedback/controls.js +280 -0
  176. package/dist/esm/feedback/index.d.ts +8 -0
  177. package/dist/esm/feedback/index.js +30 -0
  178. package/dist/esm/feedback/logs.d.ts +40 -0
  179. package/dist/esm/feedback/logs.js +188 -0
  180. package/dist/esm/feedback/send.d.ts +25 -0
  181. package/dist/esm/feedback/send.js +175 -0
  182. package/dist/esm/feedback/template.d.ts +2 -0
  183. package/dist/esm/feedback/template.js +159 -0
  184. package/dist/esm/feedback/ui.d.ts +55 -0
  185. package/dist/esm/feedback/ui.js +626 -0
  186. package/dist/esm/heatmap/index.d.ts +16 -0
  187. package/dist/esm/heatmap/index.js +17 -0
  188. package/dist/esm/heatmap/send.d.ts +13 -0
  189. package/dist/esm/heatmap/send.js +79 -0
  190. package/dist/esm/heatmap/track.d.ts +4 -0
  191. package/dist/esm/heatmap/track.js +374 -0
  192. package/dist/esm/index.d.ts +68 -0
  193. package/dist/esm/index.js +122 -0
  194. package/dist/esm/lifecycle.d.ts +14 -0
  195. package/dist/esm/lifecycle.js +534 -0
  196. package/dist/esm/package.json +3 -0
  197. package/dist/esm/remoteconfig/custom.d.ts +10 -0
  198. package/dist/esm/remoteconfig/custom.js +74 -0
  199. package/dist/esm/remoteconfig/evaluate.d.ts +24 -0
  200. package/dist/esm/remoteconfig/evaluate.js +166 -0
  201. package/dist/esm/remoteconfig/fetch.d.ts +24 -0
  202. package/dist/esm/remoteconfig/fetch.js +210 -0
  203. package/dist/esm/remoteconfig/index.d.ts +13 -0
  204. package/dist/esm/remoteconfig/index.js +85 -0
  205. package/dist/esm/remoteconfig/store.d.ts +18 -0
  206. package/dist/esm/remoteconfig/store.js +91 -0
  207. package/dist/esm/remotelog/gate.d.ts +11 -0
  208. package/dist/esm/remotelog/gate.js +48 -0
  209. package/dist/esm/remotelog/index.d.ts +25 -0
  210. package/dist/esm/remotelog/index.js +51 -0
  211. package/dist/esm/remotelog/logger.d.ts +28 -0
  212. package/dist/esm/remotelog/logger.js +136 -0
  213. package/dist/esm/remotelog/send.d.ts +13 -0
  214. package/dist/esm/remotelog/send.js +149 -0
  215. package/dist/esm/scheduler.d.ts +8 -0
  216. package/dist/esm/scheduler.js +74 -0
  217. package/dist/esm/types.d.ts +312 -0
  218. package/dist/esm/user/index.d.ts +33 -0
  219. package/dist/esm/user/index.js +170 -0
  220. package/dist/feedback.esm.min.js +3 -0
  221. package/dist/feedback.esm.min.js.map +1 -0
  222. package/dist/heatmap.esm.min.js +3 -0
  223. package/dist/heatmap.esm.min.js.map +1 -0
  224. package/dist/style.css +1 -0
  225. package/package.json +124 -7
  226. package/src/appticssdk.js +0 -3817
@@ -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;