@zoho_apptics/apptics-js-sdk 2.0.0-beta → 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 (220) hide show
  1. package/CHANGELOG.md +111 -5
  2. package/README.md +399 -300
  3. package/dist/apptics.esm.min.js +2 -2
  4. package/dist/apptics.esm.min.js.map +1 -1
  5. package/dist/apptics.min.js +2 -2
  6. package/dist/apptics.min.js.map +1 -1
  7. package/dist/chunks/lifecycle-VYr43KcB.min.js +3 -0
  8. package/dist/chunks/lifecycle-VYr43KcB.min.js.map +1 -0
  9. package/dist/cjs/auto-init.d.ts +3 -3
  10. package/dist/cjs/auto-init.js +1 -1
  11. package/dist/cjs/core/attempts.js +1 -1
  12. package/dist/cjs/core/batch.js +2 -1
  13. package/dist/cjs/core/callsite.d.ts +6 -0
  14. package/dist/cjs/core/callsite.js +25 -3
  15. package/dist/cjs/core/consent.d.ts +5 -1
  16. package/dist/cjs/core/consent.js +8 -6
  17. package/dist/cjs/core/constants.d.ts +35 -10
  18. package/dist/cjs/core/constants.js +31 -15
  19. package/dist/cjs/core/db.d.ts +12 -4
  20. package/dist/cjs/core/db.js +167 -34
  21. package/dist/cjs/core/debug.js +1 -1
  22. package/dist/cjs/core/env.js +1 -1
  23. package/dist/cjs/core/framework-id.d.ts +1 -1
  24. package/dist/cjs/core/framework-id.js +3 -3
  25. package/dist/cjs/core/guard.d.ts +9 -0
  26. package/dist/cjs/core/guard.js +27 -13
  27. package/dist/cjs/core/hooks.d.ts +2 -4
  28. package/dist/cjs/core/hooks.js +2 -3
  29. package/dist/cjs/core/locks.d.ts +9 -0
  30. package/dist/cjs/core/locks.js +22 -0
  31. package/dist/cjs/core/logger.d.ts +3 -4
  32. package/dist/cjs/core/logger.js +4 -40
  33. package/dist/cjs/core/state.d.ts +3 -2
  34. package/dist/cjs/core/state.js +2 -2
  35. package/dist/cjs/core/storage.d.ts +20 -5
  36. package/dist/cjs/core/storage.js +115 -17
  37. package/dist/cjs/core/stylesheet.d.ts +8 -0
  38. package/dist/cjs/core/stylesheet.js +29 -0
  39. package/dist/cjs/core/transport.d.ts +2 -0
  40. package/dist/cjs/core/transport.js +19 -4
  41. package/dist/cjs/core/utils.js +1 -1
  42. package/dist/cjs/core/validate.js +2 -2
  43. package/dist/cjs/device/appversion.d.ts +1 -6
  44. package/dist/cjs/device/appversion.js +13 -1
  45. package/dist/cjs/device/index.d.ts +11 -0
  46. package/dist/cjs/device/index.js +120 -20
  47. package/dist/cjs/engagement/api-rules.d.ts +32 -67
  48. package/dist/cjs/engagement/api-rules.js +144 -157
  49. package/dist/cjs/engagement/auto-api.js +2 -2
  50. package/dist/cjs/engagement/auto-screen.d.ts +2 -0
  51. package/dist/cjs/engagement/auto-screen.js +67 -3
  52. package/dist/cjs/engagement/defined-events.js +1 -1
  53. package/dist/cjs/engagement/send.js +6 -1
  54. package/dist/cjs/engagement/session.d.ts +12 -3
  55. package/dist/cjs/engagement/session.js +161 -25
  56. package/dist/cjs/engagement/track.js +45 -20
  57. package/dist/cjs/errors/send.js +1 -1
  58. package/dist/cjs/errors/track.d.ts +1 -1
  59. package/dist/cjs/errors/track.js +46 -6
  60. package/dist/cjs/feedback/controls.d.ts +6 -0
  61. package/dist/cjs/feedback/controls.js +31 -1
  62. package/dist/cjs/feedback/index.d.ts +8 -7
  63. package/dist/cjs/feedback/index.js +32 -13
  64. package/dist/cjs/feedback/logs.d.ts +10 -5
  65. package/dist/cjs/feedback/logs.js +52 -13
  66. package/dist/cjs/feedback/quartz.d.ts +18 -0
  67. package/dist/cjs/feedback/quartz.js +105 -0
  68. package/dist/cjs/feedback/send.d.ts +3 -0
  69. package/dist/cjs/feedback/send.js +28 -3
  70. package/dist/cjs/feedback/styles.d.ts +10 -0
  71. package/dist/cjs/feedback/styles.js +8 -0
  72. package/dist/cjs/feedback/template.d.ts +1 -1
  73. package/dist/cjs/feedback/template.js +12 -12
  74. package/dist/cjs/feedback/ui.d.ts +14 -6
  75. package/dist/cjs/feedback/ui.js +126 -48
  76. package/dist/cjs/heatmap/send.js +1 -1
  77. package/dist/cjs/heatmap/track.d.ts +1 -1
  78. package/dist/cjs/heatmap/track.js +87 -16
  79. package/dist/cjs/index.d.ts +17 -63
  80. package/dist/cjs/index.js +104 -92
  81. package/dist/cjs/lifecycle.d.ts +8 -1
  82. package/dist/cjs/lifecycle.js +258 -62
  83. package/dist/cjs/remoteconfig/country.d.ts +4 -0
  84. package/dist/cjs/remoteconfig/country.js +73 -0
  85. package/dist/cjs/remoteconfig/custom.d.ts +7 -7
  86. package/dist/cjs/remoteconfig/custom.js +31 -51
  87. package/dist/cjs/remoteconfig/evaluate.d.ts +3 -3
  88. package/dist/cjs/remoteconfig/evaluate.js +56 -43
  89. package/dist/cjs/remoteconfig/fetch.d.ts +3 -3
  90. package/dist/cjs/remoteconfig/fetch.js +9 -23
  91. package/dist/cjs/remoteconfig/index.d.ts +10 -8
  92. package/dist/cjs/remoteconfig/index.js +65 -39
  93. package/dist/cjs/remoteconfig/store.js +1 -1
  94. package/dist/cjs/remoteconfig/tz-countries.d.ts +8 -0
  95. package/dist/cjs/remoteconfig/tz-countries.js +13 -0
  96. package/dist/cjs/remotelog/gate.d.ts +2 -11
  97. package/dist/cjs/remotelog/gate.js +9 -35
  98. package/dist/cjs/remotelog/index.d.ts +4 -21
  99. package/dist/cjs/remotelog/logger.d.ts +11 -17
  100. package/dist/cjs/remotelog/logger.js +30 -58
  101. package/dist/cjs/remotelog/send.js +10 -10
  102. package/dist/cjs/remotelogger/index.d.ts +12 -0
  103. package/dist/cjs/remotelogger/index.js +18 -0
  104. package/dist/cjs/scheduler.js +2 -2
  105. package/dist/cjs/types.d.ts +155 -82
  106. package/dist/cjs/user/index.js +11 -6
  107. package/dist/esm/auto-init.d.ts +3 -3
  108. package/dist/esm/auto-init.js +1 -1
  109. package/dist/esm/core/attempts.js +1 -1
  110. package/dist/esm/core/batch.js +2 -1
  111. package/dist/esm/core/callsite.d.ts +6 -0
  112. package/dist/esm/core/callsite.js +25 -4
  113. package/dist/esm/core/consent.d.ts +5 -1
  114. package/dist/esm/core/consent.js +9 -7
  115. package/dist/esm/core/constants.d.ts +35 -10
  116. package/dist/esm/core/constants.js +30 -15
  117. package/dist/esm/core/db.d.ts +12 -4
  118. package/dist/esm/core/db.js +164 -35
  119. package/dist/esm/core/debug.js +1 -1
  120. package/dist/esm/core/env.js +1 -1
  121. package/dist/esm/core/framework-id.d.ts +1 -1
  122. package/dist/esm/core/framework-id.js +3 -3
  123. package/dist/esm/core/guard.d.ts +9 -0
  124. package/dist/esm/core/guard.js +27 -14
  125. package/dist/esm/core/hooks.d.ts +2 -4
  126. package/dist/esm/core/hooks.js +2 -3
  127. package/dist/esm/core/locks.d.ts +9 -0
  128. package/dist/esm/core/locks.js +20 -0
  129. package/dist/esm/core/logger.d.ts +3 -4
  130. package/dist/esm/core/logger.js +4 -40
  131. package/dist/esm/core/state.d.ts +3 -2
  132. package/dist/esm/core/state.js +2 -2
  133. package/dist/esm/core/storage.d.ts +20 -5
  134. package/dist/esm/core/storage.js +113 -18
  135. package/dist/esm/core/stylesheet.d.ts +8 -0
  136. package/dist/esm/core/stylesheet.js +27 -0
  137. package/dist/esm/core/transport.d.ts +2 -0
  138. package/dist/esm/core/transport.js +19 -5
  139. package/dist/esm/core/utils.js +1 -1
  140. package/dist/esm/core/validate.js +2 -2
  141. package/dist/esm/device/appversion.d.ts +1 -6
  142. package/dist/esm/device/appversion.js +13 -2
  143. package/dist/esm/device/index.d.ts +11 -0
  144. package/dist/esm/device/index.js +123 -24
  145. package/dist/esm/engagement/api-rules.d.ts +32 -67
  146. package/dist/esm/engagement/api-rules.js +143 -155
  147. package/dist/esm/engagement/auto-api.js +3 -3
  148. package/dist/esm/engagement/auto-screen.d.ts +2 -0
  149. package/dist/esm/engagement/auto-screen.js +67 -4
  150. package/dist/esm/engagement/defined-events.js +1 -1
  151. package/dist/esm/engagement/send.js +6 -1
  152. package/dist/esm/engagement/session.d.ts +12 -3
  153. package/dist/esm/engagement/session.js +162 -29
  154. package/dist/esm/engagement/track.js +52 -27
  155. package/dist/esm/errors/send.js +1 -1
  156. package/dist/esm/errors/track.d.ts +1 -1
  157. package/dist/esm/errors/track.js +46 -6
  158. package/dist/esm/feedback/controls.d.ts +6 -0
  159. package/dist/esm/feedback/controls.js +31 -2
  160. package/dist/esm/feedback/index.d.ts +8 -7
  161. package/dist/esm/feedback/index.js +34 -13
  162. package/dist/esm/feedback/logs.d.ts +10 -5
  163. package/dist/esm/feedback/logs.js +54 -15
  164. package/dist/esm/feedback/quartz.d.ts +18 -0
  165. package/dist/esm/feedback/quartz.js +99 -0
  166. package/dist/esm/feedback/send.d.ts +3 -0
  167. package/dist/esm/feedback/send.js +28 -5
  168. package/dist/esm/feedback/styles.d.ts +10 -0
  169. package/dist/esm/feedback/styles.js +4 -0
  170. package/dist/esm/feedback/template.d.ts +1 -1
  171. package/dist/esm/feedback/template.js +12 -12
  172. package/dist/esm/feedback/ui.d.ts +14 -6
  173. package/dist/esm/feedback/ui.js +126 -49
  174. package/dist/esm/heatmap/send.js +1 -1
  175. package/dist/esm/heatmap/track.d.ts +1 -1
  176. package/dist/esm/heatmap/track.js +87 -16
  177. package/dist/esm/index.d.ts +17 -63
  178. package/dist/esm/index.js +108 -80
  179. package/dist/esm/lifecycle.d.ts +8 -1
  180. package/dist/esm/lifecycle.js +266 -71
  181. package/dist/esm/remoteconfig/country.d.ts +4 -0
  182. package/dist/esm/remoteconfig/country.js +70 -0
  183. package/dist/esm/remoteconfig/custom.d.ts +7 -7
  184. package/dist/esm/remoteconfig/custom.js +32 -52
  185. package/dist/esm/remoteconfig/evaluate.d.ts +3 -3
  186. package/dist/esm/remoteconfig/evaluate.js +57 -44
  187. package/dist/esm/remoteconfig/fetch.d.ts +3 -3
  188. package/dist/esm/remoteconfig/fetch.js +9 -23
  189. package/dist/esm/remoteconfig/index.d.ts +10 -8
  190. package/dist/esm/remoteconfig/index.js +66 -40
  191. package/dist/esm/remoteconfig/store.js +1 -1
  192. package/dist/esm/remoteconfig/tz-countries.d.ts +8 -0
  193. package/dist/esm/remoteconfig/tz-countries.js +11 -0
  194. package/dist/esm/remotelog/gate.d.ts +2 -11
  195. package/dist/esm/remotelog/gate.js +10 -32
  196. package/dist/esm/remotelog/index.d.ts +4 -21
  197. package/dist/esm/remotelog/logger.d.ts +11 -17
  198. package/dist/esm/remotelog/logger.js +32 -60
  199. package/dist/esm/remotelog/send.js +12 -12
  200. package/dist/esm/remotelogger/index.d.ts +12 -0
  201. package/dist/esm/remotelogger/index.js +13 -0
  202. package/dist/esm/scheduler.js +2 -2
  203. package/dist/esm/types.d.ts +155 -82
  204. package/dist/esm/user/index.js +12 -6
  205. package/dist/feedback.esm.min.js +2 -2
  206. package/dist/feedback.esm.min.js.map +1 -1
  207. package/package.json +14 -16
  208. package/dist/chunks/batch-BU_mTpm1.min.js +0 -3
  209. package/dist/chunks/batch-BU_mTpm1.min.js.map +0 -1
  210. package/dist/chunks/logs-Bea5zUW_.min.js +0 -3
  211. package/dist/chunks/logs-Bea5zUW_.min.js.map +0 -1
  212. package/dist/cjs/heatmap/index.d.ts +0 -16
  213. package/dist/cjs/heatmap/index.js +0 -22
  214. package/dist/cjs/remotelog/index.js +0 -55
  215. package/dist/esm/heatmap/index.d.ts +0 -16
  216. package/dist/esm/heatmap/index.js +0 -17
  217. package/dist/esm/remotelog/index.js +0 -51
  218. package/dist/heatmap.esm.min.js +0 -3
  219. package/dist/heatmap.esm.min.js.map +0 -1
  220. package/dist/style.css +0 -1
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  var constants = require('./constants.js');
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  var logger = require('./logger.js');
@@ -220,7 +220,7 @@ function validateScreenName(str) {
220
220
  }
221
221
  // Define the regular expression pattern
222
222
  //^[a-zA-Z][\\w\\s]{1,100}$
223
- const pattern = /^[\w\s.\-_&/:]{0,99}$/;
223
+ const pattern = /^[\w\s.\-_&/:*]{0,99}$/;
224
224
  // Test if the string matches the pattern
225
225
  return pattern.test(str);
226
226
  }
@@ -1,11 +1,6 @@
1
1
  /** Whether we already hold usable ids for the app and version running now. */
2
2
  export declare function hasAppVersion(): boolean;
3
- /**
4
- * Registers this build, or reuses the stored answer.
5
- *
6
- * Resolves true when the ids are in place, false when they are not — the caller stops there
7
- * rather than carrying on to calls that would be refused for missing them.
8
- */
3
+ export declare function appVersionFailedForNetwork(): boolean;
9
4
  export declare function registerAppVersion(): Promise<boolean>;
10
5
  /**
11
6
  * Puts the stored ids back on `_ZAP._device_info`.
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  var state = require('../core/state.js');
@@ -80,7 +80,16 @@ function apply(data) {
80
80
  * Resolves true when the ids are in place, false when they are not — the caller stops there
81
81
  * rather than carrying on to calls that would be refused for missing them.
82
82
  */
83
+ /**
84
+ * Whether the last registration failed for want of a network (offline, a dropped connection, a
85
+ * timeout) rather than because the server answered no. Only the first is worth trying again.
86
+ */
87
+ var failedForNetwork = false;
88
+ function appVersionFailedForNetwork() {
89
+ return failedForNetwork;
90
+ }
83
91
  function registerAppVersion() {
92
+ failedForNetwork = false;
84
93
  if (hasAppVersion()) {
85
94
  apply(stored());
86
95
  logger.Console.log(LABEL + ': reusing the ids stored for ' + state._ZAP._defaultoptions.appversion); // no i18n
@@ -128,6 +137,8 @@ function registerAppVersion() {
128
137
  return true;
129
138
  })
130
139
  .catch(function (err) {
140
+ // a server answer carries serverResult; a request that never got one does not
141
+ failedForNetwork = !(err && err.serverResult) || navigator.onLine === false;
131
142
  logger.warnAlways(LABEL + ': could not register this app version: ' + String(err && err.message ? err.message : err)); // no i18n
132
143
  return false;
133
144
  })
@@ -152,6 +163,7 @@ function clearAppVersion() {
152
163
  storage.user_defaults.add(STORE_KEY, undefined);
153
164
  }
154
165
 
166
+ exports.appVersionFailedForNetwork = appVersionFailedForNetwork;
155
167
  exports.applyStoredAppVersion = applyStoredAppVersion;
156
168
  exports.clearAppVersion = clearAppVersion;
157
169
  exports.hasAppVersion = hasAppVersion;
@@ -1,6 +1,17 @@
1
1
  import type { DeviceInfo, Dict, ServerResult } from '../types.js';
2
2
  export declare function checkAndUpdateDeviceInfo(): void;
3
3
  export declare function addOrUpdateDeviceID(device_info: DeviceInfo, previous?: DeviceInfo): void;
4
+ /**
5
+ * Sets up this browser's device at start-up: the uuid, the device info, and a registration when
6
+ * the browser has none.
7
+ *
8
+ * Settings are this tab's own copy, loaded when it started. On a browser with no device yet, two
9
+ * tabs started together would each register it and store two devices, so the first visit runs
10
+ * under a lock shared by every tab of the site: the tab that gets it re-reads storage, registers
11
+ * only when no other tab has, and keeps the lock until the new ids are stored. The next tab then
12
+ * finds them. Start-up goes on as soon as the device info is set, without waiting for the server.
13
+ */
14
+ export declare function prepareDevice(): Promise<void>;
4
15
  /** True while the device has no server ids, so nothing can be sent yet. */
5
16
  export declare function needsDevice(): boolean;
6
17
  /**
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  var constants = require('../core/constants.js');
@@ -6,6 +6,7 @@ var state = require('../core/state.js');
6
6
  var logger = require('../core/logger.js');
7
7
  var utils = require('../core/utils.js');
8
8
  var storage = require('../core/storage.js');
9
+ var locks = require('../core/locks.js');
9
10
  var env = require('../core/env.js');
10
11
  var consent = require('../core/consent.js');
11
12
  var transport = require('../core/transport.js');
@@ -95,7 +96,11 @@ function checkAndUpdateDeviceInfo() {
95
96
  // appreleaseversionid from app/addversion
96
97
  modelid: storage.getKeyFromDeviceInfo('modelid'), // no i18n
97
98
  appreleaseversionid: storage.getKeyFromDeviceInfo('appreleaseversionid'), // no i18n
98
- timezone: env.getTimeZone()
99
+ timezone: env.getTimeZone(),
100
+ // kept here rather than as keys of their own: the id the browser is registered under, and
101
+ // whether it has had a session (a session's firstsession says so)
102
+ uuid: state._ZAP._uuid || storage.getKeyFromDeviceInfo('uuid'), // no i18n
103
+ hadsession: storage.getKeyFromDeviceInfo('hadsession') === true ? true : undefined, // no i18n
99
104
  };
100
105
  // the rebuild above starts from browser facts, so the ids app/addversion returned are put
101
106
  // back before anything is stored or compared
@@ -143,7 +148,7 @@ function addOrUpdateDeviceID(device_info, previous) {
143
148
  * out as an empty header.
144
149
  */
145
150
  const DEVICE_RESPONSE_KEYS = ['deviceid', 'anonymousid', 'aaid', 'apid', 'mapid', 'appversionid', 'osversionid', 'timezoneid', 'platformid', 'devicetypeid', 'modelid']; // no i18n
146
- /** Copies server-assigned ids into state and persists device info. */
151
+ /** Copies server-assigned ids into state and persists device info; resolves once it is stored. */
147
152
  function applyDeviceResponse(data) {
148
153
  DEVICE_RESPONSE_KEYS.forEach(function (key) {
149
154
  // an id the answer does not mention is one we already hold, or one we never had:
@@ -159,12 +164,81 @@ function applyDeviceResponse(data) {
159
164
  if (!utils.isEmpty(data.mapid)) {
160
165
  state._ZAP._mapid = data.mapid;
161
166
  }
162
- // Update the new device info into the localstorage
163
- storage.user_defaults.add('device_info', state._ZAP._device_info); // no i18n
167
+ // stored before the registration counts as done, so another tab waiting to register reads it
168
+ return storage.user_defaults.save('device_info', state._ZAP._device_info); // no i18n
169
+ }
170
+ /**
171
+ * The browser's uuid: the one in storage, or a new one stored now. Every tab of the site uses the
172
+ * same one, because the device is registered under it.
173
+ */
174
+ function useStoredUuid() {
175
+ // kept in device_info: it is the id this browser is registered under
176
+ var uuid = storage.getKeyFromDeviceInfo('uuid'); // no i18n
177
+ if (utils.isEmpty(uuid)) {
178
+ uuid = utils.getNewUUID();
179
+ storage.setDeviceInfoKey('uuid', uuid); // no i18n
180
+ }
181
+ state._ZAP._uuid = uuid;
182
+ }
183
+ /**
184
+ * The ids another tab of this site registered after this one loaded its settings: those are in
185
+ * storage but not in this tab's copy. Resolves with them, applied to this tab, or null when the
186
+ * browser is still unregistered and this tab has to register it.
187
+ */
188
+ function adoptRegisteredDevice() {
189
+ return storage.reloadSettings(['device_info']).then(function () {
190
+ var stored = storage.user_defaults.item('device_info') || {}; // no i18n
191
+ if (utils.isEmpty(stored.deviceid) || utils.isEmpty(stored.anonymousid)) {
192
+ return null;
193
+ }
194
+ // the device is registered under the uuid the other tab sent
195
+ if (!utils.isEmpty(stored.uuid)) {
196
+ state._ZAP._uuid = stored.uuid;
197
+ }
198
+ logger.Console.log('registerDeviceWithApptics: another tab registered this browser, using its device ' + stored.deviceid); // no i18n
199
+ return applyDeviceResponse(stored).then(function () {
200
+ return { result: 'success', data: stored }; // no i18n
201
+ });
202
+ });
203
+ }
204
+ /**
205
+ * Sets up this browser's device at start-up: the uuid, the device info, and a registration when
206
+ * the browser has none.
207
+ *
208
+ * Settings are this tab's own copy, loaded when it started. On a browser with no device yet, two
209
+ * tabs started together would each register it and store two devices, so the first visit runs
210
+ * under a lock shared by every tab of the site: the tab that gets it re-reads storage, registers
211
+ * only when no other tab has, and keeps the lock until the new ids are stored. The next tab then
212
+ * finds them. Start-up goes on as soon as the device info is set, without waiting for the server.
213
+ */
214
+ function prepareDevice() {
215
+ var cached = storage.user_defaults.item('device_info') || {}; // no i18n
216
+ if (!utils.isEmpty(cached.deviceid) && !utils.isEmpty(cached.anonymousid)) {
217
+ useStoredUuid();
218
+ checkAndUpdateDeviceInfo();
219
+ return Promise.resolve();
220
+ }
221
+ return new Promise(function (resolve) {
222
+ locks.withLock('device', function () {
223
+ return storage.reloadSettings(['device_info']).then(function () {
224
+ useStoredUuid();
225
+ checkAndUpdateDeviceInfo();
226
+ resolve();
227
+ // held until a registration this started is stored, or has failed
228
+ return deviceReady();
229
+ });
230
+ }).catch(function (err) {
231
+ logger.Console.log('prepareDevice: ' + err); // no i18n
232
+ }).then(function () {
233
+ resolve();
234
+ });
235
+ });
164
236
  }
165
237
  /** True while the device has no server ids, so nothing can be sent yet. */
166
238
  function needsDevice() {
167
- return utils.isEmpty(transport.getHeaderParams('apid')) && utils.isEmpty(transport.getHeaderParams('mapid')); // no i18n
239
+ // the app ids from app/addversion, and the deviceid from device/add: either missing, and the
240
+ // device is registered before anything stored is sent
241
+ return (utils.isEmpty(transport.getHeaderParams('apid')) && utils.isEmpty(transport.getHeaderParams('mapid'))) || !transport.hasDeviceId(); // no i18n
168
242
  }
169
243
  /**
170
244
  * Resolves once a registration that is in flight has settled, succeeded or not, and right away
@@ -197,8 +271,8 @@ function registerDeviceWithApptics() {
197
271
  return blocked;
198
272
  }
199
273
  if (!state._ZAP._token) {
200
- logger.Console.warn(label + ': You must call apptics.init() first'); // no i18n
201
- return Promise.reject(label + ': You must call apptics.init() first'); // no i18n
274
+ logger.Console.warn(label + ': You must call Apptics.init() first'); // no i18n
275
+ return Promise.reject(label + ': You must call Apptics.init() first'); // no i18n
202
276
  }
203
277
  var offline = transport.rejectIfOffline(label);
204
278
  if (offline) {
@@ -215,13 +289,21 @@ function registerDeviceWithApptics() {
215
289
  return;
216
290
  }
217
291
  state._ZAP._regDeviceSending = true;
218
- var payload = deviceBody(state._ZAP._device_info);
219
- // device/add is the one url that allows all four: zak and uuid identify the caller,
220
- // apid and mapid the app. app/addversion has already answered with apid and mapid by
221
- // the time registration runs, so the first call can carry them like every later one.
222
- var headers = { zak: transport.getHeaderParams('zak'), uuid: transport.getHeaderParams('uuid'), ...transport.apiHeaders() }; // no i18n
223
- transport.postToApptics('regdevice', payload, headers, label).then(function (result) {
224
- applyDeviceResponse(result.data || {});
292
+ adoptRegisteredDevice().then(function (adopted) {
293
+ if (adopted) {
294
+ return adopted;
295
+ }
296
+ var payload = deviceBody(state._ZAP._device_info);
297
+ // device/add is the one url that allows all four: zak and uuid identify the caller,
298
+ // apid and mapid the app. app/addversion has already answered with apid and mapid by
299
+ // the time registration runs, so the first call can carry them like every later one.
300
+ var headers = { zak: transport.getHeaderParams('zak'), uuid: transport.getHeaderParams('uuid'), ...transport.apiHeaders() }; // no i18n
301
+ return transport.postToApptics('regdevice', payload, headers, label).then(function (result) {
302
+ return applyDeviceResponse(result.data || {}).then(function () {
303
+ return result;
304
+ });
305
+ });
306
+ }).then(function (result) {
225
307
  settleRegistration(true, result);
226
308
  resolve(result);
227
309
  // first visit: the ids exist now, so fetch the server settings right away
@@ -257,7 +339,9 @@ function getUpdatesFromServer() {
257
339
  return transport.postToApptics('sdkconfig', '', transport.apiHeaders(), label).then(function (result) {
258
340
  var data = result.data || {};
259
341
  applyServerFlags(data);
260
- storage.user_defaults.add('trackinfo', state._ZAP._trackinfo); // no i18n
342
+ // the visitor's tracking status lives in trackinfo too, and is not the server's to replace
343
+ var saved = storage.storedTrackingStatus();
344
+ storage.user_defaults.add('trackinfo', saved === undefined ? state._ZAP._trackinfo : Object.assign({}, state._ZAP._trackinfo, { tracking_status: saved })); // no i18n
261
345
  logger.Console.log('getUpdatesFromServer: ' + JSON.stringify(state._ZAP._trackinfo)); // no i18n
262
346
  return data;
263
347
  });
@@ -316,10 +400,18 @@ function applyServerFlags(data) {
316
400
  state._ZAP._remoteLoggerEnabled = data.remoteloggerenabled !== false;
317
401
  state._ZAP._feedbackEnabled = data.feedbackenabled !== false;
318
402
  }
403
+ // screen recording, set up in the console: everything the form needs comes from here
319
404
  var quartz = (data.quartz && typeof data.quartz === 'object' ? data.quartz : {});
320
- state._ZAP._quartzEnabled = quartz.hasOwnProperty('quartz_enabled') // no i18n
321
- ? quartz.quartz_enabled !== false
322
- : data.quartzenabled !== false;
405
+ var text = function (value) {
406
+ return typeof value === 'string' ? value.trim() : ''; // no i18n
407
+ };
408
+ state._ZAP._quartz = {
409
+ enabled: quartz.hasOwnProperty('quartz_enabled') ? quartz.quartz_enabled === true : data.quartzenabled === true, // no i18n
410
+ workspace: text(quartz.quartz_workspace),
411
+ department: text(quartz.quartz_department),
412
+ domain: text(quartz.quartz_domain),
413
+ cdnUrl: text(quartz.quartz_cdn_url),
414
+ };
323
415
  // when to ask again, which replaces polling on a fixed interval
324
416
  if (typeof data.next_check_after === 'number' && data.next_check_after > 0) {
325
417
  state._ZAP._nextConfigCheck = data.next_check_after;
@@ -330,7 +422,14 @@ function applyServerFlags(data) {
330
422
  heatmaptracking: state._ZAP._heatmapTracking,
331
423
  remoteloggerenabled: state._ZAP._remoteLoggerEnabled,
332
424
  feedbackenabled: state._ZAP._feedbackEnabled,
333
- quartzenabled: state._ZAP._quartzEnabled,
425
+ // in the server's own shape, so restoring it on the next visit reads it the same way
426
+ quartz: {
427
+ quartz_enabled: state._ZAP._quartz.enabled,
428
+ quartz_workspace: state._ZAP._quartz.workspace,
429
+ quartz_department: state._ZAP._quartz.department,
430
+ quartz_domain: state._ZAP._quartz.domain,
431
+ quartz_cdn_url: state._ZAP._quartz.cdnUrl,
432
+ },
334
433
  shouldtrack: state._ZAP._shouldTrack,
335
434
  next_check_after: state._ZAP._nextConfigCheck
336
435
  };
@@ -366,6 +465,7 @@ exports.checkAndUpdateDeviceInfo = checkAndUpdateDeviceInfo;
366
465
  exports.deviceReady = deviceReady;
367
466
  exports.getUpdatesFromServer = getUpdatesFromServer;
368
467
  exports.needsDevice = needsDevice;
468
+ exports.prepareDevice = prepareDevice;
369
469
  exports.refreshServerSettings = refreshServerSettings;
370
470
  exports.registerDeviceWithApptics = registerDeviceWithApptics;
371
471
  exports.restoreServerSettings = restoreServerSettings;
@@ -1,62 +1,34 @@
1
- /**
2
- * What API tracking records, and under what name — Android's AppticsApiTracker.configure, built
3
- * with ApiTrackingBuilder the way user properties are built with UserBuilder:
4
- *
5
- * configureApiTracking(new ApiTrackingBuilder()
6
- * .allowOnlyDomains('api.zylker.com', 'api.zylker.in')
7
- * .groupDomains('api.zylker.*')
8
- * .ignoreEndpoint('/health', '/internal/**')
9
- * .addPattern('/v2/catalog/{categoryId}/items/{itemId}')
10
- * .build());
11
- *
12
- * Two jobs. Filtering decides whether a call is recorded at all: ignore rules first, and they
13
- * always win, then the allow lists. Normalization decides the path it is recorded under, so that
14
- * `/users/42/orders` and `/users/43/orders` are one endpoint on the console rather than two: the
15
- * query string goes, an explicit pattern is used when one matches, and otherwise numeric ids,
16
- * UUIDs and JWTs become `*`.
17
- *
18
- * Both apply to every call, the ones the fetch/XHR wrappers catch and the ones the app reports
19
- * with trackApi() or startTrackApi(), so one set of rules decides what the API page shows.
20
- */
21
1
  /** The rules, as ApiTrackingBuilder.build() returns them. Every list may be empty. */
22
2
  export interface ApiTrackingConfig {
23
- ignoreDomains: string[];
24
- allowOnlyDomains: string[];
25
- allowOnlyTLDs: string[];
26
- ignoreTLDs: string[];
27
- ignoreDomainPrefixes: string[];
28
- ignoreDomainSuffixes: string[];
29
- groupDomains: string[];
30
- ignoreEndpoints: string[];
31
- patterns: string[];
32
- preserveSegments: string[];
33
- autoDetection: boolean;
3
+ /** URLs recorded, exactly; with any allow rule, only calls matching one are recorded. */
4
+ allowEquals: string[];
5
+ /** URLs never recorded, exactly. */
6
+ ignoreEquals: string[];
7
+ /** Regular expressions a recorded URL may match; with any allow rule, it must match one. */
8
+ allowRegex: RegExp[];
9
+ /** Regular expressions whose URLs are never recorded. */
10
+ ignoreRegex: RegExp[];
34
11
  }
35
- /** Builds the rules for configureApiTracking, with AppticsApiTracker.configure's names. */
12
+ /**
13
+ * A URL as the rules compare it: `scheme://host[:port]/path`, the scheme and host lower-cased,
14
+ * the default port dropped, the query, fragment and a trailing slash removed. '' when it is not
15
+ * an absolute http(s) URL.
16
+ */
17
+ export declare function ruleUrl(raw: string): string;
18
+ /**
19
+ * Builds the rules configure takes. Each method may be called more than once, and takes any number
20
+ * of values: `new ApiTrackingBuilder().allowEquals(a, b).ignoreRegex(/x/).build()`.
21
+ */
36
22
  export declare class ApiTrackingBuilder {
37
23
  private rules;
38
- /** Never records these hosts. */
39
- ignoreDomains(...domains: string[]): this;
40
- /** Records only these hosts; every other is skipped. */
41
- allowOnlyDomains(...domains: string[]): this;
42
- /** Records only hosts ending in these TLDs, e.g. `.com`. */
43
- allowOnlyTLDs(...tlds: string[]): this;
44
- /** Never records hosts ending in these TLDs, e.g. `.local`. */
45
- ignoreTLDs(...tlds: string[]): this;
46
- /** Never records hosts starting with these, e.g. `dev.`. */
47
- ignoreDomainPrefixes(...prefixes: string[]): this;
48
- /** Never records hosts ending with these, e.g. `.cdn.net`. */
49
- ignoreDomainSuffixes(...suffixes: string[]): this;
50
- /** Records the hosts a pattern such as `api.myapp.*` matches under that one name. */
51
- groupDomains(...patterns: string[]): this;
52
- /** Never records these paths: exact, `*` or `{name}` for one segment, `**` at the end for a prefix. */
53
- ignoreEndpoint(...paths: string[]): this;
54
- /** Records a path this pattern matches as the pattern, with each `{name}` as `*`. Tried before auto-detection. */
55
- addPattern(...patterns: string[]): this;
56
- /** Segments never turned into `*`, e.g. `v1` or `404`. */
57
- preserveSegments(...segments: string[]): this;
58
- /** `false`: only addPattern paths are normalized; every other path is recorded as it is. */
59
- autoDetection(enabled: boolean): this;
24
+ /** Records only these URLs (and those any allowRegex matches): `https://api.example.com/orders`. */
25
+ allowEquals(...urls: string[]): this;
26
+ /** Never records these URLs: `https://api.example.com/health`. */
27
+ ignoreEquals(...urls: string[]): this;
28
+ /** Records only URLs these match (and those any allowEquals names): `/^https:\/\/api\.example\.com\//`. */
29
+ allowRegex(...patterns: Array<RegExp | string>): this;
30
+ /** Never records URLs these match: `/\/internal\//`. */
31
+ ignoreRegex(...patterns: Array<RegExp | string>): this;
60
32
  build(): ApiTrackingConfig;
61
33
  }
62
34
  /**
@@ -66,19 +38,12 @@ export declare class ApiTrackingBuilder {
66
38
  export declare function configureApiTracking(config: ApiTrackingConfig | ApiTrackingBuilder): void;
67
39
  /** The rules in force, for tests and the playground. */
68
40
  export declare function apiTrackingConfig(): ApiTrackingConfig;
69
- /** Whether calls to this host are recorded. Ignore rules are checked first and always win. */
70
- export declare function hostAllowed(hostname: string): boolean;
71
- /** The name a host is recorded under: the first groupDomains pattern it matches, or itself. */
72
- export declare function groupedHost(hostname: string): string;
73
- /** Whether a host is one of the groupDomains names, which carry a `*` no real host has. */
74
- export declare function isGroupedHost(hostname: string): boolean;
75
- /** The path without its query string or fragment, which is where ids and tokens travel. */
76
- export declare function withoutQuery(path: string): string;
77
- /** Whether ignoreEndpoint leaves this path out. Matched on the path as called, query removed. */
78
- export declare function endpointIgnored(path: string): boolean;
79
41
  /**
80
- * The path a call is recorded under. The query goes; then the first addPattern that matches is
81
- * used, with each `{name}` as `*` (the server's path rule has no room for braces); otherwise, with
82
- * autoDetection on, numeric ids, UUIDs and JWTs become `*`, except preserveSegments.
42
+ * Whether a call to `url` is recorded. Ignore rules are tried first and always win; then, when
43
+ * there are allow rules, the URL must match one. A URL that cannot be read is not recorded.
83
44
  */
45
+ export declare function urlTracked(url: string): boolean;
46
+ /** The path without its query string or fragment, which is where ids and tokens travel. */
47
+ export declare function withoutQuery(path: string): string;
48
+ /** The path a call is recorded under: the query goes, and numeric ids, UUIDs and JWTs become `*`. */
84
49
  export declare function normalizeApiPath(path: string): string;