@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,8 +1,6 @@
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
  import { _ZAP } from './state.js';
3
- import { hooks } from './hooks.js';
4
3
  import { each } from './utils.js';
5
- import { callSiteFromStack, callSite } from './callsite.js';
6
4
 
7
5
  const APConsole = typeof console !== 'undefined' ? console : null;
8
6
  function gated(method) {
@@ -36,47 +34,13 @@ function warnAlways(...args) {
36
34
  if (APConsole)
37
35
  APConsole.warn(...args);
38
36
  }
39
- function safeJson(value) {
40
- try {
41
- return JSON.stringify(value) || String(value);
42
- }
43
- catch (err) {
44
- return String(value);
45
- }
46
- }
47
37
  /**
48
- * A failure inside one of the SDK's own modules: logged to the console as usual, and sent to
49
- * console/addlog so it can be read back from the Apptics console when the SDK misbehaves in the
50
- * wild. `module` is one of AP_LOG_MODULE's values. The remote half does nothing until
51
- * the remotelog module has been loaded and its own switch allows it.
38
+ * A failure inside one of the SDK's own modules, `module` one of AP_LOG_MODULE's values: said in
39
+ * the browser console in debug mode. Nothing is sent: the Remote Logger page carries only the
40
+ * lines an app logs with AppticsLogger.
52
41
  */
53
42
  function logFailure(module, ...args) {
54
43
  Console.error.apply(null, args);
55
- hooks.remoteLog(module, args.map(function (arg) {
56
- if (arg instanceof Error) {
57
- return arg.stack || (arg.name + ': ' + arg.message); // no i18n
58
- }
59
- return typeof arg === 'string' ? arg : safeJson(arg); // no i18n
60
- }).join(' '), siteOf(args)); // no i18n
61
- }
62
- /**
63
- * Where to say the failure happened. An Error knows where it was thrown, which is the place
64
- * worth reporting; the alternative is where it was caught, which is usually a catch block three
65
- * modules away. Only a frame we could actually read counts, so an Error with no usable stack
66
- * falls through to logFailure's own caller.
67
- */
68
- function siteOf(args) {
69
- for (var i = 0; i < args.length; i++) {
70
- var arg = args[i];
71
- if (arg instanceof Error) {
72
- var thrownAt = callSiteFromStack(arg.stack, 0);
73
- if (thrownAt.linenumber > 0) {
74
- return thrownAt;
75
- }
76
- }
77
- }
78
- // past siteOf and logFailure, to whoever reported the failure
79
- return callSite(2);
80
44
  }
81
45
 
82
46
  export { Console, logFailure, warnAlways };
@@ -1,5 +1,5 @@
1
1
  import { type ApConfig } from './constants.js';
2
- import type { DeviceInfo, Dict, TrackingStatus, UserInfo } from '../types.js';
2
+ import type { DeviceInfo, Dict, QuartzSettings, TrackingStatus, UserInfo } from '../types.js';
3
3
  /** Runtime state shared by every module (the former `_ZAP` object). */
4
4
  export interface State {
5
5
  _initialised: boolean;
@@ -44,7 +44,8 @@ export interface State {
44
44
  _remoteConfigReported: boolean;
45
45
  /** getsdkconfig module 12. */
46
46
  _feedbackEnabled: boolean;
47
- _quartzEnabled: boolean;
47
+ /** getsdkconfig's `quartz` block: screen recording in the feedback form. Off until it says otherwise. */
48
+ _quartz: QuartzSettings;
48
49
  /** Epoch ms getsdkconfig asked us to wait until before asking again. 0 means no answer yet. */
49
50
  _nextConfigCheck: number;
50
51
  /**
@@ -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
  import { AP_TRACKING_STATUS, AP_CONSTANTS, DEFAULT_INACTIVE_MINUTES, AP_CONFIG } from './constants.js';
3
3
  import { nowMs } from './utils.js';
4
4
  import { FRAMEWORK_ID } from './framework-id.js';
@@ -43,7 +43,7 @@ function initialState() {
43
43
  _nextConfigCheck: 0,
44
44
  _debugUntil: 0,
45
45
  _errorTracking: true,
46
- _quartzEnabled: true,
46
+ _quartz: { enabled: false, workspace: '', department: '', domain: '', cdnUrl: '' }, // no i18n
47
47
  _trackinfo: {},
48
48
  };
49
49
  }
@@ -20,23 +20,38 @@ export declare const error_transactions: Queue;
20
20
  * These are not sent on their own: feedback/logs.ts renders them into the files that
21
21
  * feedback/add carries, and removes the ones a submission took with it.
22
22
  */
23
- export declare const log_transactions: Queue;
23
+ export declare const feedbacklog_transactions: Queue;
24
24
  /** Clicks and scrolls waiting for heatmap/add. */
25
25
  export declare const heatmap_transactions: Queue;
26
26
  /**
27
- * Remote log lines waiting for console/addlog. Stored rather than sent straight out because the
27
+ * Remote log lines waiting for log/add. Stored rather than sent straight out because the
28
28
  * endpoint takes one line per call and counts retries (`attempt`), so a line has to outlive a
29
29
  * failed send — and a reload.
30
30
  */
31
- export declare const consolelog_transactions: Queue;
32
- /** Token, uuid, appversion, device_info, users, trackinfo. */
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. */
33
38
  export declare const user_defaults: {
34
39
  all(): Dict;
35
40
  item(key: string): any;
36
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>;
37
44
  clear(): void;
38
45
  };
39
- /** Opt-in status, stored as the tracking_status setting. */
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. */
40
55
  export declare const tracking_preference: {
41
56
  _tracking_status: string;
42
57
  all(): Dict;
@@ -1,9 +1,9 @@
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
  import { AP_TRACKING_STATUS } from './constants.js';
3
3
  import { _ZAP, isExpired, getConfig } from './state.js';
4
4
  import { Console } from './logger.js';
5
- import { cloneObject, getNewUUID, sizeof } from './utils.js';
6
- import { openBackend, LEGACY_KEYS, asList, asDict } from './db.js';
5
+ import { cloneObject, getNewUUID, isEmpty, sizeof } from './utils.js';
6
+ import { openBackend, LEGACY_KEYS, asList, renameFeedbackType, asDict } from './db.js';
7
7
 
8
8
  var readyPromise = null;
9
9
  var settings = {};
@@ -28,8 +28,6 @@ function migrateLegacy(b) {
28
28
  errors: localStorage.getItem(LEGACY_KEYS.errors),
29
29
  logs: localStorage.getItem(LEGACY_KEYS.logs),
30
30
  consolelogs: localStorage.getItem(LEGACY_KEYS.consolelogs),
31
- // read for completeness of the shape only: 1.x never wrote this key
32
- heatmaps: null,
33
31
  };
34
32
  }
35
33
  catch (err) {
@@ -47,15 +45,17 @@ function migrateLegacy(b) {
47
45
  return null;
48
46
  }
49
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
50
  var queues = {
51
51
  engagements: asList(parse(raw.engagements)),
52
52
  errors: asList(parse(raw.errors)),
53
- logs: asList(parse(raw.logs)),
54
- consolelogs: asList(parse(raw.consolelogs)),
53
+ feedbacklogs: asList(parse(raw.logs)).map(renameFeedbackType),
54
+ remotelogs: asList(parse(raw.consolelogs)),
55
55
  // nothing to migrate: 1.x had no heatmaps
56
56
  heatmaps: [],
57
57
  };
58
- queues.engagements.concat(queues.errors, queues.logs, queues.consolelogs).forEach(function (item) {
58
+ queues.engagements.concat(queues.errors, queues.feedbacklogs, queues.remotelogs).forEach(function (item) {
59
59
  if (!item.id)
60
60
  item.id = getNewUUID();
61
61
  });
@@ -89,6 +89,7 @@ function storageReady() {
89
89
  }).then(function (loaded) {
90
90
  // writes made before loading finished win over stored values
91
91
  settings = Object.assign({}, loaded, settings);
92
+ moveRetiredSettings();
92
93
  return b;
93
94
  });
94
95
  }).catch(function (err) {
@@ -159,21 +160,75 @@ const error_transactions = createQueue('errors'); // no i18n
159
160
  * These are not sent on their own: feedback/logs.ts renders them into the files that
160
161
  * feedback/add carries, and removes the ones a submission took with it.
161
162
  */
162
- const log_transactions = createQueue('logs'); // no i18n
163
+ const feedbacklog_transactions = createQueue('feedbacklogs'); // no i18n
163
164
  /** Clicks and scrolls waiting for heatmap/add. */
164
165
  const heatmap_transactions = createQueue('heatmaps'); // no i18n
165
166
  /**
166
- * Remote log lines waiting for console/addlog. Stored rather than sent straight out because the
167
+ * Remote log lines waiting for log/add. Stored rather than sent straight out because the
167
168
  * endpoint takes one line per call and counts retries (`attempt`), so a line has to outlive a
168
169
  * failed send — and a reload.
169
170
  */
170
- const consolelog_transactions = createQueue('consolelogs'); // no i18n
171
+ const remotelog_transactions = createQueue('remotelogs'); // no i18n
171
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
+ }
172
177
  function setSetting(key, value) {
173
- settings[key] = value === undefined ? undefined : cloneObject(value);
174
- withBackend('save ' + key, undefined, function (b) { return b.putSetting(key, settings[key]); }); // no i18n
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
+ }
175
218
  }
176
- /** Token, uuid, appversion, device_info, users, trackinfo. */
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. */
177
232
  const user_defaults = {
178
233
  all() {
179
234
  return cloneObject(settings);
@@ -185,26 +240,66 @@ const user_defaults = {
185
240
  add(key, value) {
186
241
  setSetting(key, value);
187
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
+ },
188
253
  clear() {
189
254
  settings = {};
190
255
  withBackend('clear settings', undefined, function (b) { return b.clearSettings(); }); // no i18n
191
256
  },
192
257
  };
193
- /** Opt-in status, stored as the tracking_status setting. */
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. */
194
284
  const tracking_preference = {
195
285
  _tracking_status: 'tracking_status', // no i18n
196
286
  all() {
197
287
  return user_defaults.all();
198
288
  },
199
289
  opt_in_status() {
200
- return (settings[tracking_preference._tracking_status] || AP_TRACKING_STATUS.USAGE_TRACKING_WITHOUT_PII);
290
+ return (storedTrackingStatus() || AP_TRACKING_STATUS.USAGE_TRACKING_WITHOUT_PII);
201
291
  },
202
292
  update_status(tracking_status) {
203
293
  _ZAP._devicestatus = tracking_status;
204
294
  // Legacy order kept: this reads the status *before* the write below (setTrackingStatus recomputes it after).
205
295
  _ZAP._isanonrequired =
206
296
  tracking_preference.opt_in_status() == AP_TRACKING_STATUS.USAGE_TRACKING_WITH_PII ? false : _ZAP._isanonrequired;
207
- setSetting(tracking_preference._tracking_status, tracking_status);
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
208
303
  },
209
304
  };
210
305
  function getKeyFromDeviceInfo(key) {
@@ -216,4 +311,4 @@ function getKeyFromDeviceInfo(key) {
216
311
  return null;
217
312
  }
218
313
 
219
- export { consolelog_transactions, engagement_transactions, error_transactions, getKeyFromDeviceInfo, heatmap_transactions, log_transactions, storageReady, tracking_preference, user_defaults };
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 };
@@ -81,3 +81,5 @@ export declare function getMetaObj(): Dict;
81
81
  * and feedback (P11).
82
82
  */
83
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;
@@ -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
  import { API_VERSIONS, PATHS_WITHOUT_ORG, DEFAULT_API_PATHS, DEBUG_CAPABLE_PATHS, AP_TRACKING_STATUS, DEVICE_NAME_MAX } from './constants.js';
3
3
  import { getConfig, _ZAP } from './state.js';
4
4
  import { Console } from './logger.js';
@@ -172,8 +172,11 @@ function getParameters(path) {
172
172
  }
173
173
  return returnVal + mandatoryParams(returnVal);
174
174
  }
175
- // add userid and groupid if opt_in_status is USAGE_TRACKING_WITH_PII
176
- if (path != 'reguser' && identifiesDevice) { // no i18n
175
+ // add userid and groupid if opt_in_status is USAGE_TRACKING_WITH_PII. getupdates doesn't declare
176
+ // them, and refuses userid as EXTRA_PARAM_FOUND; it has no use for them either, since remote
177
+ // config conditions on the user are evaluated here, against the rule set it answers with
178
+ var carriesUser = path != 'reguser' && path != 'getupdates'; // no i18n
179
+ if (carriesUser && identifiesDevice) {
177
180
  if (opt_in_status() == AP_TRACKING_STATUS.USAGE_TRACKING_WITH_PII) {
178
181
  if (_ZAP._user_info.hasOwnProperty('userid') && !isEmpty(_ZAP._user_info.userid)) { // no i18n
179
182
  returnVal += '&userid=' + encodeURIComponent(String(_ZAP._user_info.userid)); // no i18n
@@ -417,9 +420,20 @@ function getMetaObj() {
417
420
  function rejectIfNoDeviceIds(label) {
418
421
  if (isEmpty(getHeaderParams('apid')) && isEmpty(getHeaderParams('mapid'))) { // no i18n
419
422
  hooks.refreshDeviceInfo();
420
- return Promise.reject(label + ': You must call apptics.init() first'); // no i18n
423
+ return Promise.reject(label + ': You must call Apptics.init() first'); // no i18n
424
+ }
425
+ // app/addversion has answered, device/add not yet (offline, or it failed): what is stored waits
426
+ // for the device it belongs to rather than going out without a deviceid. The refresh registers
427
+ // the device, joining a registration already in flight
428
+ if (!hasDeviceId()) {
429
+ hooks.refreshDeviceInfo();
430
+ return Promise.reject(label + ': the device is not registered yet, kept for the next send'); // no i18n
421
431
  }
422
432
  return null;
423
433
  }
434
+ /** Whether device/add has given this browser its deviceid. */
435
+ function hasDeviceId() {
436
+ return !isEmpty(_ZAP._device_info && _ZAP._device_info.deviceid) || !isEmpty(getKeyFromDeviceInfo('deviceid')); // no i18n
437
+ }
424
438
 
425
- export { KEEPALIVE_BUDGET, REQUEST_TIMEOUT_MS, apiHeaders, getHeaderParams, getMetaObj, getParameters, getUrlWithParams, isPermanentRefusal, makeRequest, postKeepalive, postToApptics, rejectIfDisabled, rejectIfNoDeviceIds, rejectIfOffline, usesDebugApi };
439
+ export { KEEPALIVE_BUDGET, REQUEST_TIMEOUT_MS, apiHeaders, getHeaderParams, getMetaObj, getParameters, getUrlWithParams, hasDeviceId, isPermanentRefusal, makeRequest, postKeepalive, postToApptics, rejectIfDisabled, rejectIfNoDeviceIds, rejectIfOffline, usesDebugApi };
@@ -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
  import { AP_CONSTANTS } from './constants.js';
3
3
 
4
4
  /** Returned from an `each` iterator to stop iterating objects and array-likes. */
@@ -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
  import { Console } from './logger.js';
3
3
  import { isEmpty, isEmptyObj } from './utils.js';
4
4
 
@@ -218,7 +218,7 @@ function validateScreenName(str) {
218
218
  }
219
219
  // Define the regular expression pattern
220
220
  //^[a-zA-Z][\\w\\s]{1,100}$
221
- const pattern = /^[\w\s.\-_&/:]{0,99}$/;
221
+ const pattern = /^[\w\s.\-_&/:*]{0,99}$/;
222
222
  // Test if the string matches the pattern
223
223
  return pattern.test(str);
224
224
  }
@@ -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
  import { _ZAP } from '../core/state.js';
3
3
  import { Console, warnAlways } from '../core/logger.js';
4
4
  import { isEmpty, isSuccess } from '../core/utils.js';
@@ -78,7 +78,16 @@ function apply(data) {
78
78
  * Resolves true when the ids are in place, false when they are not — the caller stops there
79
79
  * rather than carrying on to calls that would be refused for missing them.
80
80
  */
81
+ /**
82
+ * Whether the last registration failed for want of a network (offline, a dropped connection, a
83
+ * timeout) rather than because the server answered no. Only the first is worth trying again.
84
+ */
85
+ var failedForNetwork = false;
86
+ function appVersionFailedForNetwork() {
87
+ return failedForNetwork;
88
+ }
81
89
  function registerAppVersion() {
90
+ failedForNetwork = false;
82
91
  if (hasAppVersion()) {
83
92
  apply(stored());
84
93
  Console.log(LABEL + ': reusing the ids stored for ' + _ZAP._defaultoptions.appversion); // no i18n
@@ -126,6 +135,8 @@ function registerAppVersion() {
126
135
  return true;
127
136
  })
128
137
  .catch(function (err) {
138
+ // a server answer carries serverResult; a request that never got one does not
139
+ failedForNetwork = !(err && err.serverResult) || navigator.onLine === false;
129
140
  warnAlways(LABEL + ': could not register this app version: ' + String(err && err.message ? err.message : err)); // no i18n
130
141
  return false;
131
142
  })
@@ -150,4 +161,4 @@ function clearAppVersion() {
150
161
  user_defaults.add(STORE_KEY, undefined);
151
162
  }
152
163
 
153
- export { applyStoredAppVersion, clearAppVersion, hasAppVersion, registerAppVersion };
164
+ export { appVersionFailedForNetwork, applyStoredAppVersion, clearAppVersion, hasAppVersion, registerAppVersion };
@@ -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
  /**