@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,206 @@
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
+ 'use strict';
3
+
4
+ var logger = require('../core/logger.js');
5
+
6
+ /**
7
+ * Which API calls are recorded, and under what name: Android's AppticsApiTracker.configure, built
8
+ * with ApiTrackingBuilder the way user properties are built with UserBuilder:
9
+ *
10
+ * configureApiTracking(new ApiTrackingBuilder()
11
+ * .allowRegex(/^https:\/\/api\.zylker\.(com|in)\//)
12
+ * .ignoreEquals('https://api.zylker.com/health')
13
+ * .ignoreRegex(/\/internal\//)
14
+ * .build());
15
+ *
16
+ * Four rules, two kinds by two: an exact URL (equals) or a regular expression (regex), to allow or
17
+ * to ignore. Each is tried on the call's URL as `scheme://host[:port]/path`, with its query and
18
+ * fragment removed, so one rule can name a host, a path or a single endpoint. Ignore rules are
19
+ * tried first and always win; then, when there are allow rules, a call must match one of them.
20
+ *
21
+ * The name a call is recorded under is not configured: the query goes, and numeric ids, UUIDs and
22
+ * JWTs in its path become `*`, so `/users/42/orders` and `/users/43/orders` are one endpoint.
23
+ *
24
+ * Both apply to every call, the ones the fetch/XHR wrappers catch and the ones the app reports
25
+ * with startTrackApi(), so one set of rules decides what the API page shows.
26
+ */
27
+ function emptyConfig() {
28
+ return { allowEquals: [], ignoreEquals: [], allowRegex: [], ignoreRegex: [] };
29
+ }
30
+ /**
31
+ * A URL as the rules compare it: `scheme://host[:port]/path`, the scheme and host lower-cased,
32
+ * the default port dropped, the query, fragment and a trailing slash removed. '' when it is not
33
+ * an absolute http(s) URL.
34
+ */
35
+ function ruleUrl(raw) {
36
+ try {
37
+ var url = new URL(String(raw).trim());
38
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') { // no i18n
39
+ return ''; // no i18n
40
+ }
41
+ var path = url.pathname.length > 1 ? url.pathname.replace(/\/+$/, '') : url.pathname; // no i18n
42
+ return url.protocol + '//' + url.host.toLowerCase() + path; // no i18n
43
+ }
44
+ catch (err) {
45
+ return ''; // no i18n
46
+ }
47
+ }
48
+ /** The exact URLs given, as rules compare them; anything that is not an absolute URL is refused, and said. */
49
+ function cleanUrls(method, values) {
50
+ var out = [];
51
+ values.forEach(function (value) {
52
+ var url = typeof value === 'string' ? ruleUrl(value) : ''; // no i18n
53
+ if (url === '') { // no i18n
54
+ logger.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
55
+ return;
56
+ }
57
+ if (out.indexOf(url) === -1) {
58
+ out.push(url);
59
+ }
60
+ });
61
+ return out;
62
+ }
63
+ /** The regular expressions given, a RegExp or its source as a string; an invalid one is refused, and said. */
64
+ function cleanRegexes(method, values) {
65
+ var out = [];
66
+ values.forEach(function (value) {
67
+ if (value instanceof RegExp) {
68
+ out.push(value);
69
+ return;
70
+ }
71
+ if (typeof value === 'string' && value !== '') { // no i18n
72
+ try {
73
+ out.push(new RegExp(value));
74
+ return;
75
+ }
76
+ catch (err) {
77
+ // falls through to the warning
78
+ }
79
+ }
80
+ logger.warnAlways('ApiTrackingBuilder.' + method + ': ' + String(value) + ' is not a regular expression, and is left out'); // no i18n
81
+ });
82
+ return out;
83
+ }
84
+ /**
85
+ * Builds the rules configure takes. Each method may be called more than once, and takes any number
86
+ * of values: `new ApiTrackingBuilder().allowEquals(a, b).ignoreRegex(/x/).build()`.
87
+ */
88
+ class ApiTrackingBuilder {
89
+ constructor() {
90
+ this.rules = emptyConfig();
91
+ }
92
+ /** Records only these URLs (and those any allowRegex matches): `https://api.example.com/orders`. */
93
+ allowEquals(...urls) { this.rules.allowEquals.push(...cleanUrls('allowEquals', urls)); return this; }
94
+ /** Never records these URLs: `https://api.example.com/health`. */
95
+ ignoreEquals(...urls) { this.rules.ignoreEquals.push(...cleanUrls('ignoreEquals', urls)); return this; }
96
+ /** Records only URLs these match (and those any allowEquals names): `/^https:\/\/api\.example\.com\//`. */
97
+ allowRegex(...patterns) { this.rules.allowRegex.push(...cleanRegexes('allowRegex', patterns)); return this; }
98
+ /** Never records URLs these match: `/\/internal\//`. */
99
+ ignoreRegex(...patterns) { this.rules.ignoreRegex.push(...cleanRegexes('ignoreRegex', patterns)); return this; }
100
+ build() {
101
+ return {
102
+ allowEquals: this.rules.allowEquals.slice(),
103
+ ignoreEquals: this.rules.ignoreEquals.slice(),
104
+ allowRegex: this.rules.allowRegex.slice(),
105
+ ignoreRegex: this.rules.ignoreRegex.slice(),
106
+ };
107
+ }
108
+ }
109
+ /**
110
+ * 2.0.0-beta's builder methods, now gone. Called, each throws a TypeError that names what to use
111
+ * instead: a rule silently missing would record what the app meant to leave out.
112
+ */
113
+ const RETIRED_METHODS = Object.freeze({
114
+ ignoreDomains: 'ignoreRegex', // no i18n
115
+ allowOnlyDomains: 'allowRegex', // no i18n
116
+ allowOnlyTLDs: 'allowRegex', // no i18n
117
+ ignoreTLDs: 'ignoreRegex', // no i18n
118
+ ignoreDomainPrefixes: 'ignoreRegex', // no i18n
119
+ ignoreDomainSuffixes: 'ignoreRegex', // no i18n
120
+ groupDomains: '', // no i18n
121
+ ignoreEndpoint: 'ignoreEquals or ignoreRegex', // no i18n
122
+ addPattern: '', // no i18n
123
+ preserveSegments: '', // no i18n
124
+ autoDetection: '', // no i18n
125
+ });
126
+ Object.keys(RETIRED_METHODS).forEach(function (name) {
127
+ Object.defineProperty(ApiTrackingBuilder.prototype, name, {
128
+ configurable: true,
129
+ value: function () {
130
+ var instead = RETIRED_METHODS[name];
131
+ throw new TypeError('ApiTrackingBuilder.' + name + '() is no longer supported: ' // no i18n
132
+ + (instead ? 'use ' + instead + ', which match the URL without its query' : 'ids, UUIDs and tokens in a path become * on their own')); // no i18n
133
+ },
134
+ });
135
+ });
136
+ var current = emptyConfig();
137
+ /** The values of `list` that are of the kind `keep` accepts. */
138
+ function listOf(value, keep) {
139
+ return Array.isArray(value) ? value.filter(keep) : [];
140
+ }
141
+ /**
142
+ * Applies the rules, replacing any given before. Takes what build() returned, or the builder
143
+ * itself. Call it once, before the requests it should cover; it works before init().
144
+ */
145
+ function configureApiTracking(config) {
146
+ var built = (config instanceof ApiTrackingBuilder ? config.build() : config);
147
+ if (!built || typeof built !== 'object') { // no i18n
148
+ current = emptyConfig();
149
+ return;
150
+ }
151
+ var isString = function (one) { return typeof one === 'string'; }; // no i18n
152
+ var isRegExp = function (one) { return one instanceof RegExp; };
153
+ current = {
154
+ // a hand-written object gets the same clean-up the builder gives
155
+ allowEquals: cleanUrls('allowEquals', listOf(built.allowEquals, isString)), // no i18n
156
+ ignoreEquals: cleanUrls('ignoreEquals', listOf(built.ignoreEquals, isString)), // no i18n
157
+ allowRegex: listOf(built.allowRegex, isRegExp).concat(cleanRegexes('allowRegex', listOf(built.allowRegex, isString))), // no i18n
158
+ ignoreRegex: listOf(built.ignoreRegex, isRegExp).concat(cleanRegexes('ignoreRegex', listOf(built.ignoreRegex, isString))), // no i18n
159
+ };
160
+ }
161
+ /** Whether a regular expression matches, whatever its flags: a /g one keeps a position between tests. */
162
+ function regexMatches(re, url) {
163
+ re.lastIndex = 0;
164
+ return re.test(url);
165
+ }
166
+ /**
167
+ * Whether a call to `url` is recorded. Ignore rules are tried first and always win; then, when
168
+ * there are allow rules, the URL must match one. A URL that cannot be read is not recorded.
169
+ */
170
+ function urlTracked(url) {
171
+ var target = ruleUrl(url);
172
+ if (target === '') { // no i18n
173
+ return false;
174
+ }
175
+ if (current.ignoreEquals.indexOf(target) !== -1 || current.ignoreRegex.some(function (re) { return regexMatches(re, target); })) {
176
+ return false;
177
+ }
178
+ if (current.allowEquals.length === 0 && current.allowRegex.length === 0) {
179
+ return true;
180
+ }
181
+ return current.allowEquals.indexOf(target) !== -1 || current.allowRegex.some(function (re) { return regexMatches(re, target); });
182
+ }
183
+ /* ---------------- the name a call is recorded under ---------------- */
184
+ /** The path without its query string or fragment, which is where ids and tokens travel. */
185
+ function withoutQuery(path) {
186
+ var cut = String(path || '').split(/[?#]/)[0]; // no i18n
187
+ return cut === '' ? '/' : cut; // no i18n
188
+ }
189
+ const NUMERIC = /^\d+$/;
190
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
191
+ // three base64url parts, the first starting eyJ — the encoding of '{"' every JWT header opens
192
+ // with. Without that start, a file name such as jquery.min.js would pass for a token
193
+ const JWT = /^eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
194
+ /** The path a call is recorded under: the query goes, and numeric ids, UUIDs and JWTs become `*`. */
195
+ function normalizeApiPath(path) {
196
+ return withoutQuery(path).split('/').map(function (segment) {
197
+ return segment !== '' && (NUMERIC.test(segment) || UUID.test(segment) || JWT.test(segment)) ? '*' : segment; // no i18n
198
+ }).join('/'); // no i18n
199
+ }
200
+
201
+ exports.ApiTrackingBuilder = ApiTrackingBuilder;
202
+ exports.configureApiTracking = configureApiTracking;
203
+ exports.normalizeApiPath = normalizeApiPath;
204
+ exports.ruleUrl = ruleUrl;
205
+ exports.urlTracked = urlTracked;
206
+ exports.withoutQuery = 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,200 @@
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
+ 'use strict';
3
+
4
+ var state = require('../core/state.js');
5
+ var logger = require('../core/logger.js');
6
+ var utils = require('../core/utils.js');
7
+ var track = require('./track.js');
8
+ var apiRules = require('./api-rules.js');
9
+
10
+ /**
11
+ * Automatic API tracking: wraps XMLHttpRequest and fetch so calls the app makes are recorded
12
+ * without it calling startTrackApi() / endTrackApi() itself.
13
+ *
14
+ * Two rules shape everything here. The wrappers must be invisible — return values, `this`, thrown
15
+ * errors and argument forms all pass straight through, because a mistake in this file breaks the
16
+ * host app's networking rather than just losing a metric. And the SDK's own traffic must never be
17
+ * recorded: engagement/add reports API calls, so tracking it would have each batch produce the
18
+ * items for the next one.
19
+ *
20
+ * Off unless `track_api` is set. Hostnames and paths of every request an app makes is a wider
21
+ * grant than events and screens, so it is the app's decision, not a default.
22
+ */
23
+ var installed = false;
24
+ var originalOpen = null;
25
+ var originalSend = null;
26
+ var originalFetch = null;
27
+ /**
28
+ * Whether a request is the SDK's own, which is never reported: engagement/add carries API items, so
29
+ * recording it would have every batch produce the items for the next one, forever.
30
+ *
31
+ * Two checks, because one is not enough to bet a loop on. The host comparison is a prefix match, so
32
+ * it misses if the host is spelled differently in the request than in serviceUrl — a trailing
33
+ * slash is enough. The path check catches those, since every SDK call sits under the configured
34
+ * endpoint whatever host it goes to, including through a same-origin proxy.
35
+ */
36
+ function isOwnRequest(url, pathname) {
37
+ var own = [state._ZAP._defaultoptions.base_domain, state._ZAP._defaultoptions.serviceUrl];
38
+ for (var i = 0; i < own.length; i++) {
39
+ if (!utils.isEmpty(own[i]) && url.indexOf(own[i]) === 0) {
40
+ return true;
41
+ }
42
+ }
43
+ var endpoint = state.getConfig('endpoint');
44
+ return !utils.isEmpty(endpoint) && pathname.indexOf(endpoint) === 0;
45
+ }
46
+ /**
47
+ * Whether one URL is ours to report: an http(s) call, not the SDK's own, and one the
48
+ * configureApiTracking rules let through. Anything unparseable is skipped rather than guessed at.
49
+ */
50
+ function shouldTrack(rawUrl) {
51
+ if (utils.isEmpty(rawUrl)) {
52
+ return false;
53
+ }
54
+ var absolute;
55
+ try {
56
+ absolute = new URL(rawUrl, window.location.href);
57
+ }
58
+ catch (err) {
59
+ return false;
60
+ }
61
+ if (absolute.protocol !== 'https:' && absolute.protocol !== 'http:') { // no i18n
62
+ return false; // data:, blob:, chrome-extension: and friends
63
+ }
64
+ if (isOwnRequest(absolute.href, absolute.pathname)) {
65
+ return false;
66
+ }
67
+ // configureApiTracking's rules: checked here too so a call left out is not even timed. trackApi checks them again, for the
68
+ // calls an app reports itself
69
+ return apiRules.urlTracked(absolute.href);
70
+ }
71
+ /** One finished call. Never throws: a tracking failure must not surface in the app's call. */
72
+ function record(method, url, starttime, responsecode, responsemessage) {
73
+ try {
74
+ track.trackApi({
75
+ url: url,
76
+ method: method,
77
+ responsecode: responsecode,
78
+ responsemessage: responsemessage,
79
+ starttime: starttime,
80
+ endtime: utils.nowMs(),
81
+ });
82
+ }
83
+ catch (err) {
84
+ logger.Console.log('auto api tracking: ' + String(err)); // no i18n
85
+ }
86
+ }
87
+ /** The url of any of fetch's three first-argument forms. */
88
+ function fetchUrl(input) {
89
+ if (typeof input === 'string') { // no i18n
90
+ return input;
91
+ }
92
+ if (typeof Request !== 'undefined' && input instanceof Request) { // no i18n
93
+ return input.url;
94
+ }
95
+ return String(input);
96
+ }
97
+ function fetchMethod(input, init) {
98
+ if (init && init.method) {
99
+ return init.method;
100
+ }
101
+ if (typeof Request !== 'undefined' && input instanceof Request) { // no i18n
102
+ return input.method;
103
+ }
104
+ return 'GET'; // no i18n
105
+ }
106
+ function installXhr() {
107
+ if (typeof XMLHttpRequest !== 'function') { // no i18n
108
+ return;
109
+ }
110
+ originalOpen = XMLHttpRequest.prototype.open;
111
+ originalSend = XMLHttpRequest.prototype.send;
112
+ XMLHttpRequest.prototype.open = function (method, url) {
113
+ try {
114
+ var href = String(url);
115
+ if (shouldTrack(href)) {
116
+ // starttime is set in send(): open() may happen long before the call goes out
117
+ this._ap_api = { method: String(method || 'GET'), url: href, starttime: 0 }; // no i18n
118
+ }
119
+ else {
120
+ this._ap_api = undefined;
121
+ }
122
+ }
123
+ catch (err) {
124
+ this._ap_api = undefined;
125
+ }
126
+ return originalOpen.apply(this, arguments);
127
+ };
128
+ XMLHttpRequest.prototype.send = function () {
129
+ const tracked = this._ap_api;
130
+ if (tracked) {
131
+ tracked.starttime = utils.nowMs();
132
+ // loadend fires for success, error, abort and timeout alike, so one listener covers
133
+ // every ending; status 0 is how a network failure arrives here
134
+ this.addEventListener('loadend', function () {
135
+ var message = this.status === 0 ? 'Network Error' : (this.statusText || '-'); // no i18n
136
+ record(tracked.method, tracked.url, tracked.starttime, this.status, message);
137
+ });
138
+ }
139
+ return originalSend.apply(this, arguments);
140
+ };
141
+ }
142
+ function installFetch() {
143
+ if (typeof fetch !== 'function') { // no i18n
144
+ return;
145
+ }
146
+ originalFetch = fetch;
147
+ window.fetch = function (input, init) {
148
+ var url, method, starttime;
149
+ try {
150
+ url = fetchUrl(input);
151
+ method = fetchMethod(input, init);
152
+ starttime = utils.nowMs();
153
+ }
154
+ catch (err) {
155
+ return originalFetch(input, init);
156
+ }
157
+ if (!shouldTrack(url)) {
158
+ return originalFetch(input, init);
159
+ }
160
+ return originalFetch(input, init).then(function (response) {
161
+ record(method, url, starttime, response.status, response.statusText || '-'); // no i18n
162
+ return response;
163
+ }, function (err) {
164
+ // a rejected fetch never reached a status; the rejection is re-thrown untouched
165
+ record(method, url, starttime, 0, String(err && err.message ? err.message : err) || 'Network Error'); // no i18n
166
+ throw err;
167
+ });
168
+ };
169
+ }
170
+ /**
171
+ * Starts or stops automatic tracking. Safe to call repeatedly: installing twice would report each
172
+ * call twice, so the second call is a no-op.
173
+ */
174
+ function enableApiTracking(enabled) {
175
+ var on = typeof enabled === 'boolean' ? enabled : true; // no i18n
176
+ if (on === installed) {
177
+ return;
178
+ }
179
+ if (on) {
180
+ installXhr();
181
+ installFetch();
182
+ installed = true;
183
+ logger.Console.log('automatic api tracking: on'); // no i18n
184
+ return;
185
+ }
186
+ if (originalOpen) {
187
+ XMLHttpRequest.prototype.open = originalOpen;
188
+ }
189
+ if (originalSend) {
190
+ XMLHttpRequest.prototype.send = originalSend;
191
+ }
192
+ if (originalFetch) {
193
+ window.fetch = originalFetch;
194
+ }
195
+ originalOpen = originalSend = originalFetch = null;
196
+ installed = false;
197
+ logger.Console.log('automatic api tracking: off'); // no i18n
198
+ }
199
+
200
+ exports.enableApiTracking = 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;