wisetrack 2.0.0

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 (178) hide show
  1. package/LICENSE +5 -0
  2. package/README.md +128 -0
  3. package/dist/cdn/constants/constants.d.ts +20 -0
  4. package/dist/cdn/constants/endpoints.d.ts +11 -0
  5. package/dist/cdn/constants/environments.d.ts +25 -0
  6. package/dist/cdn/core/caching/queue-data.d.ts +25 -0
  7. package/dist/cdn/core/caching/request-queue-manager.d.ts +54 -0
  8. package/dist/cdn/core/fields/event-fields-builder.d.ts +8 -0
  9. package/dist/cdn/core/fields/fields-builder.d.ts +9 -0
  10. package/dist/cdn/core/network/api-client.d.ts +9 -0
  11. package/dist/cdn/core/network/network-error.d.ts +17 -0
  12. package/dist/cdn/core/network/network-manager.d.ts +22 -0
  13. package/dist/cdn/core/network/retry-policy.d.ts +8 -0
  14. package/dist/cdn/core/storage/storage-manager.d.ts +52 -0
  15. package/dist/cdn/core/wisetrack.d.ts +125 -0
  16. package/dist/cdn/core/wt-tracker.d.ts +25 -0
  17. package/dist/cdn/index.d.ts +4 -0
  18. package/dist/cdn/sdk.bundle.js +3604 -0
  19. package/dist/cdn/sdk.bundle.js.map +1 -0
  20. package/dist/cdn/sdk.bundle.min.js +1 -0
  21. package/dist/cdn/types/config/initial-config.d.ts +43 -0
  22. package/dist/cdn/types/config/wt-app-settings.d.ts +15 -0
  23. package/dist/cdn/types/config/wt-config.d.ts +18 -0
  24. package/dist/cdn/types/event/revenue-currency.d.ts +39 -0
  25. package/dist/cdn/types/event/wt-event.d.ts +94 -0
  26. package/dist/cdn/utils/activity-ticker.d.ts +12 -0
  27. package/dist/cdn/utils/country-finder.d.ts +9 -0
  28. package/dist/cdn/utils/crypto-helper.d.ts +4 -0
  29. package/dist/cdn/utils/device-detector.d.ts +41 -0
  30. package/dist/cdn/utils/logger.d.ts +36 -0
  31. package/dist/cdn/utils/storage-support.d.ts +16 -0
  32. package/dist/cdn/utils/utils.d.ts +5 -0
  33. package/dist/cdn/utils/webgl-fingerprint.d.ts +7 -0
  34. package/dist/cjs/constants/constants.d.ts +20 -0
  35. package/dist/cjs/constants/endpoints.d.ts +11 -0
  36. package/dist/cjs/constants/environments.d.ts +25 -0
  37. package/dist/cjs/core/caching/queue-data.d.ts +25 -0
  38. package/dist/cjs/core/caching/request-queue-manager.d.ts +54 -0
  39. package/dist/cjs/core/fields/event-fields-builder.d.ts +8 -0
  40. package/dist/cjs/core/fields/fields-builder.d.ts +9 -0
  41. package/dist/cjs/core/network/api-client.d.ts +9 -0
  42. package/dist/cjs/core/network/network-error.d.ts +17 -0
  43. package/dist/cjs/core/network/network-manager.d.ts +22 -0
  44. package/dist/cjs/core/network/retry-policy.d.ts +8 -0
  45. package/dist/cjs/core/storage/storage-manager.d.ts +52 -0
  46. package/dist/cjs/core/wisetrack.d.ts +125 -0
  47. package/dist/cjs/core/wt-tracker.d.ts +25 -0
  48. package/dist/cjs/index.d.ts +4 -0
  49. package/dist/cjs/index.js +3599 -0
  50. package/dist/cjs/index.js.map +1 -0
  51. package/dist/cjs/types/config/initial-config.d.ts +43 -0
  52. package/dist/cjs/types/config/wt-app-settings.d.ts +15 -0
  53. package/dist/cjs/types/config/wt-config.d.ts +18 -0
  54. package/dist/cjs/types/event/revenue-currency.d.ts +39 -0
  55. package/dist/cjs/types/event/wt-event.d.ts +94 -0
  56. package/dist/cjs/utils/activity-ticker.d.ts +12 -0
  57. package/dist/cjs/utils/country-finder.d.ts +9 -0
  58. package/dist/cjs/utils/crypto-helper.d.ts +4 -0
  59. package/dist/cjs/utils/device-detector.d.ts +41 -0
  60. package/dist/cjs/utils/logger.d.ts +36 -0
  61. package/dist/cjs/utils/storage-support.d.ts +16 -0
  62. package/dist/cjs/utils/utils.d.ts +5 -0
  63. package/dist/cjs/utils/webgl-fingerprint.d.ts +7 -0
  64. package/dist/constants/constants.d.ts +20 -0
  65. package/dist/constants/constants.js +19 -0
  66. package/dist/constants/constants.js.map +1 -0
  67. package/dist/constants/endpoints.d.ts +11 -0
  68. package/dist/constants/endpoints.js +10 -0
  69. package/dist/constants/endpoints.js.map +1 -0
  70. package/dist/constants/environments.d.ts +25 -0
  71. package/dist/constants/environments.js +37 -0
  72. package/dist/constants/environments.js.map +1 -0
  73. package/dist/core/caching/queue-data.d.ts +25 -0
  74. package/dist/core/caching/queue-data.js +50 -0
  75. package/dist/core/caching/queue-data.js.map +1 -0
  76. package/dist/core/caching/request-queue-manager.d.ts +54 -0
  77. package/dist/core/caching/request-queue-manager.js +333 -0
  78. package/dist/core/caching/request-queue-manager.js.map +1 -0
  79. package/dist/core/fields/event-fields-builder.d.ts +8 -0
  80. package/dist/core/fields/event-fields-builder.js +29 -0
  81. package/dist/core/fields/event-fields-builder.js.map +1 -0
  82. package/dist/core/fields/fields-builder.d.ts +9 -0
  83. package/dist/core/fields/fields-builder.js +120 -0
  84. package/dist/core/fields/fields-builder.js.map +1 -0
  85. package/dist/core/network/api-client.d.ts +9 -0
  86. package/dist/core/network/api-client.js +88 -0
  87. package/dist/core/network/api-client.js.map +1 -0
  88. package/dist/core/network/network-error.d.ts +17 -0
  89. package/dist/core/network/network-error.js +35 -0
  90. package/dist/core/network/network-error.js.map +1 -0
  91. package/dist/core/network/network-manager.d.ts +22 -0
  92. package/dist/core/network/network-manager.js +72 -0
  93. package/dist/core/network/network-manager.js.map +1 -0
  94. package/dist/core/network/retry-policy.d.ts +8 -0
  95. package/dist/core/network/retry-policy.js +26 -0
  96. package/dist/core/network/retry-policy.js.map +1 -0
  97. package/dist/core/storage/storage-manager.d.ts +52 -0
  98. package/dist/core/storage/storage-manager.js +221 -0
  99. package/dist/core/storage/storage-manager.js.map +1 -0
  100. package/dist/core/wisetrack.d.ts +125 -0
  101. package/dist/core/wisetrack.js +277 -0
  102. package/dist/core/wisetrack.js.map +1 -0
  103. package/dist/core/wt-tracker.d.ts +25 -0
  104. package/dist/core/wt-tracker.js +239 -0
  105. package/dist/core/wt-tracker.js.map +1 -0
  106. package/dist/esm/constants/constants.d.ts +20 -0
  107. package/dist/esm/constants/endpoints.d.ts +11 -0
  108. package/dist/esm/constants/environments.d.ts +25 -0
  109. package/dist/esm/core/caching/queue-data.d.ts +25 -0
  110. package/dist/esm/core/caching/request-queue-manager.d.ts +54 -0
  111. package/dist/esm/core/fields/event-fields-builder.d.ts +8 -0
  112. package/dist/esm/core/fields/fields-builder.d.ts +9 -0
  113. package/dist/esm/core/network/api-client.d.ts +9 -0
  114. package/dist/esm/core/network/network-error.d.ts +17 -0
  115. package/dist/esm/core/network/network-manager.d.ts +22 -0
  116. package/dist/esm/core/network/retry-policy.d.ts +8 -0
  117. package/dist/esm/core/storage/storage-manager.d.ts +52 -0
  118. package/dist/esm/core/wisetrack.d.ts +125 -0
  119. package/dist/esm/core/wt-tracker.d.ts +25 -0
  120. package/dist/esm/index.d.ts +4 -0
  121. package/dist/esm/index.js +3594 -0
  122. package/dist/esm/index.js.map +1 -0
  123. package/dist/esm/types/config/initial-config.d.ts +43 -0
  124. package/dist/esm/types/config/wt-app-settings.d.ts +15 -0
  125. package/dist/esm/types/config/wt-config.d.ts +18 -0
  126. package/dist/esm/types/event/revenue-currency.d.ts +39 -0
  127. package/dist/esm/types/event/wt-event.d.ts +94 -0
  128. package/dist/esm/utils/activity-ticker.d.ts +12 -0
  129. package/dist/esm/utils/country-finder.d.ts +9 -0
  130. package/dist/esm/utils/crypto-helper.d.ts +4 -0
  131. package/dist/esm/utils/device-detector.d.ts +41 -0
  132. package/dist/esm/utils/logger.d.ts +36 -0
  133. package/dist/esm/utils/storage-support.d.ts +16 -0
  134. package/dist/esm/utils/utils.d.ts +5 -0
  135. package/dist/esm/utils/webgl-fingerprint.d.ts +7 -0
  136. package/dist/index.d.ts +4 -0
  137. package/dist/index.js +4 -0
  138. package/dist/index.js.map +1 -0
  139. package/dist/types/config/initial-config.d.ts +43 -0
  140. package/dist/types/config/initial-config.js +2 -0
  141. package/dist/types/config/initial-config.js.map +1 -0
  142. package/dist/types/config/wt-app-settings.d.ts +15 -0
  143. package/dist/types/config/wt-app-settings.js +25 -0
  144. package/dist/types/config/wt-app-settings.js.map +1 -0
  145. package/dist/types/config/wt-config.d.ts +18 -0
  146. package/dist/types/config/wt-config.js +28 -0
  147. package/dist/types/config/wt-config.js.map +1 -0
  148. package/dist/types/event/revenue-currency.d.ts +39 -0
  149. package/dist/types/event/revenue-currency.js +39 -0
  150. package/dist/types/event/revenue-currency.js.map +1 -0
  151. package/dist/types/event/wt-event.d.ts +94 -0
  152. package/dist/types/event/wt-event.js +93 -0
  153. package/dist/types/event/wt-event.js.map +1 -0
  154. package/dist/utils/activity-ticker.d.ts +12 -0
  155. package/dist/utils/activity-ticker.js +37 -0
  156. package/dist/utils/activity-ticker.js.map +1 -0
  157. package/dist/utils/country-finder.d.ts +9 -0
  158. package/dist/utils/country-finder.js +71 -0
  159. package/dist/utils/country-finder.js.map +1 -0
  160. package/dist/utils/crypto-helper.d.ts +4 -0
  161. package/dist/utils/crypto-helper.js +7 -0
  162. package/dist/utils/crypto-helper.js.map +1 -0
  163. package/dist/utils/device-detector.d.ts +41 -0
  164. package/dist/utils/device-detector.js +101 -0
  165. package/dist/utils/device-detector.js.map +1 -0
  166. package/dist/utils/logger.d.ts +36 -0
  167. package/dist/utils/logger.js +84 -0
  168. package/dist/utils/logger.js.map +1 -0
  169. package/dist/utils/storage-support.d.ts +16 -0
  170. package/dist/utils/storage-support.js +86 -0
  171. package/dist/utils/storage-support.js.map +1 -0
  172. package/dist/utils/utils.d.ts +5 -0
  173. package/dist/utils/utils.js +95 -0
  174. package/dist/utils/utils.js.map +1 -0
  175. package/dist/utils/webgl-fingerprint.d.ts +7 -0
  176. package/dist/utils/webgl-fingerprint.js +100 -0
  177. package/dist/utils/webgl-fingerprint.js.map +1 -0
  178. package/package.json +71 -0
@@ -0,0 +1,3604 @@
1
+ var WiseTrackSDK = (function (exports) {
2
+ 'use strict';
3
+
4
+ /******************************************************************************
5
+ Copyright (c) Microsoft Corporation.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted.
9
+
10
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
15
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16
+ PERFORMANCE OF THIS SOFTWARE.
17
+ ***************************************************************************** */
18
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
19
+
20
+
21
+ function __awaiter(thisArg, _arguments, P, generator) {
22
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
23
+ return new (P || (P = Promise))(function (resolve, reject) {
24
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
25
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
26
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
27
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
28
+ });
29
+ }
30
+
31
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
32
+ var e = new Error(message);
33
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
34
+ };
35
+
36
+ /** @internal */
37
+ const WTConstants = {
38
+ SDK: {
39
+ HASH: "997bfbb583c1245a426a53dc1899ec779ff354f9",
40
+ PLATFORM: "web",
41
+ VERSION: "2.0.0",
42
+ },
43
+ CONFIG: {
44
+ BASE_URL: "https://config.wisetrack.io",
45
+ DEFAULT_ENVIRONMENT: "debug",
46
+ },
47
+ DEFAULTS: {
48
+ LOG_LEVEL: "debug",
49
+ SESSION_INTERVAL: '1800000', // 30 minutes
50
+ SUBSESSION_INTERVAL: '300000'},
51
+ };
52
+
53
+ /** @internal */
54
+ const WTSDKEnvironment = {
55
+ DEBUG: "debug",
56
+ STAGE: "stage",
57
+ PRODUCTION: "production",
58
+ };
59
+ /** @internal */
60
+ const EnvironmentUtils = {
61
+ sdkEnvironment: WTConstants.CONFIG.DEFAULT_ENVIRONMENT,
62
+ needAppSettings() {
63
+ return this.sdkEnvironment !== WTSDKEnvironment.PRODUCTION;
64
+ },
65
+ baseUrl() {
66
+ switch (this.sdkEnvironment) {
67
+ case WTSDKEnvironment.DEBUG:
68
+ return "https://core.debug.wisetrackdev.ir";
69
+ case WTSDKEnvironment.STAGE:
70
+ return "https://core.stage.wisetrackdev.ir";
71
+ case WTSDKEnvironment.PRODUCTION:
72
+ return "https://core.wisetrack.io";
73
+ default:
74
+ throw new Error(`Unknown environment: ${this.sdkEnvironment}`);
75
+ }
76
+ },
77
+ };
78
+
79
+ /** @internal */
80
+ const WTEndpoints = {
81
+ EVENTS: "/api/v1/events",
82
+ SESSIONS: "/api/v1/sessions",
83
+ SDK_CLICKS: "/api/v1/sdk_clicks",
84
+ SDK_INFOS: "/api/v1/sdk_infos",
85
+ ATTRIBUTIONS: "/api/v1/attributions",
86
+ APP_SETTINGS: "/api/v1/app_settings",
87
+ };
88
+
89
+ /** @internal */
90
+ class WTAppSettings {
91
+ constructor(events, sessions, sdkClicks, sdkInfos, attributions, sessionInterval = WTConstants.DEFAULTS.SESSION_INTERVAL, subsessionInterval = WTConstants.DEFAULTS.SUBSESSION_INTERVAL) {
92
+ this.events = events;
93
+ this.sessions = sessions;
94
+ this.sdkClicks = sdkClicks;
95
+ this.sdkInfos = sdkInfos;
96
+ this.attributions = attributions;
97
+ this.sessionInterval = sessionInterval;
98
+ this.subsessionInterval = subsessionInterval;
99
+ }
100
+ static fromConfig(config) {
101
+ return new WTAppSettings(config.events, config.sessions, config.sdkClicks, config.sdkInfos, config.attributions, config.sessionInterval, config.subsessionInterval);
102
+ }
103
+ static fromJson(json) {
104
+ var _a, _b;
105
+ return new WTAppSettings(json.events, json.sessions, json.sdk_clicks, json.sdk_infos, json.attributions, (_a = json.session_interval) !== null && _a !== void 0 ? _a : WTConstants.DEFAULTS.SESSION_INTERVAL, (_b = json.subsession_interval) !== null && _b !== void 0 ? _b : WTConstants.DEFAULTS.SUBSESSION_INTERVAL);
106
+ }
107
+ static get defaultValue() {
108
+ return new WTAppSettings(WTEndpoints.EVENTS, WTEndpoints.SESSIONS, WTEndpoints.SDK_CLICKS, WTEndpoints.SDK_INFOS, WTEndpoints.ATTRIBUTIONS, WTConstants.DEFAULTS.SESSION_INTERVAL, WTConstants.DEFAULTS.SUBSESSION_INTERVAL);
109
+ }
110
+ }
111
+
112
+ /** @internal */
113
+ class WTConfig {
114
+ constructor(baseUrl, events, sessions, sdkClicks, sdkInfos, attributions, appSettings, sdkEnabled = true, forceUpdate = false, sdkUpdate = false, sessionInterval = WTConstants.DEFAULTS.SESSION_INTERVAL, subsessionInterval = WTConstants.DEFAULTS.SUBSESSION_INTERVAL) {
115
+ this.baseUrl = baseUrl;
116
+ this.events = events;
117
+ this.sessions = sessions;
118
+ this.sdkClicks = sdkClicks;
119
+ this.sdkInfos = sdkInfos;
120
+ this.attributions = attributions;
121
+ this.appSettings = appSettings;
122
+ this.sdkEnabled = sdkEnabled;
123
+ this.forceUpdate = forceUpdate;
124
+ this.sdkUpdate = sdkUpdate;
125
+ this.sessionInterval = sessionInterval;
126
+ this.subsessionInterval = subsessionInterval;
127
+ }
128
+ static fromJson(json) {
129
+ var _a, _b, _c, _d, _e;
130
+ return new WTConfig(json.base_url, json.events, json.sessions, json.sdk_clicks, json.sdk_infos, json.attributions, json.app_settings, (_a = json.sdk_enabled) !== null && _a !== void 0 ? _a : true, (_b = json.force_update) !== null && _b !== void 0 ? _b : false, (_c = json.sdk_update) !== null && _c !== void 0 ? _c : false, (_d = json.session_interval) !== null && _d !== void 0 ? _d : WTConstants.DEFAULTS.SESSION_INTERVAL, (_e = json.subsession_interval) !== null && _e !== void 0 ? _e : WTConstants.DEFAULTS.SUBSESSION_INTERVAL);
131
+ }
132
+ static get defaultValue() {
133
+ return new WTConfig(EnvironmentUtils.baseUrl(), WTEndpoints.EVENTS, WTEndpoints.SESSIONS, WTEndpoints.SDK_CLICKS, WTEndpoints.SDK_INFOS, WTEndpoints.ATTRIBUTIONS, WTEndpoints.APP_SETTINGS);
134
+ }
135
+ }
136
+
137
+ /** @internal */
138
+ class WTLogEngine {
139
+ }
140
+ /** @internal */
141
+ class ConsoleLogEngine extends WTLogEngine {
142
+ log(level, prefix, ...args) {
143
+ switch (level) {
144
+ case "debug":
145
+ console.debug(prefix, ...args);
146
+ break;
147
+ case "info":
148
+ console.info(prefix, ...args);
149
+ break;
150
+ case "warn":
151
+ console.warn(prefix, ...args);
152
+ break;
153
+ case "error":
154
+ console.error(prefix, ...args);
155
+ break;
156
+ default:
157
+ console.log(prefix, ...args);
158
+ break;
159
+ }
160
+ }
161
+ }
162
+ /**
163
+ * Defines the available log levels for the SDK.
164
+ *
165
+ * - `DEBUG`: Logs everything, including debug info.
166
+ * - `INFO`: Logs general information.
167
+ * - `WARN`: Logs warnings.
168
+ * - `ERROR`: Logs errors only.
169
+ * - `NONE`: Disables logging.
170
+ */
171
+ const WTLogLevel = {
172
+ DEBUG: "debug",
173
+ INFO: "info",
174
+ WARN: "warn",
175
+ ERROR: "error",
176
+ NONE: "none",
177
+ };
178
+ /** @internal */
179
+ class WTLogger {
180
+ static setLevel(level) {
181
+ this.level = level;
182
+ }
183
+ static setPrefix(prefix) {
184
+ this.prefix = prefix;
185
+ }
186
+ static addOutputEngine(engine) {
187
+ this.outputEngines.push(engine);
188
+ }
189
+ static shouldLog(type) {
190
+ const levels = ["debug", "info", "warn", "error"];
191
+ const currentIndex = levels.indexOf(this.level);
192
+ const typeIndex = levels.indexOf(type);
193
+ return typeIndex >= currentIndex;
194
+ }
195
+ static log(level, ...args) {
196
+ if (!this.shouldLog(level))
197
+ return;
198
+ const prefix = `[${this.prefix}-${level.toUpperCase()}]`;
199
+ for (const output of this.outputEngines) {
200
+ output.log(level, prefix, ...args);
201
+ }
202
+ }
203
+ static debug(...args) {
204
+ this.log("debug", ...args);
205
+ }
206
+ static info(...args) {
207
+ this.log("info", ...args);
208
+ }
209
+ static warn(...args) {
210
+ this.log("warn", ...args);
211
+ }
212
+ static error(...args) {
213
+ this.log("error", ...args);
214
+ }
215
+ }
216
+ WTLogger.level = WTConstants.DEFAULTS.LOG_LEVEL;
217
+ WTLogger.prefix = "WT";
218
+ WTLogger.outputEngines = [new ConsoleLogEngine()];
219
+
220
+ const WTStorageKeys = {
221
+ DEVICE_ID: "WT.DeviceId",
222
+ INITIAL_DATE: "WT.InitialDate",
223
+ INITIAL_CONFIG: "WT.InitialConfigs",
224
+ CONFIG: "WT.Configs",
225
+ APP_SETTINGS: "WT.AppSettings",
226
+ SDK_CLICK_SUBMIT: "WT.SdkClickSubmit",
227
+ FIRST_SESSION_SUBMIT: "WT.FirstSessionSubmit",
228
+ SDK_ENABLED: "WT.SdkEnabled",
229
+ FCM_TOKEN: "WT.FcmToken", // used for calling push token request
230
+ PUSH_TOKEN: "WT.PushToken", // used in request param fields as "push_token"
231
+ EVENT_COUNT: "WT.EventCount",
232
+ SESSION_COUNT: "WT.SessionCount",
233
+ SESSION_LENGTH: "WT.SessionLenght", // ACTIVE_DURATION
234
+ SUBSESSION_COUNT: "WT.SubSessionCount",
235
+ ACTIVE_TIME: "WT.ActiveTime",
236
+ INACTIVE_TIME: "WT.InactiveTime",
237
+ INACTIVE_DURATION: "WT.InactiveDuration",
238
+ REQUEST_QUEUE: "WT.RequestQueue",
239
+ PENDING_REQUEST_QUEUE: "WT.PendingRequestQueue",
240
+ };
241
+ class StorageManager {
242
+ clear() {
243
+ localStorage.clear();
244
+ }
245
+ setJson(key, obj) {
246
+ if (!obj) {
247
+ localStorage.removeItem(key);
248
+ return;
249
+ }
250
+ try {
251
+ const encoded = JSON.stringify(obj);
252
+ localStorage.setItem(key, encoded);
253
+ }
254
+ catch (error) {
255
+ WTLogger.error(`Error in encoding object for key '${key}'`, error);
256
+ }
257
+ }
258
+ getJson(key) {
259
+ const data = localStorage.getItem(key);
260
+ if (!data) {
261
+ return null;
262
+ }
263
+ try {
264
+ const decoded = JSON.parse(data);
265
+ return decoded;
266
+ }
267
+ catch (error) {
268
+ WTLogger.error(`Error in JSON decoding for key '${key}': ${error}`, error);
269
+ return null;
270
+ }
271
+ }
272
+ optionalNumber(key) {
273
+ const value = localStorage.getItem(key);
274
+ if (value === null) {
275
+ return null;
276
+ }
277
+ const num = Number(value);
278
+ return isNaN(num) ? null : num;
279
+ }
280
+ optionalBool(key) {
281
+ const value = localStorage.getItem(key);
282
+ if (value === null) {
283
+ return null;
284
+ }
285
+ return value === "true" ? true : value === "false" ? false : null;
286
+ }
287
+ get deviceId() {
288
+ return localStorage.getItem(WTStorageKeys.DEVICE_ID);
289
+ }
290
+ set deviceId(value) {
291
+ if (value) {
292
+ localStorage.setItem(WTStorageKeys.DEVICE_ID, value);
293
+ }
294
+ else {
295
+ localStorage.removeItem(WTStorageKeys.DEVICE_ID);
296
+ }
297
+ }
298
+ get initialDate() {
299
+ return this.getJson(WTStorageKeys.INITIAL_DATE);
300
+ }
301
+ set initialDate(value) {
302
+ this.setJson(WTStorageKeys.INITIAL_DATE, value);
303
+ }
304
+ get initialConfig() {
305
+ return this.getJson(WTStorageKeys.INITIAL_CONFIG);
306
+ }
307
+ set initialConfig(value) {
308
+ this.setJson(WTStorageKeys.INITIAL_CONFIG, value);
309
+ }
310
+ get config() {
311
+ return this.getJson(WTStorageKeys.CONFIG);
312
+ }
313
+ set config(value) {
314
+ this.setJson(WTStorageKeys.CONFIG, value);
315
+ }
316
+ get appSettings() {
317
+ return this.getJson(WTStorageKeys.APP_SETTINGS);
318
+ }
319
+ set appSettings(value) {
320
+ this.setJson(WTStorageKeys.APP_SETTINGS, value);
321
+ }
322
+ get sdkEnabled() {
323
+ var _a;
324
+ return (_a = this.optionalBool(WTStorageKeys.SDK_ENABLED)) !== null && _a !== void 0 ? _a : false;
325
+ }
326
+ set sdkEnabled(value) {
327
+ localStorage.setItem(WTStorageKeys.SDK_ENABLED, value.toString());
328
+ }
329
+ get sdkClickSubmit() {
330
+ var _a;
331
+ return (_a = this.optionalBool(WTStorageKeys.SDK_CLICK_SUBMIT)) !== null && _a !== void 0 ? _a : false;
332
+ }
333
+ set sdkClickSubmit(value) {
334
+ localStorage.setItem(WTStorageKeys.SDK_CLICK_SUBMIT, value.toString());
335
+ }
336
+ get firstSessionSubmit() {
337
+ var _a;
338
+ return (_a = this.optionalBool(WTStorageKeys.FIRST_SESSION_SUBMIT)) !== null && _a !== void 0 ? _a : false;
339
+ }
340
+ set firstSessionSubmit(value) {
341
+ localStorage.setItem(WTStorageKeys.FIRST_SESSION_SUBMIT, value.toString());
342
+ }
343
+ get fcmToken() {
344
+ return localStorage.getItem(WTStorageKeys.FCM_TOKEN);
345
+ }
346
+ set fcmToken(value) {
347
+ if (value) {
348
+ localStorage.setItem(WTStorageKeys.FCM_TOKEN, value);
349
+ }
350
+ else {
351
+ localStorage.removeItem(WTStorageKeys.FCM_TOKEN);
352
+ }
353
+ }
354
+ get pushToken() {
355
+ return localStorage.getItem(WTStorageKeys.PUSH_TOKEN);
356
+ }
357
+ set pushToken(value) {
358
+ if (value) {
359
+ localStorage.setItem(WTStorageKeys.PUSH_TOKEN, value);
360
+ }
361
+ else {
362
+ localStorage.removeItem(WTStorageKeys.PUSH_TOKEN);
363
+ }
364
+ }
365
+ get sessionCount() {
366
+ var _a;
367
+ return (_a = this.optionalNumber(WTStorageKeys.SESSION_COUNT)) !== null && _a !== void 0 ? _a : 1;
368
+ }
369
+ set sessionCount(value) {
370
+ localStorage.setItem(WTStorageKeys.SESSION_COUNT, value.toString());
371
+ }
372
+ get subSessionCount() {
373
+ var _a;
374
+ return (_a = this.optionalNumber(WTStorageKeys.SUBSESSION_COUNT)) !== null && _a !== void 0 ? _a : 1;
375
+ }
376
+ set subSessionCount(value) {
377
+ localStorage.setItem(WTStorageKeys.SUBSESSION_COUNT, value.toString());
378
+ }
379
+ get activeDuration() {
380
+ var _a;
381
+ return (_a = this.optionalNumber(WTStorageKeys.SESSION_LENGTH)) !== null && _a !== void 0 ? _a : 0;
382
+ }
383
+ set activeDuration(value) {
384
+ localStorage.setItem(WTStorageKeys.SESSION_LENGTH, value.toString());
385
+ }
386
+ get inactiveDuration() {
387
+ var _a;
388
+ return (_a = this.optionalNumber(WTStorageKeys.INACTIVE_DURATION)) !== null && _a !== void 0 ? _a : 0;
389
+ }
390
+ set inactiveDuration(value) {
391
+ localStorage.setItem(WTStorageKeys.INACTIVE_DURATION, value.toString());
392
+ }
393
+ get inactiveTime() {
394
+ return this.optionalNumber(WTStorageKeys.ACTIVE_TIME);
395
+ }
396
+ set inactiveTime(value) {
397
+ if (value !== null) {
398
+ localStorage.setItem(WTStorageKeys.ACTIVE_TIME, value.toString());
399
+ }
400
+ else {
401
+ localStorage.removeItem(WTStorageKeys.ACTIVE_TIME);
402
+ }
403
+ }
404
+ get activeTime() {
405
+ return this.optionalNumber(WTStorageKeys.INACTIVE_TIME);
406
+ }
407
+ set activeTime(value) {
408
+ if (value !== null) {
409
+ localStorage.setItem(WTStorageKeys.INACTIVE_TIME, value.toString());
410
+ }
411
+ else {
412
+ localStorage.removeItem(WTStorageKeys.INACTIVE_TIME);
413
+ }
414
+ }
415
+ get requestRecords() {
416
+ var _a;
417
+ return (_a = this.getJson(WTStorageKeys.REQUEST_QUEUE)) !== null && _a !== void 0 ? _a : [];
418
+ }
419
+ set requestRecords(value) {
420
+ this.setJson(WTStorageKeys.REQUEST_QUEUE, value);
421
+ }
422
+ get pendingRequestRecords() {
423
+ var _a;
424
+ return (_a = this.getJson(WTStorageKeys.PENDING_REQUEST_QUEUE)) !== null && _a !== void 0 ? _a : [];
425
+ }
426
+ set pendingRequestRecords(value) {
427
+ this.setJson(WTStorageKeys.PENDING_REQUEST_QUEUE, value);
428
+ }
429
+ get eventCount() {
430
+ var _a;
431
+ return (_a = this.optionalNumber(WTStorageKeys.EVENT_COUNT)) !== null && _a !== void 0 ? _a : 0;
432
+ }
433
+ set eventCount(value) {
434
+ localStorage.setItem(WTStorageKeys.EVENT_COUNT, value.toString());
435
+ }
436
+ }
437
+ /** @internal */
438
+ const storageManager = new StorageManager();
439
+
440
+ /** @internal */
441
+ var ApiError;
442
+ (function (ApiError) {
443
+ class InvalidUrl extends Error {
444
+ constructor(url) {
445
+ super(`Invalid URL: ${url}`);
446
+ this.name = "InvalidUrl";
447
+ }
448
+ }
449
+ ApiError.InvalidUrl = InvalidUrl;
450
+ class ServerError extends Error {
451
+ constructor(statusCode, message) {
452
+ super(`ServerError ${statusCode}: ${message}`);
453
+ this.statusCode = statusCode;
454
+ this.message = message;
455
+ this.name = "ServerError";
456
+ }
457
+ }
458
+ ApiError.ServerError = ServerError;
459
+ class NetworkError extends Error {
460
+ constructor(message) {
461
+ super(`NetworkError: ${message}`);
462
+ this.name = "NetworkFailure";
463
+ }
464
+ }
465
+ ApiError.NetworkError = NetworkError;
466
+ class DecodingError extends Error {
467
+ constructor(message) {
468
+ super(`DecodingError: ${message}`);
469
+ this.name = "DecodingError";
470
+ }
471
+ }
472
+ ApiError.DecodingError = DecodingError;
473
+ })(ApiError || (ApiError = {}));
474
+
475
+ /** @internal */
476
+ class RetryPolicy {
477
+ constructor(maxRetries = 3, retryInterval = 2000 // milliseconds
478
+ ) {
479
+ this.maxRetries = maxRetries;
480
+ this.retryInterval = retryInterval;
481
+ }
482
+ canRetry(attempt) {
483
+ return attempt < this.maxRetries;
484
+ }
485
+ waitBeforeRetry() {
486
+ return __awaiter(this, void 0, void 0, function* () {
487
+ return new Promise((res) => setTimeout(res, this.retryInterval));
488
+ });
489
+ }
490
+ }
491
+
492
+ /** @internal */
493
+ const networkManager = {
494
+ retryPolicy() {
495
+ return new RetryPolicy();
496
+ },
497
+ sendRequest(endpoint_1) {
498
+ return __awaiter(this, arguments, void 0, function* (endpoint, options = {}) {
499
+ const retryAttempt = options.retryAttempt || 1;
500
+ WTLogger.debug(`🚀 REQUEST (${retryAttempt}) => ${options.method} ${endpoint}`);
501
+ WTLogger.debug("-- PARAMETERS =>", options.params || options.formData || {});
502
+ let body;
503
+ const requestHeaders = Object.assign({ Accept: "application/json" }, options.headers);
504
+ if (options.formData) {
505
+ const form = new FormData();
506
+ for (const key in options.formData) {
507
+ form.append(key, options.formData[key]);
508
+ }
509
+ body = form;
510
+ }
511
+ else if (options.params) {
512
+ requestHeaders["Content-Type"] = "application/json";
513
+ body = JSON.stringify(options.params);
514
+ }
515
+ try {
516
+ const response = yield fetch(endpoint, {
517
+ method: options.method,
518
+ headers: requestHeaders,
519
+ body,
520
+ });
521
+ if (!response.ok) {
522
+ let json = yield response.json();
523
+ let errorText = json.message || (yield response.text());
524
+ WTLogger.warn(`❌ API ERROR (${response.status}) =>`, errorText);
525
+ throw new ApiError.ServerError(response.status, json.message || "Server error");
526
+ }
527
+ try {
528
+ const result = yield response.json();
529
+ WTLogger.debug(`✅ API SUCCESS (${response.status}) =>`, result.message || "Request successful");
530
+ return result;
531
+ }
532
+ catch (error) {
533
+ throw new ApiError.DecodingError(error.message || String(error));
534
+ }
535
+ }
536
+ catch (err) {
537
+ if (err instanceof ApiError.ServerError ||
538
+ err instanceof ApiError.DecodingError) {
539
+ throw err;
540
+ }
541
+ WTLogger.error("Error executing request", err);
542
+ if (this.retryPolicy().canRetry(retryAttempt)) {
543
+ yield this.retryPolicy().waitBeforeRetry();
544
+ return this.sendRequest(endpoint, Object.assign(Object.assign({}, options), { retryAttempt: retryAttempt + 1 }));
545
+ }
546
+ throw new ApiError.NetworkError(err.message || "Unknown error");
547
+ }
548
+ });
549
+ },
550
+ };
551
+
552
+ /** @internal */
553
+ const apiClient = {
554
+ doGetConfig() {
555
+ return __awaiter(this, void 0, void 0, function* () {
556
+ const initialConfig = storageManager.initialConfig;
557
+ if (!initialConfig) {
558
+ throw "Initial Config is not set";
559
+ }
560
+ const params = {
561
+ app_token: initialConfig.appToken,
562
+ app_version: initialConfig.appVersion,
563
+ framework: initialConfig.appFrameWork,
564
+ env: EnvironmentUtils.sdkEnvironment,
565
+ sdk_hash: WTConstants.SDK.HASH,
566
+ package_name: window.location.hostname,
567
+ platform: WTConstants.SDK.PLATFORM,
568
+ store_name: "other",
569
+ };
570
+ const response = yield networkManager.sendRequest(WTConstants.CONFIG.BASE_URL, {
571
+ method: "POST",
572
+ formData: params,
573
+ });
574
+ return WTConfig.fromJson(response.result);
575
+ });
576
+ },
577
+ doGetAppSettings() {
578
+ return __awaiter(this, void 0, void 0, function* () {
579
+ const initialConfig = storageManager.initialConfig;
580
+ const wtConfig = storageManager.config;
581
+ if (!initialConfig)
582
+ throw "Initial Config is not set";
583
+ if (!wtConfig)
584
+ throw "SDK Config is not set";
585
+ if (!wtConfig.appSettings)
586
+ throw "AppSettings Url is not set";
587
+ const params = {
588
+ app_token: initialConfig.appToken,
589
+ app_version: initialConfig.appVersion,
590
+ framework: initialConfig.appFrameWork,
591
+ env: EnvironmentUtils.sdkEnvironment,
592
+ sdk_hash: WTConstants.SDK.HASH,
593
+ package_name: window.location.hostname,
594
+ platform: WTConstants.SDK.PLATFORM,
595
+ store_name: "other",
596
+ };
597
+ const response = yield networkManager.sendRequest(wtConfig.baseUrl + wtConfig.appSettings, {
598
+ method: "POST",
599
+ formData: params,
600
+ });
601
+ return WTAppSettings.fromJson(response.result);
602
+ });
603
+ },
604
+ doCallRequest(endpoint, params) {
605
+ return __awaiter(this, void 0, void 0, function* () {
606
+ const initialConfig = storageManager.initialConfig;
607
+ const wtConfig = storageManager.config;
608
+ if (!initialConfig)
609
+ throw "Initial Config is not set";
610
+ if (!wtConfig)
611
+ throw "SDK Config is not set";
612
+ params.updated_at = new Date().toISOString();
613
+ const response = yield networkManager.sendRequest(wtConfig.baseUrl + endpoint, {
614
+ method: "POST",
615
+ params: {
616
+ needs_response_details: EnvironmentUtils.sdkEnvironment != WTSDKEnvironment.PRODUCTION,
617
+ parameters: params,
618
+ },
619
+ });
620
+ return response.success;
621
+ });
622
+ },
623
+ };
624
+
625
+ // import { WTLogger } from "./logger";
626
+ class ActivityTicker {
627
+ constructor() {
628
+ this.tickerDelay = 1000;
629
+ this.isPaused = false;
630
+ }
631
+ start() {
632
+ if (this.tickerJob) {
633
+ clearInterval(this.tickerJob);
634
+ }
635
+ this.tickerJob = setInterval(() => {
636
+ if (this.isPaused)
637
+ return;
638
+ if (document.hidden)
639
+ return;
640
+ if (!document.hasFocus())
641
+ return;
642
+ console.log(`ActivityTicker: active duration= ${storageManager.activeDuration / 1000}s, inactive duration= ${storageManager.inactiveDuration / 1000}s`);
643
+ storageManager.activeTime = Date.now();
644
+ storageManager.activeDuration += this.tickerDelay;
645
+ }, this.tickerDelay);
646
+ }
647
+ stop() {
648
+ clearInterval(this.tickerJob);
649
+ this.tickerJob = undefined;
650
+ }
651
+ pause() {
652
+ this.isPaused = true;
653
+ }
654
+ resume() {
655
+ this.isPaused = false;
656
+ }
657
+ }
658
+ /** @internal */
659
+ const activityTicker = new ActivityTicker();
660
+
661
+ /** @internal */
662
+ class CountryFinder {
663
+ constructor() {
664
+ this._country = null;
665
+ }
666
+ getCountryCode() {
667
+ return __awaiter(this, void 0, void 0, function* () {
668
+ if (!this._country) {
669
+ this._country = yield this.tryAllEndpoints();
670
+ }
671
+ return this._country;
672
+ });
673
+ }
674
+ tryAllEndpoints() {
675
+ return __awaiter(this, void 0, void 0, function* () {
676
+ const endpoints = [
677
+ () => __awaiter(this, void 0, void 0, function* () {
678
+ const res = yield this.fetchWithTimeout("https://api.country.is");
679
+ if (!res.ok)
680
+ throw new Error("country.is failed");
681
+ const json = yield res.json();
682
+ return json.country || null;
683
+ }),
684
+ () => __awaiter(this, void 0, void 0, function* () {
685
+ const res = yield this.fetchWithTimeout("https://free.freeipapi.com/api/json");
686
+ if (!res.ok)
687
+ throw new Error("country.is failed");
688
+ const json = yield res.json();
689
+ return json.countryCode || null;
690
+ }),
691
+ () => __awaiter(this, void 0, void 0, function* () {
692
+ const res = yield this.fetchWithTimeout("https://ipwho.is/");
693
+ if (!res.ok)
694
+ throw new Error("ipwho.is failed");
695
+ const json = yield res.json();
696
+ return json.country_code || null;
697
+ }),
698
+ ];
699
+ for (const tryFetch of endpoints) {
700
+ try {
701
+ const countryCode = yield tryFetch();
702
+ if (countryCode)
703
+ return countryCode;
704
+ }
705
+ catch (_) {
706
+ // Try next API
707
+ }
708
+ }
709
+ return null;
710
+ });
711
+ }
712
+ fetchWithTimeout(url_1) {
713
+ return __awaiter(this, arguments, void 0, function* (url, timeout = 2000) {
714
+ const controller = new AbortController();
715
+ const id = setTimeout(() => controller.abort(), timeout);
716
+ return fetch(url, { signal: controller.signal }).finally(() => clearTimeout(id));
717
+ });
718
+ }
719
+ }
720
+ /** @internal */
721
+ const countryFinder = new CountryFinder();
722
+
723
+ /** @internal */
724
+ const cryptoHelper = {
725
+ generateDeviceUUID() {
726
+ return crypto.randomUUID();
727
+ }
728
+ };
729
+
730
+ /** @internal */
731
+ class RequestRecord {
732
+ constructor(endpoint, parameters) {
733
+ this.retryCount = 0;
734
+ this.maxRetries = 3;
735
+ this.id = crypto.randomUUID();
736
+ this.endpoint = endpoint;
737
+ this.parameters = parameters;
738
+ this.createdAt = Date.now();
739
+ }
740
+ }
741
+ /** @internal */
742
+ class Mutex {
743
+ constructor() {
744
+ this.locked = false;
745
+ this.waitingQueue = [];
746
+ }
747
+ acquire() {
748
+ return __awaiter(this, void 0, void 0, function* () {
749
+ return new Promise((resolve) => {
750
+ if (!this.locked) {
751
+ this.locked = true;
752
+ resolve();
753
+ }
754
+ else {
755
+ this.waitingQueue.push(resolve);
756
+ }
757
+ });
758
+ });
759
+ }
760
+ release() {
761
+ if (this.waitingQueue.length > 0) {
762
+ const next = this.waitingQueue.shift();
763
+ next();
764
+ }
765
+ else {
766
+ this.locked = false;
767
+ }
768
+ }
769
+ }
770
+
771
+ /** @internal */
772
+ class RequestsQueueManager {
773
+ constructor() {
774
+ this.isInitialized = false;
775
+ this.isProcessing = false;
776
+ this.isCurrentlyProcessing = false;
777
+ this.mutex = new Mutex();
778
+ this.processingInterval = null;
779
+ this.PROCESSING_INTERVAL_MS = 100; // Check queue every 100ms
780
+ // Backoff strategy properties
781
+ this.failedRequestDelay = 0;
782
+ this.MAX_DELAY_MS = 30000; // 30 seconds max delay
783
+ this.BACKOFF_MULTIPLIER = 2;
784
+ this.BASE_DELAY_MS = 1000; // Start with 1 second
785
+ }
786
+ initialize() {
787
+ return __awaiter(this, void 0, void 0, function* () {
788
+ // Initialize the queue manager if needed
789
+ this.isInitialized = true;
790
+ if (!this.isProcessing) {
791
+ yield this.startProcessing();
792
+ }
793
+ });
794
+ }
795
+ shutdown() {
796
+ return __awaiter(this, void 0, void 0, function* () {
797
+ if (!this.isInitialized) {
798
+ return; // Nothing to shutdown
799
+ }
800
+ yield this.stopProcessing();
801
+ this.isInitialized = false;
802
+ });
803
+ }
804
+ startProcessing() {
805
+ return __awaiter(this, void 0, void 0, function* () {
806
+ if (!this.isInitialized) {
807
+ WTLogger.warn("Queue Manager is not initialized. Call initialize() first.");
808
+ return;
809
+ }
810
+ yield this.mutex.acquire();
811
+ try {
812
+ if (this.isProcessing) {
813
+ return;
814
+ }
815
+ this.isProcessing = true;
816
+ // Start the processing loop
817
+ this.processingInterval = setInterval(() => __awaiter(this, void 0, void 0, function* () {
818
+ try {
819
+ yield this.processQueues();
820
+ }
821
+ catch (error) {
822
+ WTLogger.error("Error in processing loop:", error);
823
+ }
824
+ }), this.PROCESSING_INTERVAL_MS);
825
+ }
826
+ finally {
827
+ this.mutex.release();
828
+ }
829
+ // Process immediately after releasing the mutex
830
+ yield this.processQueues();
831
+ });
832
+ }
833
+ stopProcessing() {
834
+ return __awaiter(this, void 0, void 0, function* () {
835
+ yield this.mutex.acquire();
836
+ try {
837
+ this.isProcessing = false;
838
+ if (this.processingInterval) {
839
+ clearInterval(this.processingInterval);
840
+ this.processingInterval = null;
841
+ }
842
+ }
843
+ finally {
844
+ this.mutex.release();
845
+ }
846
+ });
847
+ }
848
+ addRequest(request) {
849
+ return __awaiter(this, void 0, void 0, function* () {
850
+ yield this.mutex.acquire();
851
+ try {
852
+ const mainQueue = this.getMainQueue();
853
+ mainQueue.push(request);
854
+ this.saveMainQueue(mainQueue);
855
+ // Reset delay when new request is added (optional - gives fresh chance)
856
+ this.failedRequestDelay = 0;
857
+ // Start processing if not already started
858
+ if (!this.isProcessing) {
859
+ // Release mutex before starting processing
860
+ this.mutex.release();
861
+ yield this.startProcessing();
862
+ return; // Exit early since mutex was already released
863
+ }
864
+ }
865
+ finally {
866
+ // Only release if we haven't already released above
867
+ if (this.isProcessing) {
868
+ this.mutex.release();
869
+ }
870
+ }
871
+ });
872
+ }
873
+ addPendingRequest(request) {
874
+ return __awaiter(this, void 0, void 0, function* () {
875
+ yield this.mutex.acquire();
876
+ try {
877
+ const mainRequestsSent = this.getMainRequestsSentFlag();
878
+ if (mainRequestsSent) {
879
+ // Main requests have been sent, add to main queue directly
880
+ const mainQueue = this.getMainQueue();
881
+ mainQueue.push(request);
882
+ this.saveMainQueue(mainQueue);
883
+ }
884
+ else {
885
+ // Main requests not sent yet, add to pending queue
886
+ const pendingQueue = this.getPendingQueue();
887
+ pendingQueue.push(request);
888
+ this.savePendingQueue(pendingQueue);
889
+ }
890
+ // Reset delay when new request is added
891
+ this.failedRequestDelay = 0;
892
+ // Start processing if not already started
893
+ if (!this.isProcessing) {
894
+ // Release mutex before starting processing
895
+ this.mutex.release();
896
+ yield this.startProcessing();
897
+ return; // Exit early since mutex was already released
898
+ }
899
+ }
900
+ finally {
901
+ // Only release if we haven't already released above
902
+ if (this.isProcessing) {
903
+ this.mutex.release();
904
+ }
905
+ }
906
+ });
907
+ }
908
+ processQueues() {
909
+ return __awaiter(this, void 0, void 0, function* () {
910
+ if (!this.isProcessing || this.isCurrentlyProcessing) {
911
+ return;
912
+ }
913
+ // Check if we're in delay period
914
+ if (this.failedRequestDelay > 0) {
915
+ if (Date.now() < this.failedRequestDelay) {
916
+ return; // Still in delay period
917
+ }
918
+ // Delay period ended
919
+ this.failedRequestDelay = 0;
920
+ WTLogger.debug("⏰ Backoff delay ended, resuming queue processing");
921
+ }
922
+ this.isCurrentlyProcessing = true;
923
+ yield this.mutex.acquire();
924
+ try {
925
+ yield this.processMainQueue();
926
+ yield this.processPendingQueue();
927
+ }
928
+ finally {
929
+ this.mutex.release();
930
+ this.isCurrentlyProcessing = false;
931
+ }
932
+ });
933
+ }
934
+ processMainQueue() {
935
+ return __awaiter(this, void 0, void 0, function* () {
936
+ const mainQueue = this.getMainQueue();
937
+ if (mainQueue.length === 0) {
938
+ return;
939
+ }
940
+ // Take the first request
941
+ const request = mainQueue[0];
942
+ try {
943
+ const success = yield this.sendRequest(request);
944
+ if (success) {
945
+ // Remove the processed request from queue
946
+ mainQueue.shift();
947
+ this.saveMainQueue(mainQueue);
948
+ // Set flag that main requests have been sent
949
+ this.postRequestCheck(request);
950
+ WTLogger.debug(`✅ Request ${request.id} processed successfully`);
951
+ }
952
+ else {
953
+ // Update retry count in the queue (not just in memory)
954
+ mainQueue[0].retryCount++;
955
+ if (mainQueue[0].retryCount >= mainQueue[0].maxRetries) {
956
+ // Calculate backoff delay
957
+ const delayMs = this.calculateBackoffDelay(mainQueue[0].retryCount);
958
+ this.failedRequestDelay = Date.now() + delayMs;
959
+ WTLogger.warn(`⏳ Request ${request.id} failed after ${request.maxRetries} attempts. ` +
960
+ `Applying backoff delay of ${delayMs}ms`);
961
+ }
962
+ else {
963
+ WTLogger.warn(`⚠️ Request ${request.id} failed. Retry ${mainQueue[0].retryCount}/${mainQueue[0].maxRetries}`);
964
+ }
965
+ // Save the updated queue with new retry count
966
+ this.saveMainQueue(mainQueue);
967
+ }
968
+ }
969
+ catch (error) {
970
+ WTLogger.error(`Error sending request ${request.endpoint}:`, error);
971
+ // Update retry count in storage
972
+ mainQueue[0].retryCount++;
973
+ if (mainQueue[0].retryCount >= mainQueue[0].maxRetries) {
974
+ // Apply backoff delay instead of removing
975
+ const delayMs = this.calculateBackoffDelay(mainQueue[0].retryCount);
976
+ this.failedRequestDelay = Date.now() + delayMs;
977
+ WTLogger.warn(`⏳ Request ${request.id} failed with error after ${mainQueue[0].maxRetries} attempts. ` +
978
+ `Applying backoff delay of ${delayMs}ms`);
979
+ }
980
+ // Save the updated queue
981
+ this.saveMainQueue(mainQueue);
982
+ }
983
+ });
984
+ }
985
+ calculateBackoffDelay(retryCount) {
986
+ // Exponential backoff: baseDelay * (multiplier ^ (retryCount - 1))
987
+ const delay = this.BASE_DELAY_MS * Math.pow(this.BACKOFF_MULTIPLIER, retryCount - 1);
988
+ return Math.min(delay, this.MAX_DELAY_MS);
989
+ }
990
+ processPendingQueue() {
991
+ return __awaiter(this, void 0, void 0, function* () {
992
+ const mainRequestsSent = this.getMainRequestsSentFlag();
993
+ if (!mainRequestsSent) {
994
+ return; // Main requests haven't been sent yet
995
+ }
996
+ const pendingQueue = this.getPendingQueue();
997
+ if (pendingQueue.length === 0) {
998
+ return;
999
+ }
1000
+ // Move all pending requests to main queue
1001
+ const mainQueue = this.getMainQueue();
1002
+ mainQueue.push(...pendingQueue);
1003
+ // Clear pending queue
1004
+ this.saveMainQueue(mainQueue);
1005
+ this.savePendingQueue([]);
1006
+ console.log(`📦 Moved ${pendingQueue.length} pending requests to main queue`);
1007
+ });
1008
+ }
1009
+ sendRequest(request_1) {
1010
+ return __awaiter(this, arguments, void 0, function* (request, attempt = 1) {
1011
+ WTLogger.debug(`💥 Sending request (${request.endpoint}): id=${request.id}`);
1012
+ let result = false;
1013
+ try {
1014
+ result = yield apiClient.doCallRequest(request.endpoint, request.parameters);
1015
+ }
1016
+ catch (error) {
1017
+ WTLogger.error(`❌ Request ${request.endpoint} failed`, error);
1018
+ }
1019
+ return result;
1020
+ });
1021
+ }
1022
+ getMainQueue() {
1023
+ return storageManager.requestRecords;
1024
+ }
1025
+ saveMainQueue(queue) {
1026
+ storageManager.requestRecords = queue;
1027
+ }
1028
+ getPendingQueue() {
1029
+ return storageManager.pendingRequestRecords;
1030
+ }
1031
+ savePendingQueue(queue) {
1032
+ storageManager.pendingRequestRecords = queue;
1033
+ }
1034
+ getMainRequestsSentFlag() {
1035
+ return storageManager.sdkClickSubmit;
1036
+ }
1037
+ postRequestCheck(request) {
1038
+ switch (request.endpoint) {
1039
+ case WTEndpoints.SDK_CLICKS:
1040
+ storageManager.sdkClickSubmit = true;
1041
+ break;
1042
+ case WTEndpoints.SESSIONS:
1043
+ if (storageManager.firstSessionSubmit) {
1044
+ storageManager.activeDuration = 0;
1045
+ storageManager.inactiveDuration = 0;
1046
+ storageManager.subSessionCount = 1;
1047
+ }
1048
+ else {
1049
+ storageManager.firstSessionSubmit = true;
1050
+ }
1051
+ break;
1052
+ case WTEndpoints.SDK_INFOS:
1053
+ storageManager.fcmToken = request.parameters.push_token;
1054
+ break;
1055
+ }
1056
+ }
1057
+ getQueueStatus() {
1058
+ return {
1059
+ mainQueueLength: this.getMainQueue().length,
1060
+ pendingQueueLength: this.getPendingQueue().length,
1061
+ isProcessing: this.isProcessing,
1062
+ mainRequestsSent: this.getMainRequestsSentFlag(),
1063
+ isInBackoffDelay: this.failedRequestDelay > 0 && Date.now() < this.failedRequestDelay,
1064
+ backoffEndsAt: this.failedRequestDelay > 0 ? this.failedRequestDelay : null,
1065
+ };
1066
+ }
1067
+ /**
1068
+ * Manually reset backoff delay (useful for testing or manual recovery)
1069
+ */
1070
+ resetBackoffDelay() {
1071
+ this.failedRequestDelay = 0;
1072
+ WTLogger.debug("🔄 Backoff delay manually reset");
1073
+ }
1074
+ /**
1075
+ * Get current backoff delay configuration
1076
+ */
1077
+ getBackoffConfig() {
1078
+ return {
1079
+ baseDelayMs: this.BASE_DELAY_MS,
1080
+ multiplier: this.BACKOFF_MULTIPLIER,
1081
+ maxDelayMs: this.MAX_DELAY_MS,
1082
+ };
1083
+ }
1084
+ }
1085
+ /** @internal */
1086
+ const queueManager = new RequestsQueueManager();
1087
+
1088
+ // Generated ESM version of ua-parser-js
1089
+ // DO NOT EDIT THIS FILE!
1090
+ // Source: /src/main/ua-parser.js
1091
+
1092
+ /////////////////////////////////////////////////////////////////////////////////
1093
+ /* UAParser.js v2.0.4
1094
+ Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
1095
+ AGPLv3 License *//*
1096
+ Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
1097
+ Supports browser & node.js environment.
1098
+ Demo : https://uaparser.dev
1099
+ Source : https://github.com/faisalman/ua-parser-js */
1100
+ /////////////////////////////////////////////////////////////////////////////////
1101
+
1102
+ /* jshint esversion: 6 */
1103
+ /* globals window */
1104
+
1105
+
1106
+
1107
+ //////////////
1108
+ // Constants
1109
+ /////////////
1110
+
1111
+ var LIBVERSION = '2.0.4',
1112
+ UA_MAX_LENGTH = 500,
1113
+ USER_AGENT = 'user-agent',
1114
+ EMPTY = '',
1115
+ UNKNOWN = '?',
1116
+
1117
+ // typeof
1118
+ FUNC_TYPE = 'function',
1119
+ UNDEF_TYPE = 'undefined',
1120
+ OBJ_TYPE = 'object',
1121
+ STR_TYPE = 'string',
1122
+
1123
+ // properties
1124
+ UA_BROWSER = 'browser',
1125
+ UA_CPU = 'cpu',
1126
+ UA_DEVICE = 'device',
1127
+ UA_ENGINE = 'engine',
1128
+ UA_OS = 'os',
1129
+ UA_RESULT = 'result',
1130
+
1131
+ NAME = 'name',
1132
+ TYPE = 'type',
1133
+ VENDOR = 'vendor',
1134
+ VERSION = 'version',
1135
+ ARCHITECTURE= 'architecture',
1136
+ MAJOR = 'major',
1137
+ MODEL = 'model',
1138
+
1139
+ // device types
1140
+ CONSOLE = 'console',
1141
+ MOBILE = 'mobile',
1142
+ TABLET = 'tablet',
1143
+ SMARTTV = 'smarttv',
1144
+ WEARABLE = 'wearable',
1145
+ XR = 'xr',
1146
+ EMBEDDED = 'embedded',
1147
+
1148
+ // browser types
1149
+ INAPP = 'inapp',
1150
+
1151
+ // client hints
1152
+ BRANDS = 'brands',
1153
+ FORMFACTORS = 'formFactors',
1154
+ FULLVERLIST = 'fullVersionList',
1155
+ PLATFORM = 'platform',
1156
+ PLATFORMVER = 'platformVersion',
1157
+ BITNESS = 'bitness',
1158
+ CH_HEADER = 'sec-ch-ua',
1159
+ CH_HEADER_FULL_VER_LIST = CH_HEADER + '-full-version-list',
1160
+ CH_HEADER_ARCH = CH_HEADER + '-arch',
1161
+ CH_HEADER_BITNESS = CH_HEADER + '-' + BITNESS,
1162
+ CH_HEADER_FORM_FACTORS = CH_HEADER + '-form-factors',
1163
+ CH_HEADER_MOBILE = CH_HEADER + '-' + MOBILE,
1164
+ CH_HEADER_MODEL = CH_HEADER + '-' + MODEL,
1165
+ CH_HEADER_PLATFORM = CH_HEADER + '-' + PLATFORM,
1166
+ CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + '-version',
1167
+ CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],
1168
+
1169
+ // device vendors
1170
+ AMAZON = 'Amazon',
1171
+ APPLE = 'Apple',
1172
+ ASUS = 'ASUS',
1173
+ BLACKBERRY = 'BlackBerry',
1174
+ GOOGLE = 'Google',
1175
+ HUAWEI = 'Huawei',
1176
+ LENOVO = 'Lenovo',
1177
+ HONOR = 'Honor',
1178
+ LG = 'LG',
1179
+ MICROSOFT = 'Microsoft',
1180
+ MOTOROLA = 'Motorola',
1181
+ NVIDIA = 'Nvidia',
1182
+ ONEPLUS = 'OnePlus',
1183
+ OPPO = 'OPPO',
1184
+ SAMSUNG = 'Samsung',
1185
+ SHARP = 'Sharp',
1186
+ SONY = 'Sony',
1187
+ XIAOMI = 'Xiaomi',
1188
+ ZEBRA = 'Zebra',
1189
+
1190
+ // browsers
1191
+ CHROME = 'Chrome',
1192
+ CHROMIUM = 'Chromium',
1193
+ CHROMECAST = 'Chromecast',
1194
+ EDGE = 'Edge',
1195
+ FIREFOX = 'Firefox',
1196
+ OPERA = 'Opera',
1197
+ FACEBOOK = 'Facebook',
1198
+ SOGOU = 'Sogou',
1199
+
1200
+ PREFIX_MOBILE = 'Mobile ',
1201
+ SUFFIX_BROWSER = ' Browser',
1202
+
1203
+ // os
1204
+ WINDOWS = 'Windows';
1205
+
1206
+ var isWindow = typeof window !== UNDEF_TYPE,
1207
+ NAVIGATOR = (isWindow && window.navigator) ?
1208
+ window.navigator :
1209
+ undefined,
1210
+ NAVIGATOR_UADATA = (NAVIGATOR && NAVIGATOR.userAgentData) ?
1211
+ NAVIGATOR.userAgentData :
1212
+ undefined;
1213
+
1214
+ ///////////
1215
+ // Helper
1216
+ //////////
1217
+
1218
+ var extend = function (defaultRgx, extensions) {
1219
+ var mergedRgx = {};
1220
+ var extraRgx = extensions;
1221
+ if (!isExtensions(extensions)) {
1222
+ extraRgx = {};
1223
+ for (var i in extensions) {
1224
+ for (var j in extensions[i]) {
1225
+ extraRgx[j] = extensions[i][j].concat(extraRgx[j] ? extraRgx[j] : []);
1226
+ }
1227
+ }
1228
+ }
1229
+ for (var k in defaultRgx) {
1230
+ mergedRgx[k] = extraRgx[k] && extraRgx[k].length % 2 === 0 ? extraRgx[k].concat(defaultRgx[k]) : defaultRgx[k];
1231
+ }
1232
+ return mergedRgx;
1233
+ },
1234
+ enumerize = function (arr) {
1235
+ var enums = {};
1236
+ for (var i=0; i<arr.length; i++) {
1237
+ enums[arr[i].toUpperCase()] = arr[i];
1238
+ }
1239
+ return enums;
1240
+ },
1241
+ has = function (str1, str2) {
1242
+ if (typeof str1 === OBJ_TYPE && str1.length > 0) {
1243
+ for (var i in str1) {
1244
+ if (lowerize(str2) == lowerize(str1[i])) return true;
1245
+ }
1246
+ return false;
1247
+ }
1248
+ return isString(str1) ? lowerize(str2) == lowerize(str1) : false;
1249
+ },
1250
+ isExtensions = function (obj, deep) {
1251
+ for (var prop in obj) {
1252
+ return /^(browser|cpu|device|engine|os)$/.test(prop) || (deep ? isExtensions(obj[prop]) : false);
1253
+ }
1254
+ },
1255
+ isString = function (val) {
1256
+ return typeof val === STR_TYPE;
1257
+ },
1258
+ itemListToArray = function (header) {
1259
+ if (!header) return undefined;
1260
+ var arr = [];
1261
+ var tokens = strip(/\\?\"/g, header).split(',');
1262
+ for (var i = 0; i < tokens.length; i++) {
1263
+ if (tokens[i].indexOf(';') > -1) {
1264
+ var token = trim(tokens[i]).split(';v=');
1265
+ arr[i] = { brand : token[0], version : token[1] };
1266
+ } else {
1267
+ arr[i] = trim(tokens[i]);
1268
+ }
1269
+ }
1270
+ return arr;
1271
+ },
1272
+ lowerize = function (str) {
1273
+ return isString(str) ? str.toLowerCase() : str;
1274
+ },
1275
+ majorize = function (version) {
1276
+ return isString(version) ? strip(/[^\d\.]/g, version).split('.')[0] : undefined;
1277
+ },
1278
+ setProps = function (arr) {
1279
+ for (var i in arr) {
1280
+ var propName = arr[i];
1281
+ if (typeof propName == OBJ_TYPE && propName.length == 2) {
1282
+ this[propName[0]] = propName[1];
1283
+ } else {
1284
+ this[propName] = undefined;
1285
+ }
1286
+ }
1287
+ return this;
1288
+ },
1289
+ strip = function (pattern, str) {
1290
+ return isString(str) ? str.replace(pattern, EMPTY) : str;
1291
+ },
1292
+ stripQuotes = function (str) {
1293
+ return strip(/\\?\"/g, str);
1294
+ },
1295
+ trim = function (str, len) {
1296
+ if (isString(str)) {
1297
+ str = strip(/^\s\s*/, str);
1298
+ return typeof len === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
1299
+ }
1300
+ };
1301
+
1302
+ ///////////////
1303
+ // Map helper
1304
+ //////////////
1305
+
1306
+ var rgxMapper = function (ua, arrays) {
1307
+
1308
+ if(!ua || !arrays) return;
1309
+
1310
+ var i = 0, j, k, p, q, matches, match;
1311
+
1312
+ // loop through all regexes maps
1313
+ while (i < arrays.length && !matches) {
1314
+
1315
+ var regex = arrays[i], // even sequence (0,2,4,..)
1316
+ props = arrays[i + 1]; // odd sequence (1,3,5,..)
1317
+ j = k = 0;
1318
+
1319
+ // try matching uastring with regexes
1320
+ while (j < regex.length && !matches) {
1321
+
1322
+ if (!regex[j]) { break; }
1323
+ matches = regex[j++].exec(ua);
1324
+
1325
+ if (!!matches) {
1326
+ for (p = 0; p < props.length; p++) {
1327
+ match = matches[++k];
1328
+ q = props[p];
1329
+ // check if given property is actually array
1330
+ if (typeof q === OBJ_TYPE && q.length > 0) {
1331
+ if (q.length === 2) {
1332
+ if (typeof q[1] == FUNC_TYPE) {
1333
+ // assign modified match
1334
+ this[q[0]] = q[1].call(this, match);
1335
+ } else {
1336
+ // assign given value, ignore regex match
1337
+ this[q[0]] = q[1];
1338
+ }
1339
+ } else if (q.length >= 3) {
1340
+ // Check whether q[1] FUNCTION or REGEX
1341
+ if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {
1342
+ if (q.length > 3) {
1343
+ this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined;
1344
+ } else {
1345
+ // call function (usually string mapper)
1346
+ this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;
1347
+ }
1348
+ } else {
1349
+ if (q.length == 3) {
1350
+ // sanitize match using given regex
1351
+ this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;
1352
+ } else if (q.length == 4) {
1353
+ this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
1354
+ } else if (q.length > 4) {
1355
+ this[q[0]] = match ? q[3].apply(this, [match.replace(q[1], q[2])].concat(q.slice(4))) : undefined;
1356
+ }
1357
+ }
1358
+ }
1359
+ } else {
1360
+ this[q] = match ? match : undefined;
1361
+ }
1362
+ }
1363
+ }
1364
+ }
1365
+ i += 2;
1366
+ }
1367
+ },
1368
+
1369
+ strMapper = function (str, map) {
1370
+
1371
+ for (var i in map) {
1372
+ // check if current value is array
1373
+ if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {
1374
+ for (var j = 0; j < map[i].length; j++) {
1375
+ if (has(map[i][j], str)) {
1376
+ return (i === UNKNOWN) ? undefined : i;
1377
+ }
1378
+ }
1379
+ } else if (has(map[i], str)) {
1380
+ return (i === UNKNOWN) ? undefined : i;
1381
+ }
1382
+ }
1383
+ return map.hasOwnProperty('*') ? map['*'] : str;
1384
+ };
1385
+
1386
+ ///////////////
1387
+ // String map
1388
+ //////////////
1389
+
1390
+ var windowsVersionMap = {
1391
+ 'ME' : '4.90',
1392
+ 'NT 3.51': '3.51',
1393
+ 'NT 4.0': '4.0',
1394
+ '2000' : ['5.0', '5.01'],
1395
+ 'XP' : ['5.1', '5.2'],
1396
+ 'Vista' : '6.0',
1397
+ '7' : '6.1',
1398
+ '8' : '6.2',
1399
+ '8.1' : '6.3',
1400
+ '10' : ['6.4', '10.0'],
1401
+ 'NT' : ''
1402
+ },
1403
+
1404
+ formFactorsMap = {
1405
+ 'embedded' : 'Automotive',
1406
+ 'mobile' : 'Mobile',
1407
+ 'tablet' : ['Tablet', 'EInk'],
1408
+ 'smarttv' : 'TV',
1409
+ 'wearable' : 'Watch',
1410
+ 'xr' : ['VR', 'XR'],
1411
+ '?' : ['Desktop', 'Unknown'],
1412
+ '*' : undefined
1413
+ },
1414
+
1415
+ browserHintsMap = {
1416
+ 'Chrome' : 'Google Chrome',
1417
+ 'Edge' : 'Microsoft Edge',
1418
+ 'Edge WebView2' : 'Microsoft Edge WebView2',
1419
+ 'Chrome WebView': 'Android WebView',
1420
+ 'Chrome Headless':'HeadlessChrome',
1421
+ 'Huawei Browser': 'HuaweiBrowser',
1422
+ 'MIUI Browser' : 'Miui Browser',
1423
+ 'Opera Mobi' : 'OperaMobile',
1424
+ 'Yandex' : 'YaBrowser'
1425
+ };
1426
+
1427
+ //////////////
1428
+ // Regex map
1429
+ /////////////
1430
+
1431
+ var defaultRegexes = {
1432
+
1433
+ browser : [[
1434
+
1435
+ // Most common regardless engine
1436
+ /\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS
1437
+ ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [
1438
+ /webview.+edge\/([\w\.]+)/i // Microsoft Edge
1439
+ ], [VERSION, [NAME, EDGE+' WebView']], [
1440
+ /edg(?:e|ios|a)?\/([\w\.]+)/i
1441
+ ], [VERSION, [NAME, 'Edge']], [
1442
+
1443
+ // Presto based
1444
+ /(opera mini)\/([-\w\.]+)/i, // Opera Mini
1445
+ /(opera [mobiletab]{3,6})\b.+version\/([-\w\.]+)/i, // Opera Mobi/Tablet
1446
+ /(opera)(?:.+version\/|[\/ ]+)([\w\.]+)/i // Opera
1447
+ ], [NAME, VERSION], [
1448
+ /opios[\/ ]+([\w\.]+)/i // Opera mini on iphone >= 8.0
1449
+ ], [VERSION, [NAME, OPERA+' Mini']], [
1450
+ /\bop(?:rg)?x\/([\w\.]+)/i // Opera GX
1451
+ ], [VERSION, [NAME, OPERA+' GX']], [
1452
+ /\bopr\/([\w\.]+)/i // Opera Webkit
1453
+ ], [VERSION, [NAME, OPERA]], [
1454
+
1455
+ // Mixed
1456
+ /\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i // Baidu
1457
+ ], [VERSION, [NAME, 'Baidu']], [
1458
+ /\b(?:mxbrowser|mxios|myie2)\/?([-\w\.]*)\b/i // Maxthon
1459
+ ], [VERSION, [NAME, 'Maxthon']], [
1460
+ /(kindle)\/([\w\.]+)/i, // Kindle
1461
+ /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\/ ]?([\w\.]*)/i,
1462
+ // Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir
1463
+ // Trident based
1464
+ /(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet
1465
+ /(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
1466
+
1467
+ // Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble
1468
+ /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:lg |qute)browser)\/([-\w\.]+)/i,
1469
+ // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon
1470
+ /(heytap|ovi|115|surf)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf
1471
+ /(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i // Ecosia/Weibo
1472
+ ], [NAME, VERSION], [
1473
+ /quark(?:pc)?\/([-\w\.]+)/i // Quark
1474
+ ], [VERSION, [NAME, 'Quark']], [
1475
+ /\bddg\/([\w\.]+)/i // DuckDuckGo
1476
+ ], [VERSION, [NAME, 'DuckDuckGo']], [
1477
+ /(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser
1478
+ ], [VERSION, [NAME, 'UCBrowser']], [
1479
+ /microm.+\bqbcore\/([\w\.]+)/i, // WeChat Desktop for Windows Built-in Browser
1480
+ /\bqbcore\/([\w\.]+).+microm/i,
1481
+ /micromessenger\/([\w\.]+)/i // WeChat
1482
+ ], [VERSION, [NAME, 'WeChat']], [
1483
+ /konqueror\/([\w\.]+)/i // Konqueror
1484
+ ], [VERSION, [NAME, 'Konqueror']], [
1485
+ /trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i // IE11
1486
+ ], [VERSION, [NAME, 'IE']], [
1487
+ /ya(?:search)?browser\/([\w\.]+)/i // Yandex
1488
+ ], [VERSION, [NAME, 'Yandex']], [
1489
+ /slbrowser\/([\w\.]+)/i // Smart Lenovo Browser
1490
+ ], [VERSION, [NAME, 'Smart ' + LENOVO + SUFFIX_BROWSER]], [
1491
+ /(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure Browser
1492
+ ], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [
1493
+ /\bfocus\/([\w\.]+)/i // Firefox Focus
1494
+ ], [VERSION, [NAME, FIREFOX+' Focus']], [
1495
+ /\bopt\/([\w\.]+)/i // Opera Touch
1496
+ ], [VERSION, [NAME, OPERA+' Touch']], [
1497
+ /coc_coc\w+\/([\w\.]+)/i // Coc Coc Browser
1498
+ ], [VERSION, [NAME, 'Coc Coc']], [
1499
+ /dolfin\/([\w\.]+)/i // Dolphin
1500
+ ], [VERSION, [NAME, 'Dolphin']], [
1501
+ /coast\/([\w\.]+)/i // Opera Coast
1502
+ ], [VERSION, [NAME, OPERA+' Coast']], [
1503
+ /miuibrowser\/([\w\.]+)/i // MIUI Browser
1504
+ ], [VERSION, [NAME, 'MIUI' + SUFFIX_BROWSER]], [
1505
+ /fxios\/([\w\.-]+)/i // Firefox for iOS
1506
+ ], [VERSION, [NAME, PREFIX_MOBILE + FIREFOX]], [
1507
+ /\bqihoobrowser\/?([\w\.]*)/i // 360
1508
+ ], [VERSION, [NAME, '360']], [
1509
+ /\b(qq)\/([\w\.]+)/i // QQ
1510
+ ], [[NAME, /(.+)/, '$1Browser'], VERSION], [
1511
+ /(oculus|sailfish|huawei|vivo|pico)browser\/([\w\.]+)/i
1512
+ ], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [ // Oculus/Sailfish/HuaweiBrowser/VivoBrowser/PicoBrowser
1513
+ /samsungbrowser\/([\w\.]+)/i // Samsung Internet
1514
+ ], [VERSION, [NAME, SAMSUNG + ' Internet']], [
1515
+ /metasr[\/ ]?([\d\.]+)/i // Sogou Explorer
1516
+ ], [VERSION, [NAME, SOGOU + ' Explorer']], [
1517
+ /(sogou)mo\w+\/([\d\.]+)/i // Sogou Mobile
1518
+ ], [[NAME, SOGOU + ' Mobile'], VERSION], [
1519
+ /(electron)\/([\w\.]+) safari/i, // Electron-based App
1520
+ /(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i, // Tesla
1521
+ /m?(qqbrowser|2345(?=browser|chrome|explorer))\w*[\/ ]?v?([\w\.]+)/i // QQ/2345
1522
+ ], [NAME, VERSION], [
1523
+ /(lbbrowser|rekonq)/i // LieBao Browser/Rekonq
1524
+ ], [NAME], [
1525
+ /ome\/([\w\.]+) \w* ?(iron) saf/i, // Iron
1526
+ /ome\/([\w\.]+).+qihu (360)[es]e/i // 360
1527
+ ], [VERSION, NAME], [
1528
+
1529
+ // WebView
1530
+ /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android
1531
+ ], [[NAME, FACEBOOK], VERSION, [TYPE, INAPP]], [
1532
+ /(kakao(?:talk|story))[\/ ]([\w\.]+)/i, // Kakao App
1533
+ /(naver)\(.*?(\d+\.[\w\.]+).*\)/i, // Naver InApp
1534
+ /(daum)apps[\/ ]([\w\.]+)/i, // Daum App
1535
+ /safari (line)\/([\w\.]+)/i, // Line App for iOS
1536
+ /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android
1537
+ /(alipay)client\/([\w\.]+)/i, // Alipay
1538
+ /(twitter)(?:and| f.+e\/([\w\.]+))/i, // Twitter
1539
+ /(instagram|snapchat|klarna)[\/ ]([-\w\.]+)/i // Instagram/Snapchat/Klarna
1540
+ ], [NAME, VERSION, [TYPE, INAPP]], [
1541
+ /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
1542
+ ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [
1543
+ /musical_ly(?:.+app_?version\/|_)([\w\.]+)/i // TikTok
1544
+ ], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [
1545
+ /\[(linkedin)app\]/i // LinkedIn App for iOS & Android
1546
+ ], [NAME, [TYPE, INAPP]], [
1547
+
1548
+ /(chromium)[\/ ]([-\w\.]+)/i // Chromium
1549
+ ], [NAME, VERSION], [
1550
+
1551
+ /headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless
1552
+ ], [VERSION, [NAME, CHROME+' Headless']], [
1553
+
1554
+ /wv\).+chrome\/([\w\.]+).+edgw\//i // Edge WebView2
1555
+ ], [VERSION, [NAME, EDGE+' WebView2']], [
1556
+
1557
+ / wv\).+(chrome)\/([\w\.]+)/i // Chrome WebView
1558
+ ], [[NAME, CHROME+' WebView'], VERSION], [
1559
+
1560
+ /droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i // Android Browser
1561
+ ], [VERSION, [NAME, 'Android' + SUFFIX_BROWSER]], [
1562
+
1563
+ /chrome\/([\w\.]+) mobile/i // Chrome Mobile
1564
+ ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [
1565
+
1566
+ /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia
1567
+ ], [NAME, VERSION], [
1568
+
1569
+ /version\/([\w\.\,]+) .*mobile(?:\/\w+ | ?)safari/i // Safari Mobile
1570
+ ], [VERSION, [NAME, PREFIX_MOBILE + 'Safari']], [
1571
+ /iphone .*mobile(?:\/\w+ | ?)safari/i
1572
+ ], [[NAME, PREFIX_MOBILE + 'Safari']], [
1573
+ /version\/([\w\.\,]+) .*(safari)/i // Safari
1574
+ ], [VERSION, NAME], [
1575
+ /webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
1576
+ ], [NAME, [VERSION, '1']], [
1577
+
1578
+ /(webkit|khtml)\/([\w\.]+)/i
1579
+ ], [NAME, VERSION], [
1580
+
1581
+ // Gecko based
1582
+ /(?:mobile|tablet);.*(firefox)\/([\w\.-]+)/i // Firefox Mobile
1583
+ ], [[NAME, PREFIX_MOBILE + FIREFOX], VERSION], [
1584
+ /(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape
1585
+ ], [[NAME, 'Netscape'], VERSION], [
1586
+ /(wolvic|librewolf)\/([\w\.]+)/i // Wolvic/LibreWolf
1587
+ ], [NAME, VERSION], [
1588
+ /mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality
1589
+ ], [VERSION, [NAME, FIREFOX+' Reality']], [
1590
+ /ekiohf.+(flow)\/([\w\.]+)/i, // Flow
1591
+ /(swiftfox)/i, // Swiftfox
1592
+ /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,
1593
+ // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
1594
+ /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
1595
+ // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
1596
+ /(firefox)\/([\w\.]+)/i, // Other Firefox-based
1597
+ /(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i, // Mozilla
1598
+
1599
+ // Other
1600
+ /(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
1601
+ // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser/Ladybird
1602
+ /\b(links) \(([\w\.]+)/i // Links
1603
+ ], [NAME, [VERSION, /_/g, '.']], [
1604
+
1605
+ /(cobalt)\/([\w\.]+)/i // Cobalt
1606
+ ], [NAME, [VERSION, /[^\d\.]+./, EMPTY]]
1607
+ ],
1608
+
1609
+ cpu : [[
1610
+
1611
+ /\b((amd|x|x86[-_]?|wow|win)64)\b/i // AMD64 (x64)
1612
+ ], [[ARCHITECTURE, 'amd64']], [
1613
+
1614
+ /(ia32(?=;))/i, // IA32 (quicktime)
1615
+ /\b((i[346]|x)86)(pc)?\b/i // IA32 (x86)
1616
+ ], [[ARCHITECTURE, 'ia32']], [
1617
+
1618
+ /\b(aarch64|arm(v?[89]e?l?|_?64))\b/i // ARM64
1619
+ ], [[ARCHITECTURE, 'arm64']], [
1620
+
1621
+ /\b(arm(v[67])?ht?n?[fl]p?)\b/i // ARMHF
1622
+ ], [[ARCHITECTURE, 'armhf']], [
1623
+
1624
+ // PocketPC mistakenly identified as PowerPC
1625
+ /( (ce|mobile); ppc;|\/[\w\.]+arm\b)/i
1626
+ ], [[ARCHITECTURE, 'arm']], [
1627
+
1628
+ /((ppc|powerpc)(64)?)( mac|;|\))/i // PowerPC
1629
+ ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [
1630
+
1631
+ / sun4\w[;\)]/i // SPARC
1632
+ ], [[ARCHITECTURE, 'sparc']], [
1633
+
1634
+ /\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i
1635
+ // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
1636
+ ], [[ARCHITECTURE, lowerize]]
1637
+ ],
1638
+
1639
+ device : [[
1640
+
1641
+ //////////////////////////
1642
+ // MOBILES & TABLETS
1643
+ /////////////////////////
1644
+
1645
+ // Samsung
1646
+ /\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i
1647
+ ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [
1648
+ /\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i,
1649
+ /samsung[- ]((?!sm-[lr]|browser)[-\w]+)/i,
1650
+ /sec-(sgh\w+)/i
1651
+ ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
1652
+
1653
+ // Apple
1654
+ /(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i // iPod/iPhone
1655
+ ], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [
1656
+ /\((ipad);[-\w\),; ]+apple/i, // iPad
1657
+ /applecoremedia\/[\w\.]+ \((ipad)/i,
1658
+ /\b(ipad)\d\d?,\d\d?[;\]].+ios/i
1659
+ ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [
1660
+ /(macintosh);/i
1661
+ ], [MODEL, [VENDOR, APPLE]], [
1662
+
1663
+ // Sharp
1664
+ /\b(sh-?[altvz]?\d\d[a-ekm]?)/i
1665
+ ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [
1666
+
1667
+ // Honor
1668
+ /\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\)|;)/i
1669
+ ], [MODEL, [VENDOR, HONOR], [TYPE, TABLET]], [
1670
+ /honor([-\w ]+)[;\)]/i
1671
+ ], [MODEL, [VENDOR, HONOR], [TYPE, MOBILE]], [
1672
+
1673
+ // Huawei
1674
+ /\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\w\. ]*(?= bui|\)))\b(?!.+d\/s)/i
1675
+ ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [
1676
+ /(?:huawei)([-\w ]+)[;\)]/i,
1677
+ /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i
1678
+ ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [
1679
+
1680
+ // Xiaomi
1681
+ /oid[^\)]+; (2[\dbc]{4}(182|283|rp\w{2})[cgl]|m2105k81a?c)(?: bui|\))/i,
1682
+ /\b((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i // Mi Pad tablets
1683
+ ],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
1684
+
1685
+ /\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i, // Xiaomi POCO
1686
+ /\b; (\w+) build\/hm\1/i, // Xiaomi Hongmi 'numeric' models
1687
+ /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi
1688
+ /\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi
1689
+ /oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i, // Xiaomi Redmi 'numeric' models
1690
+ /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite|pro)?)(?: bui|\))/i, // Xiaomi Mi
1691
+ / ([\w ]+) miui\/v?\d/i
1692
+ ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
1693
+
1694
+ // OnePlus
1695
+ /droid.+; (cph2[3-6]\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\d|p[g-k]\w[1m]10)\b/i,
1696
+ /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
1697
+ ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [
1698
+
1699
+ // OPPO
1700
+ /; (\w+) bui.+ oppo/i,
1701
+ /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i
1702
+ ], [MODEL, [VENDOR, OPPO], [TYPE, MOBILE]], [
1703
+ /\b(opd2(\d{3}a?))(?: bui|\))/i
1704
+ ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['203', '304', '403', '404', '413', '415'], '*' : OPPO }], [TYPE, TABLET]], [
1705
+
1706
+ // BLU
1707
+ /(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i // Vivo series
1708
+ ], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [
1709
+
1710
+ // Vivo
1711
+ /; vivo (\w+)(?: bui|\))/i,
1712
+ /\b(v[12]\d{3}\w?[at])(?: bui|;)/i
1713
+ ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [
1714
+
1715
+ // Realme
1716
+ /\b(rmx[1-3]\d{3})(?: bui|;|\))/i
1717
+ ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [
1718
+
1719
+ // Lenovo
1720
+ /(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i,
1721
+ /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i
1722
+ ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [
1723
+ /lenovo[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i
1724
+ ], [MODEL, [VENDOR, LENOVO], [TYPE, MOBILE]], [
1725
+
1726
+ // Motorola
1727
+ /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
1728
+ /\bmot(?:orola)?[- ]([\w\s]+)(\)| bui)/i,
1729
+ /((?:moto(?! 360)[-\w\(\) ]+|xt\d{3,4}[cgkosw\+]?[-\d]*|nexus 6)(?= bui|\)))/i
1730
+ ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [
1731
+ /\b(mz60\d|xoom[2 ]{0,2}) build\//i
1732
+ ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [
1733
+
1734
+ // LG
1735
+ /((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i
1736
+ ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [
1737
+ /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
1738
+ /\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i,
1739
+ /\blg-?([\d\w]+) bui/i
1740
+ ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [
1741
+
1742
+ // Nokia
1743
+ /(nokia) (t[12][01])/i
1744
+ ], [VENDOR, MODEL, [TYPE, TABLET]], [
1745
+ /(?:maemo|nokia).*(n900|lumia \d+|rm-\d+)/i,
1746
+ /nokia[-_ ]?(([-\w\. ]*))/i
1747
+ ], [[MODEL, /_/g, ' '], [TYPE, MOBILE], [VENDOR, 'Nokia']], [
1748
+
1749
+ // Google
1750
+ /(pixel (c|tablet))\b/i // Google Pixel C/Tablet
1751
+ ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [
1752
+ // Google Pixel
1753
+ /droid.+;(?: google)? (g(01[13]a|020[aem]|025[jn]|1b60|1f8f|2ybb|4s1m|576d|5nz6|8hhn|8vou|a02099|c15s|d1yq|e2ae|ec77|gh2x|kv4x|p4bc|pj41|r83y|tt9q|ur25|wvk6)|pixel[\d ]*a?( pro)?( xl)?( fold)?( \(5g\))?)( bui|\))/i
1754
+ ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [
1755
+ /(google) (pixelbook( go)?)/i
1756
+ ], [VENDOR, MODEL], [
1757
+
1758
+ // Sony
1759
+ /droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-\w\w\d\d)(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i
1760
+ ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [
1761
+ /sony tablet [ps]/i,
1762
+ /\b(?:sony)?sgp\w+(?: bui|\))/i
1763
+ ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [
1764
+
1765
+ // Amazon
1766
+ /(alexa)webm/i,
1767
+ /(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i, // Kindle Fire without Silk / Echo Show
1768
+ /(kf[a-z]+)( bui|\)).+silk\//i // Kindle Fire HD
1769
+ ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [
1770
+ /((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i // Fire Phone
1771
+ ], [[MODEL, /(.+)/g, 'Fire Phone $1'], [VENDOR, AMAZON], [TYPE, MOBILE]], [
1772
+
1773
+ // BlackBerry
1774
+ /(playbook);[-\w\),; ]+(rim)/i // BlackBerry PlayBook
1775
+ ], [MODEL, VENDOR, [TYPE, TABLET]], [
1776
+ /\b((?:bb[a-f]|st[hv])100-\d)/i,
1777
+ /\(bb10; (\w+)/i // BlackBerry 10
1778
+ ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [
1779
+
1780
+ // Asus
1781
+ /(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i
1782
+ ], [MODEL, [VENDOR, ASUS], [TYPE, TABLET]], [
1783
+ / (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i
1784
+ ], [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]], [
1785
+
1786
+ // HTC
1787
+ /(nexus 9)/i // HTC Nexus 9
1788
+ ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [
1789
+ /(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i, // HTC
1790
+
1791
+ // ZTE
1792
+ /(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,
1793
+ /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony
1794
+ ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [
1795
+
1796
+ // TCL
1797
+ /tcl (xess p17aa)/i,
1798
+ /droid [\w\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])(_\w(\w|\w\w))?(\)| bui)/i
1799
+ ], [MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]], [
1800
+ /droid [\w\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\w(\w|\w\w))?(\)| bui)/i
1801
+ ], [MODEL, [VENDOR, 'TCL'], [TYPE, MOBILE]], [
1802
+
1803
+ // itel
1804
+ /(itel) ((\w+))/i
1805
+ ], [[VENDOR, lowerize], MODEL, [TYPE, strMapper, { 'tablet' : ['p10001l', 'w7001'], '*' : 'mobile' }]], [
1806
+
1807
+ // Acer
1808
+ /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i
1809
+ ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [
1810
+
1811
+ // Meizu
1812
+ /droid.+; (m[1-5] note) bui/i,
1813
+ /\bmz-([-\w]{2,})/i
1814
+ ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [
1815
+
1816
+ // Ulefone
1817
+ /; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i
1818
+ ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [
1819
+
1820
+ // Energizer
1821
+ /; (energy ?\w+)(?: bui|\))/i,
1822
+ /; energizer ([\w ]+)(?: bui|\))/i
1823
+ ], [MODEL, [VENDOR, 'Energizer'], [TYPE, MOBILE]], [
1824
+
1825
+ // Cat
1826
+ /; cat (b35);/i,
1827
+ /; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\))/i
1828
+ ], [MODEL, [VENDOR, 'Cat'], [TYPE, MOBILE]], [
1829
+
1830
+ // Smartfren
1831
+ /((?:new )?andromax[\w- ]+)(?: bui|\))/i
1832
+ ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [
1833
+
1834
+ // Nothing
1835
+ /droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i
1836
+ ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [
1837
+
1838
+ // Archos
1839
+ /; (x67 5g|tikeasy \w+|ac[1789]\d\w+)( b|\))/i,
1840
+ /archos ?(5|gamepad2?|([\w ]*[t1789]|hello) ?\d+[\w ]*)( b|\))/i
1841
+ ], [MODEL, [VENDOR, 'Archos'], [TYPE, TABLET]], [
1842
+ /archos ([\w ]+)( b|\))/i,
1843
+ /; (ac[3-6]\d\w{2,8})( b|\))/i
1844
+ ], [MODEL, [VENDOR, 'Archos'], [TYPE, MOBILE]], [
1845
+
1846
+ // HMD
1847
+ /; (n159v)/i
1848
+ ], [MODEL, [VENDOR, 'HMD'], [TYPE, MOBILE]], [
1849
+
1850
+ // MIXED
1851
+ /(imo) (tab \w+)/i, // IMO
1852
+ /(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i // Infinix XPad / Tecno
1853
+ ], [VENDOR, MODEL, [TYPE, TABLET]], [
1854
+
1855
+ /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\w]*)/i,
1856
+ // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan
1857
+ /; (blu|hmd|imo|infinix|lava|oneplus|tcl)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i, // BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL
1858
+ /(hp) ([\w ]+\w)/i, // HP iPAQ
1859
+ /(microsoft); (lumia[\w ]+)/i, // Microsoft Lumia
1860
+ /(oppo) ?([\w ]+) bui/i // OPPO
1861
+ ], [VENDOR, MODEL, [TYPE, MOBILE]], [
1862
+
1863
+ /(kobo)\s(ereader|touch)/i, // Kobo
1864
+ /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad
1865
+ /(kindle)\/([\w\.]+)/i // Kindle
1866
+ ], [VENDOR, MODEL, [TYPE, TABLET]], [
1867
+
1868
+ /(surface duo)/i // Surface Duo
1869
+ ], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [
1870
+ /droid [\d\.]+; (fp\du?)(?: b|\))/i // Fairphone
1871
+ ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [
1872
+ /((?:tegranote|shield t(?!.+d tv))[\w- ]*?)(?: b|\))/i // Nvidia Tablets
1873
+ ], [MODEL, [VENDOR, NVIDIA], [TYPE, TABLET]], [
1874
+ /(sprint) (\w+)/i // Sprint Phones
1875
+ ], [VENDOR, MODEL, [TYPE, MOBILE]], [
1876
+ /(kin\.[onetw]{3})/i // Microsoft Kin
1877
+ ], [[MODEL, /\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [
1878
+ /droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i // Zebra
1879
+ ], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [
1880
+ /droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i
1881
+ ], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [
1882
+
1883
+ ///////////////////
1884
+ // SMARTTVS
1885
+ ///////////////////
1886
+
1887
+ /smart-tv.+(samsung)/i // Samsung
1888
+ ], [VENDOR, [TYPE, SMARTTV]], [
1889
+ /hbbtv.+maple;(\d+)/i
1890
+ ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [
1891
+ /(vizio)(?: |.+model\/)(\w+-\w+)/i, // Vizio
1892
+ /tcast.+(lg)e?. ([-\w]+)/i // LG SmartTV
1893
+ ], [VENDOR, MODEL, [TYPE, SMARTTV]], [
1894
+ /(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i
1895
+ ], [[VENDOR, LG], [TYPE, SMARTTV]], [
1896
+ /(apple) ?tv/i // Apple TV
1897
+ ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [
1898
+ /crkey.*devicetype\/chromecast/i // Google Chromecast Third Generation
1899
+ ], [[MODEL, CHROMECAST+' Third Generation'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
1900
+ /crkey.*devicetype\/([^/]*)/i // Google Chromecast with specific device type
1901
+ ], [[MODEL, /^/, 'Chromecast '], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
1902
+ /fuchsia.*crkey/i // Google Chromecast Nest Hub
1903
+ ], [[MODEL, CHROMECAST+' Nest Hub'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
1904
+ /crkey/i // Google Chromecast, Linux-based or unknown
1905
+ ], [[MODEL, CHROMECAST], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [
1906
+ /(portaltv)/i // Facebook Portal TV
1907
+ ], [MODEL, [VENDOR, FACEBOOK], [TYPE, SMARTTV]], [
1908
+ /droid.+aft(\w+)( bui|\))/i // Fire TV
1909
+ ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [
1910
+ /(shield \w+ tv)/i // Nvidia Shield TV
1911
+ ], [MODEL, [VENDOR, NVIDIA], [TYPE, SMARTTV]], [
1912
+ /\(dtv[\);].+(aquos)/i,
1913
+ /(aquos-tv[\w ]+)\)/i // Sharp
1914
+ ], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[
1915
+ /(bravia[\w ]+)( bui|\))/i // Sony
1916
+ ], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [
1917
+ /(mi(tv|box)-?\w+) bui/i // Xiaomi
1918
+ ], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [
1919
+ /Hbbtv.*(technisat) (.*);/i // TechniSAT
1920
+ ], [VENDOR, MODEL, [TYPE, SMARTTV]], [
1921
+ /\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, // Roku
1922
+ /hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices
1923
+ ], [[VENDOR, /.+\/(\w+)/, '$1', strMapper, {'LG':'lge'}], [MODEL, trim], [TYPE, SMARTTV]], [
1924
+ // SmartTV from Unidentified Vendors
1925
+ /droid.+; ([\w- ]+) (?:android tv|smart[- ]?tv)/i
1926
+ ], [MODEL, [TYPE, SMARTTV]], [
1927
+ /\b(android tv|smart[- ]?tv|opera tv|tv; rv:|large screen[\w ]+safari)\b/i
1928
+ ], [[TYPE, SMARTTV]], [
1929
+
1930
+ ///////////////////
1931
+ // CONSOLES
1932
+ ///////////////////
1933
+
1934
+ /(playstation \w+)/i // Playstation
1935
+ ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [
1936
+ /\b(xbox(?: one)?(?!; xbox))[\); ]/i // Microsoft Xbox
1937
+ ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [
1938
+ /(ouya)/i, // Ouya
1939
+ /(nintendo) (\w+)/i, // Nintendo
1940
+ /(retroid) (pocket ([^\)]+))/i // Retroid Pocket
1941
+ ], [VENDOR, MODEL, [TYPE, CONSOLE]], [
1942
+ /droid.+; (shield)( bui|\))/i // Nvidia Portable
1943
+ ], [MODEL, [VENDOR, NVIDIA], [TYPE, CONSOLE]], [
1944
+
1945
+ ///////////////////
1946
+ // WEARABLES
1947
+ ///////////////////
1948
+
1949
+ /\b(sm-[lr]\d\d[0156][fnuw]?s?|gear live)\b/i // Samsung Galaxy Watch
1950
+ ], [MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]], [
1951
+ /((pebble))app/i, // Pebble
1952
+ /(asus|google|lg|oppo) ((pixel |zen)?watch[\w ]*)( bui|\))/i // Asus ZenWatch / LG Watch / Pixel Watch
1953
+ ], [VENDOR, MODEL, [TYPE, WEARABLE]], [
1954
+ /(ow(?:19|20)?we?[1-3]{1,3})/i // Oppo Watch
1955
+ ], [MODEL, [VENDOR, OPPO], [TYPE, WEARABLE]], [
1956
+ /(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i // Apple Watch
1957
+ ], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [
1958
+ /(opwwe\d{3})/i // OnePlus Watch
1959
+ ], [MODEL, [VENDOR, ONEPLUS], [TYPE, WEARABLE]], [
1960
+ /(moto 360)/i // Motorola 360
1961
+ ], [MODEL, [VENDOR, MOTOROLA], [TYPE, WEARABLE]], [
1962
+ /(smartwatch 3)/i // Sony SmartWatch
1963
+ ], [MODEL, [VENDOR, SONY], [TYPE, WEARABLE]], [
1964
+ /(g watch r)/i // LG G Watch R
1965
+ ], [MODEL, [VENDOR, LG], [TYPE, WEARABLE]], [
1966
+ /droid.+; (wt63?0{2,3})\)/i
1967
+ ], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [
1968
+
1969
+ ///////////////////
1970
+ // XR
1971
+ ///////////////////
1972
+
1973
+ /droid.+; (glass) \d/i // Google Glass
1974
+ ], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [
1975
+ /(pico) (4|neo3(?: link|pro)?)/i // Pico
1976
+ ], [VENDOR, MODEL, [TYPE, XR]], [
1977
+ /(quest( \d| pro)?s?).+vr/i // Meta Quest
1978
+ ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [
1979
+ /mobile vr; rv.+firefox/i // Unidentifiable VR device using Firefox Reality / Wolvic
1980
+ ], [[TYPE, XR]], [
1981
+
1982
+ ///////////////////
1983
+ // EMBEDDED
1984
+ ///////////////////
1985
+
1986
+ /(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i // Tesla
1987
+ ], [VENDOR, [TYPE, EMBEDDED]], [
1988
+ /(aeobc)\b/i // Echo Dot
1989
+ ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [
1990
+ /(homepod).+mac os/i // Apple HomePod
1991
+ ], [MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]], [
1992
+ /windows iot/i // Unidentifiable embedded device using Windows IoT
1993
+ ], [[TYPE, EMBEDDED]], [
1994
+
1995
+ ////////////////////
1996
+ // MIXED (GENERIC)
1997
+ ///////////////////
1998
+
1999
+ /droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+?(mobile|vr|\d) safari/i
2000
+ ], [MODEL, [TYPE, strMapper, { 'mobile' : 'Mobile', 'xr' : 'VR', '*' : TABLET }]], [
2001
+ /\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet
2002
+ ], [[TYPE, TABLET]], [
2003
+ /(phone|mobile(?:[;\/]| [ \w\/\.]*safari)|pda(?=.+windows ce))/i // Unidentifiable Mobile
2004
+ ], [[TYPE, MOBILE]], [
2005
+ /droid .+?; ([\w\. -]+)( bui|\))/i // Generic Android Device
2006
+ ], [MODEL, [VENDOR, 'Generic']]
2007
+ ],
2008
+
2009
+ engine : [[
2010
+
2011
+ /windows.+ edge\/([\w\.]+)/i // EdgeHTML
2012
+ ], [VERSION, [NAME, EDGE+'HTML']], [
2013
+
2014
+ /(arkweb)\/([\w\.]+)/i // ArkWeb
2015
+ ], [NAME, VERSION], [
2016
+
2017
+ /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i // Blink
2018
+ ], [VERSION, [NAME, 'Blink']], [
2019
+
2020
+ /(presto)\/([\w\.]+)/i, // Presto
2021
+ /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo
2022
+ /ekioh(flow)\/([\w\.]+)/i, // Flow
2023
+ /(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links
2024
+ /(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab
2025
+
2026
+ /\b(libweb)/i // LibWeb
2027
+ ], [NAME, VERSION], [
2028
+ /ladybird\//i
2029
+ ], [[NAME, 'LibWeb']], [
2030
+
2031
+ /rv\:([\w\.]{1,9})\b.+(gecko)/i // Gecko
2032
+ ], [VERSION, NAME]
2033
+ ],
2034
+
2035
+ os : [[
2036
+
2037
+ // Windows
2038
+ /(windows nt) (6\.[23]); arm/i // Windows RT
2039
+ ], [[NAME, /N/, 'R'], [VERSION, strMapper, windowsVersionMap]], [
2040
+ /(windows (?:phone|mobile|iot))(?: os)?[\/ ]?([\d\.]*( se)?)/i, // Windows IoT/Mobile/Phone
2041
+ // Windows NT/3.1/95/98/ME/2000/XP/Vista/7/8/8.1/10/11
2042
+ /(windows)[\/ ](1[01]|2000|3\.1|7|8(\.1)?|9[58]|me|server 20\d\d( r2)?|vista|xp)/i
2043
+ ], [NAME, VERSION], [
2044
+ /windows nt ?([\d\.\)]*)(?!.+xbox)/i,
2045
+ /\bwin(?=3| ?9|n)(?:nt| 9x )?([\d\.;]*)/i
2046
+ ], [[VERSION, /(;|\))/g, '', strMapper, windowsVersionMap], [NAME, WINDOWS]], [
2047
+ /(windows ce)\/?([\d\.]*)/i // Windows CE
2048
+ ], [NAME, VERSION], [
2049
+
2050
+ // iOS/macOS
2051
+ /[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
2052
+ /(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,
2053
+ /cfnetwork\/.+darwin/i
2054
+ ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
2055
+ /(mac os x) ?([\w\. ]*)/i,
2056
+ /(macintosh|mac_powerpc\b)(?!.+(haiku|morphos))/i // Mac OS
2057
+ ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [
2058
+
2059
+ // Google Chromecast
2060
+ /android ([\d\.]+).*crkey/i // Google Chromecast, Android-based
2061
+ ], [VERSION, [NAME, CHROMECAST + ' Android']], [
2062
+ /fuchsia.*crkey\/([\d\.]+)/i // Google Chromecast, Fuchsia-based
2063
+ ], [VERSION, [NAME, CHROMECAST + ' Fuchsia']], [
2064
+ /crkey\/([\d\.]+).*devicetype\/smartspeaker/i // Google Chromecast, Linux-based Smart Speaker
2065
+ ], [VERSION, [NAME, CHROMECAST + ' SmartSpeaker']], [
2066
+ /linux.*crkey\/([\d\.]+)/i // Google Chromecast, Legacy Linux-based
2067
+ ], [VERSION, [NAME, CHROMECAST + ' Linux']], [
2068
+ /crkey\/([\d\.]+)/i // Google Chromecast, unknown
2069
+ ], [VERSION, [NAME, CHROMECAST]], [
2070
+
2071
+ // Mobile OSes
2072
+ /droid ([\w\.]+)\b.+(android[- ]x86)/i // Android-x86
2073
+ ], [VERSION, NAME], [
2074
+ /(ubuntu) ([\w\.]+) like android/i // Ubuntu Touch
2075
+ ], [[NAME, /(.+)/, '$1 Touch'], VERSION], [
2076
+ /(harmonyos)[\/ ]?([\d\.]*)/i, // HarmonyOS
2077
+ // Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen
2078
+ /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\w*[-\/\.; ]?([\d\.]*)/i
2079
+ ], [NAME, VERSION], [
2080
+ /\(bb(10);/i // BlackBerry 10
2081
+ ], [VERSION, [NAME, BLACKBERRY]], [
2082
+ /(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\/ ]?([\w\.]*)/i // Symbian
2083
+ ], [VERSION, [NAME, 'Symbian']], [
2084
+ /mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS
2085
+ ], [VERSION, [NAME, FIREFOX+' OS']], [
2086
+ /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS
2087
+ /webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i
2088
+ ], [VERSION, [NAME, 'webOS']], [
2089
+ /web0s;.+?(?:chr[o0]me|safari)\/(\d+)/i
2090
+ // https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine
2091
+ ], [[VERSION, strMapper, {'25':'120','24':'108','23':'94','22':'87','6':'79','5':'68','4':'53','3':'38','2':'538','1':'537','*':'TV'}], [NAME, 'webOS']], [
2092
+ /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS
2093
+ ], [VERSION, [NAME, 'watchOS']], [
2094
+
2095
+ // Google ChromeOS
2096
+ /(cros) [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS
2097
+ ], [[NAME, "Chrome OS"], VERSION],[
2098
+
2099
+ // Smart TVs
2100
+ /panasonic;(viera)/i, // Panasonic Viera
2101
+ /(netrange)mmh/i, // Netrange
2102
+ /(nettv)\/(\d+\.[\w\.]+)/i, // NetTV
2103
+
2104
+ // Console
2105
+ /(nintendo|playstation) (\w+)/i, // Nintendo/Playstation
2106
+ /(xbox); +xbox ([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)
2107
+ /(pico) .+os([\w\.]+)/i, // Pico
2108
+
2109
+ // Other
2110
+ /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, // Joli/Palm
2111
+ /linux.+(mint)[\/\(\) ]?([\w\.]*)/i, // Mint
2112
+ /(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\d\.]*)/i, // Mageia/VectorLinux/Fuchsia/ArcaOS/Arch
2113
+ /([kxln]?ubuntu|debian|suse|opensuse|gentoo|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire|knoppix)(?: gnu[\/ ]linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i,
2114
+ // Ubuntu/Debian/SUSE/Gentoo/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire/Knoppix
2115
+ /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, // Solaris
2116
+ /\b(aix)[; ]([1-9\.]{0,4})/i, // AIX
2117
+ /(hurd|linux|morphos)(?: (?:arm|x86|ppc)\w*| ?)([\w\.]*)/i, // Hurd/Linux/MorphOS
2118
+ /(gnu) ?([\w\.]*)/i, // GNU
2119
+ /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly
2120
+ /(haiku) ?(r\d)?/i // Haiku
2121
+ ], [NAME, VERSION], [
2122
+ /(sunos) ?([\d\.]*)/i // Solaris
2123
+ ], [[NAME, 'Solaris'], VERSION], [
2124
+ /\b(beos|os\/2|amigaos|openvms|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/OpenVMS/HP-UX/SerenityOS
2125
+ /(unix) ?([\w\.]*)/i // UNIX
2126
+ ], [NAME, VERSION]
2127
+ ]
2128
+ };
2129
+
2130
+ /////////////////
2131
+ // Factories
2132
+ ////////////////
2133
+
2134
+ var defaultProps = (function () {
2135
+ var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};
2136
+ setProps.call(props.init, [
2137
+ [UA_BROWSER, [NAME, VERSION, MAJOR, TYPE]],
2138
+ [UA_CPU, [ARCHITECTURE]],
2139
+ [UA_DEVICE, [TYPE, MODEL, VENDOR]],
2140
+ [UA_ENGINE, [NAME, VERSION]],
2141
+ [UA_OS, [NAME, VERSION]]
2142
+ ]);
2143
+ setProps.call(props.isIgnore, [
2144
+ [UA_BROWSER, [VERSION, MAJOR]],
2145
+ [UA_ENGINE, [VERSION]],
2146
+ [UA_OS, [VERSION]]
2147
+ ]);
2148
+ setProps.call(props.isIgnoreRgx, [
2149
+ [UA_BROWSER, / ?browser$/i],
2150
+ [UA_OS, / ?os$/i]
2151
+ ]);
2152
+ setProps.call(props.toString, [
2153
+ [UA_BROWSER, [NAME, VERSION]],
2154
+ [UA_CPU, [ARCHITECTURE]],
2155
+ [UA_DEVICE, [VENDOR, MODEL]],
2156
+ [UA_ENGINE, [NAME, VERSION]],
2157
+ [UA_OS, [NAME, VERSION]]
2158
+ ]);
2159
+ return props;
2160
+ })();
2161
+
2162
+ var createIData = function (item, itemType) {
2163
+
2164
+ var init_props = defaultProps.init[itemType],
2165
+ is_ignoreProps = defaultProps.isIgnore[itemType] || 0,
2166
+ is_ignoreRgx = defaultProps.isIgnoreRgx[itemType] || 0,
2167
+ toString_props = defaultProps.toString[itemType] || 0;
2168
+
2169
+ function IData () {
2170
+ setProps.call(this, init_props);
2171
+ }
2172
+
2173
+ IData.prototype.getItem = function () {
2174
+ return item;
2175
+ };
2176
+
2177
+ IData.prototype.withClientHints = function () {
2178
+
2179
+ // nodejs / non-client-hints browsers
2180
+ if (!NAVIGATOR_UADATA) {
2181
+ return item
2182
+ .parseCH()
2183
+ .get();
2184
+ }
2185
+
2186
+ // browsers based on chromium 85+
2187
+ return NAVIGATOR_UADATA
2188
+ .getHighEntropyValues(CH_ALL_VALUES)
2189
+ .then(function (res) {
2190
+ return item
2191
+ .setCH(new UACHData(res, false))
2192
+ .parseCH()
2193
+ .get();
2194
+ });
2195
+ };
2196
+
2197
+ IData.prototype.withFeatureCheck = function () {
2198
+ return item.detectFeature().get();
2199
+ };
2200
+
2201
+ if (itemType != UA_RESULT) {
2202
+ IData.prototype.is = function (strToCheck) {
2203
+ var is = false;
2204
+ for (var i in this) {
2205
+ if (this.hasOwnProperty(i) && !has(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) {
2206
+ is = true;
2207
+ if (strToCheck != UNDEF_TYPE) break;
2208
+ } else if (strToCheck == UNDEF_TYPE && is) {
2209
+ is = !is;
2210
+ break;
2211
+ }
2212
+ }
2213
+ return is;
2214
+ };
2215
+ IData.prototype.toString = function () {
2216
+ var str = EMPTY;
2217
+ for (var i in toString_props) {
2218
+ if (typeof(this[toString_props[i]]) !== UNDEF_TYPE) {
2219
+ str += (str ? ' ' : EMPTY) + this[toString_props[i]];
2220
+ }
2221
+ }
2222
+ return str || UNDEF_TYPE;
2223
+ };
2224
+ }
2225
+
2226
+ if (!NAVIGATOR_UADATA) {
2227
+ IData.prototype.then = function (cb) {
2228
+ var that = this;
2229
+ var IDataResolve = function () {
2230
+ for (var prop in that) {
2231
+ if (that.hasOwnProperty(prop)) {
2232
+ this[prop] = that[prop];
2233
+ }
2234
+ }
2235
+ };
2236
+ IDataResolve.prototype = {
2237
+ is : IData.prototype.is,
2238
+ toString : IData.prototype.toString
2239
+ };
2240
+ var resolveData = new IDataResolve();
2241
+ cb(resolveData);
2242
+ return resolveData;
2243
+ };
2244
+ }
2245
+
2246
+ return new IData();
2247
+ };
2248
+
2249
+ /////////////////
2250
+ // Constructor
2251
+ ////////////////
2252
+
2253
+ function UACHData (uach, isHttpUACH) {
2254
+ uach = uach || {};
2255
+ setProps.call(this, CH_ALL_VALUES);
2256
+ if (isHttpUACH) {
2257
+ setProps.call(this, [
2258
+ [BRANDS, itemListToArray(uach[CH_HEADER])],
2259
+ [FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])],
2260
+ [MOBILE, /\?1/.test(uach[CH_HEADER_MOBILE])],
2261
+ [MODEL, stripQuotes(uach[CH_HEADER_MODEL])],
2262
+ [PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])],
2263
+ [PLATFORMVER, stripQuotes(uach[CH_HEADER_PLATFORM_VER])],
2264
+ [ARCHITECTURE, stripQuotes(uach[CH_HEADER_ARCH])],
2265
+ [FORMFACTORS, itemListToArray(uach[CH_HEADER_FORM_FACTORS])],
2266
+ [BITNESS, stripQuotes(uach[CH_HEADER_BITNESS])]
2267
+ ]);
2268
+ } else {
2269
+ for (var prop in uach) {
2270
+ if(this.hasOwnProperty(prop) && typeof uach[prop] !== UNDEF_TYPE) this[prop] = uach[prop];
2271
+ }
2272
+ }
2273
+ }
2274
+
2275
+ function UAItem (itemType, ua, rgxMap, uaCH) {
2276
+
2277
+ this.get = function (prop) {
2278
+ if (!prop) return this.data;
2279
+ return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined;
2280
+ };
2281
+
2282
+ this.set = function (prop, val) {
2283
+ this.data[prop] = val;
2284
+ return this;
2285
+ };
2286
+
2287
+ this.setCH = function (ch) {
2288
+ this.uaCH = ch;
2289
+ return this;
2290
+ };
2291
+
2292
+ this.detectFeature = function () {
2293
+ if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
2294
+ switch (this.itemType) {
2295
+ case UA_BROWSER:
2296
+ // Brave-specific detection
2297
+ if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == FUNC_TYPE) {
2298
+ this.set(NAME, 'Brave');
2299
+ }
2300
+ break;
2301
+ case UA_DEVICE:
2302
+ // Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
2303
+ if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
2304
+ this.set(TYPE, MOBILE);
2305
+ }
2306
+ // iPadOS-specific detection: identified as Mac, but has some iOS-only properties
2307
+ if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== UNDEF_TYPE && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
2308
+ this.set(MODEL, 'iPad')
2309
+ .set(TYPE, TABLET);
2310
+ }
2311
+ break;
2312
+ case UA_OS:
2313
+ // Chrome-specific detection: check for 'platform' value of navigator.userAgentData
2314
+ if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
2315
+ this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
2316
+ }
2317
+ break;
2318
+ case UA_RESULT:
2319
+ var data = this.data;
2320
+ var detect = function (itemType) {
2321
+ return data[itemType]
2322
+ .getItem()
2323
+ .detectFeature()
2324
+ .get();
2325
+ };
2326
+ this.set(UA_BROWSER, detect(UA_BROWSER))
2327
+ .set(UA_CPU, detect(UA_CPU))
2328
+ .set(UA_DEVICE, detect(UA_DEVICE))
2329
+ .set(UA_ENGINE, detect(UA_ENGINE))
2330
+ .set(UA_OS, detect(UA_OS));
2331
+ }
2332
+ }
2333
+ return this;
2334
+ };
2335
+
2336
+ this.parseUA = function () {
2337
+ if (this.itemType != UA_RESULT) {
2338
+ rgxMapper.call(this.data, this.ua, this.rgxMap);
2339
+ }
2340
+ if (this.itemType == UA_BROWSER) {
2341
+ this.set(MAJOR, majorize(this.get(VERSION)));
2342
+ }
2343
+ return this;
2344
+ };
2345
+
2346
+ this.parseCH = function () {
2347
+ var uaCH = this.uaCH,
2348
+ rgxMap = this.rgxMap;
2349
+
2350
+ switch (this.itemType) {
2351
+ case UA_BROWSER:
2352
+ case UA_ENGINE:
2353
+ var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
2354
+ if (brands) {
2355
+ for (var i in brands) {
2356
+ var brandName = brands[i].brand || brands[i],
2357
+ brandVersion = brands[i].version;
2358
+ if (this.itemType == UA_BROWSER &&
2359
+ !/not.a.brand/i.test(brandName) &&
2360
+ (!prevName ||
2361
+ (/Chrom/.test(prevName) && brandName != CHROMIUM) ||
2362
+ (prevName == EDGE && /WebView2/.test(brandName))
2363
+ )) {
2364
+ brandName = strMapper(brandName, browserHintsMap);
2365
+ prevName = this.get(NAME);
2366
+ if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) {
2367
+ this.set(NAME, brandName)
2368
+ .set(VERSION, brandVersion)
2369
+ .set(MAJOR, majorize(brandVersion));
2370
+ }
2371
+ prevName = brandName;
2372
+ }
2373
+ if (this.itemType == UA_ENGINE && brandName == CHROMIUM) {
2374
+ this.set(VERSION, brandVersion);
2375
+ }
2376
+ }
2377
+ }
2378
+ break;
2379
+ case UA_CPU:
2380
+ var archName = uaCH[ARCHITECTURE];
2381
+ if (archName) {
2382
+ if (archName && uaCH[BITNESS] == '64') archName += '64';
2383
+ rgxMapper.call(this.data, archName + ';', rgxMap);
2384
+ }
2385
+ break;
2386
+ case UA_DEVICE:
2387
+ if (uaCH[MOBILE]) {
2388
+ this.set(TYPE, MOBILE);
2389
+ }
2390
+ if (uaCH[MODEL]) {
2391
+ this.set(MODEL, uaCH[MODEL]);
2392
+ if (!this.get(TYPE) || !this.get(VENDOR)) {
2393
+ var reParse = {};
2394
+ rgxMapper.call(reParse, 'droid 9; ' + uaCH[MODEL] + ')', rgxMap);
2395
+ if (!this.get(TYPE) && !!reParse.type) {
2396
+ this.set(TYPE, reParse.type);
2397
+ }
2398
+ if (!this.get(VENDOR) && !!reParse.vendor) {
2399
+ this.set(VENDOR, reParse.vendor);
2400
+ }
2401
+ }
2402
+ }
2403
+ if (uaCH[FORMFACTORS]) {
2404
+ var ff;
2405
+ if (typeof uaCH[FORMFACTORS] !== 'string') {
2406
+ var idx = 0;
2407
+ while (!ff && idx < uaCH[FORMFACTORS].length) {
2408
+ ff = strMapper(uaCH[FORMFACTORS][idx++], formFactorsMap);
2409
+ }
2410
+ } else {
2411
+ ff = strMapper(uaCH[FORMFACTORS], formFactorsMap);
2412
+ }
2413
+ this.set(TYPE, ff);
2414
+ }
2415
+ break;
2416
+ case UA_OS:
2417
+ var osName = uaCH[PLATFORM];
2418
+ if(osName) {
2419
+ var osVersion = uaCH[PLATFORMVER];
2420
+ if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');
2421
+ this.set(NAME, osName)
2422
+ .set(VERSION, osVersion);
2423
+ }
2424
+ // Xbox-Specific Detection
2425
+ if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') {
2426
+ this.set(NAME, 'Xbox')
2427
+ .set(VERSION, undefined);
2428
+ }
2429
+ break;
2430
+ case UA_RESULT:
2431
+ var data = this.data;
2432
+ var parse = function (itemType) {
2433
+ return data[itemType]
2434
+ .getItem()
2435
+ .setCH(uaCH)
2436
+ .parseCH()
2437
+ .get();
2438
+ };
2439
+ this.set(UA_BROWSER, parse(UA_BROWSER))
2440
+ .set(UA_CPU, parse(UA_CPU))
2441
+ .set(UA_DEVICE, parse(UA_DEVICE))
2442
+ .set(UA_ENGINE, parse(UA_ENGINE))
2443
+ .set(UA_OS, parse(UA_OS));
2444
+ }
2445
+ return this;
2446
+ };
2447
+
2448
+ setProps.call(this, [
2449
+ ['itemType', itemType],
2450
+ ['ua', ua],
2451
+ ['uaCH', uaCH],
2452
+ ['rgxMap', rgxMap],
2453
+ ['data', createIData(this, itemType)]
2454
+ ]);
2455
+
2456
+ return this;
2457
+ }
2458
+
2459
+ function UAParser (ua, extensions, headers) {
2460
+
2461
+ if (typeof ua === OBJ_TYPE) {
2462
+ if (isExtensions(ua, true)) {
2463
+ if (typeof extensions === OBJ_TYPE) {
2464
+ headers = extensions; // case UAParser(extensions, headers)
2465
+ }
2466
+ extensions = ua; // case UAParser(extensions)
2467
+ } else {
2468
+ headers = ua; // case UAParser(headers)
2469
+ extensions = undefined;
2470
+ }
2471
+ ua = undefined;
2472
+ } else if (typeof ua === STR_TYPE && !isExtensions(extensions, true)) {
2473
+ headers = extensions; // case UAParser(ua, headers)
2474
+ extensions = undefined;
2475
+ }
2476
+
2477
+ // Convert Headers object into a plain object
2478
+ if (headers && typeof headers.append === FUNC_TYPE) {
2479
+ var kv = {};
2480
+ headers.forEach(function (v, k) { kv[k] = v; });
2481
+ headers = kv;
2482
+ }
2483
+
2484
+ if (!(this instanceof UAParser)) {
2485
+ return new UAParser(ua, extensions, headers).getResult();
2486
+ }
2487
+
2488
+ var userAgent = typeof ua === STR_TYPE ? ua : // Passed user-agent string
2489
+ (headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers
2490
+ ((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent
2491
+ EMPTY)), // empty string
2492
+
2493
+ httpUACH = new UACHData(headers, true),
2494
+ regexMap = extensions ?
2495
+ extend(defaultRegexes, extensions) :
2496
+ defaultRegexes,
2497
+
2498
+ createItemFunc = function (itemType) {
2499
+ if (itemType == UA_RESULT) {
2500
+ return function () {
2501
+ return new UAItem(itemType, userAgent, regexMap, httpUACH)
2502
+ .set('ua', userAgent)
2503
+ .set(UA_BROWSER, this.getBrowser())
2504
+ .set(UA_CPU, this.getCPU())
2505
+ .set(UA_DEVICE, this.getDevice())
2506
+ .set(UA_ENGINE, this.getEngine())
2507
+ .set(UA_OS, this.getOS())
2508
+ .get();
2509
+ };
2510
+ } else {
2511
+ return function () {
2512
+ return new UAItem(itemType, userAgent, regexMap[itemType], httpUACH)
2513
+ .parseUA()
2514
+ .get();
2515
+ };
2516
+ }
2517
+ };
2518
+
2519
+ // public methods
2520
+ setProps.call(this, [
2521
+ ['getBrowser', createItemFunc(UA_BROWSER)],
2522
+ ['getCPU', createItemFunc(UA_CPU)],
2523
+ ['getDevice', createItemFunc(UA_DEVICE)],
2524
+ ['getEngine', createItemFunc(UA_ENGINE)],
2525
+ ['getOS', createItemFunc(UA_OS)],
2526
+ ['getResult', createItemFunc(UA_RESULT)],
2527
+ ['getUA', function () { return userAgent; }],
2528
+ ['setUA', function (ua) {
2529
+ if (isString(ua))
2530
+ userAgent = ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
2531
+ return this;
2532
+ }]
2533
+ ])
2534
+ .setUA(userAgent);
2535
+
2536
+ return this;
2537
+ }
2538
+
2539
+ UAParser.VERSION = LIBVERSION;
2540
+ UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR, TYPE]);
2541
+ UAParser.CPU = enumerize([ARCHITECTURE]);
2542
+ UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);
2543
+ UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);
2544
+
2545
+ class DeviceDetector {
2546
+ getDeviceInfo() {
2547
+ const parser = new UAParser();
2548
+ const result = parser.getResult();
2549
+ return {
2550
+ browser: result.browser,
2551
+ os: result.os,
2552
+ device: result.device,
2553
+ engine: result.engine,
2554
+ cpu: result.cpu,
2555
+ ua: result.ua,
2556
+ };
2557
+ }
2558
+ get screenDensity() {
2559
+ if (window.devicePixelRatio >= 3)
2560
+ return "high";
2561
+ if (window.devicePixelRatio >= 2)
2562
+ return "medium";
2563
+ return "low";
2564
+ }
2565
+ get screenFormat() {
2566
+ return window.innerHeight > window.innerWidth ? "long" : "normal";
2567
+ }
2568
+ get screenSize() {
2569
+ const width = window.innerWidth;
2570
+ if (width < 480)
2571
+ return "small";
2572
+ else if (width < 768)
2573
+ return "normal";
2574
+ else if (width < 1440)
2575
+ return "large";
2576
+ else
2577
+ return "xlarge";
2578
+ }
2579
+ get uiMode() {
2580
+ var _a, _b, _c;
2581
+ const deviceInfo = this.getDeviceInfo();
2582
+ const deviceType = ((_a = deviceInfo.device) === null || _a === void 0 ? void 0 : _a.type) || ""; // 'mobile', 'tablet', 'smarttv', 'console', 'wearable', 'embedded'
2583
+ const model = ((_c = (_b = deviceInfo.device) === null || _b === void 0 ? void 0 : _b.model) === null || _c === void 0 ? void 0 : _c.toLowerCase()) || "";
2584
+ const ua = deviceInfo.ua.toLowerCase();
2585
+ if (deviceType === "wearable" || model.includes("watch")) {
2586
+ return 6; // UI_MODE_TYPE_WATCH
2587
+ }
2588
+ if (deviceType === "smarttv" ||
2589
+ ua.includes("smart-tv") ||
2590
+ ua.includes("hbbtv") ||
2591
+ ua.includes("netcast") ||
2592
+ ua.includes("googletv") ||
2593
+ ua.includes("appletv")) {
2594
+ return 4; // UI_MODE_TYPE_TELEVISION
2595
+ }
2596
+ if (deviceType === "console" ||
2597
+ ua.includes("playstation") ||
2598
+ ua.includes("xbox") ||
2599
+ ua.includes("nintendo")) {
2600
+ return 5; // UI_MODE_TYPE_APPLIANCE
2601
+ }
2602
+ if (ua.includes("car") ||
2603
+ ua.includes("android auto") ||
2604
+ ua.includes("carplay")) {
2605
+ return 3; // UI_MODE_TYPE_CAR
2606
+ }
2607
+ if (ua.includes("oculus") ||
2608
+ ua.includes("vive") ||
2609
+ ua.includes("vr") ||
2610
+ deviceType === "embedded") {
2611
+ return 7; // UI_MODE_TYPE_VR_HEADSET
2612
+ }
2613
+ if (deviceType === "mobile" || deviceType === "tablet") {
2614
+ return 1; // UI_MODE_TYPE_NORMAL
2615
+ }
2616
+ if (deviceType === "" || deviceType === "desktop") {
2617
+ return 2; // UI_MODE_TYPE_DESK
2618
+ }
2619
+ return 0; // UI_MODE_TYPE_UNDEFINED
2620
+ }
2621
+ get uiStyle() {
2622
+ const isDarkMode = window.matchMedia &&
2623
+ window.matchMedia("(prefers-color-scheme: dark)").matches;
2624
+ return isDarkMode ? "1" : "0";
2625
+ }
2626
+ get displaySize() {
2627
+ const dpr = window.devicePixelRatio || 1;
2628
+ const pixelWidth = screen.width * dpr;
2629
+ const pixelHeight = screen.height * dpr;
2630
+ const assumedDPI = 160;
2631
+ const widthInInches = pixelWidth / assumedDPI;
2632
+ const heightInInches = pixelHeight / assumedDPI;
2633
+ const diagonal = Math.sqrt(Math.pow(widthInInches, 2) + Math.pow(heightInInches, 2));
2634
+ return diagonal.toFixed(2);
2635
+ }
2636
+ get screenType() {
2637
+ return "ontouchstart" in window || navigator.maxTouchPoints > 0
2638
+ ? "touch"
2639
+ : "pointer";
2640
+ }
2641
+ }
2642
+ /** @internal */
2643
+ const deviceDetector = new DeviceDetector();
2644
+
2645
+ class StorageSupport {
2646
+ constructor() {
2647
+ this.supportResults = null;
2648
+ }
2649
+ getSupportResult() {
2650
+ return __awaiter(this, void 0, void 0, function* () {
2651
+ if (this.supportResults)
2652
+ return this.supportResults;
2653
+ const localStorageSupported = this.isLocalStorageSupported();
2654
+ const sessionStorageSupported = this.isSessionStorageSupported();
2655
+ const indexedDBSupported = yield this.isIndexedDBSupported();
2656
+ this.supportResults = {
2657
+ localStorage: localStorageSupported,
2658
+ sessionStorage: sessionStorageSupported,
2659
+ indexedDB: indexedDBSupported,
2660
+ };
2661
+ return this.supportResults;
2662
+ });
2663
+ }
2664
+ getStorageSizeBytes(storage) {
2665
+ let total = 0;
2666
+ for (let i = 0; i < storage.length; i++) {
2667
+ const key = storage.key(i);
2668
+ if (!key)
2669
+ continue;
2670
+ const value = storage.getItem(key);
2671
+ if (value == null)
2672
+ continue;
2673
+ total += key.length * 2;
2674
+ total += value.length * 2;
2675
+ }
2676
+ return total;
2677
+ }
2678
+ isLocalStorageSupported() {
2679
+ try {
2680
+ const testKey = "__test__";
2681
+ localStorage.setItem(testKey, "1");
2682
+ localStorage.removeItem(testKey);
2683
+ return true;
2684
+ }
2685
+ catch (e) {
2686
+ return false;
2687
+ }
2688
+ }
2689
+ isSessionStorageSupported() {
2690
+ try {
2691
+ const testKey = "__test__";
2692
+ sessionStorage.setItem(testKey, "1");
2693
+ sessionStorage.removeItem(testKey);
2694
+ return true;
2695
+ }
2696
+ catch (e) {
2697
+ return false;
2698
+ }
2699
+ }
2700
+ isIndexedDBSupported() {
2701
+ if (!("indexedDB" in window))
2702
+ return Promise.resolve(false);
2703
+ return new Promise((resolve) => {
2704
+ try {
2705
+ const request = indexedDB.open("__test__check__");
2706
+ request.onerror = () => resolve(false);
2707
+ request.onsuccess = () => {
2708
+ request.result.close();
2709
+ indexedDB.deleteDatabase("__test__check__");
2710
+ resolve(true);
2711
+ };
2712
+ }
2713
+ catch (_a) {
2714
+ resolve(false);
2715
+ }
2716
+ });
2717
+ }
2718
+ }
2719
+ /** @internal */
2720
+ const storageSupport = new StorageSupport();
2721
+
2722
+ /** @internal */
2723
+ class Utils {
2724
+ static getUTMParamsString() {
2725
+ const params = new URLSearchParams(window.location.search);
2726
+ const utmParams = {};
2727
+ for (const [key, value] of params.entries()) {
2728
+ if (key.startsWith("utm_") && value) {
2729
+ utmParams[key] = value;
2730
+ }
2731
+ }
2732
+ if (!utmParams["utm_source"]) {
2733
+ const referrer = document.referrer;
2734
+ utmParams["utm_source"] = referrer ? new URL(referrer).hostname : "other";
2735
+ }
2736
+ if (!utmParams["utm_medium"]) {
2737
+ utmParams["utm_medium"] = "organic";
2738
+ }
2739
+ return Object.entries(utmParams)
2740
+ .map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
2741
+ .join("&");
2742
+ }
2743
+ }
2744
+ Utils.detectWebFramework = () => {
2745
+ // Next.js (React)
2746
+ if (!!document.querySelector("script[id=__NEXT_DATA__]") ||
2747
+ [...document.scripts].some((s) => s.src.includes("/_next/")))
2748
+ return "Next.js";
2749
+ // React (if next.js dosn't exists)
2750
+ if (!!window.React ||
2751
+ !!document.querySelector("[data-reactroot], [data-reactid]") ||
2752
+ Array.from(document.querySelectorAll("*")).some((e) => e._reactRootContainer !== undefined ||
2753
+ Object.keys(e).some((k) => k.startsWith("__reactContainer"))) ||
2754
+ window.__REACT_DEVTOOLS_GLOBAL_HOOK__)
2755
+ return "React";
2756
+ // Vue / Nuxt.js
2757
+ if ([...document.scripts].some((s) => s.src.includes("/_nuxt/")))
2758
+ return "Nuxt.js";
2759
+ if (window.__VUE__ ||
2760
+ window.Vue ||
2761
+ document.querySelector("[data-v-app], [data-v-]"))
2762
+ return "Vue.js";
2763
+ // Gatsby.js
2764
+ if (!!document.querySelector("[id=___gatsby]"))
2765
+ return "Gatsby.js";
2766
+ // Angular
2767
+ if (!!window ||
2768
+ !!document.querySelector(".ng-binding, [ng-app], [data-ng-app], [ng-controller], [data-ng-controller], [ng-repeat], [data-ng-repeat]") ||
2769
+ !!document.querySelector('script[src*="angular.js"], script[src*="angular.min.js"]') ||
2770
+ window.ng ||
2771
+ document.querySelector("[ng-version]"))
2772
+ return "Angular";
2773
+ // Svelte
2774
+ if ([...document.scripts].some((s) => { var _a; return s.src.includes("svelte") || ((_a = s.textContent) === null || _a === void 0 ? void 0 : _a.includes("svelte")); }))
2775
+ return "Svelte";
2776
+ // Alpine.js
2777
+ if (document.querySelector("[x-data], [x-init], [x-bind]"))
2778
+ return "Alpine.js";
2779
+ // jQuery
2780
+ if (window.jQuery)
2781
+ return "jQuery";
2782
+ // Backbone
2783
+ if (!!window.Backbone)
2784
+ return "Backbone.js";
2785
+ // Meteor
2786
+ if (!!window.Meteor)
2787
+ return "Meteor.js";
2788
+ // Zepto
2789
+ if (!!window.Zepto)
2790
+ return "Zepto.js";
2791
+ // WordPress (CMS)
2792
+ if (document.querySelector('meta[name="generator"][content*="WordPress"]') ||
2793
+ [...document.scripts].some((s) => s.src.includes("wp-content") || s.src.includes("wp-includes")))
2794
+ return "WordPress";
2795
+ // Laravel
2796
+ if ([...document.scripts].some((s) => s.src.includes("/js/app.js") || s.src.includes("mix-manifest.json")))
2797
+ return "Laravel";
2798
+ // Drupal (CMS)
2799
+ if (document.querySelector('meta[name="generator"][content*="Drupal"]') ||
2800
+ document.documentElement.innerHTML.includes("drupal-settings-json"))
2801
+ return "Drupal";
2802
+ // Shopify
2803
+ if (document.documentElement.innerHTML.includes("cdn.shopify.com"))
2804
+ return "Shopify";
2805
+ // Squarespace
2806
+ if ([...document.scripts].some((s) => s.src.includes("static.squarespace.com")))
2807
+ return "Squarespace";
2808
+ // Wix
2809
+ if ([...document.scripts].some((s) => s.src.includes("wix.com")))
2810
+ return "Wix";
2811
+ // Ghost CMS
2812
+ if (document.querySelector('meta[name="generator"][content*="Ghost"]'))
2813
+ return "Ghost CMS";
2814
+ return undefined;
2815
+ };
2816
+
2817
+ /** @internal */
2818
+ class DeviceFingerprint {
2819
+ static isWebGLSupported() {
2820
+ try {
2821
+ const canvas = document.createElement("canvas");
2822
+ return !!(canvas.getContext("webgl") || canvas.getContext("experimental-webgl"));
2823
+ }
2824
+ catch (e) {
2825
+ return false;
2826
+ }
2827
+ }
2828
+ static getWebGLFingerprint() {
2829
+ return __awaiter(this, void 0, void 0, function* () {
2830
+ const canvas = document.createElement("canvas");
2831
+ const gl = (canvas.getContext("webgl") ||
2832
+ canvas.getContext("experimental-webgl"));
2833
+ if (!gl)
2834
+ return undefined;
2835
+ const info = {
2836
+ version: gl.getParameter(gl.VERSION),
2837
+ shadingLangVersion: gl.getParameter(gl.SHADING_LANGUAGE_VERSION),
2838
+ maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE),
2839
+ maxRenderBufferSize: gl.getParameter(gl.MAX_RENDERBUFFER_SIZE),
2840
+ supportedExtensions: gl.getSupportedExtensions(),
2841
+ };
2842
+ try {
2843
+ const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
2844
+ info.vendor = debugInfo
2845
+ ? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL)
2846
+ : gl.getParameter(gl.VENDOR);
2847
+ }
2848
+ catch (_) {
2849
+ info.vendor = gl.getParameter(gl.VENDOR);
2850
+ }
2851
+ try {
2852
+ const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
2853
+ info.renderer = debugInfo
2854
+ ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL)
2855
+ : gl.getParameter(gl.RENDERER);
2856
+ }
2857
+ catch (_) {
2858
+ info.renderer = gl.getParameter(gl.RENDERER);
2859
+ }
2860
+ return yield this.hashData(JSON.stringify(info));
2861
+ });
2862
+ }
2863
+ static getCanvasFingerprint() {
2864
+ return __awaiter(this, void 0, void 0, function* () {
2865
+ const canvas = document.createElement("canvas");
2866
+ canvas.width = 200;
2867
+ canvas.height = 50;
2868
+ const ctx = canvas.getContext("2d");
2869
+ if (!ctx)
2870
+ return undefined;
2871
+ ctx.textBaseline = "top";
2872
+ ctx.font = "14px 'Arial'";
2873
+ ctx.fillStyle = "#f60";
2874
+ ctx.fillRect(0, 0, 200, 50);
2875
+ ctx.fillStyle = "#069";
2876
+ ctx.fillText("WiseTrack WebGL Fingerprint!", 2, 2);
2877
+ return yield this.hashData(canvas.toDataURL());
2878
+ });
2879
+ }
2880
+ // static async generateFingerprint(): Promise<string> {
2881
+ // const webglData = this.getWebGLFingerprint();
2882
+ // const canvasData = this.getCanvasFingerprint();
2883
+ // const combined = webglData + "|" + canvasData;
2884
+ // const encoder = new TextEncoder();
2885
+ // const data = encoder.encode(combined);
2886
+ // const hashBuffer = await crypto.subtle.digest("SHA-256", data);
2887
+ // const hashArray = Array.from(new Uint8Array(hashBuffer));
2888
+ // const hashHex = hashArray
2889
+ // .map((b) => b.toString(16).padStart(2, "0"))
2890
+ // .join("");
2891
+ // return hashHex;
2892
+ // }
2893
+ static hashData(input) {
2894
+ return __awaiter(this, void 0, void 0, function* () {
2895
+ const str = typeof input === "string" ? input : JSON.stringify(input);
2896
+ const encoder = new TextEncoder();
2897
+ const data = encoder.encode(str);
2898
+ const hashBuffer = yield crypto.subtle.digest("SHA-256", data);
2899
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
2900
+ const hashHex = hashArray
2901
+ .map((b) => b.toString(16).padStart(2, "0"))
2902
+ .join("");
2903
+ return hashHex;
2904
+ });
2905
+ }
2906
+ }
2907
+
2908
+ /** @internal */
2909
+ class FieldsBuilder {
2910
+ build() {
2911
+ return __awaiter(this, void 0, void 0, function* () {
2912
+ const startTime = window.performance.now();
2913
+ let fields = {};
2914
+ fields.created_at = new Date().toISOString();
2915
+ Object.assign(fields, this.getLocalFields());
2916
+ Object.assign(fields, yield this.getApplicationFields());
2917
+ Object.assign(fields, this.getDeviceFields());
2918
+ fields.time_spent = (window.performance.now() - startTime).toFixed(1);
2919
+ {
2920
+ fields = Object.fromEntries(Object.entries(fields).filter(([_, value]) => value !== null && value !== undefined));
2921
+ }
2922
+ return fields;
2923
+ });
2924
+ }
2925
+ getApplicationFields() {
2926
+ return __awaiter(this, void 0, void 0, function* () {
2927
+ const storageSupportResult = yield storageSupport.getSupportResult();
2928
+ return {
2929
+ connectivity_type: navigator.onLine ? "1" : "-1",
2930
+ country: yield countryFinder.getCountryCode(),
2931
+ package_name: window.location.hostname,
2932
+ session_storage_enabled: storageSupportResult.sessionStorage,
2933
+ indexed_db_enabled: storageSupportResult.indexedDB,
2934
+ local_storage_enabled: storageSupportResult.localStorage,
2935
+ session_storage: storageSupport
2936
+ .getStorageSizeBytes(sessionStorage)
2937
+ .toFixed(0),
2938
+ local_storage: storageSupport
2939
+ .getStorageSizeBytes(localStorage)
2940
+ .toFixed(0),
2941
+ web_gl_support: DeviceFingerprint.isWebGLSupported(),
2942
+ web_gl_fingerprint: yield DeviceFingerprint.getWebGLFingerprint(),
2943
+ web_gl_canvas_fingerprint: yield DeviceFingerprint.getCanvasFingerprint(),
2944
+ };
2945
+ });
2946
+ }
2947
+ getLocalFields() {
2948
+ const initialConfig = storageManager.initialConfig;
2949
+ if (!initialConfig)
2950
+ return {};
2951
+ return {
2952
+ uuid: storageManager.deviceId,
2953
+ app_token: initialConfig.appToken,
2954
+ environment: initialConfig.userEnvironment,
2955
+ store_name: "other",
2956
+ app_version: initialConfig.appVersion,
2957
+ push_token: storageManager.pushToken,
2958
+ custom_device_id: initialConfig.customDeviceId,
2959
+ default_tracker: initialConfig.defaultTracker,
2960
+ platform: WTConstants.SDK.PLATFORM,
2961
+ framework: initialConfig.appFrameWork.toLowerCase(),
2962
+ initiated_by: `${WTConstants.SDK.PLATFORM}_${initialConfig.appFrameWork.toLowerCase()}`,
2963
+ initiated_version: WTConstants.SDK.VERSION,
2964
+ referrer: Utils.getUTMParamsString(),
2965
+ installed_at: storageManager.initialDate,
2966
+ session_count: storageManager.sessionCount.toString(),
2967
+ session_length: parseInt((storageManager.activeDuration / 1000).toString()).toString(),
2968
+ subsession_count: parseInt((storageManager.subSessionCount / 1000).toString()).toString(),
2969
+ last_interval: parseInt((storageManager.inactiveDuration / 1000).toString()).toString(),
2970
+ };
2971
+ }
2972
+ getDeviceFields() {
2973
+ const deviceInfo = deviceDetector.getDeviceInfo();
2974
+ return {
2975
+ browser_version: deviceInfo.browser.version,
2976
+ device_manufacturer: deviceInfo.device.vendor,
2977
+ device_name: deviceInfo.device.model,
2978
+ device_type: deviceInfo.device.type,
2979
+ os_name: deviceInfo.os.name,
2980
+ os_version: deviceInfo.os.version,
2981
+ cpu_type: deviceInfo.cpu.architecture,
2982
+ web_user_agent: deviceInfo.ua,
2983
+ display_height: window.innerHeight.toFixed(0),
2984
+ display_width: window.innerWidth.toFixed(0),
2985
+ language: navigator.language.split("-")[0],
2986
+ screen_density: deviceDetector.screenDensity,
2987
+ screen_format: deviceDetector.screenFormat,
2988
+ screen_size: deviceDetector.screenSize,
2989
+ ui_mode: deviceDetector.uiMode.toString(),
2990
+ cpu_lpc: navigator.hardwareConcurrency.toString(),
2991
+ ui_style: deviceDetector.uiStyle,
2992
+ wout_width: window.outerWidth.toString(),
2993
+ wout_height: window.outerHeight.toString(),
2994
+ web_engine: deviceInfo.engine.name,
2995
+ web_engine_version: deviceInfo.engine.version,
2996
+ display_size: deviceDetector.displaySize,
2997
+ screen_type: deviceDetector.screenType,
2998
+ };
2999
+ }
3000
+ }
3001
+ /** @internal */
3002
+ const fieldsBuilder = new FieldsBuilder();
3003
+
3004
+ /** @internal */
3005
+ class EventFieldsBuilder extends FieldsBuilder {
3006
+ constructor(event) {
3007
+ super();
3008
+ this.event = event;
3009
+ }
3010
+ build() {
3011
+ const _super = Object.create(null, {
3012
+ build: { get: () => super.build }
3013
+ });
3014
+ return __awaiter(this, void 0, void 0, function* () {
3015
+ const fields = yield _super.build.call(this);
3016
+ return new Promise((resolve) => {
3017
+ resolve(Object.assign(Object.assign({}, fields), this.event.toJSON()));
3018
+ });
3019
+ });
3020
+ }
3021
+ }
3022
+
3023
+ /** @internal */
3024
+ class WTTracker {
3025
+ constructor() {
3026
+ this.isRunning = false;
3027
+ this.initialized = false;
3028
+ }
3029
+ get isEnabled() {
3030
+ return storageManager.sdkEnabled;
3031
+ }
3032
+ initialize() {
3033
+ return __awaiter(this, void 0, void 0, function* () {
3034
+ this.getCountryCode();
3035
+ yield this.setActivityTimes();
3036
+ this.createDeviceID();
3037
+ this.addObservers();
3038
+ this.initialized = true;
3039
+ });
3040
+ }
3041
+ startTracking() {
3042
+ return __awaiter(this, void 0, void 0, function* () {
3043
+ if (!this.isEnabled) {
3044
+ WTLogger.warn("SDK is not enabled to start tracking!");
3045
+ return;
3046
+ }
3047
+ WTLogger.debug("WT Tracker started");
3048
+ yield queueManager.initialize();
3049
+ yield this.checkSdkClicks();
3050
+ yield this.checkFirstSession();
3051
+ yield this.createAttribution();
3052
+ this.isRunning = true;
3053
+ });
3054
+ }
3055
+ stopTracking() {
3056
+ return __awaiter(this, void 0, void 0, function* () {
3057
+ this.isRunning = false;
3058
+ activityTicker.stop();
3059
+ yield queueManager.shutdown();
3060
+ WTLogger.debug("WT Tracker stopped");
3061
+ });
3062
+ }
3063
+ checkPushToken(token) {
3064
+ return __awaiter(this, void 0, void 0, function* () {
3065
+ storageManager.pushToken = token;
3066
+ if (!this.isEnabled) {
3067
+ WTLogger.warn("CheckPushToken: SDK is not enabled");
3068
+ return;
3069
+ }
3070
+ if (storageManager.fcmToken === token) {
3071
+ WTLogger.info("This Notification token has sent to server previously");
3072
+ return;
3073
+ }
3074
+ yield this.createRequest({
3075
+ endpoint: WTEndpoints.SDK_INFOS,
3076
+ queueType: "pending",
3077
+ });
3078
+ });
3079
+ }
3080
+ trackEvent(event) {
3081
+ return __awaiter(this, void 0, void 0, function* () {
3082
+ if (!this.isEnabled) {
3083
+ WTLogger.warn("trackEvent: SDK is not enabled");
3084
+ return;
3085
+ }
3086
+ if (!this.initialized) {
3087
+ WTLogger.warn("trackEvent: SDK is not initialized yet");
3088
+ return;
3089
+ }
3090
+ storageManager.eventCount += 1;
3091
+ yield this.createRequest({
3092
+ endpoint: WTEndpoints.EVENTS,
3093
+ fBuilder: new EventFieldsBuilder(event),
3094
+ queueType: "pending",
3095
+ });
3096
+ });
3097
+ }
3098
+ // =======================================================================
3099
+ getCountryCode() {
3100
+ countryFinder.getCountryCode();
3101
+ }
3102
+ createAttribution() {
3103
+ return __awaiter(this, void 0, void 0, function* () {
3104
+ if (!this.isEnabled) {
3105
+ WTLogger.warn("Creating Attribution: SDK is not enabled!");
3106
+ return;
3107
+ }
3108
+ yield this.createRequest({
3109
+ endpoint: WTEndpoints.ATTRIBUTIONS,
3110
+ queueType: "pending",
3111
+ });
3112
+ });
3113
+ }
3114
+ checkFirstSession() {
3115
+ return __awaiter(this, void 0, void 0, function* () {
3116
+ if (!this.isEnabled) {
3117
+ WTLogger.warn("Creating First Session: SDK is not enabled!");
3118
+ return;
3119
+ }
3120
+ if (storageManager.firstSessionSubmit) {
3121
+ WTLogger.debug("Creating Session: First-Session has already submitted");
3122
+ return;
3123
+ }
3124
+ yield this.createRequest({
3125
+ endpoint: WTEndpoints.SESSIONS,
3126
+ queueType: storageManager.sdkClickSubmit ? "main" : "pending",
3127
+ });
3128
+ });
3129
+ }
3130
+ checkSdkClicks() {
3131
+ return __awaiter(this, void 0, void 0, function* () {
3132
+ if (!this.isEnabled) {
3133
+ WTLogger.warn("Creating Install: SDK is not enabled!");
3134
+ return;
3135
+ }
3136
+ if (storageManager.sdkClickSubmit) {
3137
+ WTLogger.debug("Creating Install: SDK-Clicks has already submitted");
3138
+ return;
3139
+ }
3140
+ yield this.createRequest({
3141
+ endpoint: WTEndpoints.SDK_CLICKS,
3142
+ });
3143
+ });
3144
+ }
3145
+ createRequest(_a) {
3146
+ return __awaiter(this, arguments, void 0, function* ({ endpoint, fBuilder = fieldsBuilder, queueType = "main", }) {
3147
+ const fields = yield fBuilder.build();
3148
+ const request = new RequestRecord(endpoint, fields);
3149
+ if (queueType === "pending") {
3150
+ WTLogger.info(`Add ${endpoint} request to pending queue`);
3151
+ yield queueManager.addPendingRequest(request);
3152
+ }
3153
+ else {
3154
+ WTLogger.info(`Add ${endpoint} request to main queue`);
3155
+ yield queueManager.addRequest(request);
3156
+ }
3157
+ const queueStatus = queueManager.getQueueStatus();
3158
+ console.log(JSON.stringify(queueStatus));
3159
+ });
3160
+ }
3161
+ createDeviceID() {
3162
+ if (!storageManager.deviceId) {
3163
+ storageManager.deviceId = cryptoHelper.generateDeviceUUID();
3164
+ }
3165
+ if (!storageManager.initialDate) {
3166
+ storageManager.initialDate = new Date().toISOString();
3167
+ }
3168
+ }
3169
+ setActivityTimes() {
3170
+ return __awaiter(this, void 0, void 0, function* () {
3171
+ // Update inactive time to last stored active time
3172
+ if (storageManager.activeTime) {
3173
+ storageManager.inactiveTime = storageManager.activeTime;
3174
+ const inteval = Date.now() - storageManager.inactiveTime;
3175
+ storageManager.inactiveDuration += inteval;
3176
+ console.log(`User was inactived for ${inteval / 1000}s | (${storageManager.inactiveDuration / 1000}s Totaly)`);
3177
+ yield this.checkSessionIntervals();
3178
+ }
3179
+ // update active time to now and start ticker for update active time/duration per 1s
3180
+ storageManager.activeTime = Date.now();
3181
+ activityTicker.start();
3182
+ });
3183
+ }
3184
+ checkSessionIntervals() {
3185
+ return __awaiter(this, void 0, void 0, function* () {
3186
+ var _a, _b;
3187
+ const inactiveTime = storageManager.inactiveTime;
3188
+ const sessionInterval = (_a = storageManager.appSettings) === null || _a === void 0 ? void 0 : _a.sessionInterval;
3189
+ const subsessionInterval = (_b = storageManager.appSettings) === null || _b === void 0 ? void 0 : _b.subsessionInterval;
3190
+ if (!this.isEnabled) {
3191
+ WTLogger.warn("Creating Session: SDK is not enabled!");
3192
+ return;
3193
+ }
3194
+ if (!inactiveTime || !sessionInterval || !subsessionInterval) {
3195
+ return;
3196
+ }
3197
+ const interval = Date.now() - inactiveTime;
3198
+ if (interval > parseInt(sessionInterval)) {
3199
+ storageManager.sessionCount += 1;
3200
+ yield this.createRequest({
3201
+ endpoint: WTEndpoints.SESSIONS,
3202
+ queueType: storageManager.sdkClickSubmit ? "main" : "pending",
3203
+ });
3204
+ }
3205
+ else if (interval > parseInt(subsessionInterval)) {
3206
+ storageManager.subSessionCount += 1;
3207
+ }
3208
+ });
3209
+ }
3210
+ isVisibleFocused() {
3211
+ return document.visibilityState === "visible" && document.hasFocus();
3212
+ }
3213
+ addObservers() {
3214
+ // document.addEventListener("load", () => {
3215
+ // this.setActivityTimes();
3216
+ // });
3217
+ window.addEventListener("beforeunload", () => {
3218
+ activityTicker.stop();
3219
+ });
3220
+ document.addEventListener("visibilitychange", () => {
3221
+ if (this.isVisibleFocused()) {
3222
+ this.createAttribution();
3223
+ this.setActivityTimes();
3224
+ }
3225
+ else {
3226
+ activityTicker.stop();
3227
+ }
3228
+ });
3229
+ window.addEventListener("focus", () => {
3230
+ if (this.isVisibleFocused()) {
3231
+ this.createAttribution();
3232
+ this.setActivityTimes();
3233
+ }
3234
+ });
3235
+ window.addEventListener("blur", () => {
3236
+ activityTicker.stop();
3237
+ });
3238
+ }
3239
+ }
3240
+ /** @internal */
3241
+ const tracker = new WTTracker();
3242
+
3243
+ /**
3244
+ * The main entry point for the WiseTrack Web SDK.
3245
+ *
3246
+ * Use this singleton to initialize the SDK, configure its behavior, and track events.
3247
+ *
3248
+ * @example
3249
+ * ```ts
3250
+ * const initialConfig: WTInitialConfig = {
3251
+ * appToken: appToken ?? "rMN5ZCwpOzY7",
3252
+ * appFrameWork: "native",
3253
+ * appVersion: "1.0.0",
3254
+ * };
3255
+ * await WiseTrack.instance.init(initialConfig);
3256
+ * ```
3257
+ */
3258
+ class WiseTrack {
3259
+ /**
3260
+ * Returns the singleton instance of the WiseTrack SDK.
3261
+ */
3262
+ static get instance() {
3263
+ if (!WiseTrack._instance) {
3264
+ WiseTrack._instance = new WiseTrack();
3265
+ }
3266
+ return WiseTrack._instance;
3267
+ }
3268
+ constructor() {
3269
+ this.sdkInitialized = false;
3270
+ }
3271
+ /**
3272
+ * Initializes the WiseTrack SDK with the given configuration.
3273
+ *
3274
+ * This method must be called before using any tracking features.
3275
+ *
3276
+ * @param initConfig - The initial configuration object.
3277
+ *
3278
+ * @example
3279
+ * ```ts
3280
+ * const initialConfig: WTInitialConfig = {
3281
+ * appToken: appToken ?? "rMN5ZCwpOzY7",
3282
+ * appFrameWork: "native", // your current web app framework (native, reactjs, nextjs, ...)
3283
+ * appVersion: "1.0.0", // your current web app version
3284
+ * };
3285
+ *
3286
+ * ```
3287
+ */
3288
+ init(initConfig) {
3289
+ return __awaiter(this, void 0, void 0, function* () {
3290
+ var _a, _b;
3291
+ const config = yield this.getConfig(initConfig);
3292
+ this.checkSdkEnabled(config);
3293
+ this.checkSdkUpdate(config);
3294
+ this.setEnabled(true);
3295
+ yield this.updateAppSettings(config);
3296
+ this.sdkInitialized = true;
3297
+ yield tracker.initialize();
3298
+ const autoStart = (_a = initConfig.startTrackerAutomatically) !== null && _a !== void 0 ? _a : true;
3299
+ if (autoStart) {
3300
+ setTimeout(() => this.startTracking(), ((_b = initConfig.trackingWaitingTime) !== null && _b !== void 0 ? _b : 0) * 1000);
3301
+ }
3302
+ });
3303
+ }
3304
+ /**
3305
+ * Sets the log level for internal SDK logging.
3306
+ *
3307
+ * @param level - The desired log level.
3308
+ *
3309
+ * @example
3310
+ * ```ts
3311
+ * WiseTrack.instance.setLogLevel(WTLogLevel.WARN)
3312
+ * // or
3313
+ * WiseTrack.instance.setLogLevel("warn")
3314
+ *
3315
+ * ```
3316
+ */
3317
+ setLogLevel(level) {
3318
+ WTLogger.setLevel(level);
3319
+ }
3320
+ /**
3321
+ * Clears all stored data and stops the tracker.
3322
+ */
3323
+ flush() {
3324
+ WTLogger.info("Clearing Data and stop tracker!");
3325
+ storageManager.clear();
3326
+ this.stopTracking();
3327
+ }
3328
+ /**
3329
+ * Returns whether the SDK is currently enabled.
3330
+ */
3331
+ isEnabled() {
3332
+ return storageManager.sdkEnabled;
3333
+ }
3334
+ /**
3335
+ * Enables or disables the SDK.
3336
+ *
3337
+ * Throws an error if the SDK is disabled by the server or needs an update.
3338
+ *
3339
+ * @param enabled - Whether to enable the SDK.
3340
+ * @throws If the server has disabled the SDK or a forced update is required.
3341
+ */
3342
+ setEnabled(enabled) {
3343
+ const config = storageManager.config;
3344
+ if (!config) {
3345
+ throw new Error("Config is not set!");
3346
+ }
3347
+ if (!config.sdkEnabled) {
3348
+ throw new Error("SDK is disabled form server, contact your adminstrator!");
3349
+ }
3350
+ if (config.forceUpdate) {
3351
+ throw new Error("The version you are currently using has expired and is no longer supported. Please update to the latest version to continue using the SDK");
3352
+ }
3353
+ storageManager.sdkEnabled = enabled;
3354
+ }
3355
+ /**
3356
+ * Starts the tracking process.
3357
+ *
3358
+ * @remarks
3359
+ * The SDK must be initialized and enabled before calling this method.
3360
+ *
3361
+ * NOTE: call this method just if you set startTrackerAutomatically=false in WTInitialConfig
3362
+ */
3363
+ startTracking() {
3364
+ return __awaiter(this, void 0, void 0, function* () {
3365
+ if (!this.sdkInitialized) {
3366
+ WTLogger.warn("‼️ Start Tracking: SDK is not initialized yet");
3367
+ return;
3368
+ }
3369
+ if (!this.isEnabled()) {
3370
+ WTLogger.warn("Start Tracking: SDK is not enabled!");
3371
+ return;
3372
+ }
3373
+ yield tracker.startTracking();
3374
+ });
3375
+ }
3376
+ /**
3377
+ * Stops the tracking process.
3378
+ */
3379
+ stopTracking() {
3380
+ return __awaiter(this, void 0, void 0, function* () {
3381
+ yield tracker.stopTracking();
3382
+ });
3383
+ }
3384
+ /**
3385
+ * Sets the Firebase Cloud Messaging (FCM) push token for server.
3386
+ *
3387
+ * @param token - The FCM token.
3388
+ */
3389
+ setFCMToken(token) {
3390
+ return __awaiter(this, void 0, void 0, function* () {
3391
+ if (!this.sdkInitialized) {
3392
+ WTLogger.warn("‼️ Set Fcm Token: SDK is not initialized yet");
3393
+ return;
3394
+ }
3395
+ if (!this.isEnabled()) {
3396
+ WTLogger.warn("Set Fcm Token: SDK is not enabled!");
3397
+ return;
3398
+ }
3399
+ yield tracker.checkPushToken(token);
3400
+ });
3401
+ }
3402
+ /**
3403
+ * Tracks a custom event or revenue event.
3404
+ *
3405
+ * @param event - The event object to be tracked.
3406
+ *
3407
+ * @example
3408
+ * ```ts
3409
+ * // Create a Default Event
3410
+ * const defaultEvent = new WTEvent.Default("default-event");
3411
+ * defaultEvent.addParam("key1", "value1");
3412
+ * defaultEvent.addParam("key2", 123);
3413
+ * defaultEvent.addParam("key3", true);
3414
+ * await WiseTrack.instance.trackEvent(defaultEvent);
3415
+ *
3416
+ * // Create a Revenue Event
3417
+ * const revenueEvent = new WTEvent.Revenue("revenue-event", 100, "USD");
3418
+ * revenueEvent.addParam("item_id", "item123");
3419
+ * revenueEvent.addParam("quantity", 2);
3420
+ * await WiseTrack.instance.trackEvent(revenueEvent);
3421
+ * ```
3422
+ */
3423
+ trackEvent(event) {
3424
+ return __awaiter(this, void 0, void 0, function* () {
3425
+ if (!this.sdkInitialized) {
3426
+ WTLogger.warn("‼️ Track Event: SDK is not initialized yet");
3427
+ return;
3428
+ }
3429
+ if (!this.isEnabled()) {
3430
+ WTLogger.warn("Track Event: SDK is not enabled!");
3431
+ return;
3432
+ }
3433
+ yield tracker.trackEvent(event);
3434
+ });
3435
+ }
3436
+ // ===========================================================================
3437
+ /** @internal */
3438
+ getConfig(initConfig) {
3439
+ return __awaiter(this, void 0, void 0, function* () {
3440
+ storageManager.initialConfig = initConfig;
3441
+ let config;
3442
+ try {
3443
+ config = yield apiClient.doGetConfig();
3444
+ }
3445
+ catch (error) {
3446
+ if (!(error instanceof ApiError.NetworkError)) {
3447
+ WTLogger.info("‼️ SDK Config NOT set!, check errors.");
3448
+ throw error;
3449
+ }
3450
+ config = storageManager.config || WTConfig.defaultValue;
3451
+ }
3452
+ storageManager.config = config;
3453
+ WTLogger.info("SDK Config set");
3454
+ return config;
3455
+ });
3456
+ }
3457
+ /** @internal */
3458
+ updateAppSettings(config) {
3459
+ return __awaiter(this, void 0, void 0, function* () {
3460
+ let appSettings;
3461
+ if (!EnvironmentUtils.needAppSettings()) {
3462
+ appSettings = WTAppSettings.fromConfig(config);
3463
+ }
3464
+ else {
3465
+ WTLogger.debug(`Need to get app-settings for ${EnvironmentUtils.sdkEnvironment} environment`);
3466
+ try {
3467
+ appSettings = yield apiClient.doGetAppSettings();
3468
+ }
3469
+ catch (error) {
3470
+ if (!(error instanceof ApiError.NetworkError)) {
3471
+ WTLogger.info("‼️ App Settings NOT set!, check errors.");
3472
+ throw error;
3473
+ }
3474
+ appSettings = WTAppSettings.defaultValue;
3475
+ }
3476
+ }
3477
+ storageManager.appSettings = appSettings;
3478
+ WTLogger.info("App Settings set");
3479
+ return appSettings;
3480
+ });
3481
+ }
3482
+ /** @internal */
3483
+ checkSdkEnabled(config) {
3484
+ if (!config.sdkEnabled) {
3485
+ const message = "SDK is disabled form server, contact your adminstrator!";
3486
+ WTLogger.error(message);
3487
+ throw new Error(message);
3488
+ }
3489
+ }
3490
+ /** @internal */
3491
+ checkSdkUpdate(config) {
3492
+ if (config.forceUpdate) {
3493
+ const message = "The version you are currently using has expired and is no longer supported. Please update to the latest version to continue using the SDK";
3494
+ WTLogger.error(message);
3495
+ throw new Error(message);
3496
+ }
3497
+ if (config.sdkUpdate) {
3498
+ WTLogger.warn("A new version of the SDK is available. It is recommended to update to the latest version to enjoy improved features and better performance.");
3499
+ }
3500
+ }
3501
+ }
3502
+
3503
+ exports.WTEvent = void 0;
3504
+ (function (WTEvent) {
3505
+ /**
3506
+ * Represents a generic custom event.
3507
+ *
3508
+ * Use this class to log custom actions performed by the user.
3509
+ *
3510
+ * @example
3511
+ * ```ts
3512
+ * const event = new WTEvent.Default("signup");
3513
+ * event.addParam("method", "Google");
3514
+ * WiseTrack.instance.trackEvent(event);
3515
+ * ```
3516
+ */
3517
+ class Default {
3518
+ /**
3519
+ * Creates a new custom event.
3520
+ * @param name - The name of the event.
3521
+ */
3522
+ constructor(name) {
3523
+ /**
3524
+ * The type of event.
3525
+ * @internal
3526
+ */
3527
+ this.type = "default";
3528
+ this.name = name;
3529
+ }
3530
+ /**
3531
+ * Adds a parameter to the event.
3532
+ *
3533
+ * @param key - The parameter key.
3534
+ * @param value - The parameter value.
3535
+ */
3536
+ addParam(key, value) {
3537
+ var _a;
3538
+ let _params = (_a = this.params) !== null && _a !== void 0 ? _a : {};
3539
+ _params[key] = value;
3540
+ this.params = _params;
3541
+ }
3542
+ /** @internal */
3543
+ toJSON() {
3544
+ return {
3545
+ event_type: this.type,
3546
+ event_name: this.name,
3547
+ partner_params: this.params,
3548
+ };
3549
+ }
3550
+ }
3551
+ WTEvent.Default = Default;
3552
+ /**
3553
+ * Represents a revenue event with an amount and currency.
3554
+ *
3555
+ * Use this class to log purchases or monetary transactions.
3556
+ *
3557
+ * @example
3558
+ * ```ts
3559
+ * const purchase = new WTEvent.Revenue("order_complete", 49.99, RevenueCurrency.USD);
3560
+ * purchase.addParam("item_count", "3");
3561
+ * WiseTrack.instance.trackEvent(purchase);
3562
+ * ```
3563
+ */
3564
+ class Revenue extends Default {
3565
+ /**
3566
+ * Creates a new revenue event.
3567
+ *
3568
+ * @param name - The name of the revenue event.
3569
+ * @param amount - The amount of revenue.
3570
+ * @param currency - The currency of the revenue.
3571
+ */
3572
+ constructor(name, amount, currency) {
3573
+ super(name);
3574
+ /**
3575
+ * The type of event.
3576
+ * @internal
3577
+ */
3578
+ this.type = "revenue";
3579
+ this.amount = amount;
3580
+ this.currency = currency;
3581
+ }
3582
+ /** @internal */
3583
+ toJSON() {
3584
+ return {
3585
+ event_type: this.type,
3586
+ event_name: this.name,
3587
+ revenue: this.amount,
3588
+ currency: this.currency,
3589
+ partner_params: this.params,
3590
+ };
3591
+ }
3592
+ }
3593
+ WTEvent.Revenue = Revenue;
3594
+ })(exports.WTEvent || (exports.WTEvent = {}));
3595
+
3596
+ exports.WTLogEngine = WTLogEngine;
3597
+ exports.WTLogLevel = WTLogLevel;
3598
+ exports.WTLogger = WTLogger;
3599
+ exports.WiseTrack = WiseTrack;
3600
+
3601
+ return exports;
3602
+
3603
+ })({});
3604
+ //# sourceMappingURL=sdk.bundle.js.map