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