@zoho_apptics/apptics-js-sdk 1.0.2 → 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 -1
@@ -0,0 +1,42 @@
1
+ import type { Dict, QueueItem } from '../types.js';
2
+ export declare function currentScreen(): Promise<QueueItem | undefined>;
3
+ /**
4
+ * Ends one screen view, by id: it gets its end time and, with it, a duration, and becomes sendable
5
+ * (an open screen, endtime 0, waits like an open session does). A view already ended keeps its end.
6
+ */
7
+ export declare function closeScreen(id: string, time: number): Promise<void>;
8
+ /**
9
+ * Ends this tab's current screen view: the page is hidden or closing. By id, so a screen another
10
+ * tab has open is never closed from here.
11
+ */
12
+ export declare function updateScreenWithEndtime(): Promise<void>;
13
+ /**
14
+ * Track the session.
15
+ * @param sessionData A set of properties belonging to the session.
16
+ */
17
+ export declare function trackSession(sessionData: Dict): Promise<void>;
18
+ /** This tab's session when it has one, otherwise the newest open session in storage. */
19
+ export declare function currentSession(): Promise<QueueItem | undefined>;
20
+ /**
21
+ * Writes the waiting session, if there is one. Called by the timer and by anything that tracks an
22
+ * item, so an event in the first seconds takes its session with it.
23
+ */
24
+ export declare function commitPendingSession(): Promise<void>;
25
+ /** Forgets a session that never earned its place, on a tab closing inside the minimum. */
26
+ export declare function dropPendingSession(): boolean;
27
+ /** Whether a session is waiting to be written. Used by tests and by the page-closing path. */
28
+ export declare function hasPendingSession(): boolean;
29
+ export declare function startNewSession(time: number): Promise<void>;
30
+ /**
31
+ * Closes this tab's session, so it can be sent: the tab is closing or the page is being replaced.
32
+ * Nothing happens when the session is already closed.
33
+ */
34
+ export declare function endCurrentSession(): Promise<void>;
35
+ /**
36
+ * Closes sessions left open by a tab that was killed before it could close its own: anything
37
+ * idle for longer than inactiveduration. A live tab in another window keeps its session,
38
+ * because that one's lastactivetime is recent.
39
+ */
40
+ export declare function closeAbandonedSessions(): Promise<void>;
41
+ export declare function checkAndUpdateSession(): Promise<void>;
42
+ export declare function updateLastActiveTimeOfSession(): Promise<void>;
@@ -0,0 +1,327 @@
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 env = require('../core/env.js');
10
+ var consent = require('../core/consent.js');
11
+
12
+ /** The most recently started item of `type` that is still open (endtime 0). */
13
+ function latestOpen(type, items) {
14
+ return items.filter(function (item) {
15
+ return item.type == type && item.endtime === 0;
16
+ }).sort(function (a, b) {
17
+ return b.starttime - a.starttime;
18
+ })[0];
19
+ }
20
+ /**
21
+ * Ends one screen view, by id: it gets its end time and, with it, a duration, and becomes sendable
22
+ * (an open screen, endtime 0, waits like an open session does). A view already ended keeps its end.
23
+ */
24
+ function closeScreen(id, time) {
25
+ if (utils.isEmpty(id)) {
26
+ return Promise.resolve();
27
+ }
28
+ if (state._ZAP._current_screen && state._ZAP._current_screen.id === id && !state._ZAP._current_screen.endtime) {
29
+ state._ZAP._current_screen = Object.assign({}, state._ZAP._current_screen, { endtime: time });
30
+ }
31
+ return storage.engagement_transactions.all().then(function (items) {
32
+ var open = items.filter(function (item) {
33
+ return item.type == constants.AP_CONSTANTS.SCREEN && item.id === id && item.endtime === 0;
34
+ })[0];
35
+ if (open) {
36
+ return storage.engagement_transactions.update(Object.assign({}, open, { endtime: Math.max(time, open.starttime) }));
37
+ }
38
+ });
39
+ }
40
+ /**
41
+ * Ends this tab's current screen view: the page is hidden or closing. By id, so a screen another
42
+ * tab has open is never closed from here.
43
+ */
44
+ function updateScreenWithEndtime() {
45
+ var current = state._ZAP._current_screen;
46
+ return current && current.id ? closeScreen(current.id, utils.nowMs()) : Promise.resolve();
47
+ }
48
+ /** Ends the screen views a session left open, at `time`: the session itself has ended. */
49
+ function closeScreensOf(session, time) {
50
+ return storage.engagement_transactions.all().then(function (items) {
51
+ var open = items.filter(function (item) {
52
+ return item.type == constants.AP_CONSTANTS.SCREEN && item.endtime === 0 && item.sessionstarttime === session.starttime;
53
+ });
54
+ return open.reduce(function (done, item) {
55
+ return done.then(function () {
56
+ return storage.engagement_transactions.update(Object.assign({}, item, { endtime: Math.max(time, item.starttime) }));
57
+ });
58
+ }, Promise.resolve());
59
+ });
60
+ }
61
+ /** `track_session: false`, Android's automaticSessionsTrackingStatus: no sessions are recorded. */
62
+ function sessionsOff() {
63
+ return state.getConfig('track_session') === false; // no i18n
64
+ }
65
+ /**
66
+ * Track the session.
67
+ * @param sessionData A set of properties belonging to the session.
68
+ */
69
+ function trackSession(sessionData) {
70
+ if (!consent.canTrackEngagement('trackSession')) { // no i18n
71
+ return Promise.resolve();
72
+ }
73
+ if (sessionData && typeof sessionData !== 'object') { // no i18n
74
+ logger.logFailure(constants.AP_LOG_MODULE.SESSION, 'apptics.trackSession: sessionData param must be an object'); // no i18n
75
+ return Promise.resolve();
76
+ }
77
+ var written = storage.engagement_transactions.add(sessionData);
78
+ logger.Console.log('apptics.trackSession(' + JSON.stringify(sessionData || {}) + ')'); // no i18n
79
+ logger.Console.dir(sessionData);
80
+ return written;
81
+ }
82
+ /** This tab's session when it has one, otherwise the newest open session in storage. */
83
+ function currentSession() {
84
+ var mine = tabSessionId();
85
+ return storage.engagement_transactions.all().then(function (items) {
86
+ if (mine) {
87
+ var ours = items.filter(function (item) {
88
+ return item.type == constants.AP_CONSTANTS.SESSION && item.id === mine;
89
+ })[0];
90
+ if (ours) {
91
+ return ours;
92
+ }
93
+ }
94
+ return latestOpen(constants.AP_CONSTANTS.SESSION, items);
95
+ });
96
+ }
97
+ /** The id of this tab's session. sessionStorage is per tab and survives a reload. */
98
+ const TAB_KEY = 'apptics-session'; // no i18n
99
+ function tabSessionId() {
100
+ try {
101
+ return sessionStorage.getItem(TAB_KEY) || ''; // no i18n
102
+ }
103
+ catch (err) {
104
+ return ''; // no sessionStorage (private mode, sandboxed frame): fall back to the store
105
+ }
106
+ }
107
+ function rememberTabSession(id) {
108
+ try {
109
+ sessionStorage.setItem(TAB_KEY, id);
110
+ }
111
+ catch (err) {
112
+ // the session still works, it just can't be recognised after a reload
113
+ }
114
+ }
115
+ /** True until the first session on this device has been recorded. */
116
+ function isFirstEverSession() {
117
+ return utils.isEmpty(storage.user_defaults.item(HAD_SESSION_KEY));
118
+ }
119
+ const HAD_SESSION_KEY = 'hadsession'; // no i18n
120
+ /**
121
+ * A session that has begun but is not stored yet.
122
+ *
123
+ * A visit shorter than `min_session_duration` and with nothing tracked in it is not a session worth
124
+ * reporting — a bounce, a preview, a crawler that runs scripts. So the session is held here for
125
+ * those first seconds and written only once it has earned it: when the timer fires, or the moment
126
+ * anything is tracked that needs a session to belong to, whichever comes first.
127
+ *
128
+ * `_ZAP._current_session` is set as soon as the session begins even though this is pending, so
129
+ * anything tracked in those seconds still reads the right `sessionstarttime`. Committing does not
130
+ * change `starttime`: it stays the moment the session began, so the wait is never counted as a gap.
131
+ */
132
+ var pendingSession = null;
133
+ var pendingTimer = null;
134
+ function clearPendingTimer() {
135
+ if (pendingTimer !== null) {
136
+ clearTimeout(pendingTimer);
137
+ pendingTimer = null;
138
+ }
139
+ }
140
+ /**
141
+ * Writes the waiting session, if there is one. Called by the timer and by anything that tracks an
142
+ * item, so an event in the first seconds takes its session with it.
143
+ */
144
+ function commitPendingSession() {
145
+ if (!pendingSession) {
146
+ return Promise.resolve();
147
+ }
148
+ var session = pendingSession;
149
+ pendingSession = null;
150
+ clearPendingTimer();
151
+ // the flag is set here rather than at the start, so a dropped session does not consume it and
152
+ // leave the next real session reporting firstsession false
153
+ if (session.firstsession) {
154
+ storage.user_defaults.add(HAD_SESSION_KEY, true);
155
+ }
156
+ return trackSession(session);
157
+ }
158
+ /** Forgets a session that never earned its place, on a tab closing inside the minimum. */
159
+ function dropPendingSession() {
160
+ if (!pendingSession) {
161
+ return false;
162
+ }
163
+ logger.Console.log('session: dropped, shorter than the minimum with nothing tracked in it'); // no i18n
164
+ pendingSession = null;
165
+ clearPendingTimer();
166
+ return true;
167
+ }
168
+ function startNewSession(time) {
169
+ state._ZAP._current_session = {
170
+ id: utils.getNewUUID(),
171
+ type: constants.AP_CONSTANTS.SESSION,
172
+ starttime: time,
173
+ endtime: 0,
174
+ edge: env.getConnectionType(),
175
+ orientation: env.getOrientation(),
176
+ firstsession: isFirstEverSession(),
177
+ networkstatus: env.getNetworkStatus(),
178
+ lastactivetime: time,
179
+ };
180
+ // ram is optional in sessionWebSDK but checked against ram_rom ('4 GB'), which an empty
181
+ // string cannot match. navigator.deviceMemory is Chromium-only, so Firefox and Safari have
182
+ // nothing to put here - and a key that fails its regex does not lose the session, it loses
183
+ // the whole batch the session was sent in, permanently
184
+ var ram = env.getRam();
185
+ if (!utils.isEmpty(ram)) {
186
+ state._ZAP._current_session.ram = ram;
187
+ }
188
+ rememberTabSession(state._ZAP._current_session.id);
189
+ var minimum = Number(state.getConfig('min_session_duration'));
190
+ if (!(minimum > 0)) {
191
+ return commitNow(state._ZAP._current_session);
192
+ }
193
+ // held, not stored: see pendingSession above
194
+ pendingSession = state._ZAP._current_session;
195
+ clearPendingTimer();
196
+ pendingTimer = setTimeout(function () {
197
+ pendingTimer = null;
198
+ commitPendingSession();
199
+ }, minimum);
200
+ return Promise.resolve();
201
+ }
202
+ /** The un-deferred path, for a minimum of 0. */
203
+ function commitNow(session) {
204
+ if (session.firstsession) {
205
+ storage.user_defaults.add(HAD_SESSION_KEY, true);
206
+ }
207
+ return trackSession(session);
208
+ }
209
+ /**
210
+ * Closes this tab's session, so it can be sent: the tab is closing or the page is being replaced.
211
+ * Nothing happens when the session is already closed.
212
+ */
213
+ function endCurrentSession() {
214
+ var time = utils.nowMs();
215
+ // nothing was tracked and the minimum was never reached: this visit is not reported at all
216
+ if (dropPendingSession()) {
217
+ return Promise.resolve();
218
+ }
219
+ return currentSession().then(function (_currentSession) {
220
+ if (!_currentSession || _currentSession.endtime !== 0) {
221
+ return;
222
+ }
223
+ var closed = Object.assign({}, _currentSession, { endtime: time, lastactivetime: time });
224
+ state._ZAP._current_session = closed;
225
+ logger.Console.log('endCurrentSession: closing the session opened at ' + closed.starttime); // no i18n
226
+ return storage.engagement_transactions.update(closed).then(function () {
227
+ return closeScreensOf(closed, time);
228
+ });
229
+ });
230
+ }
231
+ /**
232
+ * Closes sessions left open by a tab that was killed before it could close its own: anything
233
+ * idle for longer than inactiveduration. A live tab in another window keeps its session,
234
+ * because that one's lastactivetime is recent.
235
+ */
236
+ function closeAbandonedSessions() {
237
+ var cutoff = utils.nowMs() - state._ZAP.inactiveduration * 60 * 1000;
238
+ var mine = tabSessionId();
239
+ return storage.engagement_transactions.all().then(function (items) {
240
+ var abandoned = items.filter(function (item) {
241
+ return item.type == constants.AP_CONSTANTS.SESSION && item.endtime === 0 &&
242
+ item.id !== mine && item.lastactivetime < cutoff;
243
+ });
244
+ if (!abandoned.length) {
245
+ return Promise.resolve();
246
+ }
247
+ logger.Console.log('closeAbandonedSessions: closing ' + abandoned.length + ' session(s) left open by a closed tab'); // no i18n
248
+ return abandoned.reduce(function (done, item) {
249
+ return done.then(function () {
250
+ return storage.engagement_transactions.update(Object.assign({}, item, { endtime: item.lastactivetime }));
251
+ }).then(function () {
252
+ // the screen the closed tab was on ends with its session
253
+ return closeScreensOf(item, item.lastactivetime);
254
+ });
255
+ }, Promise.resolve());
256
+ });
257
+ }
258
+ function checkAndUpdateSession() {
259
+ if (!state._ZAP._token) {
260
+ logger.logFailure(constants.AP_LOG_MODULE.SESSION, 'checkAndUpdateSession: You must call apptics.init() first'); // no i18n
261
+ return Promise.resolve();
262
+ }
263
+ if (env.is_apptics_disabled()) {
264
+ return Promise.resolve();
265
+ }
266
+ if (sessionsOff()) {
267
+ return Promise.resolve();
268
+ }
269
+ var time = utils.nowMs();
270
+ // a tab that was killed before it could close its session: close it so it gets sent
271
+ return closeAbandonedSessions().then(currentSession).then(function (_currentSession) {
272
+ // a closed session belongs to a tab that has gone: this tab starts its own
273
+ if (!_currentSession || _currentSession.endtime !== 0) {
274
+ return startNewSession(time);
275
+ }
276
+ state._ZAP._current_session = _currentSession;
277
+ // Check if the user is inactive for the past 30 minutes
278
+ if ((time - _currentSession.lastactivetime) > (state._ZAP.inactiveduration * 1000 * 60)) {
279
+ logger.Console.log('checkAndUpdateSession: User is inactive for the past ' + state._ZAP.inactiveduration + ' minutes so starting a new session'); // no i18n
280
+ // ends when the user was last active, so the idle gap isn't counted as session time
281
+ var _newSession = Object.assign({}, _currentSession, { endtime: _currentSession.lastactivetime });
282
+ logger.Console.log('checkAndUpdateSession: (' + JSON.stringify(_newSession) + ')'); // no i18n
283
+ logger.Console.dir(_newSession);
284
+ return storage.engagement_transactions.update(_newSession).then(function () {
285
+ // the screen left open over the idle gap ends with the session, when it was last used
286
+ return closeScreensOf(_newSession, _newSession.endtime);
287
+ }).then(function () {
288
+ return startNewSession(time);
289
+ });
290
+ }
291
+ logger.Console.log('checkAndUpdateSession: User is back before ' + state._ZAP.inactiveduration + ' minutes so updating the lastactivitytime - ' + time); // no i18n
292
+ return updateLastActiveTimeOfSession();
293
+ });
294
+ }
295
+ function updateLastActiveTimeOfSession() {
296
+ if (sessionsOff()) {
297
+ return Promise.resolve();
298
+ }
299
+ var time = utils.nowMs();
300
+ // a pending session is not in the store yet, so it is updated in place instead
301
+ if (pendingSession) {
302
+ pendingSession.lastactivetime = time;
303
+ state._ZAP._current_session = pendingSession;
304
+ return Promise.resolve();
305
+ }
306
+ return currentSession().then(function (_currentSession) {
307
+ if (!_currentSession) {
308
+ return;
309
+ }
310
+ logger.Console.log('updateLastActiveTimeOfSession: Updating the lastactivitytime - ' + time); // no i18n
311
+ var _newSession = Object.assign({}, _currentSession, { lastactivetime: time });
312
+ state._ZAP._current_session = _newSession;
313
+ return storage.engagement_transactions.update(_newSession);
314
+ });
315
+ }
316
+
317
+ exports.checkAndUpdateSession = checkAndUpdateSession;
318
+ exports.closeAbandonedSessions = closeAbandonedSessions;
319
+ exports.closeScreen = closeScreen;
320
+ exports.commitPendingSession = commitPendingSession;
321
+ exports.currentSession = currentSession;
322
+ exports.dropPendingSession = dropPendingSession;
323
+ exports.endCurrentSession = endCurrentSession;
324
+ exports.startNewSession = startNewSession;
325
+ exports.trackSession = trackSession;
326
+ exports.updateLastActiveTimeOfSession = updateLastActiveTimeOfSession;
327
+ exports.updateScreenWithEndtime = updateScreenWithEndtime;
@@ -0,0 +1,56 @@
1
+ import type { Dict, Properties } from '../types.js';
2
+ import { type DefinedEvent } from './defined-events.js';
3
+ /**
4
+ * Records an event: `trackEvent(name, group?, properties?)`, or a defined event with
5
+ * `trackEvent(DefinedEvents.AP_USER_LOGIN, properties?)`, which brings its own group.
6
+ *
7
+ * As on Android, an invalid name or group is not logged. A group left out is `default`, so the
8
+ * one-argument form keeps working; a group given but invalid is a mistake worth being told about,
9
+ * not one to file quietly under `default`.
10
+ */
11
+ export declare function trackEvent(eventName: string | DefinedEvent, groupName?: string | Properties, jsonObj?: Properties): void;
12
+ /** The app's own screen view. Automatic screen tracking calls recordScreen() instead. */
13
+ export declare function inScreen(screenName: string, jsonObj?: Properties): string;
14
+ /**
15
+ * The app's own screen view with a known id and start. The public inScreen takes the id and the
16
+ * time when the app calls it, so the id it hands back is the view's even when start-up is still
17
+ * running and this runs a moment later.
18
+ */
19
+ export declare function inScreenAt(screenName: string, jsonObj: Properties | undefined, id: string, startedAt: number): void;
20
+ /** Ends the screen view inScreen() began, as Android's AppticsScreenTracker.outScreen(id). */
21
+ export declare function outScreenAt(id: string, endedAt: number): void;
22
+ /**
23
+ * Queues a screen view and makes it the current screen.
24
+ *
25
+ * The view is stored open (endtime 0) and closed when the next screen starts, when the page is
26
+ * hidden or closed, when its session ends, or by outScreen() — which is what gives it a duration.
27
+ * An open view is not sent until it is closed, as an open session is not.
28
+ */
29
+ export declare function recordScreen(screenName: string, jsonObj?: Properties, id?: string, startedAt?: number, implicit?: boolean): void;
30
+ /**
31
+ * The screen a heatmap record belongs to, making sure engagement/add has a view of it: the console
32
+ * places a record by its screen, and a screen that was never sent as a view leaves it nowhere.
33
+ *
34
+ * A screen the app or automatic screen tracking named is used as it is — that one already has its
35
+ * view. Otherwise (automatic tracking off and no inScreen() call) the page is named the way
36
+ * automatic tracking would name it, and a view is recorded for it: once per screen, a new one when
37
+ * the path changes, and given way as soon as anything else names the screen.
38
+ */
39
+ export declare function screenForRecord(): string;
40
+ /**
41
+ * Back in view after being hidden: the hide ended the screen view, so the screen the user is on
42
+ * starts a new one, as an Android activity coming back to the foreground does.
43
+ */
44
+ export declare function resumeScreen(): void;
45
+ export declare function trackApi(jsonObj?: Dict): void;
46
+ /**
47
+ * Begins timing one API call, as Android's AppticsApiTracker.startTrackApi(url, method): returns
48
+ * the id to hand to endTrackApi once the response is in. Records nothing by itself.
49
+ */
50
+ export declare function startTrackApi(url: string, method?: string): string;
51
+ /**
52
+ * Finishes a call startTrackApi began and records it, timed from start to `endedAt`. The public
53
+ * wrapper takes `endedAt` when the app calls it, so a call ended while start-up is still running
54
+ * keeps its real duration even though it is recorded a moment later.
55
+ */
56
+ export declare function endTrackApiAt(id: string, responseCode: number, responseMessage: string | undefined, endedAt: number): void;