@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,538 @@
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('./core/constants.js');
5
+ var state = require('./core/state.js');
6
+ var logger = require('./core/logger.js');
7
+ var utils = require('./core/utils.js');
8
+ var storage = require('./core/storage.js');
9
+ var hooks = require('./core/hooks.js');
10
+ var debug = require('./core/debug.js');
11
+ var env = require('./core/env.js');
12
+ var consent = require('./core/consent.js');
13
+ var index = require('./device/index.js');
14
+ var appversion = require('./device/appversion.js');
15
+ var session = require('./engagement/session.js');
16
+ var autoApi = require('./engagement/auto-api.js');
17
+ var autoScreen = require('./engagement/auto-screen.js');
18
+ var track = require('./engagement/track.js');
19
+ var track$1 = require('./errors/track.js');
20
+ var scheduler = require('./scheduler.js');
21
+ require('./remotelog/index.js');
22
+ var index$1 = require('./user/index.js');
23
+ var attempts = require('./core/attempts.js');
24
+ var send = require('./remotelog/send.js');
25
+
26
+ let listenersAttached = false;
27
+ /** The config init() was last called with; reset() starts again from it. */
28
+ let lastConfig = null;
29
+ /** Bumped by every init(); a start() from an earlier init() that was reset in between does nothing. */
30
+ let generation = 0;
31
+ function isBrowser() {
32
+ if (typeof window === 'undefined' || typeof document === 'undefined' || typeof Promise === 'undefined') { // no i18n
33
+ return false;
34
+ }
35
+ try {
36
+ return typeof indexedDB !== 'undefined' || !!window.localStorage; // no i18n
37
+ }
38
+ catch (err) {
39
+ return false; // storage access can throw in sandboxed frames
40
+ }
41
+ }
42
+ /**
43
+ * Canonical config: serviceUrl, zak, identifier, appversion.
44
+ * The console snippet uses older names (base_domain, token), which are accepted here.
45
+ * serviceUrl loses any trailing slash, because request paths add their own.
46
+ */
47
+ function normaliseConfig(config) {
48
+ var settings = Object.assign({}, config);
49
+ Object.keys(constants.CONFIG_ALIASES).forEach(function (key) {
50
+ if (utils.isEmpty(settings[key]) && !utils.isEmpty(settings[constants.CONFIG_ALIASES[key]])) {
51
+ settings[key] = settings[constants.CONFIG_ALIASES[key]];
52
+ }
53
+ });
54
+ if (!utils.isEmpty(settings.serviceUrl)) {
55
+ settings.serviceUrl = String(settings.serviceUrl).replace(/\/+$/, ''); // no i18n
56
+ }
57
+ settings.appversion = appVersionText(settings.appversion);
58
+ return settings;
59
+ }
60
+ /**
61
+ * The version as the text it is stored and sent as: a string trimmed, a finite number as its digits.
62
+ * Anything else — blank, NaN, an object — is '', which init() reports as missing.
63
+ */
64
+ function appVersionText(value) {
65
+ if (typeof value === 'number') { // no i18n
66
+ return isFinite(value) ? String(value) : ''; // no i18n
67
+ }
68
+ return typeof value === 'string' ? value.trim() : ''; // no i18n
69
+ }
70
+ /**
71
+ * The placeholders the console's snippets and the docs show for appversion. Starting with one
72
+ * would register a version that was never shipped, and every visit after it would report under it.
73
+ */
74
+ const APPVERSION_PLACEHOLDERS = ['YOUR_APP_VERSION', 'YOUR_BUILD_OR_APP_VERSION', 'YOUR_APPVERSION']; // no i18n
75
+ function isAppVersionPlaceholder(version) {
76
+ return APPVERSION_PLACEHOLDERS.indexOf(version.toUpperCase()) !== -1;
77
+ }
78
+ /** Which app this browser's stored data belongs to, before app/addversion has named it. */
79
+ function appKey(settings) {
80
+ return settings.serviceUrl + '|' + settings.identifier; // no i18n
81
+ }
82
+ /**
83
+ * Data stored for another app on this origin is discarded before anything else reads it,
84
+ * including the stored app/addversion answer that would otherwise hand out that app's ids.
85
+ */
86
+ function discardOtherAppData(settings) {
87
+ var stored = storage.user_defaults.item('appkey'); // no i18n
88
+ if (!utils.isEmpty(stored) && stored !== appKey(settings)) {
89
+ logger.Console.log('init: stored data belongs to another app, resetting'); // no i18n
90
+ clearStorage();
91
+ }
92
+ storage.user_defaults.add('appkey', appKey(settings)); // no i18n
93
+ }
94
+ /**
95
+ * Timing an app may tune in init(). Each has a range: a value outside it is ignored with a
96
+ * warning rather than applied, since a 10 ms flush interval would hammer the server.
97
+ */
98
+ const TUNABLE = Object.freeze([
99
+ { key: 'batch_flush_interval', min: 1000, max: 3600000 }, // no i18n
100
+ { key: 'getupdates_interval', min: 10000, max: 86400000 }, // no i18n
101
+ { key: 'batch_size', min: 1, max: 500 }, // no i18n
102
+ { key: 'batch_request_timeout', min: 1, max: 30 }, // no i18n
103
+ { key: 'min_session_duration', min: 0, max: 60000 }, // no i18n
104
+ { key: 'heatmap_max_per_session', min: 0, max: 10000 }, // no i18n
105
+ ]);
106
+ /** Reads the tunable timings out of the config. Anything missing goes back to its default. */
107
+ function applyIntervals(config) {
108
+ TUNABLE.forEach(function (rule) {
109
+ var value = config[rule.key];
110
+ // every init() decides these on its own, so a value from an earlier one never lingers
111
+ state._ZAP._config[rule.key] = constants.AP_CONFIG[rule.key];
112
+ if (utils.isEmpty(value)) {
113
+ return;
114
+ }
115
+ var num = Number(value);
116
+ if (!isFinite(num) || num < rule.min || num > rule.max) {
117
+ logger.warnAlways('Apptics.init: ' + rule.key + ' must be between ' + rule.min + ' and ' + rule.max + ', keeping ' + state._ZAP._config[rule.key]); // no i18n
118
+ return;
119
+ }
120
+ state._ZAP._config[rule.key] = num;
121
+ logger.Console.log('Apptics.init: ' + rule.key + ' set to ' + num); // no i18n
122
+ });
123
+ // inactiveduration lives on state, not in _config
124
+ state._ZAP.inactiveduration = constants.DEFAULT_INACTIVE_MINUTES;
125
+ if (!utils.isEmpty(config.inactiveduration)) {
126
+ var minutes = Number(config.inactiveduration);
127
+ if (!isFinite(minutes) || minutes < 1 || minutes > 1440) {
128
+ logger.warnAlways('Apptics.init: inactiveduration must be between 1 and 1440 minutes, keeping ' + state._ZAP.inactiveduration); // no i18n
129
+ }
130
+ else {
131
+ state._ZAP.inactiveduration = minutes;
132
+ logger.Console.log('Apptics.init: inactiveduration set to ' + minutes); // no i18n
133
+ }
134
+ }
135
+ }
136
+ function clearStorage() {
137
+ attempts.clearAttempts();
138
+ storage.user_defaults.clear();
139
+ storage.engagement_transactions.clear();
140
+ storage.error_transactions.clear();
141
+ }
142
+ /**
143
+ * Starts the SDK. The config object is required: pass it directly, or let the console snippet
144
+ * supply it (auto-init reads window.appticssettings._defaultoptions and calls init with it).
145
+ * Returns true when the config has serviceUrl, zak, identifier and appversion and start-up has
146
+ * begun (see ready()), false when it was already running, the config is missing or incomplete, or
147
+ * there is no browser. Start-up calls app/addversion with those four, which answers with aaid, the
148
+ * portal and project ids and the rest; then device/add registers the browser, as in 1.x.
149
+ */
150
+ function init(config) {
151
+ if (!config || typeof config !== 'object') { // no i18n
152
+ logger.warnAlways('Apptics.init: a config object is required, e.g. apptics.init({ serviceUrl, zak, identifier, appversion })'); // no i18n
153
+ return false;
154
+ }
155
+ if (state._ZAP._initialised) {
156
+ logger.Console.warn('Apptics.init: already initialised; call apptics.reset() to start again'); // no i18n
157
+ return false;
158
+ }
159
+ if (!isBrowser()) {
160
+ logger.warnAlways('Apptics.init: skipped, no browser with storage and Promise support'); // no i18n
161
+ return false;
162
+ }
163
+ var settings = normaliseConfig(config);
164
+ var missing = constants.REQUIRED_CONFIG.filter(function (key) {
165
+ return utils.isEmpty(settings[key]);
166
+ });
167
+ if (missing.length > 0) {
168
+ logger.warnAlways('Apptics.init: missing required config: ' + missing.join(', ')); // no i18n
169
+ return false;
170
+ }
171
+ if (isAppVersionPlaceholder(settings.appversion)) {
172
+ logger.warnAlways('Apptics.init: appversion is still the placeholder "' + settings.appversion // no i18n
173
+ + '"; replace it with your app\'s version or build number, e.g. \'2.4.0\''); // no i18n
174
+ return false;
175
+ }
176
+ state._ZAP._defaultoptions = settings;
177
+ // every request goes to serviceUrl; there is no other host to learn about
178
+ state._ZAP._defaultoptions.base_domain = settings.serviceUrl;
179
+ // marks the SDK as started for the checks that need it; app/addversion replaces it with aaid
180
+ state._ZAP._token = settings.identifier;
181
+ // console_log: the SDK's own activity in the browser console
182
+ if (!utils.isEmpty(config.console_log)) {
183
+ state._ZAP._config.debug = !!config.console_log;
184
+ }
185
+ // track_session: false records no sessions, as Android's automaticSessionsTrackingStatus
186
+ state._ZAP._config.track_session = typeof config.track_session === 'boolean' ? config.track_session : constants.AP_CONFIG.track_session; // no i18n
187
+ // show_logs: the app's own logger lines in the browser console, as Android's showLogs
188
+ state._ZAP._config.show_logs = typeof config.show_logs === 'boolean' ? config.show_logs : constants.AP_CONFIG.show_logs; // no i18n
189
+ if (typeof config.ignore_do_not_track === 'boolean') { // no i18n
190
+ state._ZAP._config.ignore_do_not_track = config.ignore_do_not_track;
191
+ }
192
+ // debug: debug mode, the debug endpoints. Same payloads, but the answer says where to trace the
193
+ // request. debug_api is its earlier name and still works; debug wins when both are given
194
+ state._ZAP._config.debug_api = typeof config.debug === 'boolean' ? config.debug // no i18n
195
+ : typeof config.debug_api === 'boolean' ? config.debug_api : constants.AP_CONFIG.debug_api; // no i18n
196
+ // starts (or clears) the idle hour that closes debug mode on its own
197
+ // an enableDebug() or disableDebug() call the app already made wins over the config
198
+ debug.applyDebugConfig(state._ZAP._config.debug_api);
199
+ // what to call this device in the debug stream; see devicename in core/transport.ts
200
+ state._ZAP._config.device_name = typeof config.device_name === 'string' ? config.device_name : constants.AP_CONFIG.device_name; // no i18n
201
+ // remote logging: the SDK's own diagnostics, sent to console/addlog
202
+ state._ZAP._config.remote_log = constants.AP_CONFIG.remote_log;
203
+ if (typeof config.remote_log === 'boolean') { // no i18n
204
+ state._ZAP._config.remote_log = config.remote_log;
205
+ }
206
+ // automatic api tracking: the app's own requests, wrapped. Which hosts it records is
207
+ // configureApiTracking's to say; the two keys that once did it are refused out loud rather
208
+ // than quietly ignored, since an app relying on them would otherwise record hosts it meant not to
209
+ state._ZAP._config.track_api = constants.AP_CONFIG.track_api;
210
+ ['track_api_hosts', 'track_api_exclude_hosts'].forEach(function (key) {
211
+ if (config[key] !== undefined) {
212
+ logger.warnAlways('Apptics.init: ' + key + ' is no longer supported; use configureApiTracking(new ApiTrackingBuilder().' // no i18n
213
+ + (key === 'track_api_hosts' ? 'allowOnlyDomains' : 'ignoreDomains') + '(...).build())'); // no i18n
214
+ }
215
+ });
216
+ if (typeof config.track_api === 'boolean') { // no i18n
217
+ state._ZAP._config.track_api = config.track_api;
218
+ }
219
+ autoApi.enableApiTracking(state._ZAP._config.track_api);
220
+ // heatmap capture: a no-op unless the app imported the heatmap entry, which sets the hook
221
+ state._ZAP._config.track_heatmap = typeof config.track_heatmap === 'boolean' // no i18n
222
+ ? config.track_heatmap
223
+ : constants.AP_CONFIG.track_heatmap;
224
+ hooks.hooks.enableHeatmap(state._ZAP._config.track_heatmap);
225
+ // automatic screen tracking, on unless the config says false: switched on by start(), once a
226
+ // screen view can be stored
227
+ state._ZAP._config.track_screen = typeof config.track_screen === 'boolean' ? config.track_screen : constants.AP_CONFIG.track_screen; // no i18n
228
+ applyIntervals(config);
229
+ lastConfig = config;
230
+ state._ZAP._initialised = true;
231
+ state._ZAP._ready = false;
232
+ state._ZAP._pending = [];
233
+ var myGeneration = ++generation;
234
+ state._ZAP._readyPromise = storage.storageReady().then(function (backend) {
235
+ if (myGeneration !== generation) {
236
+ return false;
237
+ }
238
+ if (!backend) {
239
+ logger.warnAlways('Apptics.init: no usable storage (IndexedDB or localStorage), not starting'); // no i18n
240
+ state._ZAP._initialised = false;
241
+ state._ZAP._token = ''; // no i18n
242
+ state._ZAP._pending = [];
243
+ return false;
244
+ }
245
+ discardOtherAppData(state._ZAP._defaultoptions);
246
+ // app/addversion is the first call and everything waits on it: it is what turns the four
247
+ // values init() was given into aaid, the portal and project ids every url carries, and
248
+ // appreleaseversionid, which metaWebSDKV2 refuses a payload without
249
+ return appversion.registerAppVersion().then(function (registered) {
250
+ if (myGeneration !== generation) {
251
+ return false;
252
+ }
253
+ if (!registered) {
254
+ logger.warnAlways('Apptics.init: app/addversion did not return the app ids, not starting'); // no i18n
255
+ state._ZAP._initialised = false;
256
+ state._ZAP._token = ''; // no i18n
257
+ state._ZAP._pending = [];
258
+ return false;
259
+ }
260
+ return start(config, myGeneration);
261
+ });
262
+ }).catch(function (err) {
263
+ logger.Console.error('Apptics.init: start-up failed', err); // no i18n
264
+ return false;
265
+ });
266
+ return true;
267
+ }
268
+ /** Resolves true once start-up has finished, false if init() refused or storage is unusable. */
269
+ function ready() {
270
+ return state._ZAP._readyPromise || Promise.resolve(false);
271
+ }
272
+ function start(config, myGeneration) {
273
+ // app/addversion named the app; data stored for another one was discarded before it ran
274
+ state._ZAP._token = String(state._ZAP._defaultoptions.aaid);
275
+ storage.user_defaults.add('token', state._ZAP._token); // no i18n
276
+ // last known server settings (getupdates) apply before anything is tracked
277
+ index.restoreServerSettings();
278
+ // required by init(), so _defaultoptions.appversion is always the app's own version, as the
279
+ // text normaliseConfig made of it: there is no default to fall back to, and the stored value
280
+ // below is kept only to notice when the version changes
281
+ var uuid = storage.user_defaults.item('uuid'); // no i18n
282
+ if (utils.isEmpty(uuid)) {
283
+ uuid = utils.getNewUUID();
284
+ storage.user_defaults.add('uuid', uuid); // no i18n
285
+ }
286
+ state._ZAP._uuid = uuid;
287
+ var stored_appversion = storage.user_defaults.item('appversion'); // no i18n
288
+ if (utils.isEmpty(stored_appversion)) {
289
+ storage.user_defaults.add('appversion', state._ZAP._defaultoptions.appversion); // no i18n
290
+ stored_appversion = state._ZAP._defaultoptions.appversion;
291
+ }
292
+ var appVersionChanged = stored_appversion != state._ZAP._defaultoptions.appversion;
293
+ state._ZAP._ignoreDnt = state._ZAP._config.ignore_do_not_track;
294
+ storage.tracking_preference.update_status(consent.getTrackingStatus());
295
+ index.checkAndUpdateDeviceInfo();
296
+ // returning visit: ask the server for its settings now instead of waiting 2 minutes
297
+ // (first visit: device/add triggers it once the ids exist)
298
+ index.refreshServerSettings();
299
+ if (appVersionChanged) {
300
+ state._ZAP._device_info.appversionid = ''; // no i18n
301
+ index.updateDeviceWithApptics(state._ZAP._device_info).then(function (result) {
302
+ if (utils.isSuccess(result)) {
303
+ storage.user_defaults.add('appversion', state._ZAP._defaultoptions.appversion); // no i18n
304
+ logger.Console.log('init: appversion updated to ' + state._ZAP._defaultoptions.appversion); // no i18n
305
+ }
306
+ }).catch(function (err) {
307
+ logger.Console.log('init: error updating appversion: ' + err); // no i18n
308
+ });
309
+ }
310
+ // attempt to resolve connection type
311
+ state._ZAP._device_info.connectionType = env.getConnectionType();
312
+ attachListeners();
313
+ state._ZAP._properties.orientation = env.getOrientation();
314
+ index$1.getUserInfo();
315
+ return session.checkAndUpdateSession().then(function () {
316
+ if (myGeneration !== generation) {
317
+ return false;
318
+ }
319
+ scheduler.startTimers();
320
+ send.sendStoredLogs();
321
+ state._ZAP._ready = true;
322
+ // replay calls made while storage was loading, in order
323
+ var pending = state._ZAP._pending;
324
+ state._ZAP._pending = [];
325
+ pending.forEach(function (call) {
326
+ try {
327
+ call();
328
+ }
329
+ catch (err) {
330
+ logger.Console.error('apptics: buffered call failed', err); // no i18n
331
+ }
332
+ });
333
+ // after the replay, so a inScreen() the app made during start-up keeps its place, and
334
+ // the first automatic view is the page as it is now
335
+ autoScreen.enableScreenTracking(state._ZAP._config.track_screen);
336
+ // a no-op unless the remote-config entry was imported, which sets the hook
337
+ hooks.hooks.remoteConfigStarted();
338
+ window.appticsReadyStatus = true;
339
+ if (typeof window.appticsReady == 'function') { // no i18n
340
+ window.appticsReady();
341
+ }
342
+ return true;
343
+ });
344
+ }
345
+ /** Clears stored identity and queues, then starts again from the snippet. */
346
+ function reset() {
347
+ generation++;
348
+ scheduler.stopTimers();
349
+ // the wrappers come off with everything else; the init() below puts them back if the config
350
+ // asked for them, so a reset that has no config to restore leaves XHR and fetch untouched
351
+ autoApi.enableApiTracking(false);
352
+ autoScreen.enableScreenTracking(false);
353
+ appversion.clearAppVersion();
354
+ hooks.hooks.enableHeatmap(false);
355
+ hooks.hooks.resetHeatmap();
356
+ hooks.hooks.resetRemoteConfig();
357
+ clearStorage();
358
+ state._ZAP._initialised = false;
359
+ state._ZAP._ready = false;
360
+ state._ZAP._pending = [];
361
+ state._ZAP._readyPromise = null;
362
+ state._ZAP._device_info = {};
363
+ state._ZAP._user_info = {};
364
+ state._ZAP._current_screen = {};
365
+ state._ZAP._current_session = {};
366
+ state._ZAP._uuid = ''; // no i18n
367
+ state._ZAP._apid = ''; // no i18n
368
+ state._ZAP._mapid = ''; // no i18n
369
+ state._ZAP._sending = false;
370
+ logger.Console.log('apptics.reset()'); // no i18n
371
+ // start again with the config init() was called with
372
+ if (lastConfig) {
373
+ init(lastConfig);
374
+ }
375
+ }
376
+ function isActive() {
377
+ return state._ZAP._ready;
378
+ }
379
+ // Declarative click tracking: <el apeventaction="name" apeventprops='{"k":"v"}'> inside <el apgroupaction="group">
380
+ function onDocumentClick(event) {
381
+ if (!window.appticsReadyStatus || !isActive()) {
382
+ return;
383
+ }
384
+ var start = event.target;
385
+ if (start && typeof start.closest !== 'function') { // no i18n
386
+ start = start.parentElement;
387
+ }
388
+ if (!start) {
389
+ return;
390
+ }
391
+ var targetElem = start.closest('[apeventaction]:not([apeventaction=""])'); // no i18n
392
+ if (!targetElem) {
393
+ return;
394
+ }
395
+ var eventName = targetElem.getAttribute('apeventaction') || ''; // no i18n
396
+ var groupElem = targetElem.closest('[apgroupaction]'); // no i18n
397
+ var groupName = (groupElem && groupElem.getAttribute('apgroupaction')) || constants.AP_CONFIG.default_group_name; // no i18n
398
+ var eventProps = {};
399
+ var rawProps = targetElem.getAttribute('apeventprops'); // no i18n
400
+ if (!utils.isEmpty(rawProps)) {
401
+ try {
402
+ eventProps = JSON.parse(rawProps);
403
+ }
404
+ catch (err) {
405
+ logger.Console.warn('apptics: invalid JSON in apeventprops for "' + eventName + '", sending no properties'); // no i18n
406
+ eventProps = {};
407
+ }
408
+ }
409
+ if (!utils.isEmpty(eventName)) {
410
+ track.trackEvent(eventName, groupName, eventProps);
411
+ }
412
+ }
413
+ /**
414
+ * Page is in the background but still there: close the open screen and send what's queued.
415
+ * By keepalive, because hidden is often the last moment before the tab closes, and a send still
416
+ * waiting on its answer would hold the queue as pagehide tries to send it.
417
+ */
418
+ function onPageHidden() {
419
+ if (!isActive())
420
+ return;
421
+ session.updateScreenWithEndtime();
422
+ scheduler.flush(true);
423
+ logger.Console.log('page hidden: closing the open screen and flushing'); // no i18n
424
+ }
425
+ /**
426
+ * The tab is closing, or the page is being replaced or frozen into the back/forward cache.
427
+ * The session ends here, and everything queued goes out by keepalive, since a normal
428
+ * request would be cancelled with the page.
429
+ */
430
+ function onPageClosing() {
431
+ if (!isActive())
432
+ return;
433
+ logger.Console.log('page closing: ending the session and sending what is queued'); // no i18n
434
+ session.updateScreenWithEndtime();
435
+ send.forgetStoredLogs();
436
+ session.endCurrentSession().then(function () {
437
+ return scheduler.flush(true);
438
+ });
439
+ }
440
+ function attachListeners() {
441
+ if (listenersAttached) {
442
+ return;
443
+ }
444
+ listenersAttached = true;
445
+ // listen for connection change events (only available in w3c implementation)
446
+ var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
447
+ if (connection && connection.addEventListener) {
448
+ connection.addEventListener('change', function () {
449
+ state._ZAP._device_info.connectionType = env.getConnectionType();
450
+ });
451
+ }
452
+ // Track when the window loses focus (user switches to another window or application)
453
+ window.addEventListener('blur', function () {
454
+ if (!isActive())
455
+ return;
456
+ logger.Console.log('Window lost focus, user switched to another window or application'); // no i18n
457
+ session.updateLastActiveTimeOfSession();
458
+ });
459
+ // Track when the window gains focus (user switches back to the window)
460
+ window.addEventListener('focus', function () {
461
+ if (!isActive())
462
+ return;
463
+ logger.Console.log('Window regained focus, user switched back to the window'); // no i18n
464
+ session.checkAndUpdateSession();
465
+ scheduler.startTimers();
466
+ });
467
+ // IndexedDB writes are async, so unload work starts on pagehide rather than beforeunload
468
+ window.addEventListener('pagehide', onPageClosing); // no i18n
469
+ // back/forward cache: pagehide ended the session, so coming back starts a new one
470
+ window.addEventListener('pageshow', function (event) {
471
+ if (!isActive() || !event.persisted)
472
+ return;
473
+ logger.Console.log('restored from the back/forward cache: starting a new session'); // no i18n
474
+ // the screen the page was left on starts a new view, in the new session
475
+ session.checkAndUpdateSession().then(track.resumeScreen);
476
+ scheduler.startTimers();
477
+ });
478
+ document.addEventListener('visibilitychange', function () {
479
+ if (!isActive())
480
+ return;
481
+ if (document.visibilityState === 'hidden') { // no i18n
482
+ onPageHidden();
483
+ return;
484
+ }
485
+ // back in view: the server's tracking flags may have changed while we were away
486
+ logger.Console.log('page visible: refreshing the server settings'); // no i18n
487
+ // hiding ended the screen view; the screen the user is back on starts a new one, after the
488
+ // session is settled so the view belongs to the right one
489
+ session.checkAndUpdateSession().then(track.resumeScreen);
490
+ index.refreshServerSettings();
491
+ });
492
+ // if we are running in cordova use ondeviceready otherwise onload
493
+ window.addEventListener(window.cordova ? 'deviceready' : 'load', function () {
494
+ if (isActive())
495
+ session.checkAndUpdateSession();
496
+ }, { passive: true });
497
+ // Always send pending requests when the connection comes back online
498
+ window.addEventListener('online', function () {
499
+ if (!isActive())
500
+ return;
501
+ // a first visit that started offline has no device ids yet, and nothing can be sent
502
+ // until it has them: register before flushing, and flush once that has landed
503
+ if (index.needsDevice()) {
504
+ logger.Console.log('back online: registering this device before sending'); // no i18n
505
+ index.checkAndUpdateDeviceInfo();
506
+ index.deviceReady().then(function () {
507
+ if (!isActive())
508
+ return;
509
+ scheduler.flush();
510
+ // the lines logged while offline are waiting too, and log/add needs the same ids
511
+ send.sendStoredLogs();
512
+ });
513
+ return;
514
+ }
515
+ scheduler.flush();
516
+ send.sendStoredLogs();
517
+ }, { passive: true });
518
+ if (window.screen && window.screen.orientation && typeof window.screen.orientation.addEventListener === 'function') { // no i18n
519
+ window.screen.orientation.addEventListener('change', function () {
520
+ state._ZAP._properties.orientation = env.getOrientation();
521
+ });
522
+ }
523
+ window.addEventListener('unhandledrejection', function (event) {
524
+ if (isActive() && state._ZAP._isGlobalErrorTracking) {
525
+ track$1.trackError(event);
526
+ }
527
+ });
528
+ window.addEventListener('error', function (event) {
529
+ if (isActive() && state._ZAP._isGlobalErrorTracking) {
530
+ track$1.trackError(event);
531
+ }
532
+ });
533
+ window.addEventListener('click', onDocumentClick, true); // no i18n
534
+ }
535
+
536
+ exports.init = init;
537
+ exports.ready = ready;
538
+ exports.reset = reset;
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,10 @@
1
+ /** The value set for a custom criteria key, or undefined when none is. */
2
+ export declare function customConditionValue(key: string): string | undefined;
3
+ /**
4
+ * Sets what this device is for a custom criteria, or removes it with an empty value. Re-applies
5
+ * the stored rules as soon as storage is ready, so the next read sees the new result without a
6
+ * fetch.
7
+ */
8
+ export declare function setCustomConditionValue(key: string, value: string | number | boolean | null | undefined): void;
9
+ /** reset(): forgets the values set on this page; the stored ones go with the rest of storage. */
10
+ export declare function clearCustomConditionValues(): void;
@@ -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 storage = require('../core/storage.js');
5
+ var logger = require('../core/logger.js');
6
+ var store = require('./store.js');
7
+
8
+ /**
9
+ * Custom condition values, as Android's AppticsRemoteConfig.setCustomConditionValue: the app says
10
+ * what this device is for a custom criteria the console defines (a condition key with a list of
11
+ * values), and a condition on that key matches when the value set here is one of the listed ones.
12
+ *
13
+ * AppticsRemoteConfig.setCustomConditionValue('plan_tier', 'gold');
14
+ *
15
+ * The rules are evaluated on the device, so the values have to be here on the next visit too:
16
+ * they are stored, and a value set on this page wins over a stored one. Setting one before
17
+ * storage has loaded — before init(), say — is kept in memory and saved once it has.
18
+ *
19
+ * Assumed wire format, until the server confirms it: a custom criteria arrives with the custom
20
+ * key as its `key` and operator 1 ("is one of"), the same shape as the built-in criteria. A
21
+ * different shape fails closed — the condition does not match and the default is used.
22
+ */
23
+ const STORE_KEY = 'remoteconfig_custom'; // no i18n
24
+ /** This page's values; null marks a key removed here, so a stored value no longer counts. */
25
+ var mine = {};
26
+ function stored() {
27
+ var saved = storage.user_defaults.item(STORE_KEY);
28
+ return saved && typeof saved === 'object' ? saved : {}; // no i18n
29
+ }
30
+ /** The value set for a custom criteria key, or undefined when none is. */
31
+ function customConditionValue(key) {
32
+ if (Object.prototype.hasOwnProperty.call(mine, key)) {
33
+ var here = mine[key];
34
+ return here === null ? undefined : here;
35
+ }
36
+ var saved = stored();
37
+ return Object.prototype.hasOwnProperty.call(saved, key) ? saved[key] : undefined;
38
+ }
39
+ /**
40
+ * Sets what this device is for a custom criteria, or removes it with an empty value. Re-applies
41
+ * the stored rules as soon as storage is ready, so the next read sees the new result without a
42
+ * fetch.
43
+ */
44
+ function setCustomConditionValue(key, value) {
45
+ var name = typeof key === 'string' ? key.trim() : ''; // no i18n
46
+ if (name === '') { // no i18n
47
+ logger.Console.warn('AppticsRemoteConfig.setCustomConditionValue: a condition key is required'); // no i18n
48
+ return;
49
+ }
50
+ var text = value === null || value === undefined ? '' : String(value).trim(); // no i18n
51
+ mine[name] = text === '' ? null : text; // no i18n
52
+ storage.storageReady().then(function (backend) {
53
+ if (!backend) {
54
+ return;
55
+ }
56
+ var saved = stored();
57
+ Object.keys(mine).forEach(function (one) {
58
+ var here = mine[one];
59
+ if (here === null || here === undefined) {
60
+ delete saved[one];
61
+ }
62
+ else {
63
+ saved[one] = here;
64
+ }
65
+ });
66
+ storage.user_defaults.add(STORE_KEY, saved);
67
+ // only once storage has loaded: re-resolving before it would read an empty rule set and keep it
68
+ store.reresolve();
69
+ });
70
+ }
71
+ /** reset(): forgets the values set on this page; the stored ones go with the rest of storage. */
72
+ function clearCustomConditionValues() {
73
+ mine = {};
74
+ }
75
+
76
+ exports.clearCustomConditionValues = clearCustomConditionValues;
77
+ exports.customConditionValue = customConditionValue;
78
+ exports.setCustomConditionValue = setCustomConditionValue;
@@ -0,0 +1,24 @@
1
+ import type { Dict } from '../types.js';
2
+ /** Forgets what has been complained about, so a new rule set is judged afresh. */
3
+ export declare function resetEvaluationWarnings(): void;
4
+ /**
5
+ * Whether a condition holds: every one of its criteria must. The template requires at least one
6
+ * (`array-size=">=1"`), so a condition with none is malformed and does not match — rather than
7
+ * matching vacuously, which would apply it to every device.
8
+ */
9
+ export declare function conditionMatches(condition: Dict): boolean;
10
+ /**
11
+ * The value of one parameter on this device, as the string the server stores it as.
12
+ *
13
+ * `byId` is every condition the answer carried, keyed by its id — the mapping on the parameter
14
+ * names a condition but does not repeat its criteria.
15
+ */
16
+ export declare function resolve(parameter: Dict, byId: Record<string, Dict>): string;
17
+ /**
18
+ * Every parameter resolved against this device, as a flat name -> value map.
19
+ *
20
+ * Built in one pass and kept, rather than resolved per read: the rule set only changes when a
21
+ * fetch brings a new one, and an app reading twenty flags during a render should not walk every
22
+ * condition twenty times.
23
+ */
24
+ export declare function resolveAll(remoteconfig: Dict): Record<string, string>;