@zoho_apptics/apptics-js-sdk 1.0.2 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/CHANGELOG.md +193 -0
  2. package/LICENSE +13 -0
  3. package/README.md +846 -11
  4. package/dist/apptics.esm.min.js +3 -0
  5. package/dist/apptics.esm.min.js.map +1 -0
  6. package/dist/apptics.min.js +3 -0
  7. package/dist/apptics.min.js.map +1 -0
  8. package/dist/chunks/lifecycle-VYr43KcB.min.js +3 -0
  9. package/dist/chunks/lifecycle-VYr43KcB.min.js.map +1 -0
  10. package/dist/cjs/auto-init.d.ts +8 -0
  11. package/dist/cjs/auto-init.js +32 -0
  12. package/dist/cjs/core/attempts.d.ts +28 -0
  13. package/dist/cjs/core/attempts.js +113 -0
  14. package/dist/cjs/core/batch.d.ts +32 -0
  15. package/dist/cjs/core/batch.js +116 -0
  16. package/dist/cjs/core/callsite.d.ts +34 -0
  17. package/dist/cjs/core/callsite.js +115 -0
  18. package/dist/cjs/core/consent.d.ts +27 -0
  19. package/dist/cjs/core/consent.js +132 -0
  20. package/dist/cjs/core/constants.d.ts +237 -0
  21. package/dist/cjs/core/constants.js +315 -0
  22. package/dist/cjs/core/db.d.ts +48 -0
  23. package/dist/cjs/core/db.js +467 -0
  24. package/dist/cjs/core/debug.d.ts +22 -0
  25. package/dist/cjs/core/debug.js +88 -0
  26. package/dist/cjs/core/env.d.ts +28 -0
  27. package/dist/cjs/core/env.js +267 -0
  28. package/dist/cjs/core/framework-id.d.ts +1 -0
  29. package/dist/cjs/core/framework-id.js +9 -0
  30. package/dist/cjs/core/guard.d.ts +11 -0
  31. package/dist/cjs/core/guard.js +86 -0
  32. package/dist/cjs/core/hooks.d.ts +39 -0
  33. package/dist/cjs/core/hooks.js +22 -0
  34. package/dist/cjs/core/locks.d.ts +9 -0
  35. package/dist/cjs/core/locks.js +22 -0
  36. package/dist/cjs/core/logger.d.ts +15 -0
  37. package/dist/cjs/core/logger.js +50 -0
  38. package/dist/cjs/core/state.d.ts +70 -0
  39. package/dist/cjs/core/state.js +78 -0
  40. package/dist/cjs/core/storage.d.ts +61 -0
  41. package/dist/cjs/core/storage.js +327 -0
  42. package/dist/cjs/core/stylesheet.d.ts +8 -0
  43. package/dist/cjs/core/stylesheet.js +29 -0
  44. package/dist/cjs/core/transport.d.ts +85 -0
  45. package/dist/cjs/core/transport.js +456 -0
  46. package/dist/cjs/core/utils.d.ts +26 -0
  47. package/dist/cjs/core/utils.js +175 -0
  48. package/dist/cjs/core/validate.d.ts +18 -0
  49. package/dist/cjs/core/validate.js +233 -0
  50. package/dist/cjs/device/appversion.d.ts +15 -0
  51. package/dist/cjs/device/appversion.js +170 -0
  52. package/dist/cjs/device/index.d.ts +34 -0
  53. package/dist/cjs/device/index.js +472 -0
  54. package/dist/cjs/engagement/api-rules.d.ts +49 -0
  55. package/dist/cjs/engagement/api-rules.js +206 -0
  56. package/dist/cjs/engagement/auto-api.d.ts +7 -0
  57. package/dist/cjs/engagement/auto-api.js +200 -0
  58. package/dist/cjs/engagement/auto-screen.d.ts +18 -0
  59. package/dist/cjs/engagement/auto-screen.js +305 -0
  60. package/dist/cjs/engagement/defined-events.d.ts +23 -0
  61. package/dist/cjs/engagement/defined-events.js +58 -0
  62. package/dist/cjs/engagement/send.d.ts +6 -0
  63. package/dist/cjs/engagement/send.js +104 -0
  64. package/dist/cjs/engagement/session.d.ts +51 -0
  65. package/dist/cjs/engagement/session.js +463 -0
  66. package/dist/cjs/engagement/track.d.ts +56 -0
  67. package/dist/cjs/engagement/track.js +375 -0
  68. package/dist/cjs/errors/send.d.ts +6 -0
  69. package/dist/cjs/errors/send.js +73 -0
  70. package/dist/cjs/errors/track.d.ts +4 -0
  71. package/dist/cjs/errors/track.js +167 -0
  72. package/dist/cjs/feedback/controls.d.ts +37 -0
  73. package/dist/cjs/feedback/controls.js +316 -0
  74. package/dist/cjs/feedback/index.d.ts +9 -0
  75. package/dist/cjs/feedback/index.js +56 -0
  76. package/dist/cjs/feedback/logs.d.ts +45 -0
  77. package/dist/cjs/feedback/logs.js +241 -0
  78. package/dist/cjs/feedback/quartz.d.ts +18 -0
  79. package/dist/cjs/feedback/quartz.js +105 -0
  80. package/dist/cjs/feedback/send.d.ts +28 -0
  81. package/dist/cjs/feedback/send.js +203 -0
  82. package/dist/cjs/feedback/styles.d.ts +10 -0
  83. package/dist/cjs/feedback/styles.js +8 -0
  84. package/dist/cjs/feedback/template.d.ts +2 -0
  85. package/dist/cjs/feedback/template.js +162 -0
  86. package/dist/cjs/feedback/ui.d.ts +63 -0
  87. package/dist/cjs/feedback/ui.js +709 -0
  88. package/dist/cjs/heatmap/send.d.ts +13 -0
  89. package/dist/cjs/heatmap/send.js +82 -0
  90. package/dist/cjs/heatmap/track.d.ts +4 -0
  91. package/dist/cjs/heatmap/track.js +448 -0
  92. package/dist/cjs/index.d.ts +22 -0
  93. package/dist/cjs/index.js +162 -0
  94. package/dist/cjs/lifecycle.d.ts +21 -0
  95. package/dist/cjs/lifecycle.js +734 -0
  96. package/dist/cjs/package.json +3 -0
  97. package/dist/cjs/remoteconfig/country.d.ts +4 -0
  98. package/dist/cjs/remoteconfig/country.js +73 -0
  99. package/dist/cjs/remoteconfig/custom.d.ts +10 -0
  100. package/dist/cjs/remoteconfig/custom.js +58 -0
  101. package/dist/cjs/remoteconfig/evaluate.d.ts +24 -0
  102. package/dist/cjs/remoteconfig/evaluate.js +184 -0
  103. package/dist/cjs/remoteconfig/fetch.d.ts +24 -0
  104. package/dist/cjs/remoteconfig/fetch.js +200 -0
  105. package/dist/cjs/remoteconfig/index.d.ts +15 -0
  106. package/dist/cjs/remoteconfig/index.js +116 -0
  107. package/dist/cjs/remoteconfig/store.d.ts +18 -0
  108. package/dist/cjs/remoteconfig/store.js +98 -0
  109. package/dist/cjs/remoteconfig/tz-countries.d.ts +8 -0
  110. package/dist/cjs/remoteconfig/tz-countries.js +13 -0
  111. package/dist/cjs/remotelog/gate.d.ts +2 -0
  112. package/dist/cjs/remotelog/gate.js +28 -0
  113. package/dist/cjs/remotelog/index.d.ts +8 -0
  114. package/dist/cjs/remotelog/logger.d.ts +22 -0
  115. package/dist/cjs/remotelog/logger.js +111 -0
  116. package/dist/cjs/remotelog/send.d.ts +13 -0
  117. package/dist/cjs/remotelog/send.js +153 -0
  118. package/dist/cjs/remotelogger/index.d.ts +12 -0
  119. package/dist/cjs/remotelogger/index.js +18 -0
  120. package/dist/cjs/scheduler.d.ts +8 -0
  121. package/dist/cjs/scheduler.js +78 -0
  122. package/dist/cjs/types.d.ts +385 -0
  123. package/dist/cjs/user/index.d.ts +33 -0
  124. package/dist/cjs/user/index.js +183 -0
  125. package/dist/esm/auto-init.d.ts +8 -0
  126. package/dist/esm/auto-init.js +29 -0
  127. package/dist/esm/core/attempts.d.ts +28 -0
  128. package/dist/esm/core/attempts.js +106 -0
  129. package/dist/esm/core/batch.d.ts +32 -0
  130. package/dist/esm/core/batch.js +109 -0
  131. package/dist/esm/core/callsite.d.ts +34 -0
  132. package/dist/esm/core/callsite.js +110 -0
  133. package/dist/esm/core/consent.d.ts +27 -0
  134. package/dist/esm/core/consent.js +122 -0
  135. package/dist/esm/core/constants.d.ts +237 -0
  136. package/dist/esm/core/constants.js +292 -0
  137. package/dist/esm/core/db.d.ts +48 -0
  138. package/dist/esm/core/db.js +453 -0
  139. package/dist/esm/core/debug.d.ts +22 -0
  140. package/dist/esm/core/debug.js +81 -0
  141. package/dist/esm/core/env.d.ts +28 -0
  142. package/dist/esm/core/env.js +251 -0
  143. package/dist/esm/core/framework-id.d.ts +1 -0
  144. package/dist/esm/core/framework-id.js +7 -0
  145. package/dist/esm/core/guard.d.ts +11 -0
  146. package/dist/esm/core/guard.js +83 -0
  147. package/dist/esm/core/hooks.d.ts +39 -0
  148. package/dist/esm/core/hooks.js +20 -0
  149. package/dist/esm/core/locks.d.ts +9 -0
  150. package/dist/esm/core/locks.js +20 -0
  151. package/dist/esm/core/logger.d.ts +15 -0
  152. package/dist/esm/core/logger.js +46 -0
  153. package/dist/esm/core/state.d.ts +70 -0
  154. package/dist/esm/core/state.js +73 -0
  155. package/dist/esm/core/storage.d.ts +61 -0
  156. package/dist/esm/core/storage.js +314 -0
  157. package/dist/esm/core/stylesheet.d.ts +8 -0
  158. package/dist/esm/core/stylesheet.js +27 -0
  159. package/dist/esm/core/transport.d.ts +85 -0
  160. package/dist/esm/core/transport.js +439 -0
  161. package/dist/esm/core/utils.d.ts +26 -0
  162. package/dist/esm/core/utils.js +161 -0
  163. package/dist/esm/core/validate.d.ts +18 -0
  164. package/dist/esm/core/validate.js +226 -0
  165. package/dist/esm/device/appversion.d.ts +15 -0
  166. package/dist/esm/device/appversion.js +164 -0
  167. package/dist/esm/device/index.d.ts +34 -0
  168. package/dist/esm/device/index.js +461 -0
  169. package/dist/esm/engagement/api-rules.d.ts +49 -0
  170. package/dist/esm/engagement/api-rules.js +199 -0
  171. package/dist/esm/engagement/auto-api.d.ts +7 -0
  172. package/dist/esm/engagement/auto-api.js +198 -0
  173. package/dist/esm/engagement/auto-screen.d.ts +18 -0
  174. package/dist/esm/engagement/auto-screen.js +301 -0
  175. package/dist/esm/engagement/defined-events.d.ts +23 -0
  176. package/dist/esm/engagement/defined-events.js +55 -0
  177. package/dist/esm/engagement/send.d.ts +6 -0
  178. package/dist/esm/engagement/send.js +101 -0
  179. package/dist/esm/engagement/session.d.ts +51 -0
  180. package/dist/esm/engagement/session.js +448 -0
  181. package/dist/esm/engagement/track.d.ts +56 -0
  182. package/dist/esm/engagement/track.js +365 -0
  183. package/dist/esm/errors/send.d.ts +6 -0
  184. package/dist/esm/errors/send.js +70 -0
  185. package/dist/esm/errors/track.d.ts +4 -0
  186. package/dist/esm/errors/track.js +163 -0
  187. package/dist/esm/feedback/controls.d.ts +37 -0
  188. package/dist/esm/feedback/controls.js +309 -0
  189. package/dist/esm/feedback/index.d.ts +9 -0
  190. package/dist/esm/feedback/index.js +51 -0
  191. package/dist/esm/feedback/logs.d.ts +45 -0
  192. package/dist/esm/feedback/logs.js +227 -0
  193. package/dist/esm/feedback/quartz.d.ts +18 -0
  194. package/dist/esm/feedback/quartz.js +99 -0
  195. package/dist/esm/feedback/send.d.ts +28 -0
  196. package/dist/esm/feedback/send.js +198 -0
  197. package/dist/esm/feedback/styles.d.ts +10 -0
  198. package/dist/esm/feedback/styles.js +4 -0
  199. package/dist/esm/feedback/template.d.ts +2 -0
  200. package/dist/esm/feedback/template.js +159 -0
  201. package/dist/esm/feedback/ui.d.ts +63 -0
  202. package/dist/esm/feedback/ui.js +703 -0
  203. package/dist/esm/heatmap/send.d.ts +13 -0
  204. package/dist/esm/heatmap/send.js +79 -0
  205. package/dist/esm/heatmap/track.d.ts +4 -0
  206. package/dist/esm/heatmap/track.js +445 -0
  207. package/dist/esm/index.d.ts +22 -0
  208. package/dist/esm/index.js +150 -0
  209. package/dist/esm/lifecycle.d.ts +21 -0
  210. package/dist/esm/lifecycle.js +729 -0
  211. package/dist/esm/package.json +3 -0
  212. package/dist/esm/remoteconfig/country.d.ts +4 -0
  213. package/dist/esm/remoteconfig/country.js +70 -0
  214. package/dist/esm/remoteconfig/custom.d.ts +10 -0
  215. package/dist/esm/remoteconfig/custom.js +54 -0
  216. package/dist/esm/remoteconfig/evaluate.d.ts +24 -0
  217. package/dist/esm/remoteconfig/evaluate.js +179 -0
  218. package/dist/esm/remoteconfig/fetch.d.ts +24 -0
  219. package/dist/esm/remoteconfig/fetch.js +196 -0
  220. package/dist/esm/remoteconfig/index.d.ts +15 -0
  221. package/dist/esm/remoteconfig/index.js +111 -0
  222. package/dist/esm/remoteconfig/store.d.ts +18 -0
  223. package/dist/esm/remoteconfig/store.js +91 -0
  224. package/dist/esm/remoteconfig/tz-countries.d.ts +8 -0
  225. package/dist/esm/remoteconfig/tz-countries.js +11 -0
  226. package/dist/esm/remotelog/gate.d.ts +2 -0
  227. package/dist/esm/remotelog/gate.js +26 -0
  228. package/dist/esm/remotelog/index.d.ts +8 -0
  229. package/dist/esm/remotelog/logger.d.ts +22 -0
  230. package/dist/esm/remotelog/logger.js +108 -0
  231. package/dist/esm/remotelog/send.d.ts +13 -0
  232. package/dist/esm/remotelog/send.js +149 -0
  233. package/dist/esm/remotelogger/index.d.ts +12 -0
  234. package/dist/esm/remotelogger/index.js +13 -0
  235. package/dist/esm/scheduler.d.ts +8 -0
  236. package/dist/esm/scheduler.js +74 -0
  237. package/dist/esm/types.d.ts +385 -0
  238. package/dist/esm/user/index.d.ts +33 -0
  239. package/dist/esm/user/index.js +176 -0
  240. package/dist/feedback.esm.min.js +3 -0
  241. package/dist/feedback.esm.min.js.map +1 -0
  242. package/package.json +122 -7
  243. package/src/appticssdk.js +0 -1
@@ -0,0 +1,199 @@
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
+ import { warnAlways } from '../core/logger.js';
3
+
4
+ /**
5
+ * Which API calls are recorded, and under what name: Android's AppticsApiTracker.configure, built
6
+ * with ApiTrackingBuilder the way user properties are built with UserBuilder:
7
+ *
8
+ * configureApiTracking(new ApiTrackingBuilder()
9
+ * .allowRegex(/^https:\/\/api\.zylker\.(com|in)\//)
10
+ * .ignoreEquals('https://api.zylker.com/health')
11
+ * .ignoreRegex(/\/internal\//)
12
+ * .build());
13
+ *
14
+ * Four rules, two kinds by two: an exact URL (equals) or a regular expression (regex), to allow or
15
+ * to ignore. Each is tried on the call's URL as `scheme://host[:port]/path`, with its query and
16
+ * fragment removed, so one rule can name a host, a path or a single endpoint. Ignore rules are
17
+ * tried first and always win; then, when there are allow rules, a call must match one of them.
18
+ *
19
+ * The name a call is recorded under is not configured: the query goes, and numeric ids, UUIDs and
20
+ * JWTs in its path become `*`, so `/users/42/orders` and `/users/43/orders` are one endpoint.
21
+ *
22
+ * Both apply to every call, the ones the fetch/XHR wrappers catch and the ones the app reports
23
+ * with startTrackApi(), so one set of rules decides what the API page shows.
24
+ */
25
+ function emptyConfig() {
26
+ return { allowEquals: [], ignoreEquals: [], allowRegex: [], ignoreRegex: [] };
27
+ }
28
+ /**
29
+ * A URL as the rules compare it: `scheme://host[:port]/path`, the scheme and host lower-cased,
30
+ * the default port dropped, the query, fragment and a trailing slash removed. '' when it is not
31
+ * an absolute http(s) URL.
32
+ */
33
+ function ruleUrl(raw) {
34
+ try {
35
+ var url = new URL(String(raw).trim());
36
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') { // no i18n
37
+ return ''; // no i18n
38
+ }
39
+ var path = url.pathname.length > 1 ? url.pathname.replace(/\/+$/, '') : url.pathname; // no i18n
40
+ return url.protocol + '//' + url.host.toLowerCase() + path; // no i18n
41
+ }
42
+ catch (err) {
43
+ return ''; // no i18n
44
+ }
45
+ }
46
+ /** The exact URLs given, as rules compare them; anything that is not an absolute URL is refused, and said. */
47
+ function cleanUrls(method, values) {
48
+ var out = [];
49
+ values.forEach(function (value) {
50
+ var url = typeof value === 'string' ? ruleUrl(value) : ''; // no i18n
51
+ if (url === '') { // no i18n
52
+ warnAlways('ApiTrackingBuilder.' + method + ': ' + JSON.stringify(value) + ' is not a full http(s) URL, as https://api.example.com/health, and is left out'); // no i18n
53
+ return;
54
+ }
55
+ if (out.indexOf(url) === -1) {
56
+ out.push(url);
57
+ }
58
+ });
59
+ return out;
60
+ }
61
+ /** The regular expressions given, a RegExp or its source as a string; an invalid one is refused, and said. */
62
+ function cleanRegexes(method, values) {
63
+ var out = [];
64
+ values.forEach(function (value) {
65
+ if (value instanceof RegExp) {
66
+ out.push(value);
67
+ return;
68
+ }
69
+ if (typeof value === 'string' && value !== '') { // no i18n
70
+ try {
71
+ out.push(new RegExp(value));
72
+ return;
73
+ }
74
+ catch (err) {
75
+ // falls through to the warning
76
+ }
77
+ }
78
+ warnAlways('ApiTrackingBuilder.' + method + ': ' + String(value) + ' is not a regular expression, and is left out'); // no i18n
79
+ });
80
+ return out;
81
+ }
82
+ /**
83
+ * Builds the rules configure takes. Each method may be called more than once, and takes any number
84
+ * of values: `new ApiTrackingBuilder().allowEquals(a, b).ignoreRegex(/x/).build()`.
85
+ */
86
+ class ApiTrackingBuilder {
87
+ constructor() {
88
+ this.rules = emptyConfig();
89
+ }
90
+ /** Records only these URLs (and those any allowRegex matches): `https://api.example.com/orders`. */
91
+ allowEquals(...urls) { this.rules.allowEquals.push(...cleanUrls('allowEquals', urls)); return this; }
92
+ /** Never records these URLs: `https://api.example.com/health`. */
93
+ ignoreEquals(...urls) { this.rules.ignoreEquals.push(...cleanUrls('ignoreEquals', urls)); return this; }
94
+ /** Records only URLs these match (and those any allowEquals names): `/^https:\/\/api\.example\.com\//`. */
95
+ allowRegex(...patterns) { this.rules.allowRegex.push(...cleanRegexes('allowRegex', patterns)); return this; }
96
+ /** Never records URLs these match: `/\/internal\//`. */
97
+ ignoreRegex(...patterns) { this.rules.ignoreRegex.push(...cleanRegexes('ignoreRegex', patterns)); return this; }
98
+ build() {
99
+ return {
100
+ allowEquals: this.rules.allowEquals.slice(),
101
+ ignoreEquals: this.rules.ignoreEquals.slice(),
102
+ allowRegex: this.rules.allowRegex.slice(),
103
+ ignoreRegex: this.rules.ignoreRegex.slice(),
104
+ };
105
+ }
106
+ }
107
+ /**
108
+ * 2.0.0-beta's builder methods, now gone. Called, each throws a TypeError that names what to use
109
+ * instead: a rule silently missing would record what the app meant to leave out.
110
+ */
111
+ const RETIRED_METHODS = Object.freeze({
112
+ ignoreDomains: 'ignoreRegex', // no i18n
113
+ allowOnlyDomains: 'allowRegex', // no i18n
114
+ allowOnlyTLDs: 'allowRegex', // no i18n
115
+ ignoreTLDs: 'ignoreRegex', // no i18n
116
+ ignoreDomainPrefixes: 'ignoreRegex', // no i18n
117
+ ignoreDomainSuffixes: 'ignoreRegex', // no i18n
118
+ groupDomains: '', // no i18n
119
+ ignoreEndpoint: 'ignoreEquals or ignoreRegex', // no i18n
120
+ addPattern: '', // no i18n
121
+ preserveSegments: '', // no i18n
122
+ autoDetection: '', // no i18n
123
+ });
124
+ Object.keys(RETIRED_METHODS).forEach(function (name) {
125
+ Object.defineProperty(ApiTrackingBuilder.prototype, name, {
126
+ configurable: true,
127
+ value: function () {
128
+ var instead = RETIRED_METHODS[name];
129
+ throw new TypeError('ApiTrackingBuilder.' + name + '() is no longer supported: ' // no i18n
130
+ + (instead ? 'use ' + instead + ', which match the URL without its query' : 'ids, UUIDs and tokens in a path become * on their own')); // no i18n
131
+ },
132
+ });
133
+ });
134
+ var current = emptyConfig();
135
+ /** The values of `list` that are of the kind `keep` accepts. */
136
+ function listOf(value, keep) {
137
+ return Array.isArray(value) ? value.filter(keep) : [];
138
+ }
139
+ /**
140
+ * Applies the rules, replacing any given before. Takes what build() returned, or the builder
141
+ * itself. Call it once, before the requests it should cover; it works before init().
142
+ */
143
+ function configureApiTracking(config) {
144
+ var built = (config instanceof ApiTrackingBuilder ? config.build() : config);
145
+ if (!built || typeof built !== 'object') { // no i18n
146
+ current = emptyConfig();
147
+ return;
148
+ }
149
+ var isString = function (one) { return typeof one === 'string'; }; // no i18n
150
+ var isRegExp = function (one) { return one instanceof RegExp; };
151
+ current = {
152
+ // a hand-written object gets the same clean-up the builder gives
153
+ allowEquals: cleanUrls('allowEquals', listOf(built.allowEquals, isString)), // no i18n
154
+ ignoreEquals: cleanUrls('ignoreEquals', listOf(built.ignoreEquals, isString)), // no i18n
155
+ allowRegex: listOf(built.allowRegex, isRegExp).concat(cleanRegexes('allowRegex', listOf(built.allowRegex, isString))), // no i18n
156
+ ignoreRegex: listOf(built.ignoreRegex, isRegExp).concat(cleanRegexes('ignoreRegex', listOf(built.ignoreRegex, isString))), // no i18n
157
+ };
158
+ }
159
+ /** Whether a regular expression matches, whatever its flags: a /g one keeps a position between tests. */
160
+ function regexMatches(re, url) {
161
+ re.lastIndex = 0;
162
+ return re.test(url);
163
+ }
164
+ /**
165
+ * Whether a call to `url` is recorded. Ignore rules are tried first and always win; then, when
166
+ * there are allow rules, the URL must match one. A URL that cannot be read is not recorded.
167
+ */
168
+ function urlTracked(url) {
169
+ var target = ruleUrl(url);
170
+ if (target === '') { // no i18n
171
+ return false;
172
+ }
173
+ if (current.ignoreEquals.indexOf(target) !== -1 || current.ignoreRegex.some(function (re) { return regexMatches(re, target); })) {
174
+ return false;
175
+ }
176
+ if (current.allowEquals.length === 0 && current.allowRegex.length === 0) {
177
+ return true;
178
+ }
179
+ return current.allowEquals.indexOf(target) !== -1 || current.allowRegex.some(function (re) { return regexMatches(re, target); });
180
+ }
181
+ /* ---------------- the name a call is recorded under ---------------- */
182
+ /** The path without its query string or fragment, which is where ids and tokens travel. */
183
+ function withoutQuery(path) {
184
+ var cut = String(path || '').split(/[?#]/)[0]; // no i18n
185
+ return cut === '' ? '/' : cut; // no i18n
186
+ }
187
+ const NUMERIC = /^\d+$/;
188
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
189
+ // three base64url parts, the first starting eyJ — the encoding of '{"' every JWT header opens
190
+ // with. Without that start, a file name such as jquery.min.js would pass for a token
191
+ const JWT = /^eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
192
+ /** The path a call is recorded under: the query goes, and numeric ids, UUIDs and JWTs become `*`. */
193
+ function normalizeApiPath(path) {
194
+ return withoutQuery(path).split('/').map(function (segment) {
195
+ return segment !== '' && (NUMERIC.test(segment) || UUID.test(segment) || JWT.test(segment)) ? '*' : segment; // no i18n
196
+ }).join('/'); // no i18n
197
+ }
198
+
199
+ export { ApiTrackingBuilder, configureApiTracking, normalizeApiPath, ruleUrl, urlTracked, withoutQuery };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Starts or stops automatic tracking. Safe to call repeatedly: installing twice would report each
3
+ * call twice, so the second call is a no-op.
4
+ */
5
+ export declare function enableApiTracking(enabled?: boolean): void;
6
+ /** Whether the wrappers are currently in place. */
7
+ export declare function isApiTrackingEnabled(): boolean;
@@ -0,0 +1,198 @@
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
+ import { _ZAP, getConfig } from '../core/state.js';
3
+ import { Console } from '../core/logger.js';
4
+ import { nowMs, isEmpty } from '../core/utils.js';
5
+ import { trackApi } from './track.js';
6
+ import { urlTracked } from './api-rules.js';
7
+
8
+ /**
9
+ * Automatic API tracking: wraps XMLHttpRequest and fetch so calls the app makes are recorded
10
+ * without it calling startTrackApi() / endTrackApi() itself.
11
+ *
12
+ * Two rules shape everything here. The wrappers must be invisible — return values, `this`, thrown
13
+ * errors and argument forms all pass straight through, because a mistake in this file breaks the
14
+ * host app's networking rather than just losing a metric. And the SDK's own traffic must never be
15
+ * recorded: engagement/add reports API calls, so tracking it would have each batch produce the
16
+ * items for the next one.
17
+ *
18
+ * Off unless `track_api` is set. Hostnames and paths of every request an app makes is a wider
19
+ * grant than events and screens, so it is the app's decision, not a default.
20
+ */
21
+ var installed = false;
22
+ var originalOpen = null;
23
+ var originalSend = null;
24
+ var originalFetch = null;
25
+ /**
26
+ * Whether a request is the SDK's own, which is never reported: engagement/add carries API items, so
27
+ * recording it would have every batch produce the items for the next one, forever.
28
+ *
29
+ * Two checks, because one is not enough to bet a loop on. The host comparison is a prefix match, so
30
+ * it misses if the host is spelled differently in the request than in serviceUrl — a trailing
31
+ * slash is enough. The path check catches those, since every SDK call sits under the configured
32
+ * endpoint whatever host it goes to, including through a same-origin proxy.
33
+ */
34
+ function isOwnRequest(url, pathname) {
35
+ var own = [_ZAP._defaultoptions.base_domain, _ZAP._defaultoptions.serviceUrl];
36
+ for (var i = 0; i < own.length; i++) {
37
+ if (!isEmpty(own[i]) && url.indexOf(own[i]) === 0) {
38
+ return true;
39
+ }
40
+ }
41
+ var endpoint = getConfig('endpoint');
42
+ return !isEmpty(endpoint) && pathname.indexOf(endpoint) === 0;
43
+ }
44
+ /**
45
+ * Whether one URL is ours to report: an http(s) call, not the SDK's own, and one the
46
+ * configureApiTracking rules let through. Anything unparseable is skipped rather than guessed at.
47
+ */
48
+ function shouldTrack(rawUrl) {
49
+ if (isEmpty(rawUrl)) {
50
+ return false;
51
+ }
52
+ var absolute;
53
+ try {
54
+ absolute = new URL(rawUrl, window.location.href);
55
+ }
56
+ catch (err) {
57
+ return false;
58
+ }
59
+ if (absolute.protocol !== 'https:' && absolute.protocol !== 'http:') { // no i18n
60
+ return false; // data:, blob:, chrome-extension: and friends
61
+ }
62
+ if (isOwnRequest(absolute.href, absolute.pathname)) {
63
+ return false;
64
+ }
65
+ // configureApiTracking's rules: checked here too so a call left out is not even timed. trackApi checks them again, for the
66
+ // calls an app reports itself
67
+ return urlTracked(absolute.href);
68
+ }
69
+ /** One finished call. Never throws: a tracking failure must not surface in the app's call. */
70
+ function record(method, url, starttime, responsecode, responsemessage) {
71
+ try {
72
+ trackApi({
73
+ url: url,
74
+ method: method,
75
+ responsecode: responsecode,
76
+ responsemessage: responsemessage,
77
+ starttime: starttime,
78
+ endtime: nowMs(),
79
+ });
80
+ }
81
+ catch (err) {
82
+ Console.log('auto api tracking: ' + String(err)); // no i18n
83
+ }
84
+ }
85
+ /** The url of any of fetch's three first-argument forms. */
86
+ function fetchUrl(input) {
87
+ if (typeof input === 'string') { // no i18n
88
+ return input;
89
+ }
90
+ if (typeof Request !== 'undefined' && input instanceof Request) { // no i18n
91
+ return input.url;
92
+ }
93
+ return String(input);
94
+ }
95
+ function fetchMethod(input, init) {
96
+ if (init && init.method) {
97
+ return init.method;
98
+ }
99
+ if (typeof Request !== 'undefined' && input instanceof Request) { // no i18n
100
+ return input.method;
101
+ }
102
+ return 'GET'; // no i18n
103
+ }
104
+ function installXhr() {
105
+ if (typeof XMLHttpRequest !== 'function') { // no i18n
106
+ return;
107
+ }
108
+ originalOpen = XMLHttpRequest.prototype.open;
109
+ originalSend = XMLHttpRequest.prototype.send;
110
+ XMLHttpRequest.prototype.open = function (method, url) {
111
+ try {
112
+ var href = String(url);
113
+ if (shouldTrack(href)) {
114
+ // starttime is set in send(): open() may happen long before the call goes out
115
+ this._ap_api = { method: String(method || 'GET'), url: href, starttime: 0 }; // no i18n
116
+ }
117
+ else {
118
+ this._ap_api = undefined;
119
+ }
120
+ }
121
+ catch (err) {
122
+ this._ap_api = undefined;
123
+ }
124
+ return originalOpen.apply(this, arguments);
125
+ };
126
+ XMLHttpRequest.prototype.send = function () {
127
+ const tracked = this._ap_api;
128
+ if (tracked) {
129
+ tracked.starttime = nowMs();
130
+ // loadend fires for success, error, abort and timeout alike, so one listener covers
131
+ // every ending; status 0 is how a network failure arrives here
132
+ this.addEventListener('loadend', function () {
133
+ var message = this.status === 0 ? 'Network Error' : (this.statusText || '-'); // no i18n
134
+ record(tracked.method, tracked.url, tracked.starttime, this.status, message);
135
+ });
136
+ }
137
+ return originalSend.apply(this, arguments);
138
+ };
139
+ }
140
+ function installFetch() {
141
+ if (typeof fetch !== 'function') { // no i18n
142
+ return;
143
+ }
144
+ originalFetch = fetch;
145
+ window.fetch = function (input, init) {
146
+ var url, method, starttime;
147
+ try {
148
+ url = fetchUrl(input);
149
+ method = fetchMethod(input, init);
150
+ starttime = nowMs();
151
+ }
152
+ catch (err) {
153
+ return originalFetch(input, init);
154
+ }
155
+ if (!shouldTrack(url)) {
156
+ return originalFetch(input, init);
157
+ }
158
+ return originalFetch(input, init).then(function (response) {
159
+ record(method, url, starttime, response.status, response.statusText || '-'); // no i18n
160
+ return response;
161
+ }, function (err) {
162
+ // a rejected fetch never reached a status; the rejection is re-thrown untouched
163
+ record(method, url, starttime, 0, String(err && err.message ? err.message : err) || 'Network Error'); // no i18n
164
+ throw err;
165
+ });
166
+ };
167
+ }
168
+ /**
169
+ * Starts or stops automatic tracking. Safe to call repeatedly: installing twice would report each
170
+ * call twice, so the second call is a no-op.
171
+ */
172
+ function enableApiTracking(enabled) {
173
+ var on = typeof enabled === 'boolean' ? enabled : true; // no i18n
174
+ if (on === installed) {
175
+ return;
176
+ }
177
+ if (on) {
178
+ installXhr();
179
+ installFetch();
180
+ installed = true;
181
+ Console.log('automatic api tracking: on'); // no i18n
182
+ return;
183
+ }
184
+ if (originalOpen) {
185
+ XMLHttpRequest.prototype.open = originalOpen;
186
+ }
187
+ if (originalSend) {
188
+ XMLHttpRequest.prototype.send = originalSend;
189
+ }
190
+ if (originalFetch) {
191
+ window.fetch = originalFetch;
192
+ }
193
+ originalOpen = originalSend = originalFetch = null;
194
+ installed = false;
195
+ Console.log('automatic api tracking: off'); // no i18n
196
+ }
197
+
198
+ export { enableApiTracking };
@@ -0,0 +1,18 @@
1
+ /** A path as screen_routes compares it: no query or fragment, no trailing slash but on the root. */
2
+ export declare function routePath(path: string): string;
3
+ /**
4
+ * Starts or stops automatic screen tracking. Starting records the screen the page is on, unless
5
+ * the app has already called inScreen() for it. Safe to call repeatedly: wrapping history twice
6
+ * would check every navigation twice, so a second start does nothing. `wait` replaces SETTLE_MS,
7
+ * for tests.
8
+ */
9
+ export declare function enableScreenTracking(enabled?: boolean, wait?: number): void;
10
+ /**
11
+ * The name automatic tracking gives the page as it is now: the cleaned path. For records that
12
+ * need a screen when none has been
13
+ * tracked — heatmaps with `track_screen: false` and no inScreen() call, say. '' when the page
14
+ * has no name.
15
+ */
16
+ export declare function automaticScreenName(): string;
17
+ /** Whether history is being watched right now. */
18
+ export declare function isScreenTrackingEnabled(): boolean;