@vitejs/devtools-kit 0.0.0-alpha.9 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js CHANGED
@@ -1,37 +1,1752 @@
1
- import { createRpcClient } from "@vitejs/devtools-rpc";
1
+ import { DEVTOOLS_CONNECTION_META_FILENAME, DEVTOOLS_MOUNT_PATH, DEVTOOLS_RPC_DUMP_MANIFEST_FILENAME } from "./constants.js";
2
+ import { createEventEmitter } from "./utils/events.js";
3
+ import { nanoid } from "./utils/nanoid.js";
4
+ import { createSharedState } from "./utils/shared-state.js";
5
+ import { RpcFunctionsCollectorBase } from "@vitejs/devtools-rpc";
6
+ import { createRpcClient } from "@vitejs/devtools-rpc/client";
2
7
  import { createWsRpcPreset } from "@vitejs/devtools-rpc/presets/ws/client";
3
-
4
- //#region src/client/index.ts
8
+ //#region src/client/rpc-shared-state.ts
9
+ function createRpcSharedStateClientHost(rpc) {
10
+ const sharedState = /* @__PURE__ */ new Map();
11
+ const isStaticBackend = rpc.connectionMeta.backend === "static";
12
+ rpc.client.register({
13
+ name: "devtoolskit:internal:rpc:client-state:updated",
14
+ type: "event",
15
+ handler: (key, fullState, syncId) => {
16
+ const state = sharedState.get(key);
17
+ if (!state || state.syncIds.has(syncId)) return;
18
+ state.mutate(() => fullState, syncId);
19
+ }
20
+ });
21
+ rpc.client.register({
22
+ name: "devtoolskit:internal:rpc:client-state:patch",
23
+ type: "event",
24
+ handler: (key, patches, syncId) => {
25
+ const state = sharedState.get(key);
26
+ if (!state || state.syncIds.has(syncId)) return;
27
+ state.patch(patches, syncId);
28
+ }
29
+ });
30
+ function registerSharedState(key, state) {
31
+ const offs = [];
32
+ offs.push(state.on("updated", (fullState, patches, syncId) => {
33
+ if (isStaticBackend) return;
34
+ if (patches) rpc.callEvent("devtoolskit:internal:rpc:server-state:patch", key, patches, syncId);
35
+ else rpc.callEvent("devtoolskit:internal:rpc:server-state:set", key, fullState, syncId);
36
+ }));
37
+ return () => {
38
+ for (const off of offs) off();
39
+ };
40
+ }
41
+ return {
42
+ keys: () => Array.from(sharedState.keys()),
43
+ get: async (key, options) => {
44
+ if (sharedState.has(key)) return sharedState.get(key);
45
+ const state = createSharedState({
46
+ initialValue: options?.initialValue,
47
+ enablePatches: false
48
+ });
49
+ async function initSharedState() {
50
+ if (!isStaticBackend) rpc.callEvent("devtoolskit:internal:rpc:server-state:subscribe", key);
51
+ if (options?.initialValue !== void 0) {
52
+ sharedState.set(key, state);
53
+ rpc.call("devtoolskit:internal:rpc:server-state:get", key).then((serverState) => {
54
+ state.mutate(() => serverState);
55
+ }).catch((error) => {
56
+ console.error("Error getting server state", error);
57
+ });
58
+ registerSharedState(key, state);
59
+ return state;
60
+ } else {
61
+ const initialValue = await rpc.call("devtoolskit:internal:rpc:server-state:get", key);
62
+ state.mutate(() => initialValue);
63
+ sharedState.set(key, state);
64
+ registerSharedState(key, state);
65
+ return state;
66
+ }
67
+ }
68
+ return new Promise((resolve) => {
69
+ if (!rpc.isTrusted) {
70
+ resolve(state);
71
+ rpc.events.on("rpc:is-trusted:updated", (isTrusted) => {
72
+ if (isTrusted) initSharedState();
73
+ });
74
+ } else initSharedState().then(resolve);
75
+ });
76
+ }
77
+ };
78
+ }
79
+ //#endregion
80
+ //#region ../../node_modules/.pnpm/ohash@2.0.11/node_modules/ohash/dist/shared/ohash.D__AXeF1.mjs
81
+ function serialize(o) {
82
+ return typeof o == "string" ? `'${o}'` : new c().serialize(o);
83
+ }
84
+ const c = /* @__PURE__ */ function() {
85
+ class o {
86
+ #t = /* @__PURE__ */ new Map();
87
+ compare(t, r) {
88
+ const e = typeof t, n = typeof r;
89
+ return e === "string" && n === "string" ? t.localeCompare(r) : e === "number" && n === "number" ? t - r : String.prototype.localeCompare.call(this.serialize(t, true), this.serialize(r, true));
90
+ }
91
+ serialize(t, r) {
92
+ if (t === null) return "null";
93
+ switch (typeof t) {
94
+ case "string": return r ? t : `'${t}'`;
95
+ case "bigint": return `${t}n`;
96
+ case "object": return this.$object(t);
97
+ case "function": return this.$function(t);
98
+ }
99
+ return String(t);
100
+ }
101
+ serializeObject(t) {
102
+ const r = Object.prototype.toString.call(t);
103
+ if (r !== "[object Object]") return this.serializeBuiltInType(r.length < 10 ? `unknown:${r}` : r.slice(8, -1), t);
104
+ const e = t.constructor, n = e === Object || e === void 0 ? "" : e.name;
105
+ if (n !== "" && globalThis[n] === e) return this.serializeBuiltInType(n, t);
106
+ if (typeof t.toJSON == "function") {
107
+ const i = t.toJSON();
108
+ return n + (i !== null && typeof i == "object" ? this.$object(i) : `(${this.serialize(i)})`);
109
+ }
110
+ return this.serializeObjectEntries(n, Object.entries(t));
111
+ }
112
+ serializeBuiltInType(t, r) {
113
+ const e = this["$" + t];
114
+ if (e) return e.call(this, r);
115
+ if (typeof r?.entries == "function") return this.serializeObjectEntries(t, r.entries());
116
+ throw new Error(`Cannot serialize ${t}`);
117
+ }
118
+ serializeObjectEntries(t, r) {
119
+ const e = Array.from(r).sort((i, a) => this.compare(i[0], a[0]));
120
+ let n = `${t}{`;
121
+ for (let i = 0; i < e.length; i++) {
122
+ const [a, l] = e[i];
123
+ n += `${this.serialize(a, true)}:${this.serialize(l)}`, i < e.length - 1 && (n += ",");
124
+ }
125
+ return n + "}";
126
+ }
127
+ $object(t) {
128
+ let r = this.#t.get(t);
129
+ return r === void 0 && (this.#t.set(t, `#${this.#t.size}`), r = this.serializeObject(t), this.#t.set(t, r)), r;
130
+ }
131
+ $function(t) {
132
+ const r = Function.prototype.toString.call(t);
133
+ return r.slice(-15) === "[native code] }" ? `${t.name || ""}()[native]` : `${t.name}(${t.length})${r.replace(/\s*\n\s*/g, "")}`;
134
+ }
135
+ $Array(t) {
136
+ let r = "[";
137
+ for (let e = 0; e < t.length; e++) r += this.serialize(t[e]), e < t.length - 1 && (r += ",");
138
+ return r + "]";
139
+ }
140
+ $Date(t) {
141
+ try {
142
+ return `Date(${t.toISOString()})`;
143
+ } catch {
144
+ return "Date(null)";
145
+ }
146
+ }
147
+ $ArrayBuffer(t) {
148
+ return `ArrayBuffer[${new Uint8Array(t).join(",")}]`;
149
+ }
150
+ $Set(t) {
151
+ return `Set${this.$Array(Array.from(t).sort((r, e) => this.compare(r, e)))}`;
152
+ }
153
+ $Map(t) {
154
+ return this.serializeObjectEntries("Map", t.entries());
155
+ }
156
+ }
157
+ for (const s of [
158
+ "Error",
159
+ "RegExp",
160
+ "URL"
161
+ ]) o.prototype["$" + s] = function(t) {
162
+ return `${s}(${t})`;
163
+ };
164
+ for (const s of [
165
+ "Int8Array",
166
+ "Uint8Array",
167
+ "Uint8ClampedArray",
168
+ "Int16Array",
169
+ "Uint16Array",
170
+ "Int32Array",
171
+ "Uint32Array",
172
+ "Float32Array",
173
+ "Float64Array"
174
+ ]) o.prototype["$" + s] = function(t) {
175
+ return `${s}[${t.join(",")}]`;
176
+ };
177
+ for (const s of ["BigInt64Array", "BigUint64Array"]) o.prototype["$" + s] = function(t) {
178
+ return `${s}[${t.join("n,")}${t.length > 0 ? "n" : ""}]`;
179
+ };
180
+ return o;
181
+ }();
182
+ //#endregion
183
+ //#region ../../node_modules/.pnpm/ohash@2.0.11/node_modules/ohash/dist/crypto/js/index.mjs
184
+ const z = [
185
+ 1779033703,
186
+ -1150833019,
187
+ 1013904242,
188
+ -1521486534,
189
+ 1359893119,
190
+ -1694144372,
191
+ 528734635,
192
+ 1541459225
193
+ ], R = [
194
+ 1116352408,
195
+ 1899447441,
196
+ -1245643825,
197
+ -373957723,
198
+ 961987163,
199
+ 1508970993,
200
+ -1841331548,
201
+ -1424204075,
202
+ -670586216,
203
+ 310598401,
204
+ 607225278,
205
+ 1426881987,
206
+ 1925078388,
207
+ -2132889090,
208
+ -1680079193,
209
+ -1046744716,
210
+ -459576895,
211
+ -272742522,
212
+ 264347078,
213
+ 604807628,
214
+ 770255983,
215
+ 1249150122,
216
+ 1555081692,
217
+ 1996064986,
218
+ -1740746414,
219
+ -1473132947,
220
+ -1341970488,
221
+ -1084653625,
222
+ -958395405,
223
+ -710438585,
224
+ 113926993,
225
+ 338241895,
226
+ 666307205,
227
+ 773529912,
228
+ 1294757372,
229
+ 1396182291,
230
+ 1695183700,
231
+ 1986661051,
232
+ -2117940946,
233
+ -1838011259,
234
+ -1564481375,
235
+ -1474664885,
236
+ -1035236496,
237
+ -949202525,
238
+ -778901479,
239
+ -694614492,
240
+ -200395387,
241
+ 275423344,
242
+ 430227734,
243
+ 506948616,
244
+ 659060556,
245
+ 883997877,
246
+ 958139571,
247
+ 1322822218,
248
+ 1537002063,
249
+ 1747873779,
250
+ 1955562222,
251
+ 2024104815,
252
+ -2067236844,
253
+ -1933114872,
254
+ -1866530822,
255
+ -1538233109,
256
+ -1090935817,
257
+ -965641998
258
+ ], S = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", r = [];
259
+ var k = class {
260
+ _data = new l();
261
+ _hash = new l([...z]);
262
+ _nDataBytes = 0;
263
+ _minBufferSize = 0;
264
+ finalize(e) {
265
+ e && this._append(e);
266
+ const s = this._nDataBytes * 8, t = this._data.sigBytes * 8;
267
+ return this._data.words[t >>> 5] |= 128 << 24 - t % 32, this._data.words[(t + 64 >>> 9 << 4) + 14] = Math.floor(s / 4294967296), this._data.words[(t + 64 >>> 9 << 4) + 15] = s, this._data.sigBytes = this._data.words.length * 4, this._process(), this._hash;
268
+ }
269
+ _doProcessBlock(e, s) {
270
+ const t = this._hash.words;
271
+ let i = t[0], o = t[1], a = t[2], c = t[3], h = t[4], g = t[5], f = t[6], y = t[7];
272
+ for (let n = 0; n < 64; n++) {
273
+ if (n < 16) r[n] = e[s + n] | 0;
274
+ else {
275
+ const d = r[n - 15], j = (d << 25 | d >>> 7) ^ (d << 14 | d >>> 18) ^ d >>> 3, B = r[n - 2], x = (B << 15 | B >>> 17) ^ (B << 13 | B >>> 19) ^ B >>> 10;
276
+ r[n] = j + r[n - 7] + x + r[n - 16];
277
+ }
278
+ const m = h & g ^ ~h & f, p = i & o ^ i & a ^ o & a, u = (i << 30 | i >>> 2) ^ (i << 19 | i >>> 13) ^ (i << 10 | i >>> 22), b = (h << 26 | h >>> 6) ^ (h << 21 | h >>> 11) ^ (h << 7 | h >>> 25), w = y + b + m + R[n] + r[n], M = u + p;
279
+ y = f, f = g, g = h, h = c + w | 0, c = a, a = o, o = i, i = w + M | 0;
280
+ }
281
+ t[0] = t[0] + i | 0, t[1] = t[1] + o | 0, t[2] = t[2] + a | 0, t[3] = t[3] + c | 0, t[4] = t[4] + h | 0, t[5] = t[5] + g | 0, t[6] = t[6] + f | 0, t[7] = t[7] + y | 0;
282
+ }
283
+ _append(e) {
284
+ typeof e == "string" && (e = l.fromUtf8(e)), this._data.concat(e), this._nDataBytes += e.sigBytes;
285
+ }
286
+ _process(e) {
287
+ let s, t = this._data.sigBytes / 64;
288
+ e ? t = Math.ceil(t) : t = Math.max((t | 0) - this._minBufferSize, 0);
289
+ const i = t * 16, o = Math.min(i * 4, this._data.sigBytes);
290
+ if (i) {
291
+ for (let a = 0; a < i; a += 16) this._doProcessBlock(this._data.words, a);
292
+ s = this._data.words.splice(0, i), this._data.sigBytes -= o;
293
+ }
294
+ return new l(s, o);
295
+ }
296
+ };
297
+ var l = class l {
298
+ words;
299
+ sigBytes;
300
+ constructor(e, s) {
301
+ e = this.words = e || [], this.sigBytes = s === void 0 ? e.length * 4 : s;
302
+ }
303
+ static fromUtf8(e) {
304
+ const s = unescape(encodeURIComponent(e)), t = s.length, i = [];
305
+ for (let o = 0; o < t; o++) i[o >>> 2] |= (s.charCodeAt(o) & 255) << 24 - o % 4 * 8;
306
+ return new l(i, t);
307
+ }
308
+ toBase64() {
309
+ const e = [];
310
+ for (let s = 0; s < this.sigBytes; s += 3) {
311
+ const t = this.words[s >>> 2] >>> 24 - s % 4 * 8 & 255, i = this.words[s + 1 >>> 2] >>> 24 - (s + 1) % 4 * 8 & 255, o = this.words[s + 2 >>> 2] >>> 24 - (s + 2) % 4 * 8 & 255, a = t << 16 | i << 8 | o;
312
+ for (let c = 0; c < 4 && s * 8 + c * 6 < this.sigBytes * 8; c++) e.push(S.charAt(a >>> 6 * (3 - c) & 63));
313
+ }
314
+ return e.join("");
315
+ }
316
+ concat(e) {
317
+ if (this.words[this.sigBytes >>> 2] &= 4294967295 << 32 - this.sigBytes % 4 * 8, this.words.length = Math.ceil(this.sigBytes / 4), this.sigBytes % 4) for (let s = 0; s < e.sigBytes; s++) {
318
+ const t = e.words[s >>> 2] >>> 24 - s % 4 * 8 & 255;
319
+ this.words[this.sigBytes + s >>> 2] |= t << 24 - (this.sigBytes + s) % 4 * 8;
320
+ }
321
+ else for (let s = 0; s < e.sigBytes; s += 4) this.words[this.sigBytes + s >>> 2] = e.words[s >>> 2];
322
+ this.sigBytes += e.sigBytes;
323
+ }
324
+ };
325
+ function digest(_) {
326
+ return new k().finalize(_).toBase64();
327
+ }
328
+ //#endregion
329
+ //#region ../../node_modules/.pnpm/ohash@2.0.11/node_modules/ohash/dist/index.mjs
330
+ function hash(input) {
331
+ return digest(serialize(input));
332
+ }
333
+ //#endregion
334
+ //#region src/client/static-rpc.ts
335
+ function isStaticEntry(value) {
336
+ return typeof value === "object" && value !== null && value.type === "static" && typeof value.path === "string";
337
+ }
338
+ function isQueryEntry(value) {
339
+ return typeof value === "object" && value !== null && value.type === "query" && typeof value.records === "object" && value.records !== null;
340
+ }
341
+ function isRecord(value) {
342
+ return typeof value === "object" && value !== null && ("output" in value || "error" in value);
343
+ }
344
+ function resolveRecordOutput(record) {
345
+ if (record.error) {
346
+ const error = new Error(record.error.message);
347
+ error.name = record.error.name;
348
+ throw error;
349
+ }
350
+ return record.output;
351
+ }
352
+ function createStaticRpcCaller(manifest, fetchJson) {
353
+ const staticCache = /* @__PURE__ */ new Map();
354
+ const queryRecordCache = /* @__PURE__ */ new Map();
355
+ async function loadStatic(entry) {
356
+ if (!staticCache.has(entry.path)) staticCache.set(entry.path, fetchJson(entry.path));
357
+ const data = await staticCache.get(entry.path);
358
+ if (isRecord(data)) return resolveRecordOutput(data);
359
+ return data;
360
+ }
361
+ async function loadQueryRecord(path) {
362
+ if (!queryRecordCache.has(path)) queryRecordCache.set(path, fetchJson(path));
363
+ return await queryRecordCache.get(path);
364
+ }
365
+ async function call(functionName, args) {
366
+ if (!(functionName in manifest)) throw new Error(`[devtools-rpc] Function "${functionName}" not found in dump store`);
367
+ const entry = manifest[functionName];
368
+ if (isStaticEntry(entry)) {
369
+ if (args.length > 0) throw new Error(`[devtools-rpc] No dump match for "${functionName}" with args: ${JSON.stringify(args)}`);
370
+ return await loadStatic(entry);
371
+ }
372
+ if (isQueryEntry(entry)) {
373
+ const argsHash = hash(args);
374
+ const recordPath = entry.records[argsHash];
375
+ if (recordPath) return resolveRecordOutput(await loadQueryRecord(recordPath));
376
+ if (entry.fallback) return resolveRecordOutput(await loadQueryRecord(entry.fallback));
377
+ throw new Error(`[devtools-rpc] No dump match for "${functionName}" with args: ${JSON.stringify(args)}`);
378
+ }
379
+ if (args.length === 0) return entry;
380
+ throw new Error(`[devtools-rpc] No dump match for "${functionName}" with args: ${JSON.stringify(args)}`);
381
+ }
382
+ return {
383
+ call: async (functionName, args) => await call(functionName, args),
384
+ callOptional: async (functionName, args) => {
385
+ if (!(functionName in manifest)) return void 0;
386
+ return await call(functionName, args);
387
+ },
388
+ callEvent: async (_functionName, _args) => {}
389
+ };
390
+ }
391
+ //#endregion
392
+ //#region src/client/rpc-static.ts
393
+ async function createStaticRpcClientMode(options) {
394
+ const staticCaller = createStaticRpcCaller(await options.fetchJsonFromBases(DEVTOOLS_RPC_DUMP_MANIFEST_FILENAME), options.fetchJsonFromBases);
395
+ return {
396
+ isTrusted: true,
397
+ requestTrust: async () => true,
398
+ ensureTrusted: async () => true,
399
+ call: (...args) => staticCaller.call(args[0], args.slice(1)),
400
+ callEvent: (...args) => staticCaller.callEvent(args[0], args.slice(1)),
401
+ callOptional: (...args) => staticCaller.callOptional(args[0], args.slice(1))
402
+ };
403
+ }
404
+ //#endregion
405
+ //#region ../../node_modules/.pnpm/ua-parser-modern@0.1.1/node_modules/ua-parser-modern/dist/index.mjs
406
+ const EMPTY = "";
407
+ const UNKNOWN = "?";
408
+ const MAJOR = "major";
409
+ const MODEL = "model";
410
+ const NAME = "name";
411
+ const TYPE = "type";
412
+ const VENDOR = "vendor";
413
+ const VERSION = "version";
414
+ const ARCHITECTURE = "architecture";
415
+ const CONSOLE = "console";
416
+ const MOBILE = "mobile";
417
+ const TABLET = "tablet";
418
+ const SMARTTV = "smarttv";
419
+ const WEARABLE = "wearable";
420
+ const EMBEDDED = "embedded";
421
+ const UA_MAX_LENGTH = 500;
422
+ const AMAZON = "Amazon";
423
+ const APPLE = "Apple";
424
+ const ASUS = "ASUS";
425
+ const BLACKBERRY = "BlackBerry";
426
+ const BROWSER_LABEL = "Browser";
427
+ const CHROME = "Chrome";
428
+ const EDGE = "Edge";
429
+ const FIREFOX = "Firefox";
430
+ const GOOGLE = "Google";
431
+ const HUAWEI = "Huawei";
432
+ const LG = "LG";
433
+ const MICROSOFT = "Microsoft";
434
+ const MOTOROLA = "Motorola";
435
+ const OPERA = "Opera";
436
+ const SAMSUNG = "Samsung";
437
+ const SHARP = "Sharp";
438
+ const SONY = "Sony";
439
+ const XIAOMI = "Xiaomi";
440
+ const ZEBRA = "Zebra";
441
+ const FACEBOOK = "Facebook";
442
+ const CHROMIUM_OS = "Chromium OS";
443
+ const MAC_OS = "Mac OS";
444
+ function extend(regexes, extensions = {}) {
445
+ const mergedRegexes = {};
446
+ for (const key of Object.keys(regexes)) {
447
+ const extension = extensions[key];
448
+ if (extension && extension.length % 2 === 0) mergedRegexes[key] = [...extension, ...regexes[key]];
449
+ else mergedRegexes[key] = regexes[key];
450
+ }
451
+ return mergedRegexes;
452
+ }
453
+ function enumerize(arr) {
454
+ const enums = {};
455
+ for (let i = 0; i < arr.length; i++) enums[arr[i].toUpperCase()] = arr[i];
456
+ return enums;
457
+ }
458
+ function lowerize(str) {
459
+ return str.toLowerCase();
460
+ }
461
+ function has(str1, str2) {
462
+ return typeof str1 === "string" ? lowerize(str2).includes(lowerize(str1)) : false;
463
+ }
464
+ function majorize(version) {
465
+ return typeof version === "string" ? version.replace(/[^\d.]/g, EMPTY).split(".")[0] : void 0;
466
+ }
467
+ function trim(str, len) {
468
+ const result = str.replace(/^\s+/, EMPTY);
469
+ return typeof len === "undefined" ? result : result.substring(0, len);
470
+ }
471
+ function rgxMapper(ua, arrays, augment) {
472
+ const result = augment ?? {};
473
+ for (let i = 0; i < arrays.length; i += 2) {
474
+ const regex = arrays[i];
475
+ const props = arrays[i + 1];
476
+ for (let j = 0; j < regex.length; j++) {
477
+ const matcher = regex[j];
478
+ if (!matcher) break;
479
+ const matches = matcher.exec(ua);
480
+ if (!matches) continue;
481
+ for (let p = 0; p < props.length; p++) {
482
+ const match = matches[p + 1];
483
+ const q = props[p];
484
+ if (Array.isArray(q)) {
485
+ const key = q[0];
486
+ const length = q.length;
487
+ if (length === 2) {
488
+ const value = q[1];
489
+ if (typeof value === "function") result[key] = value(match, void 0, result);
490
+ else result[key] = value;
491
+ } else if (length === 3) {
492
+ const arg1 = q[1];
493
+ const arg2 = q[2];
494
+ if (typeof arg1 === "function" && !("exec" in arg1) && !("test" in arg1)) result[key] = match ? arg1(match, arg2, result) : void 0;
495
+ else result[key] = match ? match.replace(arg1, arg2) : void 0;
496
+ } else if (length === 4) result[key] = match ? q[3](match.replace(q[1], q[2]), void 0, result) : void 0;
497
+ } else result[q] = match || void 0;
498
+ }
499
+ return result;
500
+ }
501
+ }
502
+ return result;
503
+ }
504
+ function strMapper(str, map) {
505
+ for (const i in map) {
506
+ const value = map[i];
507
+ if (Array.isArray(value) && value.length > 0) {
508
+ for (let j = 0; j < value.length; j++) if (has(value[j], str)) return i === UNKNOWN ? void 0 : i;
509
+ } else if (has(value, str)) return i === UNKNOWN ? void 0 : i;
510
+ }
511
+ return str;
512
+ }
513
+ const oldSafariMap = {
514
+ "1.0": "/8",
515
+ "1.2": "/1",
516
+ "1.3": "/3",
517
+ "2.0": "/412",
518
+ "2.0.2": "/416",
519
+ "2.0.3": "/417",
520
+ "2.0.4": "/419",
521
+ "?": "/"
522
+ };
523
+ const windowsVersionMap = {
524
+ "ME": "4.90",
525
+ "NT 3.11": "NT3.51",
526
+ "NT 4.0": "NT4.0",
527
+ "2000": "NT 5.0",
528
+ "XP": ["NT 5.1", "NT 5.2"],
529
+ "Vista": "NT 6.0",
530
+ "7": "NT 6.1",
531
+ "8": "NT 6.2",
532
+ "8.1": "NT 6.3",
533
+ "10": ["NT 6.4", "NT 10.0"],
534
+ "RT": "ARM"
535
+ };
536
+ const regexes = {
537
+ browser: [
538
+ [/\b(?:crmo|crios)\/([\w.]+)/i],
539
+ [VERSION, [NAME, "Chrome"]],
540
+ [/edg(?:e|ios|a)?\/([\w.]+)/i],
541
+ [VERSION, [NAME, "Edge"]],
542
+ [
543
+ /(opera mini)\/([-\w.]+)/i,
544
+ /(opera [mobileta]{3,6})\b.+version\/([-\w.]+)/i,
545
+ /(opera)(?:.+version\/|[/ ]+)([\w.]+)/i
546
+ ],
547
+ [NAME, VERSION],
548
+ [/opios[/ ]+([\w.]+)/i],
549
+ [VERSION, [NAME, `${OPERA} Mini`]],
550
+ [/\bop(?:rg)?x\/([\w.]+)/i],
551
+ [VERSION, [NAME, `${OPERA} GX`]],
552
+ [/\bopr\/([\w.]+)/i],
553
+ [VERSION, [NAME, OPERA]],
554
+ [/\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[/ ]?([\w.]+)/i],
555
+ [VERSION, [NAME, "Baidu"]],
556
+ [
557
+ /(kindle)\/([\w.]+)/i,
558
+ /(lunascape|maxthon|netfront|jasmine|blazer)[/ ]?([\w.]*)/i,
559
+ /(avant|iemobile|slim)\s?(?:browser)?[/ ]?([\w.]*)/i,
560
+ /(?:ms|\()(ie) ([\w.]+)/i,
561
+ /(flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|qq|duckduckgo)\/([-\w.]+)/i,
562
+ /(heytap|ovi)browser\/([\d.]+)/i,
563
+ /(weibo)__([\d.]+)/i
564
+ ],
565
+ [NAME, VERSION],
566
+ [/\bddg\/([\w.]+)/i],
567
+ [VERSION, [NAME, "DuckDuckGo"]],
568
+ [/(?:\buc? ?browser|juc.+ucweb)[/ ]?([\w.]+)/i],
569
+ [VERSION, [NAME, `UC${BROWSER_LABEL}`]],
570
+ [
571
+ /microm.+\bqbcore\/([\w.]+)/i,
572
+ /\bqbcore\/([\w.]+).+microm/i,
573
+ /micromessenger\/([\w.]+)/i
574
+ ],
575
+ [VERSION, [NAME, "WeChat"]],
576
+ [/konqueror\/([\w.]+)/i],
577
+ [VERSION, [NAME, "Konqueror"]],
578
+ [/trident.+rv[: ]([\w.]{1,9})\b.+like gecko/i],
579
+ [VERSION, [NAME, "IE"]],
580
+ [/ya(?:search)?browser\/([\w.]+)/i],
581
+ [VERSION, [NAME, "Yandex"]],
582
+ [/slbrowser\/([\w.]+)/i],
583
+ [VERSION, [NAME, `Smart Lenovo ${BROWSER_LABEL}`]],
584
+ [/(avast|avg)\/([\w.]+)/i],
585
+ [[
586
+ NAME,
587
+ /(.+)/,
588
+ `$1 Secure ${BROWSER_LABEL}`
589
+ ], VERSION],
590
+ [/\bfocus\/([\w.]+)/i],
591
+ [VERSION, [NAME, `${FIREFOX} Focus`]],
592
+ [/\bopt\/([\w.]+)/i],
593
+ [VERSION, [NAME, `${OPERA} Touch`]],
594
+ [/coc_coc\w+\/([\w.]+)/i],
595
+ [VERSION, [NAME, "Coc Coc"]],
596
+ [/dolfin\/([\w.]+)/i],
597
+ [VERSION, [NAME, "Dolphin"]],
598
+ [/coast\/([\w.]+)/i],
599
+ [VERSION, [NAME, `${OPERA} Coast`]],
600
+ [/miuibrowser\/([\w.]+)/i],
601
+ [VERSION, [NAME, `MIUI ${BROWSER_LABEL}`]],
602
+ [/fxios\/([-\w.]+)/i],
603
+ [VERSION, [NAME, FIREFOX]],
604
+ [/\bqihu|(qi?ho{0,2}|360)browser/i],
605
+ [[NAME, `360 ${BROWSER_LABEL}`]],
606
+ [/(oculus|sailfish|huawei|vivo)browser\/([\w.]+)/i],
607
+ [[
608
+ NAME,
609
+ /(.+)/,
610
+ `$1 ${BROWSER_LABEL}`
611
+ ], VERSION],
612
+ [/samsungbrowser\/([\w.]+)/i],
613
+ [VERSION, [NAME, `${SAMSUNG} Internet`]],
614
+ [/(comodo_dragon)\/([\w.]+)/i],
615
+ [[
616
+ NAME,
617
+ /_/g,
618
+ " "
619
+ ], VERSION],
620
+ [/metasr[/ ]?([\d.]+)/i],
621
+ [VERSION, [NAME, "Sogou Explorer"]],
622
+ [/(sogou)mo\w+\/([\d.]+)/i],
623
+ [[NAME, "Sogou Mobile"], VERSION],
624
+ [
625
+ /(electron)\/([\w.]+) safari/i,
626
+ /(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w.]+))/i,
627
+ /m?(qqbrowser|2345Explorer)[/ ]?([\w.]+)/i
628
+ ],
629
+ [NAME, VERSION],
630
+ [/(lbbrowser)/i, /\[(linkedin)app\]/i],
631
+ [NAME],
632
+ [/((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w.]+);)/i],
633
+ [[NAME, FACEBOOK], VERSION],
634
+ [
635
+ /(Klarna)\/([\w.]+)/i,
636
+ /(kakao(?:talk|story))[/ ]([\w.]+)/i,
637
+ /(naver)\(.*?(\d+\.[\w.]+).*\)/i,
638
+ /safari (line)\/([\w.]+)/i,
639
+ /\b(line)\/([\w.]+)\/iab/i,
640
+ /(alipay)client\/([\w.]+)/i,
641
+ /(twitter)(?:and| f.+e\/([\w.]+))/i,
642
+ /(chromium|instagram|snapchat)[/ ]([-\w.]+)/i
643
+ ],
644
+ [NAME, VERSION],
645
+ [/\bgsa\/([\w.]+) .*safari\//i],
646
+ [VERSION, [NAME, "GSA"]],
647
+ [/musical_ly(?:.+app_?version\/|_)([\w.]+)/i],
648
+ [VERSION, [NAME, "TikTok"]],
649
+ [/headlesschrome(?:\/([\w.]+)| )/i],
650
+ [VERSION, [NAME, `${CHROME} Headless`]],
651
+ [/ wv\).+(chrome)\/([\w.]+)/i],
652
+ [[NAME, `${CHROME} WebView`], VERSION],
653
+ [/droid.+ version\/([\w.]+)\b.+(?:mobile safari|safari)/i],
654
+ [VERSION, [NAME, `Android ${BROWSER_LABEL}`]],
655
+ [/(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w.]+)/i],
656
+ [NAME, VERSION],
657
+ [/version\/([\w.,]+) .*mobile\/\w+ (safari)/i],
658
+ [VERSION, [NAME, "Mobile Safari"]],
659
+ [/version\/([\w(.|,)]+) .*(mobile ?safari|safari)/i],
660
+ [VERSION, NAME],
661
+ [/webkit.+?(mobile ?safari|safari)(\/[\w.]+)/i],
662
+ [NAME, [
663
+ VERSION,
664
+ strMapper,
665
+ oldSafariMap
666
+ ]],
667
+ [/(webkit|khtml)\/([\w.]+)/i],
668
+ [NAME, VERSION],
669
+ [/(navigator|netscape\d?)\/([-\w.]+)/i],
670
+ [[NAME, "Netscape"], VERSION],
671
+ [/mobile vr; rv:([\w.]+)\).+firefox/i],
672
+ [VERSION, [NAME, `${FIREFOX} Reality`]],
673
+ [
674
+ /ekiohf.+(flow)\/([\w.]+)/i,
675
+ /(swiftfox)/i,
676
+ /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror|klar)[/ ]?([\w.+]+)/i,
677
+ /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w.]+)$/i,
678
+ /(firefox)\/([\w.]+)/i,
679
+ /(mozilla)\/([\w.]+) .+rv:.+gecko\/\d+/i,
680
+ /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir|obigo|mosaic|(?:go|ice|up)[. ]?browser)[-/ ]?v?([\w.]+)/i,
681
+ /(links) \(([\w.]+)/i,
682
+ /panasonic;(viera)/i
683
+ ],
684
+ [NAME, VERSION],
685
+ [/(cobalt)\/([\w.]+)/i],
686
+ [NAME, [
687
+ VERSION,
688
+ /master.|lts./,
689
+ ""
690
+ ]]
691
+ ],
692
+ cpu: [
693
+ [/(amd|x(?:(?:86|64)[-_])?|wow|win)64[;)]/i],
694
+ [[ARCHITECTURE, "amd64"]],
695
+ [/(ia32(?=;))/i],
696
+ [[ARCHITECTURE, lowerize]],
697
+ [/((?:i[346]|x)86)[;)]/i],
698
+ [[ARCHITECTURE, "ia32"]],
699
+ [/\b(aarch64|arm(v?8e?l?|_?64))\b/i],
700
+ [[ARCHITECTURE, "arm64"]],
701
+ [/\b(arm(?:v[67])?ht?n?[fl]p?)\b/i],
702
+ [[ARCHITECTURE, "armhf"]],
703
+ [/windows (ce|mobile); ppc;/i],
704
+ [[ARCHITECTURE, "arm"]],
705
+ [/((?:ppc|powerpc)(?:64)?)(?: mac|;|\))/i],
706
+ [[
707
+ ARCHITECTURE,
708
+ /ower/,
709
+ EMPTY,
710
+ lowerize
711
+ ]],
712
+ [/(sun4\w)[;)]/i],
713
+ [[ARCHITECTURE, "sparc"]],
714
+ [/(avr32|ia64(?=;)|68k(?=\))|\barm(?=v(?:[1-7]|[5-7]1)l?|;|eabi)|(?=atmel )avr|(?:irix|mips|sparc)(?:64)?\b|pa-risc)/i],
715
+ [[ARCHITECTURE, lowerize]]
716
+ ],
717
+ device: [
718
+ [/\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],
719
+ [
720
+ MODEL,
721
+ [VENDOR, SAMSUNG],
722
+ [TYPE, TABLET]
723
+ ],
724
+ [
725
+ /\b((?:s[cgp]h|gt|sm)-\w+|sc[g-]?\d+a?|galaxy nexus)/i,
726
+ /samsung[- ]([-\w]+)/i,
727
+ /sec-(sgh\w+)/i
728
+ ],
729
+ [
730
+ MODEL,
731
+ [VENDOR, SAMSUNG],
732
+ [TYPE, MOBILE]
733
+ ],
734
+ [/(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i],
735
+ [
736
+ MODEL,
737
+ [VENDOR, APPLE],
738
+ [TYPE, MOBILE]
739
+ ],
740
+ [
741
+ /\((ipad);[-\w),; ]+apple/i,
742
+ /applecoremedia\/[\w.]+ \((ipad)/i,
743
+ /\b(ipad)\d\d?,\d\d?[;\]].+ios/i
744
+ ],
745
+ [
746
+ MODEL,
747
+ [VENDOR, APPLE],
748
+ [TYPE, TABLET]
749
+ ],
750
+ [/(macintosh);/i],
751
+ [MODEL, [VENDOR, APPLE]],
752
+ [/\b(sh-?[altvz]?\d\d[a-ekm]?)/i],
753
+ [
754
+ MODEL,
755
+ [VENDOR, SHARP],
756
+ [TYPE, MOBILE]
757
+ ],
758
+ [/\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\d{2})\b(?!.+d\/s)/i],
759
+ [
760
+ MODEL,
761
+ [VENDOR, HUAWEI],
762
+ [TYPE, TABLET]
763
+ ],
764
+ [/(?:huawei|honor)([-\w ]+)[;)]/i, /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][0-359c][adn]?)\b(?!.+d\/s)/i],
765
+ [
766
+ MODEL,
767
+ [VENDOR, HUAWEI],
768
+ [TYPE, MOBILE]
769
+ ],
770
+ [
771
+ /\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i,
772
+ /\b; (\w+) build\/hm\1/i,
773
+ /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i,
774
+ /\b(redmi[\-_ ]?[\w ]+)(?: bui|\))/i,
775
+ /oid[^)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i,
776
+ /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?\d?\w?[_ ]?(?:plus|se|lite)?)(?: bui|\))/i
777
+ ],
778
+ [
779
+ [
780
+ MODEL,
781
+ /_/g,
782
+ " "
783
+ ],
784
+ [VENDOR, XIAOMI],
785
+ [TYPE, MOBILE]
786
+ ],
787
+ [/oid[^)]+; (2\d{4}(283|rpbf)[cgl])( bui|\))/i, /\b(mi[-_ ]?pad[\w ]+)(?: bui|\))/i],
788
+ [
789
+ [
790
+ MODEL,
791
+ /_/g,
792
+ " "
793
+ ],
794
+ [VENDOR, XIAOMI],
795
+ [TYPE, TABLET]
796
+ ],
797
+ [/; (\w+) bui.+ oppo/i, /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i],
798
+ [
799
+ MODEL,
800
+ [VENDOR, "OPPO"],
801
+ [TYPE, MOBILE]
802
+ ],
803
+ [/\b(opd2\d{3}a?) bui/i],
804
+ [
805
+ MODEL,
806
+ [VENDOR, "OPPO"],
807
+ [TYPE, TABLET]
808
+ ],
809
+ [/vivo (\w+)(?: bui|\))/i, /\b(v[12]\d{3}\w?[at])(?: bui|;)/i],
810
+ [
811
+ MODEL,
812
+ [VENDOR, "Vivo"],
813
+ [TYPE, MOBILE]
814
+ ],
815
+ [/\b(rmx[1-3]\d{3})(?: bui|;|\))/i],
816
+ [
817
+ MODEL,
818
+ [VENDOR, "Realme"],
819
+ [TYPE, MOBILE]
820
+ ],
821
+ [
822
+ /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
823
+ /\bmot(?:orola)?[- ](\w*)/i,
824
+ /((?:moto[\w() ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i
825
+ ],
826
+ [
827
+ MODEL,
828
+ [VENDOR, MOTOROLA],
829
+ [TYPE, MOBILE]
830
+ ],
831
+ [/\b(mz60\d|xoom[2 ]{0,2}) build\//i],
832
+ [
833
+ MODEL,
834
+ [VENDOR, MOTOROLA],
835
+ [TYPE, TABLET]
836
+ ],
837
+ [/((?=lg)?[vl]k-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i],
838
+ [
839
+ MODEL,
840
+ [VENDOR, LG],
841
+ [TYPE, TABLET]
842
+ ],
843
+ [
844
+ /(lm(?:-?f100[nv]?|-[\w.]+)(?= bui|\))|nexus [45])/i,
845
+ /\blg[-e;/ ]+((?!browser|netcast|android tv)\w+)/i,
846
+ /\blg-?(\w+) bui/i
847
+ ],
848
+ [
849
+ MODEL,
850
+ [VENDOR, LG],
851
+ [TYPE, MOBILE]
852
+ ],
853
+ [/(ideatab[-\w ]+)/i, /lenovo ?(s[56]000[-\w]+|tab[\w ]+|yt[-\w]{6}|tb[-\w]{6})/i],
854
+ [
855
+ MODEL,
856
+ [VENDOR, "Lenovo"],
857
+ [TYPE, TABLET]
858
+ ],
859
+ [/(?:maemo|nokia).*(n900|lumia \d+)/i, /nokia[-_ ]?([-\w.]*)/i],
860
+ [
861
+ [
862
+ MODEL,
863
+ /_/g,
864
+ " "
865
+ ],
866
+ [VENDOR, "Nokia"],
867
+ [TYPE, MOBILE]
868
+ ],
869
+ [/(pixel c)\b/i],
870
+ [
871
+ MODEL,
872
+ [VENDOR, GOOGLE],
873
+ [TYPE, TABLET]
874
+ ],
875
+ [/droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i],
876
+ [
877
+ MODEL,
878
+ [VENDOR, GOOGLE],
879
+ [TYPE, MOBILE]
880
+ ],
881
+ [/droid.+ (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]?\d\.))/i],
882
+ [
883
+ MODEL,
884
+ [VENDOR, SONY],
885
+ [TYPE, MOBILE]
886
+ ],
887
+ [/sony tablet [ps]/i, /\b(?:sony)?sgp\w+(?: bui|\))/i],
888
+ [
889
+ [MODEL, "Xperia Tablet"],
890
+ [VENDOR, SONY],
891
+ [TYPE, TABLET]
892
+ ],
893
+ [/ (kb2005|in20[12]5|be20[12][59])\b/i, /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i],
894
+ [
895
+ MODEL,
896
+ [VENDOR, "OnePlus"],
897
+ [TYPE, MOBILE]
898
+ ],
899
+ [
900
+ /(alexa)webm/i,
901
+ /(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i,
902
+ /(kf[a-z]+)( bui|\)).+silk\//i
903
+ ],
904
+ [
905
+ MODEL,
906
+ [VENDOR, AMAZON],
907
+ [TYPE, TABLET]
908
+ ],
909
+ [/((?:sd|kf)[0349hijor-uw]+)( bui|\)).+silk\//i],
910
+ [
911
+ [
912
+ MODEL,
913
+ /(.+)/g,
914
+ "Fire Phone $1"
915
+ ],
916
+ [VENDOR, AMAZON],
917
+ [TYPE, MOBILE]
918
+ ],
919
+ [/(playbook);[-\w),; ]+(rim)/i],
920
+ [
921
+ MODEL,
922
+ VENDOR,
923
+ [TYPE, TABLET]
924
+ ],
925
+ [/\b((?:bb[a-f]|st[hv])100-\d)/i, /\(bb10; (\w+)/i],
926
+ [
927
+ MODEL,
928
+ [VENDOR, BLACKBERRY],
929
+ [TYPE, MOBILE]
930
+ ],
931
+ [/(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i],
932
+ [
933
+ MODEL,
934
+ [VENDOR, ASUS],
935
+ [TYPE, TABLET]
936
+ ],
937
+ [/ (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i],
938
+ [
939
+ MODEL,
940
+ [VENDOR, ASUS],
941
+ [TYPE, MOBILE]
942
+ ],
943
+ [/(nexus 9)/i],
944
+ [
945
+ MODEL,
946
+ [VENDOR, "HTC"],
947
+ [TYPE, TABLET]
948
+ ],
949
+ [
950
+ /(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i,
951
+ /(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,
952
+ /(alcatel|geeksphone|nexian|panasonic(?!;|\.)|sony(?!-bra))[-_ ]?([-\w]*)/i
953
+ ],
954
+ [
955
+ VENDOR,
956
+ [
957
+ MODEL,
958
+ /_/g,
959
+ " "
960
+ ],
961
+ [TYPE, MOBILE]
962
+ ],
963
+ [/droid.+; ([ab][1-7]-?[0178a]\d\d?)/i],
964
+ [
965
+ MODEL,
966
+ [VENDOR, "Acer"],
967
+ [TYPE, TABLET]
968
+ ],
969
+ [/droid.+; (m[1-5] note) bui/i, /\bmz-([-\w]{2,})/i],
970
+ [
971
+ MODEL,
972
+ [VENDOR, "Meizu"],
973
+ [TYPE, MOBILE]
974
+ ],
975
+ [/; ((?:power )?armor[\w ]{0,8})(?: bui|\))/i],
976
+ [
977
+ MODEL,
978
+ [VENDOR, "Ulefone"],
979
+ [TYPE, MOBILE]
980
+ ],
981
+ [
982
+ /(blackberry|benq|palm(?=-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i,
983
+ /(hp) ([\w ]+\w)/i,
984
+ /(asus)-?(\w+)/i,
985
+ /(microsoft); (lumia[\w ]+)/i,
986
+ /(lenovo)[-_ ]?([-\w]+)/i,
987
+ /(jolla)/i,
988
+ /(oppo) ?([\w ]+) bui/i
989
+ ],
990
+ [
991
+ VENDOR,
992
+ MODEL,
993
+ [TYPE, MOBILE]
994
+ ],
995
+ [
996
+ /(kobo)\s(ereader|touch)/i,
997
+ /(archos) (gamepad2?)/i,
998
+ /(hp).+(touchpad(?!.+tablet)|tablet)/i,
999
+ /(kindle)\/([\w.]+)/i,
1000
+ /(nook)[\w ]+build\/(\w+)/i,
1001
+ /(dell) (strea[kpr\d ]*[\dko])/i,
1002
+ /(le[- ]+pan)[- ]+(\w{1,9}) bui/i,
1003
+ /(trinity)[- ]*(t\d{3}) bui/i,
1004
+ /(gigaset)[- ]+(q\w{1,9}) bui/i,
1005
+ /(vodafone) ([\w ]+)(?:\)| bui)/i
1006
+ ],
1007
+ [
1008
+ VENDOR,
1009
+ MODEL,
1010
+ [TYPE, TABLET]
1011
+ ],
1012
+ [/(surface duo)/i],
1013
+ [
1014
+ MODEL,
1015
+ [VENDOR, MICROSOFT],
1016
+ [TYPE, TABLET]
1017
+ ],
1018
+ [/droid [\d.]+; (fp\du?)(?: b|\))/i],
1019
+ [
1020
+ MODEL,
1021
+ [VENDOR, "Fairphone"],
1022
+ [TYPE, MOBILE]
1023
+ ],
1024
+ [/(u304aa)/i],
1025
+ [
1026
+ MODEL,
1027
+ [VENDOR, "AT&T"],
1028
+ [TYPE, MOBILE]
1029
+ ],
1030
+ [/\bsie-(\w*)/i],
1031
+ [
1032
+ MODEL,
1033
+ [VENDOR, "Siemens"],
1034
+ [TYPE, MOBILE]
1035
+ ],
1036
+ [/\b(rct\w+) b/i],
1037
+ [
1038
+ MODEL,
1039
+ [VENDOR, "RCA"],
1040
+ [TYPE, TABLET]
1041
+ ],
1042
+ [/\b(venue[\d ]{2,7}) b/i],
1043
+ [
1044
+ MODEL,
1045
+ [VENDOR, "Dell"],
1046
+ [TYPE, TABLET]
1047
+ ],
1048
+ [/\b(q(?:mv|ta)\w+) b/i],
1049
+ [
1050
+ MODEL,
1051
+ [VENDOR, "Verizon"],
1052
+ [TYPE, TABLET]
1053
+ ],
1054
+ [/\b(?:barnes[& ]+noble |bn[rt])([\w+ ]*) b/i],
1055
+ [
1056
+ MODEL,
1057
+ [VENDOR, "Barnes & Noble"],
1058
+ [TYPE, TABLET]
1059
+ ],
1060
+ [/\b(tm\d{3}\w+) b/i],
1061
+ [
1062
+ MODEL,
1063
+ [VENDOR, "NuVision"],
1064
+ [TYPE, TABLET]
1065
+ ],
1066
+ [/\b(k88) b/i],
1067
+ [
1068
+ MODEL,
1069
+ [VENDOR, "ZTE"],
1070
+ [TYPE, TABLET]
1071
+ ],
1072
+ [/\b(nx\d{3}j) b/i],
1073
+ [
1074
+ MODEL,
1075
+ [VENDOR, "ZTE"],
1076
+ [TYPE, MOBILE]
1077
+ ],
1078
+ [/\b(gen\d{3}) b.+49h/i],
1079
+ [
1080
+ MODEL,
1081
+ [VENDOR, "Swiss"],
1082
+ [TYPE, MOBILE]
1083
+ ],
1084
+ [/\b(zur\d{3}) b/i],
1085
+ [
1086
+ MODEL,
1087
+ [VENDOR, "Swiss"],
1088
+ [TYPE, TABLET]
1089
+ ],
1090
+ [/\b((zeki)?tb.*\b) b/i],
1091
+ [
1092
+ MODEL,
1093
+ [VENDOR, "Zeki"],
1094
+ [TYPE, TABLET]
1095
+ ],
1096
+ [/\b([yr]\d{2}) b/i, /\b(dragon[- ]+touch |dt)(\w{5}) b/i],
1097
+ [
1098
+ [VENDOR, "Dragon Touch"],
1099
+ MODEL,
1100
+ [TYPE, TABLET]
1101
+ ],
1102
+ [/\b(ns-?\w{0,9}) b/i],
1103
+ [
1104
+ MODEL,
1105
+ [VENDOR, "Insignia"],
1106
+ [TYPE, TABLET]
1107
+ ],
1108
+ [/\b((nxa|next)-?\w{0,9}) b/i],
1109
+ [
1110
+ MODEL,
1111
+ [VENDOR, "NextBook"],
1112
+ [TYPE, TABLET]
1113
+ ],
1114
+ [/\b(xtreme_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i],
1115
+ [
1116
+ [VENDOR, "Voice"],
1117
+ MODEL,
1118
+ [TYPE, MOBILE]
1119
+ ],
1120
+ [/\b(lvtel-)?(v1[12]) b/i],
1121
+ [
1122
+ [VENDOR, "LvTel"],
1123
+ MODEL,
1124
+ [TYPE, MOBILE]
1125
+ ],
1126
+ [/\b(ph-1) /i],
1127
+ [
1128
+ MODEL,
1129
+ [VENDOR, "Essential"],
1130
+ [TYPE, MOBILE]
1131
+ ],
1132
+ [/\b(v(100md|700na|7011|917g).*\b) b/i],
1133
+ [
1134
+ MODEL,
1135
+ [VENDOR, "Envizen"],
1136
+ [TYPE, TABLET]
1137
+ ],
1138
+ [/\b(trio[-\w. ]+) b/i],
1139
+ [
1140
+ MODEL,
1141
+ [VENDOR, "MachSpeed"],
1142
+ [TYPE, TABLET]
1143
+ ],
1144
+ [/\btu_(1491) b/i],
1145
+ [
1146
+ MODEL,
1147
+ [VENDOR, "Rotor"],
1148
+ [TYPE, TABLET]
1149
+ ],
1150
+ [/(shield[\w ]+) b/i],
1151
+ [
1152
+ MODEL,
1153
+ [VENDOR, "Nvidia"],
1154
+ [TYPE, TABLET]
1155
+ ],
1156
+ [/(sprint) (\w+)/i],
1157
+ [
1158
+ VENDOR,
1159
+ MODEL,
1160
+ [TYPE, MOBILE]
1161
+ ],
1162
+ [/(kin\.[onetw]{3})/i],
1163
+ [
1164
+ [
1165
+ MODEL,
1166
+ /\./g,
1167
+ " "
1168
+ ],
1169
+ [VENDOR, MICROSOFT],
1170
+ [TYPE, MOBILE]
1171
+ ],
1172
+ [/droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i],
1173
+ [
1174
+ MODEL,
1175
+ [VENDOR, ZEBRA],
1176
+ [TYPE, TABLET]
1177
+ ],
1178
+ [/droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i],
1179
+ [
1180
+ MODEL,
1181
+ [VENDOR, ZEBRA],
1182
+ [TYPE, MOBILE]
1183
+ ],
1184
+ [/smart-tv.+(samsung)/i],
1185
+ [VENDOR, [TYPE, SMARTTV]],
1186
+ [/hbbtv.+maple;(\d+)/i],
1187
+ [
1188
+ [
1189
+ MODEL,
1190
+ /^/,
1191
+ "SmartTV"
1192
+ ],
1193
+ [VENDOR, SAMSUNG],
1194
+ [TYPE, SMARTTV]
1195
+ ],
1196
+ [/(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i],
1197
+ [[VENDOR, LG], [TYPE, SMARTTV]],
1198
+ [/(apple) ?tv/i],
1199
+ [
1200
+ VENDOR,
1201
+ [MODEL, `${APPLE} TV`],
1202
+ [TYPE, SMARTTV]
1203
+ ],
1204
+ [/crkey/i],
1205
+ [
1206
+ [MODEL, `${CHROME}cast`],
1207
+ [VENDOR, GOOGLE],
1208
+ [TYPE, SMARTTV]
1209
+ ],
1210
+ [/droid.+aft(\w+)( bui|\))/i],
1211
+ [
1212
+ MODEL,
1213
+ [VENDOR, AMAZON],
1214
+ [TYPE, SMARTTV]
1215
+ ],
1216
+ [/\(dtv[);].+(aquos)/i, /(aquos-tv[\w ]+)\)/i],
1217
+ [
1218
+ MODEL,
1219
+ [VENDOR, SHARP],
1220
+ [TYPE, SMARTTV]
1221
+ ],
1222
+ [/(bravia[\w ]+)( bui|\))/i],
1223
+ [
1224
+ MODEL,
1225
+ [VENDOR, SONY],
1226
+ [TYPE, SMARTTV]
1227
+ ],
1228
+ [/(mitv-\w{5}) bui/i],
1229
+ [
1230
+ MODEL,
1231
+ [VENDOR, XIAOMI],
1232
+ [TYPE, SMARTTV]
1233
+ ],
1234
+ [/Hbbtv.*(technisat) (.*);/i],
1235
+ [
1236
+ VENDOR,
1237
+ MODEL,
1238
+ [TYPE, SMARTTV]
1239
+ ],
1240
+ [/\b(roku)[\dx]*[)/]((?:dvp-)?[\d.]*)/i, /hbbtv\/\d+\.\d+\.\d+ +\([\w+ ]*; *(\w[^;]*);([^;]*)/i],
1241
+ [
1242
+ [VENDOR, trim],
1243
+ [MODEL, trim],
1244
+ [TYPE, SMARTTV]
1245
+ ],
1246
+ [/\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i],
1247
+ [[TYPE, SMARTTV]],
1248
+ [/(ouya)/i, /(nintendo) ([wids3utch]+)/i],
1249
+ [
1250
+ VENDOR,
1251
+ MODEL,
1252
+ [TYPE, CONSOLE]
1253
+ ],
1254
+ [/droid.+; (shield) bui/i],
1255
+ [
1256
+ MODEL,
1257
+ [VENDOR, "Nvidia"],
1258
+ [TYPE, CONSOLE]
1259
+ ],
1260
+ [/(playstation [345portablevi]+)/i],
1261
+ [
1262
+ MODEL,
1263
+ [VENDOR, SONY],
1264
+ [TYPE, CONSOLE]
1265
+ ],
1266
+ [/\b(xbox(?: one)?(?!; xbox))[); ]/i],
1267
+ [
1268
+ MODEL,
1269
+ [VENDOR, MICROSOFT],
1270
+ [TYPE, CONSOLE]
1271
+ ],
1272
+ [/((pebble))app/i],
1273
+ [
1274
+ VENDOR,
1275
+ MODEL,
1276
+ [TYPE, WEARABLE]
1277
+ ],
1278
+ [/(watch)(?: ?os[,/]|\d,\d\/)[\d.]+/i],
1279
+ [
1280
+ MODEL,
1281
+ [VENDOR, APPLE],
1282
+ [TYPE, WEARABLE]
1283
+ ],
1284
+ [/droid.+; (glass) \d/i],
1285
+ [
1286
+ MODEL,
1287
+ [VENDOR, GOOGLE],
1288
+ [TYPE, WEARABLE]
1289
+ ],
1290
+ [/droid.+; (wt63?0{2,3})\)/i],
1291
+ [
1292
+ MODEL,
1293
+ [VENDOR, ZEBRA],
1294
+ [TYPE, WEARABLE]
1295
+ ],
1296
+ [/(quest( \d| pro)?)/i],
1297
+ [
1298
+ MODEL,
1299
+ [VENDOR, FACEBOOK],
1300
+ [TYPE, WEARABLE]
1301
+ ],
1302
+ [/(tesla)(?: qtcarbrowser|\/[-\w.]+)/i],
1303
+ [VENDOR, [TYPE, EMBEDDED]],
1304
+ [/(aeobc)\b/i],
1305
+ [
1306
+ MODEL,
1307
+ [VENDOR, AMAZON],
1308
+ [TYPE, EMBEDDED]
1309
+ ],
1310
+ [/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+? mobile safari/i],
1311
+ [MODEL, [TYPE, MOBILE]],
1312
+ [/droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i],
1313
+ [MODEL, [TYPE, TABLET]],
1314
+ [/\b((tablet|tab)[;/]|focus\/\d(?!.+mobile))/i],
1315
+ [[TYPE, TABLET]],
1316
+ [/(phone|mobile(?:[;/]| [ \w/.]*safari)|pda(?=.+windows ce))/i],
1317
+ [[TYPE, MOBILE]],
1318
+ [/(android[-\w. ]{0,9});.+buil/i],
1319
+ [MODEL, [VENDOR, "Generic"]]
1320
+ ],
1321
+ engine: [
1322
+ [/windows.+ edge\/([\w.]+)/i],
1323
+ [VERSION, [NAME, `${EDGE}HTML`]],
1324
+ [/webkit\/537\.36.+chrome\/(?!27)([\w.]+)/i],
1325
+ [VERSION, [NAME, "Blink"]],
1326
+ [
1327
+ /(presto)\/([\w.]+)/i,
1328
+ /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w.]+)/i,
1329
+ /ekioh(flow)\/([\w.]+)/i,
1330
+ /(khtml|tasman|links)[/ ]\(?([\w.]+)/i,
1331
+ /(icab)[/ ]([23]\.[\d.]+)/i,
1332
+ /\b(libweb)/i
1333
+ ],
1334
+ [NAME, VERSION],
1335
+ [/rv:([\w.]{1,9})\b.+(gecko)/i],
1336
+ [VERSION, NAME]
1337
+ ],
1338
+ os: [
1339
+ [/microsoft (windows) (vista|xp)/i],
1340
+ [NAME, VERSION],
1341
+ [/(windows (?:phone(?: os)?|mobile))[/ ]?([.\w ]*)/i],
1342
+ [NAME, [
1343
+ VERSION,
1344
+ strMapper,
1345
+ windowsVersionMap
1346
+ ]],
1347
+ [
1348
+ /windows nt 6\.2; (arm)/i,
1349
+ /windows[/ ]?([ntce\d. ]+\w)(?!.+xbox)/i,
1350
+ /(?:win(?=[39n])|win 9x )([nt\d.]+)/i
1351
+ ],
1352
+ [[
1353
+ VERSION,
1354
+ strMapper,
1355
+ windowsVersionMap
1356
+ ], [NAME, "Windows"]],
1357
+ [
1358
+ /ip[honead]{2,4}\b(?:.*os (\w+) like mac|; opera)/i,
1359
+ /(?:ios;fbsv\/|iphone.+ios[/ ])([\d.]+)/i,
1360
+ /cfnetwork\/.+darwin/i
1361
+ ],
1362
+ [[
1363
+ VERSION,
1364
+ /_/g,
1365
+ "."
1366
+ ], [NAME, "iOS"]],
1367
+ [/(mac os x) ?([\w. ]*)/i, /(macintosh|mac_powerpc\b)(?!.+haiku)/i],
1368
+ [[NAME, MAC_OS], [
1369
+ VERSION,
1370
+ /_/g,
1371
+ "."
1372
+ ]],
1373
+ [/droid ([\w.]+)\b.+(android[- ]x86|harmonyos)/i],
1374
+ [VERSION, NAME],
1375
+ [
1376
+ /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-/ ]?([\w.]*)/i,
1377
+ /(blackberry)\w*\/([\w.]*)/i,
1378
+ /(tizen|kaios)[/ ]([\w.]+)/i,
1379
+ /\((series40);/i
1380
+ ],
1381
+ [NAME, VERSION],
1382
+ [/\(bb(10);/i],
1383
+ [VERSION, [NAME, BLACKBERRY]],
1384
+ [/(?:symbian ?os|symbos|s60(?=;)|series60)[-/ ]?([\w.]*)/i],
1385
+ [VERSION, [NAME, "Symbian"]],
1386
+ [/mozilla\/[\d.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w.]+)/i],
1387
+ [VERSION, [NAME, `${FIREFOX} OS`]],
1388
+ [/web0s;.+rt(tv)/i, /\b(?:hp)?wos(?:browser)?\/([\w.]+)/i],
1389
+ [VERSION, [NAME, "webOS"]],
1390
+ [/watch(?: ?os[,/]|\d,\d\/)([\d.]+)/i],
1391
+ [VERSION, [NAME, "watchOS"]],
1392
+ [/crkey\/([\d.]+)/i],
1393
+ [VERSION, [NAME, `${CHROME}cast`]],
1394
+ [/(cros) \w+(?:\)| ([\w.]+)\b)/i],
1395
+ [[NAME, CHROMIUM_OS], VERSION],
1396
+ [
1397
+ /panasonic;(viera)/i,
1398
+ /(netrange)mmh/i,
1399
+ /(nettv)\/(\d+\.[\w.]+)/i,
1400
+ /(nintendo|playstation) ([wids345portablevuch]+)/i,
1401
+ /(xbox); +xbox ([^);]+)/i,
1402
+ /\b(joli|palm)\b ?(?:os)?\/?([\w.]*)/i,
1403
+ /(mint)[/() ]?(\w*)/i,
1404
+ /(mageia|vectorlinux)[; ]/i,
1405
+ /([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-/ ]?(?!chrom|package)([-\w.]*)/i,
1406
+ /(hurd|linux) ?([\w.]*)/i,
1407
+ /(gnu) ?([\w.]*)/i,
1408
+ /\b([-e-hrntopcs]{0,5}bsd|dragonfly)[/ ]?(?!amd|[ix346]{1,2}86)([\w.]*)/i,
1409
+ /(haiku) (\w+)/i
1410
+ ],
1411
+ [NAME, VERSION],
1412
+ [/(sunos) ?([\w.]*)/i],
1413
+ [[NAME, "Solaris"], VERSION],
1414
+ [
1415
+ /((?:open)?solaris)[-/ ]?([\w.]*)/i,
1416
+ /(aix) ((\d)(?=[.) ])[\w.])*/i,
1417
+ /\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i,
1418
+ /(unix) ?([\w.]*)/i
1419
+ ],
1420
+ [NAME, VERSION]
1421
+ ]
1422
+ };
1423
+ function isExtensionsInput(input) {
1424
+ return typeof input === "object" && input !== null;
1425
+ }
1426
+ Object.freeze(enumerize([
1427
+ NAME,
1428
+ VERSION,
1429
+ MAJOR
1430
+ ]));
1431
+ Object.freeze(enumerize([ARCHITECTURE]));
1432
+ Object.freeze(enumerize([
1433
+ MODEL,
1434
+ VENDOR,
1435
+ TYPE,
1436
+ CONSOLE,
1437
+ MOBILE,
1438
+ SMARTTV,
1439
+ TABLET,
1440
+ WEARABLE,
1441
+ EMBEDDED
1442
+ ]));
1443
+ Object.freeze(enumerize([NAME, VERSION]));
1444
+ Object.freeze(enumerize([NAME, VERSION]));
1445
+ function getRuntimeNavigator() {
1446
+ if (typeof window === "undefined" || !window.navigator) return void 0;
1447
+ return window.navigator;
1448
+ }
1449
+ function normalizeUA(ua) {
1450
+ return ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
1451
+ }
1452
+ function createDefaultParserContext(uastring) {
1453
+ if (typeof uastring === "string") return {
1454
+ ua: normalizeUA(uastring),
1455
+ isSelfNavigator: false,
1456
+ navigator: void 0,
1457
+ userAgentData: void 0,
1458
+ regexMap: regexes
1459
+ };
1460
+ const navigator = getRuntimeNavigator();
1461
+ const ua = normalizeUA(navigator && navigator.userAgent ? navigator.userAgent : EMPTY);
1462
+ return {
1463
+ ua,
1464
+ isSelfNavigator: Boolean(navigator && navigator.userAgent === ua),
1465
+ navigator,
1466
+ userAgentData: navigator?.userAgentData,
1467
+ regexMap: regexes
1468
+ };
1469
+ }
1470
+ function createParserContext(uastringOrExtensions, extensions) {
1471
+ if (!extensions && !isExtensionsInput(uastringOrExtensions)) return createDefaultParserContext(uastringOrExtensions);
1472
+ const navigator = getRuntimeNavigator();
1473
+ const uastring = isExtensionsInput(uastringOrExtensions) ? void 0 : uastringOrExtensions;
1474
+ const resolvedExtensions = isExtensionsInput(uastringOrExtensions) ? uastringOrExtensions : extensions;
1475
+ const ua = normalizeUA(uastring || (navigator && navigator.userAgent ? navigator.userAgent : EMPTY));
1476
+ const userAgentData = navigator?.userAgentData;
1477
+ return {
1478
+ ua,
1479
+ isSelfNavigator: Boolean(navigator && navigator.userAgent === ua),
1480
+ navigator,
1481
+ userAgentData,
1482
+ regexMap: resolvedExtensions ? extend(regexes, resolvedExtensions) : regexes
1483
+ };
1484
+ }
1485
+ function parseBrowserFromContext(context) {
1486
+ const browser = {
1487
+ name: void 0,
1488
+ version: void 0,
1489
+ major: void 0
1490
+ };
1491
+ rgxMapper(context.ua, context.regexMap.browser, browser);
1492
+ browser.major = majorize(browser.version);
1493
+ if (context.isSelfNavigator && context.navigator?.brave && typeof context.navigator.brave.isBrave === "function") browser.name = "Brave";
1494
+ return browser;
1495
+ }
1496
+ function parseCPUFromContext(context) {
1497
+ const cpu = { architecture: void 0 };
1498
+ rgxMapper(context.ua, context.regexMap.cpu, cpu);
1499
+ return cpu;
1500
+ }
1501
+ function parseDeviceFromContext(context) {
1502
+ const device = {
1503
+ vendor: void 0,
1504
+ model: void 0,
1505
+ type: void 0
1506
+ };
1507
+ rgxMapper(context.ua, context.regexMap.device, device);
1508
+ if (context.isSelfNavigator && !device.type && context.userAgentData?.mobile) device.type = MOBILE;
1509
+ if (context.isSelfNavigator && device.model === "Macintosh" && context.navigator && typeof context.navigator.standalone !== "undefined" && context.navigator.maxTouchPoints && context.navigator.maxTouchPoints > 2) {
1510
+ device.model = "iPad";
1511
+ device.type = TABLET;
1512
+ }
1513
+ return device;
1514
+ }
1515
+ function parseEngineFromContext(context) {
1516
+ const engine = {
1517
+ name: void 0,
1518
+ version: void 0
1519
+ };
1520
+ rgxMapper(context.ua, context.regexMap.engine, engine);
1521
+ return engine;
1522
+ }
1523
+ function parseOSFromContext(context) {
1524
+ const os = {
1525
+ name: void 0,
1526
+ version: void 0
1527
+ };
1528
+ rgxMapper(context.ua, context.regexMap.os, os);
1529
+ if (context.isSelfNavigator && !os.name && context.userAgentData?.platform && context.userAgentData.platform !== "Unknown") os.name = context.userAgentData.platform.replace(/chrome os/i, CHROMIUM_OS).replace(/macos/i, MAC_OS);
1530
+ return os;
1531
+ }
1532
+ function parseUA(uastringOrExtensions, extensions) {
1533
+ let context;
1534
+ let browserCache;
1535
+ let engineCache;
1536
+ let osCache;
1537
+ let deviceCache;
1538
+ let cpuCache;
1539
+ const getContext = () => context ||= createParserContext(uastringOrExtensions, extensions);
1540
+ return {
1541
+ get ua() {
1542
+ return getContext().ua;
1543
+ },
1544
+ get browser() {
1545
+ browserCache ||= parseBrowserFromContext(getContext());
1546
+ return browserCache;
1547
+ },
1548
+ get engine() {
1549
+ engineCache ||= parseEngineFromContext(getContext());
1550
+ return engineCache;
1551
+ },
1552
+ get os() {
1553
+ osCache ||= parseOSFromContext(getContext());
1554
+ return osCache;
1555
+ },
1556
+ get device() {
1557
+ deviceCache ||= parseDeviceFromContext(getContext());
1558
+ return deviceCache;
1559
+ },
1560
+ get cpu() {
1561
+ cpuCache ||= parseCPUFromContext(getContext());
1562
+ return cpuCache;
1563
+ }
1564
+ };
1565
+ }
1566
+ //#endregion
1567
+ //#region src/utils/promise.ts
1568
+ function promiseWithResolver() {
1569
+ let resolve;
1570
+ let reject;
1571
+ return {
1572
+ promise: new Promise((_resolve, _reject) => {
1573
+ resolve = _resolve;
1574
+ reject = _reject;
1575
+ }),
1576
+ resolve,
1577
+ reject
1578
+ };
1579
+ }
1580
+ //#endregion
1581
+ //#region src/client/rpc-ws.ts
5
1582
  function isNumeric(str) {
6
1583
  if (str == null) return false;
7
1584
  return `${+str}` === `${str}`;
8
1585
  }
1586
+ function createWsRpcClientMode(options) {
1587
+ const { authId, connectionMeta, events, clientRpc, rpcOptions = {}, wsOptions = {} } = options;
1588
+ let isTrusted = false;
1589
+ const trustedPromise = promiseWithResolver();
1590
+ const url = isNumeric(connectionMeta.websocket) ? `${location.protocol.replace("http", "ws")}//${location.hostname}:${connectionMeta.websocket}` : connectionMeta.websocket;
1591
+ const serverRpc = createRpcClient(clientRpc.functions, {
1592
+ preset: createWsRpcPreset({
1593
+ url,
1594
+ authId,
1595
+ ...wsOptions
1596
+ }),
1597
+ rpcOptions
1598
+ });
1599
+ async function requestTrust() {
1600
+ if (isTrusted) return true;
1601
+ const info = parseUA(navigator.userAgent);
1602
+ const ua = [
1603
+ info.browser.name,
1604
+ info.browser.version,
1605
+ "|",
1606
+ info.os.name,
1607
+ info.os.version,
1608
+ info.device.type
1609
+ ].filter((i) => i).join(" ");
1610
+ const result = await serverRpc.$call("vite:anonymous:auth", {
1611
+ authId,
1612
+ ua,
1613
+ origin: location.origin
1614
+ });
1615
+ isTrusted = result.isTrusted;
1616
+ trustedPromise.resolve(isTrusted);
1617
+ events.emit("rpc:is-trusted:updated", isTrusted);
1618
+ return result.isTrusted;
1619
+ }
1620
+ async function ensureTrusted(timeout = 6e4) {
1621
+ if (isTrusted) trustedPromise.resolve(true);
1622
+ if (timeout <= 0) return trustedPromise.promise;
1623
+ let clear = () => {};
1624
+ await Promise.race([trustedPromise.promise.then(clear), new Promise((resolve, reject) => {
1625
+ const id = setTimeout(() => {
1626
+ reject(/* @__PURE__ */ new Error("[Vite DevTools] Timeout waiting for rpc to be trusted"));
1627
+ }, timeout);
1628
+ clear = () => clearTimeout(id);
1629
+ })]);
1630
+ return isTrusted;
1631
+ }
1632
+ return {
1633
+ get isTrusted() {
1634
+ return isTrusted;
1635
+ },
1636
+ requestTrust,
1637
+ ensureTrusted,
1638
+ call: (...args) => {
1639
+ return serverRpc.$call(...args);
1640
+ },
1641
+ callEvent: (...args) => {
1642
+ return serverRpc.$callEvent(...args);
1643
+ },
1644
+ callOptional: (...args) => {
1645
+ return serverRpc.$callOptional(...args);
1646
+ }
1647
+ };
1648
+ }
1649
+ //#endregion
1650
+ //#region src/client/rpc.ts
1651
+ const CONNECTION_META_KEY = "__VITE_DEVTOOLS_CONNECTION_META__";
1652
+ const CONNECTION_AUTH_ID_KEY = "__VITE_DEVTOOLS_CONNECTION_AUTH_ID__";
1653
+ function getConnectionAuthIdFromWindows(userAuthId) {
1654
+ const getters = [
1655
+ () => userAuthId,
1656
+ () => localStorage.getItem(CONNECTION_AUTH_ID_KEY),
1657
+ () => window?.[CONNECTION_AUTH_ID_KEY],
1658
+ () => globalThis?.[CONNECTION_AUTH_ID_KEY],
1659
+ () => parent.window?.[CONNECTION_AUTH_ID_KEY]
1660
+ ];
1661
+ let value;
1662
+ for (const getter of getters) try {
1663
+ value = getter();
1664
+ if (value) break;
1665
+ } catch {}
1666
+ if (!value) value = nanoid();
1667
+ localStorage.setItem(CONNECTION_AUTH_ID_KEY, value);
1668
+ globalThis[CONNECTION_AUTH_ID_KEY] = value;
1669
+ return value;
1670
+ }
1671
+ function findConnectionMetaFromWindows() {
1672
+ const getters = [
1673
+ () => window?.[CONNECTION_META_KEY],
1674
+ () => globalThis?.[CONNECTION_META_KEY],
1675
+ () => parent.window?.[CONNECTION_META_KEY]
1676
+ ];
1677
+ for (const getter of getters) try {
1678
+ const value = getter();
1679
+ if (value) return value;
1680
+ } catch {}
1681
+ }
9
1682
  async function getDevToolsRpcClient(options = {}) {
10
- const { baseURL = "/.devtools/" } = options;
11
- const urls = Array.isArray(baseURL) ? baseURL : [baseURL];
12
- let connectionMeta = options.connectionMeta;
1683
+ const { baseURL = DEVTOOLS_MOUNT_PATH, rpcOptions = {} } = options;
1684
+ const events = createEventEmitter();
1685
+ const bases = Array.isArray(baseURL) ? baseURL : [baseURL];
1686
+ let connectionMeta = options.connectionMeta || findConnectionMetaFromWindows();
1687
+ let resolvedBaseURL = bases[0] ?? "/.devtools/";
1688
+ function normalizeBase(base) {
1689
+ return base.endsWith("/") ? base : `${base}/`;
1690
+ }
1691
+ function resolveBasePath(base, path) {
1692
+ if (/^https?:\/\//.test(path)) return path;
1693
+ if (path.startsWith("/")) return path;
1694
+ return `${normalizeBase(base)}${path}`;
1695
+ }
13
1696
  if (!connectionMeta) {
14
1697
  const errors = [];
15
- for (const url of urls) try {
16
- connectionMeta = await fetch(`${url}.vdt-connection.json`).then((r) => r.json());
1698
+ for (const base of bases) try {
1699
+ connectionMeta = await fetch(resolveBasePath(base, DEVTOOLS_CONNECTION_META_FILENAME)).then((r) => r.json());
1700
+ resolvedBaseURL = base;
1701
+ globalThis[CONNECTION_META_KEY] = connectionMeta;
17
1702
  break;
18
1703
  } catch (e) {
19
1704
  errors.push(e);
20
1705
  }
21
- if (!connectionMeta) throw new Error(`Failed to get connection meta from ${urls.join(", ")}`, { cause: errors });
1706
+ if (!connectionMeta) throw new Error(`Failed to get connection meta from ${bases.join(", ")}`, { cause: errors });
22
1707
  }
23
- const rpc = createRpcClient({}, {
24
- preset: createWsRpcPreset({
25
- url: isNumeric(connectionMeta.websocket) ? `${location.protocol.replace("http", "ws")}//${location.hostname}:${connectionMeta.websocket}` : connectionMeta.websocket,
26
- ...options.wsOptions
27
- }),
28
- ...options.rpcOptions
1708
+ const context = { rpc: void 0 };
1709
+ const authId = getConnectionAuthIdFromWindows(options.authId);
1710
+ const clientRpc = new RpcFunctionsCollectorBase(context);
1711
+ async function fetchJsonFromBases(path) {
1712
+ const candidates = [resolvedBaseURL, ...bases.filter((base) => base !== resolvedBaseURL)].filter((x) => x != null);
1713
+ const errors = [];
1714
+ for (const base of candidates) try {
1715
+ return await fetch(resolveBasePath(base, path)).then((r) => {
1716
+ if (!r.ok) throw new Error(`Failed to fetch ${path} from ${base}: ${r.status}`);
1717
+ return r.json();
1718
+ });
1719
+ } catch (error) {
1720
+ errors.push(error);
1721
+ }
1722
+ throw new Error(`Failed to load ${path} from ${candidates.join(", ")}`, { cause: errors });
1723
+ }
1724
+ const mode = connectionMeta.backend === "static" ? await createStaticRpcClientMode({ fetchJsonFromBases }) : createWsRpcClientMode({
1725
+ authId,
1726
+ connectionMeta,
1727
+ events,
1728
+ clientRpc,
1729
+ rpcOptions,
1730
+ wsOptions: options.wsOptions
29
1731
  });
30
- return {
1732
+ const rpc = {
1733
+ events,
1734
+ get isTrusted() {
1735
+ return mode.isTrusted;
1736
+ },
31
1737
  connectionMeta,
32
- rpc
1738
+ ensureTrusted: mode.ensureTrusted,
1739
+ requestTrust: mode.requestTrust,
1740
+ call: mode.call,
1741
+ callEvent: mode.callEvent,
1742
+ callOptional: mode.callOptional,
1743
+ client: clientRpc,
1744
+ sharedState: void 0
33
1745
  };
1746
+ rpc.sharedState = createRpcSharedStateClientHost(rpc);
1747
+ context.rpc = rpc;
1748
+ mode.requestTrust();
1749
+ return rpc;
34
1750
  }
35
-
36
1751
  //#endregion
37
- export { getDevToolsRpcClient };
1752
+ export { getDevToolsRpcClient };