devframe 0.9.0-beta.1 → 0.9.0-beta.10
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/{_shared-DmpWW-HH.d.mts → _shared-BPmX9fqK.d.mts} +2 -4
- package/dist/{_shared-CttmCMBi.mjs → _shared-CbZ_yhbz.mjs} +2 -4
- package/dist/adapters/build.d.mts +10 -12
- package/dist/adapters/build.mjs +26 -30
- package/dist/adapters/cac.d.mts +1 -1
- package/dist/adapters/cac.mjs +6 -7
- package/dist/adapters/dev.d.mts +22 -8
- package/dist/adapters/dev.mjs +2 -2
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/initiate.d.mts +5 -4
- package/dist/adapters/initiate.mjs +1 -1
- package/dist/adapters/mcp.d.mts +1 -8
- package/dist/adapters/mcp.mjs +1 -1
- package/dist/{agent-tool-name-C3b5vEwJ.mjs → agent-tool-name-EgfoFO8C.mjs} +0 -3
- package/dist/cli/main.d.mts +0 -2
- package/dist/cli/main.mjs +4 -8
- package/dist/client/index.d.mts +5 -5
- package/dist/client/index.mjs +24 -1179
- package/dist/constants.d.mts +10 -2
- package/dist/constants.mjs +10 -2
- package/dist/{context-CSCwoABx.d.mts → context-B3YUu_95.d.mts} +19 -1
- package/dist/{context-Du11TLcO.mjs → context-CEe4PBz1.mjs} +23 -305
- package/dist/{context-C33rR7n0.mjs → context-xdynGSLP.mjs} +10 -1
- package/dist/{dev-BEveeA5H.mjs → dev--rAPzbvO.mjs} +16 -10
- package/dist/{devframe-Bdd9YXTy.d.mts → devframe-DJMg0WLe.d.mts} +97 -113
- package/dist/{diagnostics-hwjXp_UV.mjs → diagnostics-CD8nlgll.mjs} +1 -3
- package/dist/{diagnostics-DLYH5oD3.mjs → diagnostics-DOQPnQmX.mjs} +35 -5
- package/dist/{dist-D8jAMwxU.mjs → dist-eNI9qM_I.mjs} +1 -0
- package/dist/{host-agent-CpbAoqBx.mjs → host-agent-xLCSe65D.mjs} +41 -7
- package/dist/{host-h3-CzCZwtuV.mjs → host-h3-Crkzm42q.mjs} +2 -2
- package/dist/{http-DLr_cJZ7.mjs → http-DYpK0cUi.mjs} +5 -12
- package/dist/{index-CZRd2K1C.d.mts → index-CB-fSUyn.d.mts} +2 -2
- package/dist/{index-DSCq4M4q.d.mts → index-tdrk1bzV.d.mts} +1 -1
- package/dist/index.d.mts +7 -5
- package/dist/{instance-registry-BQqGoDO9.mjs → instance-registry-WvQkt42E.mjs} +1 -7
- package/dist/{instance-shell-KRdee1QF.mjs → instance-shell-CMFyszWJ.mjs} +9 -8
- package/dist/{instance-shell-DBTXTSjN.d.mts → instance-shell-CljiKq1c.d.mts} +3 -12
- package/dist/internal/index.d.mts +265 -18
- package/dist/internal/index.mjs +9 -7
- package/dist/node/auth.d.mts +2 -2
- package/dist/node/auth.mjs +1 -1
- package/dist/node/hub-internals.d.mts +2 -2
- package/dist/node/hub-internals.mjs +2 -2
- package/dist/node/index.d.mts +3 -3
- package/dist/node/index.mjs +2 -2
- package/dist/nostics-CzECRXpE.mjs +59 -0
- package/dist/nostics-SPGDgHEP.d.mts +33 -0
- package/dist/recipes/common-rpc-functions.d.mts +3 -3
- package/dist/recipes/interactive-auth.d.mts +2 -2
- package/dist/recipes/interactive-auth.mjs +3 -3
- package/dist/remote-assets-Bg4gCUZ_.d.mts +123 -0
- package/dist/remote-assets-nTTxY2MU.mjs +636 -0
- package/dist/rpc/dump.d.mts +1 -1
- package/dist/rpc/dump.mjs +1 -1
- package/dist/rpc/index.d.mts +2 -2
- package/dist/rpc/index.mjs +3 -3
- package/dist/rpc/transports/sse-client.d.mts +1 -1
- package/dist/rpc/transports/sse-client.mjs +1 -1
- package/dist/rpc/transports/sse-server.d.mts +2 -2
- package/dist/rpc/transports/sse-server.mjs +2 -2
- package/dist/rpc/transports/ws-bun.d.mts +2 -2
- package/dist/rpc/transports/ws-bun.mjs +1 -1
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +1 -1
- package/dist/rpc/transports/ws-server.d.mts +1 -1
- package/dist/rpc/transports/ws-server.mjs +1 -1
- package/dist/{rpc-core-CGctXToO.d.mts → rpc-core-Cc4lucI0.d.mts} +3 -3
- package/dist/{rpc-core-CqcJkAu9.mjs → rpc-core-DMTe-hLo.mjs} +1 -1
- package/dist/{serialization-BHY8M5NQ.mjs → serialization-BGzEwAdr.mjs} +1 -1
- package/dist/{sse-client-BsIK3hMD.d.mts → sse-client-CFBOIaUi.d.mts} +1 -1
- package/dist/state-Cc1IeSmQ.mjs +1291 -0
- package/dist/{static-CvjkO8QE.mjs → static-BPZ1_OPA.mjs} +2 -2
- package/dist/storage-CYye7P7L.mjs +137 -0
- package/dist/types/index.d.mts +6 -4
- package/dist/{types-CnJSgRVa.d.mts → types-Djq7CBXh.d.mts} +0 -7
- package/dist/utils/agent-tool-name.d.mts +0 -3
- package/dist/utils/agent-tool-name.mjs +0 -3
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/get-port.d.mts +17 -0
- package/dist/utils/get-port.mjs +2 -0
- package/dist/utils/nostics.d.mts +2 -0
- package/dist/utils/nostics.mjs +2 -0
- package/dist/utils/open.d.mts +2 -10
- package/dist/utils/open.mjs +56 -1
- package/dist/utils/remote-assets.d.mts +15 -0
- package/dist/utils/remote-assets.mjs +2 -0
- package/dist/utils/serve-static.d.mts +13 -5
- package/dist/utils/serve-static.mjs +119 -9
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/{validation-BiuDXTKW.mjs → validation-CpXFB6Dz.mjs} +1 -1
- package/dist/{wire-codec-9VhIKnyp.mjs → wire-codec-0K-o5MYW.mjs} +1 -3
- package/dist/{ws-client-CdNuATYa.d.mts → ws-client-DhjNyQo3.d.mts} +1 -1
- package/dist/{ws-server-Bk1hOG3X.mjs → ws-server-BdSLrhxE.mjs} +1 -1
- package/dist/{ws-server-Ces08fjP.d.mts → ws-server-D1d3QM9f.d.mts} +1 -1
- package/package.json +4 -4
- package/skills/devframe/SKILL.md +10 -11
- package/dist/diagnostics-reporter-CsIG85Q5.mjs +0 -38
- package/dist/helpers/vite.d.mts +0 -104
- package/dist/helpers/vite.mjs +0 -93
- package/dist/open-Dz4V4irZ.mjs +0 -547
- package/dist/state-BeUHDDjk.mjs +0 -108
- package/dist/storage-BcmVEJRc.mjs +0 -1122
- package/skills/devframe/templates/spa-devframe.ts +0 -38
|
@@ -0,0 +1,1291 @@
|
|
|
1
|
+
import { DEVFRAME_OTP_URL_PARAM } from "./constants.mjs";
|
|
2
|
+
import { n as randomToken, r as timingSafeEqual, t as randomDigits } from "./crypto-token-XCqTSMg9.mjs";
|
|
3
|
+
//#region ../../node_modules/.pnpm/ua-parser-modern@0.1.1/node_modules/ua-parser-modern/dist/index.mjs
|
|
4
|
+
const EMPTY = "";
|
|
5
|
+
const UNKNOWN = "?";
|
|
6
|
+
const MAJOR = "major";
|
|
7
|
+
const MODEL = "model";
|
|
8
|
+
const NAME = "name";
|
|
9
|
+
const TYPE = "type";
|
|
10
|
+
const VENDOR = "vendor";
|
|
11
|
+
const VERSION = "version";
|
|
12
|
+
const ARCHITECTURE = "architecture";
|
|
13
|
+
const CONSOLE = "console";
|
|
14
|
+
const MOBILE = "mobile";
|
|
15
|
+
const TABLET = "tablet";
|
|
16
|
+
const SMARTTV = "smarttv";
|
|
17
|
+
const WEARABLE = "wearable";
|
|
18
|
+
const EMBEDDED = "embedded";
|
|
19
|
+
const UA_MAX_LENGTH = 500;
|
|
20
|
+
const AMAZON = "Amazon";
|
|
21
|
+
const APPLE = "Apple";
|
|
22
|
+
const ASUS = "ASUS";
|
|
23
|
+
const BLACKBERRY = "BlackBerry";
|
|
24
|
+
const BROWSER_LABEL = "Browser";
|
|
25
|
+
const CHROME = "Chrome";
|
|
26
|
+
const EDGE = "Edge";
|
|
27
|
+
const FIREFOX = "Firefox";
|
|
28
|
+
const GOOGLE = "Google";
|
|
29
|
+
const HUAWEI = "Huawei";
|
|
30
|
+
const LG = "LG";
|
|
31
|
+
const MICROSOFT = "Microsoft";
|
|
32
|
+
const MOTOROLA = "Motorola";
|
|
33
|
+
const OPERA = "Opera";
|
|
34
|
+
const SAMSUNG = "Samsung";
|
|
35
|
+
const SHARP = "Sharp";
|
|
36
|
+
const SONY = "Sony";
|
|
37
|
+
const XIAOMI = "Xiaomi";
|
|
38
|
+
const ZEBRA = "Zebra";
|
|
39
|
+
const FACEBOOK = "Facebook";
|
|
40
|
+
const CHROMIUM_OS = "Chromium OS";
|
|
41
|
+
const MAC_OS = "Mac OS";
|
|
42
|
+
function extend(regexes, extensions = {}) {
|
|
43
|
+
const mergedRegexes = {};
|
|
44
|
+
for (const key of Object.keys(regexes)) {
|
|
45
|
+
const extension = extensions[key];
|
|
46
|
+
if (extension && extension.length % 2 === 0) mergedRegexes[key] = [...extension, ...regexes[key]];
|
|
47
|
+
else mergedRegexes[key] = regexes[key];
|
|
48
|
+
}
|
|
49
|
+
return mergedRegexes;
|
|
50
|
+
}
|
|
51
|
+
function enumerize(arr) {
|
|
52
|
+
const enums = {};
|
|
53
|
+
for (let i = 0; i < arr.length; i++) enums[arr[i].toUpperCase()] = arr[i];
|
|
54
|
+
return enums;
|
|
55
|
+
}
|
|
56
|
+
function lowerize(str) {
|
|
57
|
+
return str.toLowerCase();
|
|
58
|
+
}
|
|
59
|
+
function has(str1, str2) {
|
|
60
|
+
return typeof str1 === "string" ? lowerize(str2).includes(lowerize(str1)) : false;
|
|
61
|
+
}
|
|
62
|
+
function majorize(version) {
|
|
63
|
+
return typeof version === "string" ? version.replace(/[^\d.]/g, EMPTY).split(".")[0] : void 0;
|
|
64
|
+
}
|
|
65
|
+
function trim(str, len) {
|
|
66
|
+
const result = str.replace(/^\s+/, EMPTY);
|
|
67
|
+
return typeof len === "undefined" ? result : result.substring(0, len);
|
|
68
|
+
}
|
|
69
|
+
function rgxMapper(ua, arrays, augment) {
|
|
70
|
+
const result = augment ?? {};
|
|
71
|
+
for (let i = 0; i < arrays.length; i += 2) {
|
|
72
|
+
const regex = arrays[i];
|
|
73
|
+
const props = arrays[i + 1];
|
|
74
|
+
for (let j = 0; j < regex.length; j++) {
|
|
75
|
+
const matcher = regex[j];
|
|
76
|
+
if (!matcher) break;
|
|
77
|
+
const matches = matcher.exec(ua);
|
|
78
|
+
if (!matches) continue;
|
|
79
|
+
for (let p = 0; p < props.length; p++) {
|
|
80
|
+
const match = matches[p + 1];
|
|
81
|
+
const q = props[p];
|
|
82
|
+
if (Array.isArray(q)) {
|
|
83
|
+
const key = q[0];
|
|
84
|
+
const length = q.length;
|
|
85
|
+
if (length === 2) {
|
|
86
|
+
const value = q[1];
|
|
87
|
+
if (typeof value === "function") result[key] = value(match, void 0, result);
|
|
88
|
+
else result[key] = value;
|
|
89
|
+
} else if (length === 3) {
|
|
90
|
+
const arg1 = q[1];
|
|
91
|
+
const arg2 = q[2];
|
|
92
|
+
if (typeof arg1 === "function" && !("exec" in arg1) && !("test" in arg1)) result[key] = match ? arg1(match, arg2, result) : void 0;
|
|
93
|
+
else result[key] = match ? match.replace(arg1, arg2) : void 0;
|
|
94
|
+
} else if (length === 4) result[key] = match ? q[3](match.replace(q[1], q[2]), void 0, result) : void 0;
|
|
95
|
+
} else result[q] = match || void 0;
|
|
96
|
+
}
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
function strMapper(str, map) {
|
|
103
|
+
for (const i in map) {
|
|
104
|
+
const value = map[i];
|
|
105
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
106
|
+
for (let j = 0; j < value.length; j++) if (has(value[j], str)) return i === UNKNOWN ? void 0 : i;
|
|
107
|
+
} else if (has(value, str)) return i === UNKNOWN ? void 0 : i;
|
|
108
|
+
}
|
|
109
|
+
return str;
|
|
110
|
+
}
|
|
111
|
+
const oldSafariMap = {
|
|
112
|
+
"1.0": "/8",
|
|
113
|
+
"1.2": "/1",
|
|
114
|
+
"1.3": "/3",
|
|
115
|
+
"2.0": "/412",
|
|
116
|
+
"2.0.2": "/416",
|
|
117
|
+
"2.0.3": "/417",
|
|
118
|
+
"2.0.4": "/419",
|
|
119
|
+
"?": "/"
|
|
120
|
+
};
|
|
121
|
+
const windowsVersionMap = {
|
|
122
|
+
"ME": "4.90",
|
|
123
|
+
"NT 3.11": "NT3.51",
|
|
124
|
+
"NT 4.0": "NT4.0",
|
|
125
|
+
"2000": "NT 5.0",
|
|
126
|
+
"XP": ["NT 5.1", "NT 5.2"],
|
|
127
|
+
"Vista": "NT 6.0",
|
|
128
|
+
"7": "NT 6.1",
|
|
129
|
+
"8": "NT 6.2",
|
|
130
|
+
"8.1": "NT 6.3",
|
|
131
|
+
"10": ["NT 6.4", "NT 10.0"],
|
|
132
|
+
"RT": "ARM"
|
|
133
|
+
};
|
|
134
|
+
const regexes = {
|
|
135
|
+
browser: [
|
|
136
|
+
[/\b(?:crmo|crios)\/([\w.]+)/i],
|
|
137
|
+
[VERSION, [NAME, "Chrome"]],
|
|
138
|
+
[/edg(?:e|ios|a)?\/([\w.]+)/i],
|
|
139
|
+
[VERSION, [NAME, "Edge"]],
|
|
140
|
+
[
|
|
141
|
+
/(opera mini)\/([-\w.]+)/i,
|
|
142
|
+
/(opera [mobileta]{3,6})\b.+version\/([-\w.]+)/i,
|
|
143
|
+
/(opera)(?:.+version\/|[/ ]+)([\w.]+)/i
|
|
144
|
+
],
|
|
145
|
+
[NAME, VERSION],
|
|
146
|
+
[/opios[/ ]+([\w.]+)/i],
|
|
147
|
+
[VERSION, [NAME, `${OPERA} Mini`]],
|
|
148
|
+
[/\bop(?:rg)?x\/([\w.]+)/i],
|
|
149
|
+
[VERSION, [NAME, `${OPERA} GX`]],
|
|
150
|
+
[/\bopr\/([\w.]+)/i],
|
|
151
|
+
[VERSION, [NAME, OPERA]],
|
|
152
|
+
[/\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[/ ]?([\w.]+)/i],
|
|
153
|
+
[VERSION, [NAME, "Baidu"]],
|
|
154
|
+
[
|
|
155
|
+
/(kindle)\/([\w.]+)/i,
|
|
156
|
+
/(lunascape|maxthon|netfront|jasmine|blazer)[/ ]?([\w.]*)/i,
|
|
157
|
+
/(avant|iemobile|slim)\s?(?:browser)?[/ ]?([\w.]*)/i,
|
|
158
|
+
/(?:ms|\()(ie) ([\w.]+)/i,
|
|
159
|
+
/(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,
|
|
160
|
+
/(heytap|ovi)browser\/([\d.]+)/i,
|
|
161
|
+
/(weibo)__([\d.]+)/i
|
|
162
|
+
],
|
|
163
|
+
[NAME, VERSION],
|
|
164
|
+
[/\bddg\/([\w.]+)/i],
|
|
165
|
+
[VERSION, [NAME, "DuckDuckGo"]],
|
|
166
|
+
[/(?:\buc? ?browser|juc.+ucweb)[/ ]?([\w.]+)/i],
|
|
167
|
+
[VERSION, [NAME, `UC${BROWSER_LABEL}`]],
|
|
168
|
+
[
|
|
169
|
+
/microm.+\bqbcore\/([\w.]+)/i,
|
|
170
|
+
/\bqbcore\/([\w.]+).+microm/i,
|
|
171
|
+
/micromessenger\/([\w.]+)/i
|
|
172
|
+
],
|
|
173
|
+
[VERSION, [NAME, "WeChat"]],
|
|
174
|
+
[/konqueror\/([\w.]+)/i],
|
|
175
|
+
[VERSION, [NAME, "Konqueror"]],
|
|
176
|
+
[/trident.+rv[: ]([\w.]{1,9})\b.+like gecko/i],
|
|
177
|
+
[VERSION, [NAME, "IE"]],
|
|
178
|
+
[/ya(?:search)?browser\/([\w.]+)/i],
|
|
179
|
+
[VERSION, [NAME, "Yandex"]],
|
|
180
|
+
[/slbrowser\/([\w.]+)/i],
|
|
181
|
+
[VERSION, [NAME, `Smart Lenovo ${BROWSER_LABEL}`]],
|
|
182
|
+
[/(avast|avg)\/([\w.]+)/i],
|
|
183
|
+
[[
|
|
184
|
+
NAME,
|
|
185
|
+
/(.+)/,
|
|
186
|
+
`$1 Secure ${BROWSER_LABEL}`
|
|
187
|
+
], VERSION],
|
|
188
|
+
[/\bfocus\/([\w.]+)/i],
|
|
189
|
+
[VERSION, [NAME, `${FIREFOX} Focus`]],
|
|
190
|
+
[/\bopt\/([\w.]+)/i],
|
|
191
|
+
[VERSION, [NAME, `${OPERA} Touch`]],
|
|
192
|
+
[/coc_coc\w+\/([\w.]+)/i],
|
|
193
|
+
[VERSION, [NAME, "Coc Coc"]],
|
|
194
|
+
[/dolfin\/([\w.]+)/i],
|
|
195
|
+
[VERSION, [NAME, "Dolphin"]],
|
|
196
|
+
[/coast\/([\w.]+)/i],
|
|
197
|
+
[VERSION, [NAME, `${OPERA} Coast`]],
|
|
198
|
+
[/miuibrowser\/([\w.]+)/i],
|
|
199
|
+
[VERSION, [NAME, `MIUI ${BROWSER_LABEL}`]],
|
|
200
|
+
[/fxios\/([-\w.]+)/i],
|
|
201
|
+
[VERSION, [NAME, FIREFOX]],
|
|
202
|
+
[/\bqihu|(qi?ho{0,2}|360)browser/i],
|
|
203
|
+
[[NAME, `360 ${BROWSER_LABEL}`]],
|
|
204
|
+
[/(oculus|sailfish|huawei|vivo)browser\/([\w.]+)/i],
|
|
205
|
+
[[
|
|
206
|
+
NAME,
|
|
207
|
+
/(.+)/,
|
|
208
|
+
`$1 ${BROWSER_LABEL}`
|
|
209
|
+
], VERSION],
|
|
210
|
+
[/samsungbrowser\/([\w.]+)/i],
|
|
211
|
+
[VERSION, [NAME, `${SAMSUNG} Internet`]],
|
|
212
|
+
[/(comodo_dragon)\/([\w.]+)/i],
|
|
213
|
+
[[
|
|
214
|
+
NAME,
|
|
215
|
+
/_/g,
|
|
216
|
+
" "
|
|
217
|
+
], VERSION],
|
|
218
|
+
[/metasr[/ ]?([\d.]+)/i],
|
|
219
|
+
[VERSION, [NAME, "Sogou Explorer"]],
|
|
220
|
+
[/(sogou)mo\w+\/([\d.]+)/i],
|
|
221
|
+
[[NAME, "Sogou Mobile"], VERSION],
|
|
222
|
+
[
|
|
223
|
+
/(electron)\/([\w.]+) safari/i,
|
|
224
|
+
/(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w.]+))/i,
|
|
225
|
+
/m?(qqbrowser|2345Explorer)[/ ]?([\w.]+)/i
|
|
226
|
+
],
|
|
227
|
+
[NAME, VERSION],
|
|
228
|
+
[/(lbbrowser)/i, /\[(linkedin)app\]/i],
|
|
229
|
+
[NAME],
|
|
230
|
+
[/((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w.]+);)/i],
|
|
231
|
+
[[NAME, FACEBOOK], VERSION],
|
|
232
|
+
[
|
|
233
|
+
/(Klarna)\/([\w.]+)/i,
|
|
234
|
+
/(kakao(?:talk|story))[/ ]([\w.]+)/i,
|
|
235
|
+
/(naver)\(.*?(\d+\.[\w.]+).*\)/i,
|
|
236
|
+
/safari (line)\/([\w.]+)/i,
|
|
237
|
+
/\b(line)\/([\w.]+)\/iab/i,
|
|
238
|
+
/(alipay)client\/([\w.]+)/i,
|
|
239
|
+
/(twitter)(?:and| f.+e\/([\w.]+))/i,
|
|
240
|
+
/(chromium|instagram|snapchat)[/ ]([-\w.]+)/i
|
|
241
|
+
],
|
|
242
|
+
[NAME, VERSION],
|
|
243
|
+
[/\bgsa\/([\w.]+) .*safari\//i],
|
|
244
|
+
[VERSION, [NAME, "GSA"]],
|
|
245
|
+
[/musical_ly(?:.+app_?version\/|_)([\w.]+)/i],
|
|
246
|
+
[VERSION, [NAME, "TikTok"]],
|
|
247
|
+
[/headlesschrome(?:\/([\w.]+)| )/i],
|
|
248
|
+
[VERSION, [NAME, `${CHROME} Headless`]],
|
|
249
|
+
[/ wv\).+(chrome)\/([\w.]+)/i],
|
|
250
|
+
[[NAME, `${CHROME} WebView`], VERSION],
|
|
251
|
+
[/droid.+ version\/([\w.]+)\b.+(?:mobile safari|safari)/i],
|
|
252
|
+
[VERSION, [NAME, `Android ${BROWSER_LABEL}`]],
|
|
253
|
+
[/(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w.]+)/i],
|
|
254
|
+
[NAME, VERSION],
|
|
255
|
+
[/version\/([\w.,]+) .*mobile\/\w+ (safari)/i],
|
|
256
|
+
[VERSION, [NAME, "Mobile Safari"]],
|
|
257
|
+
[/version\/([\w(.|,)]+) .*(mobile ?safari|safari)/i],
|
|
258
|
+
[VERSION, NAME],
|
|
259
|
+
[/webkit.+?(mobile ?safari|safari)(\/[\w.]+)/i],
|
|
260
|
+
[NAME, [
|
|
261
|
+
VERSION,
|
|
262
|
+
strMapper,
|
|
263
|
+
oldSafariMap
|
|
264
|
+
]],
|
|
265
|
+
[/(webkit|khtml)\/([\w.]+)/i],
|
|
266
|
+
[NAME, VERSION],
|
|
267
|
+
[/(navigator|netscape\d?)\/([-\w.]+)/i],
|
|
268
|
+
[[NAME, "Netscape"], VERSION],
|
|
269
|
+
[/mobile vr; rv:([\w.]+)\).+firefox/i],
|
|
270
|
+
[VERSION, [NAME, `${FIREFOX} Reality`]],
|
|
271
|
+
[
|
|
272
|
+
/ekiohf.+(flow)\/([\w.]+)/i,
|
|
273
|
+
/(swiftfox)/i,
|
|
274
|
+
/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror|klar)[/ ]?([\w.+]+)/i,
|
|
275
|
+
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w.]+)$/i,
|
|
276
|
+
/(firefox)\/([\w.]+)/i,
|
|
277
|
+
/(mozilla)\/([\w.]+) .+rv:.+gecko\/\d+/i,
|
|
278
|
+
/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir|obigo|mosaic|(?:go|ice|up)[. ]?browser)[-/ ]?v?([\w.]+)/i,
|
|
279
|
+
/(links) \(([\w.]+)/i,
|
|
280
|
+
/panasonic;(viera)/i
|
|
281
|
+
],
|
|
282
|
+
[NAME, VERSION],
|
|
283
|
+
[/(cobalt)\/([\w.]+)/i],
|
|
284
|
+
[NAME, [
|
|
285
|
+
VERSION,
|
|
286
|
+
/master.|lts./,
|
|
287
|
+
""
|
|
288
|
+
]]
|
|
289
|
+
],
|
|
290
|
+
cpu: [
|
|
291
|
+
[/(amd|x(?:(?:86|64)[-_])?|wow|win)64[;)]/i],
|
|
292
|
+
[[ARCHITECTURE, "amd64"]],
|
|
293
|
+
[/(ia32(?=;))/i],
|
|
294
|
+
[[ARCHITECTURE, lowerize]],
|
|
295
|
+
[/((?:i[346]|x)86)[;)]/i],
|
|
296
|
+
[[ARCHITECTURE, "ia32"]],
|
|
297
|
+
[/\b(aarch64|arm(v?8e?l?|_?64))\b/i],
|
|
298
|
+
[[ARCHITECTURE, "arm64"]],
|
|
299
|
+
[/\b(arm(?:v[67])?ht?n?[fl]p?)\b/i],
|
|
300
|
+
[[ARCHITECTURE, "armhf"]],
|
|
301
|
+
[/windows (ce|mobile); ppc;/i],
|
|
302
|
+
[[ARCHITECTURE, "arm"]],
|
|
303
|
+
[/((?:ppc|powerpc)(?:64)?)(?: mac|;|\))/i],
|
|
304
|
+
[[
|
|
305
|
+
ARCHITECTURE,
|
|
306
|
+
/ower/,
|
|
307
|
+
EMPTY,
|
|
308
|
+
lowerize
|
|
309
|
+
]],
|
|
310
|
+
[/(sun4\w)[;)]/i],
|
|
311
|
+
[[ARCHITECTURE, "sparc"]],
|
|
312
|
+
[/(avr32|ia64(?=;)|68k(?=\))|\barm(?=v(?:[1-7]|[5-7]1)l?|;|eabi)|(?=atmel )avr|(?:irix|mips|sparc)(?:64)?\b|pa-risc)/i],
|
|
313
|
+
[[ARCHITECTURE, lowerize]]
|
|
314
|
+
],
|
|
315
|
+
device: [
|
|
316
|
+
[/\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],
|
|
317
|
+
[
|
|
318
|
+
MODEL,
|
|
319
|
+
[VENDOR, SAMSUNG],
|
|
320
|
+
[TYPE, TABLET]
|
|
321
|
+
],
|
|
322
|
+
[
|
|
323
|
+
/\b((?:s[cgp]h|gt|sm)-\w+|sc[g-]?\d+a?|galaxy nexus)/i,
|
|
324
|
+
/samsung[- ]([-\w]+)/i,
|
|
325
|
+
/sec-(sgh\w+)/i
|
|
326
|
+
],
|
|
327
|
+
[
|
|
328
|
+
MODEL,
|
|
329
|
+
[VENDOR, SAMSUNG],
|
|
330
|
+
[TYPE, MOBILE]
|
|
331
|
+
],
|
|
332
|
+
[/(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i],
|
|
333
|
+
[
|
|
334
|
+
MODEL,
|
|
335
|
+
[VENDOR, APPLE],
|
|
336
|
+
[TYPE, MOBILE]
|
|
337
|
+
],
|
|
338
|
+
[
|
|
339
|
+
/\((ipad);[-\w),; ]+apple/i,
|
|
340
|
+
/applecoremedia\/[\w.]+ \((ipad)/i,
|
|
341
|
+
/\b(ipad)\d\d?,\d\d?[;\]].+ios/i
|
|
342
|
+
],
|
|
343
|
+
[
|
|
344
|
+
MODEL,
|
|
345
|
+
[VENDOR, APPLE],
|
|
346
|
+
[TYPE, TABLET]
|
|
347
|
+
],
|
|
348
|
+
[/(macintosh);/i],
|
|
349
|
+
[MODEL, [VENDOR, APPLE]],
|
|
350
|
+
[/\b(sh-?[altvz]?\d\d[a-ekm]?)/i],
|
|
351
|
+
[
|
|
352
|
+
MODEL,
|
|
353
|
+
[VENDOR, SHARP],
|
|
354
|
+
[TYPE, MOBILE]
|
|
355
|
+
],
|
|
356
|
+
[/\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\d{2})\b(?!.+d\/s)/i],
|
|
357
|
+
[
|
|
358
|
+
MODEL,
|
|
359
|
+
[VENDOR, HUAWEI],
|
|
360
|
+
[TYPE, TABLET]
|
|
361
|
+
],
|
|
362
|
+
[/(?:huawei|honor)([-\w ]+)[;)]/i, /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][0-359c][adn]?)\b(?!.+d\/s)/i],
|
|
363
|
+
[
|
|
364
|
+
MODEL,
|
|
365
|
+
[VENDOR, HUAWEI],
|
|
366
|
+
[TYPE, MOBILE]
|
|
367
|
+
],
|
|
368
|
+
[
|
|
369
|
+
/\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i,
|
|
370
|
+
/\b; (\w+) build\/hm\1/i,
|
|
371
|
+
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i,
|
|
372
|
+
/\b(redmi[\-_ ]?[\w ]+)(?: bui|\))/i,
|
|
373
|
+
/oid[^)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i,
|
|
374
|
+
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?\d?\w?[_ ]?(?:plus|se|lite)?)(?: bui|\))/i
|
|
375
|
+
],
|
|
376
|
+
[
|
|
377
|
+
[
|
|
378
|
+
MODEL,
|
|
379
|
+
/_/g,
|
|
380
|
+
" "
|
|
381
|
+
],
|
|
382
|
+
[VENDOR, XIAOMI],
|
|
383
|
+
[TYPE, MOBILE]
|
|
384
|
+
],
|
|
385
|
+
[/oid[^)]+; (2\d{4}(283|rpbf)[cgl])( bui|\))/i, /\b(mi[-_ ]?pad[\w ]+)(?: bui|\))/i],
|
|
386
|
+
[
|
|
387
|
+
[
|
|
388
|
+
MODEL,
|
|
389
|
+
/_/g,
|
|
390
|
+
" "
|
|
391
|
+
],
|
|
392
|
+
[VENDOR, XIAOMI],
|
|
393
|
+
[TYPE, TABLET]
|
|
394
|
+
],
|
|
395
|
+
[/; (\w+) bui.+ oppo/i, /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i],
|
|
396
|
+
[
|
|
397
|
+
MODEL,
|
|
398
|
+
[VENDOR, "OPPO"],
|
|
399
|
+
[TYPE, MOBILE]
|
|
400
|
+
],
|
|
401
|
+
[/\b(opd2\d{3}a?) bui/i],
|
|
402
|
+
[
|
|
403
|
+
MODEL,
|
|
404
|
+
[VENDOR, "OPPO"],
|
|
405
|
+
[TYPE, TABLET]
|
|
406
|
+
],
|
|
407
|
+
[/vivo (\w+)(?: bui|\))/i, /\b(v[12]\d{3}\w?[at])(?: bui|;)/i],
|
|
408
|
+
[
|
|
409
|
+
MODEL,
|
|
410
|
+
[VENDOR, "Vivo"],
|
|
411
|
+
[TYPE, MOBILE]
|
|
412
|
+
],
|
|
413
|
+
[/\b(rmx[1-3]\d{3})(?: bui|;|\))/i],
|
|
414
|
+
[
|
|
415
|
+
MODEL,
|
|
416
|
+
[VENDOR, "Realme"],
|
|
417
|
+
[TYPE, MOBILE]
|
|
418
|
+
],
|
|
419
|
+
[
|
|
420
|
+
/\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
|
|
421
|
+
/\bmot(?:orola)?[- ](\w*)/i,
|
|
422
|
+
/((?:moto[\w() ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i
|
|
423
|
+
],
|
|
424
|
+
[
|
|
425
|
+
MODEL,
|
|
426
|
+
[VENDOR, MOTOROLA],
|
|
427
|
+
[TYPE, MOBILE]
|
|
428
|
+
],
|
|
429
|
+
[/\b(mz60\d|xoom[2 ]{0,2}) build\//i],
|
|
430
|
+
[
|
|
431
|
+
MODEL,
|
|
432
|
+
[VENDOR, MOTOROLA],
|
|
433
|
+
[TYPE, TABLET]
|
|
434
|
+
],
|
|
435
|
+
[/((?=lg)?[vl]k-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i],
|
|
436
|
+
[
|
|
437
|
+
MODEL,
|
|
438
|
+
[VENDOR, LG],
|
|
439
|
+
[TYPE, TABLET]
|
|
440
|
+
],
|
|
441
|
+
[
|
|
442
|
+
/(lm(?:-?f100[nv]?|-[\w.]+)(?= bui|\))|nexus [45])/i,
|
|
443
|
+
/\blg[-e;/ ]+((?!browser|netcast|android tv)\w+)/i,
|
|
444
|
+
/\blg-?(\w+) bui/i
|
|
445
|
+
],
|
|
446
|
+
[
|
|
447
|
+
MODEL,
|
|
448
|
+
[VENDOR, LG],
|
|
449
|
+
[TYPE, MOBILE]
|
|
450
|
+
],
|
|
451
|
+
[/(ideatab[-\w ]+)/i, /lenovo ?(s[56]000[-\w]+|tab[\w ]+|yt[-\w]{6}|tb[-\w]{6})/i],
|
|
452
|
+
[
|
|
453
|
+
MODEL,
|
|
454
|
+
[VENDOR, "Lenovo"],
|
|
455
|
+
[TYPE, TABLET]
|
|
456
|
+
],
|
|
457
|
+
[/(?:maemo|nokia).*(n900|lumia \d+)/i, /nokia[-_ ]?([-\w.]*)/i],
|
|
458
|
+
[
|
|
459
|
+
[
|
|
460
|
+
MODEL,
|
|
461
|
+
/_/g,
|
|
462
|
+
" "
|
|
463
|
+
],
|
|
464
|
+
[VENDOR, "Nokia"],
|
|
465
|
+
[TYPE, MOBILE]
|
|
466
|
+
],
|
|
467
|
+
[/(pixel c)\b/i],
|
|
468
|
+
[
|
|
469
|
+
MODEL,
|
|
470
|
+
[VENDOR, GOOGLE],
|
|
471
|
+
[TYPE, TABLET]
|
|
472
|
+
],
|
|
473
|
+
[/droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i],
|
|
474
|
+
[
|
|
475
|
+
MODEL,
|
|
476
|
+
[VENDOR, GOOGLE],
|
|
477
|
+
[TYPE, MOBILE]
|
|
478
|
+
],
|
|
479
|
+
[/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],
|
|
480
|
+
[
|
|
481
|
+
MODEL,
|
|
482
|
+
[VENDOR, SONY],
|
|
483
|
+
[TYPE, MOBILE]
|
|
484
|
+
],
|
|
485
|
+
[/sony tablet [ps]/i, /\b(?:sony)?sgp\w+(?: bui|\))/i],
|
|
486
|
+
[
|
|
487
|
+
[MODEL, "Xperia Tablet"],
|
|
488
|
+
[VENDOR, SONY],
|
|
489
|
+
[TYPE, TABLET]
|
|
490
|
+
],
|
|
491
|
+
[/ (kb2005|in20[12]5|be20[12][59])\b/i, /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i],
|
|
492
|
+
[
|
|
493
|
+
MODEL,
|
|
494
|
+
[VENDOR, "OnePlus"],
|
|
495
|
+
[TYPE, MOBILE]
|
|
496
|
+
],
|
|
497
|
+
[
|
|
498
|
+
/(alexa)webm/i,
|
|
499
|
+
/(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i,
|
|
500
|
+
/(kf[a-z]+)( bui|\)).+silk\//i
|
|
501
|
+
],
|
|
502
|
+
[
|
|
503
|
+
MODEL,
|
|
504
|
+
[VENDOR, AMAZON],
|
|
505
|
+
[TYPE, TABLET]
|
|
506
|
+
],
|
|
507
|
+
[/((?:sd|kf)[0349hijor-uw]+)( bui|\)).+silk\//i],
|
|
508
|
+
[
|
|
509
|
+
[
|
|
510
|
+
MODEL,
|
|
511
|
+
/(.+)/g,
|
|
512
|
+
"Fire Phone $1"
|
|
513
|
+
],
|
|
514
|
+
[VENDOR, AMAZON],
|
|
515
|
+
[TYPE, MOBILE]
|
|
516
|
+
],
|
|
517
|
+
[/(playbook);[-\w),; ]+(rim)/i],
|
|
518
|
+
[
|
|
519
|
+
MODEL,
|
|
520
|
+
VENDOR,
|
|
521
|
+
[TYPE, TABLET]
|
|
522
|
+
],
|
|
523
|
+
[/\b((?:bb[a-f]|st[hv])100-\d)/i, /\(bb10; (\w+)/i],
|
|
524
|
+
[
|
|
525
|
+
MODEL,
|
|
526
|
+
[VENDOR, BLACKBERRY],
|
|
527
|
+
[TYPE, MOBILE]
|
|
528
|
+
],
|
|
529
|
+
[/(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i],
|
|
530
|
+
[
|
|
531
|
+
MODEL,
|
|
532
|
+
[VENDOR, ASUS],
|
|
533
|
+
[TYPE, TABLET]
|
|
534
|
+
],
|
|
535
|
+
[/ (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i],
|
|
536
|
+
[
|
|
537
|
+
MODEL,
|
|
538
|
+
[VENDOR, ASUS],
|
|
539
|
+
[TYPE, MOBILE]
|
|
540
|
+
],
|
|
541
|
+
[/(nexus 9)/i],
|
|
542
|
+
[
|
|
543
|
+
MODEL,
|
|
544
|
+
[VENDOR, "HTC"],
|
|
545
|
+
[TYPE, TABLET]
|
|
546
|
+
],
|
|
547
|
+
[
|
|
548
|
+
/(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i,
|
|
549
|
+
/(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,
|
|
550
|
+
/(alcatel|geeksphone|nexian|panasonic(?!;|\.)|sony(?!-bra))[-_ ]?([-\w]*)/i
|
|
551
|
+
],
|
|
552
|
+
[
|
|
553
|
+
VENDOR,
|
|
554
|
+
[
|
|
555
|
+
MODEL,
|
|
556
|
+
/_/g,
|
|
557
|
+
" "
|
|
558
|
+
],
|
|
559
|
+
[TYPE, MOBILE]
|
|
560
|
+
],
|
|
561
|
+
[/droid.+; ([ab][1-7]-?[0178a]\d\d?)/i],
|
|
562
|
+
[
|
|
563
|
+
MODEL,
|
|
564
|
+
[VENDOR, "Acer"],
|
|
565
|
+
[TYPE, TABLET]
|
|
566
|
+
],
|
|
567
|
+
[/droid.+; (m[1-5] note) bui/i, /\bmz-([-\w]{2,})/i],
|
|
568
|
+
[
|
|
569
|
+
MODEL,
|
|
570
|
+
[VENDOR, "Meizu"],
|
|
571
|
+
[TYPE, MOBILE]
|
|
572
|
+
],
|
|
573
|
+
[/; ((?:power )?armor[\w ]{0,8})(?: bui|\))/i],
|
|
574
|
+
[
|
|
575
|
+
MODEL,
|
|
576
|
+
[VENDOR, "Ulefone"],
|
|
577
|
+
[TYPE, MOBILE]
|
|
578
|
+
],
|
|
579
|
+
[
|
|
580
|
+
/(blackberry|benq|palm(?=-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i,
|
|
581
|
+
/(hp) ([\w ]+\w)/i,
|
|
582
|
+
/(asus)-?(\w+)/i,
|
|
583
|
+
/(microsoft); (lumia[\w ]+)/i,
|
|
584
|
+
/(lenovo)[-_ ]?([-\w]+)/i,
|
|
585
|
+
/(jolla)/i,
|
|
586
|
+
/(oppo) ?([\w ]+) bui/i
|
|
587
|
+
],
|
|
588
|
+
[
|
|
589
|
+
VENDOR,
|
|
590
|
+
MODEL,
|
|
591
|
+
[TYPE, MOBILE]
|
|
592
|
+
],
|
|
593
|
+
[
|
|
594
|
+
/(kobo)\s(ereader|touch)/i,
|
|
595
|
+
/(archos) (gamepad2?)/i,
|
|
596
|
+
/(hp).+(touchpad(?!.+tablet)|tablet)/i,
|
|
597
|
+
/(kindle)\/([\w.]+)/i,
|
|
598
|
+
/(nook)[\w ]+build\/(\w+)/i,
|
|
599
|
+
/(dell) (strea[kpr\d ]*[\dko])/i,
|
|
600
|
+
/(le[- ]+pan)[- ]+(\w{1,9}) bui/i,
|
|
601
|
+
/(trinity)[- ]*(t\d{3}) bui/i,
|
|
602
|
+
/(gigaset)[- ]+(q\w{1,9}) bui/i,
|
|
603
|
+
/(vodafone) ([\w ]+)(?:\)| bui)/i
|
|
604
|
+
],
|
|
605
|
+
[
|
|
606
|
+
VENDOR,
|
|
607
|
+
MODEL,
|
|
608
|
+
[TYPE, TABLET]
|
|
609
|
+
],
|
|
610
|
+
[/(surface duo)/i],
|
|
611
|
+
[
|
|
612
|
+
MODEL,
|
|
613
|
+
[VENDOR, MICROSOFT],
|
|
614
|
+
[TYPE, TABLET]
|
|
615
|
+
],
|
|
616
|
+
[/droid [\d.]+; (fp\du?)(?: b|\))/i],
|
|
617
|
+
[
|
|
618
|
+
MODEL,
|
|
619
|
+
[VENDOR, "Fairphone"],
|
|
620
|
+
[TYPE, MOBILE]
|
|
621
|
+
],
|
|
622
|
+
[/(u304aa)/i],
|
|
623
|
+
[
|
|
624
|
+
MODEL,
|
|
625
|
+
[VENDOR, "AT&T"],
|
|
626
|
+
[TYPE, MOBILE]
|
|
627
|
+
],
|
|
628
|
+
[/\bsie-(\w*)/i],
|
|
629
|
+
[
|
|
630
|
+
MODEL,
|
|
631
|
+
[VENDOR, "Siemens"],
|
|
632
|
+
[TYPE, MOBILE]
|
|
633
|
+
],
|
|
634
|
+
[/\b(rct\w+) b/i],
|
|
635
|
+
[
|
|
636
|
+
MODEL,
|
|
637
|
+
[VENDOR, "RCA"],
|
|
638
|
+
[TYPE, TABLET]
|
|
639
|
+
],
|
|
640
|
+
[/\b(venue[\d ]{2,7}) b/i],
|
|
641
|
+
[
|
|
642
|
+
MODEL,
|
|
643
|
+
[VENDOR, "Dell"],
|
|
644
|
+
[TYPE, TABLET]
|
|
645
|
+
],
|
|
646
|
+
[/\b(q(?:mv|ta)\w+) b/i],
|
|
647
|
+
[
|
|
648
|
+
MODEL,
|
|
649
|
+
[VENDOR, "Verizon"],
|
|
650
|
+
[TYPE, TABLET]
|
|
651
|
+
],
|
|
652
|
+
[/\b(?:barnes[& ]+noble |bn[rt])([\w+ ]*) b/i],
|
|
653
|
+
[
|
|
654
|
+
MODEL,
|
|
655
|
+
[VENDOR, "Barnes & Noble"],
|
|
656
|
+
[TYPE, TABLET]
|
|
657
|
+
],
|
|
658
|
+
[/\b(tm\d{3}\w+) b/i],
|
|
659
|
+
[
|
|
660
|
+
MODEL,
|
|
661
|
+
[VENDOR, "NuVision"],
|
|
662
|
+
[TYPE, TABLET]
|
|
663
|
+
],
|
|
664
|
+
[/\b(k88) b/i],
|
|
665
|
+
[
|
|
666
|
+
MODEL,
|
|
667
|
+
[VENDOR, "ZTE"],
|
|
668
|
+
[TYPE, TABLET]
|
|
669
|
+
],
|
|
670
|
+
[/\b(nx\d{3}j) b/i],
|
|
671
|
+
[
|
|
672
|
+
MODEL,
|
|
673
|
+
[VENDOR, "ZTE"],
|
|
674
|
+
[TYPE, MOBILE]
|
|
675
|
+
],
|
|
676
|
+
[/\b(gen\d{3}) b.+49h/i],
|
|
677
|
+
[
|
|
678
|
+
MODEL,
|
|
679
|
+
[VENDOR, "Swiss"],
|
|
680
|
+
[TYPE, MOBILE]
|
|
681
|
+
],
|
|
682
|
+
[/\b(zur\d{3}) b/i],
|
|
683
|
+
[
|
|
684
|
+
MODEL,
|
|
685
|
+
[VENDOR, "Swiss"],
|
|
686
|
+
[TYPE, TABLET]
|
|
687
|
+
],
|
|
688
|
+
[/\b((zeki)?tb.*\b) b/i],
|
|
689
|
+
[
|
|
690
|
+
MODEL,
|
|
691
|
+
[VENDOR, "Zeki"],
|
|
692
|
+
[TYPE, TABLET]
|
|
693
|
+
],
|
|
694
|
+
[/\b([yr]\d{2}) b/i, /\b(dragon[- ]+touch |dt)(\w{5}) b/i],
|
|
695
|
+
[
|
|
696
|
+
[VENDOR, "Dragon Touch"],
|
|
697
|
+
MODEL,
|
|
698
|
+
[TYPE, TABLET]
|
|
699
|
+
],
|
|
700
|
+
[/\b(ns-?\w{0,9}) b/i],
|
|
701
|
+
[
|
|
702
|
+
MODEL,
|
|
703
|
+
[VENDOR, "Insignia"],
|
|
704
|
+
[TYPE, TABLET]
|
|
705
|
+
],
|
|
706
|
+
[/\b((nxa|next)-?\w{0,9}) b/i],
|
|
707
|
+
[
|
|
708
|
+
MODEL,
|
|
709
|
+
[VENDOR, "NextBook"],
|
|
710
|
+
[TYPE, TABLET]
|
|
711
|
+
],
|
|
712
|
+
[/\b(xtreme_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i],
|
|
713
|
+
[
|
|
714
|
+
[VENDOR, "Voice"],
|
|
715
|
+
MODEL,
|
|
716
|
+
[TYPE, MOBILE]
|
|
717
|
+
],
|
|
718
|
+
[/\b(lvtel-)?(v1[12]) b/i],
|
|
719
|
+
[
|
|
720
|
+
[VENDOR, "LvTel"],
|
|
721
|
+
MODEL,
|
|
722
|
+
[TYPE, MOBILE]
|
|
723
|
+
],
|
|
724
|
+
[/\b(ph-1) /i],
|
|
725
|
+
[
|
|
726
|
+
MODEL,
|
|
727
|
+
[VENDOR, "Essential"],
|
|
728
|
+
[TYPE, MOBILE]
|
|
729
|
+
],
|
|
730
|
+
[/\b(v(100md|700na|7011|917g).*\b) b/i],
|
|
731
|
+
[
|
|
732
|
+
MODEL,
|
|
733
|
+
[VENDOR, "Envizen"],
|
|
734
|
+
[TYPE, TABLET]
|
|
735
|
+
],
|
|
736
|
+
[/\b(trio[-\w. ]+) b/i],
|
|
737
|
+
[
|
|
738
|
+
MODEL,
|
|
739
|
+
[VENDOR, "MachSpeed"],
|
|
740
|
+
[TYPE, TABLET]
|
|
741
|
+
],
|
|
742
|
+
[/\btu_(1491) b/i],
|
|
743
|
+
[
|
|
744
|
+
MODEL,
|
|
745
|
+
[VENDOR, "Rotor"],
|
|
746
|
+
[TYPE, TABLET]
|
|
747
|
+
],
|
|
748
|
+
[/(shield[\w ]+) b/i],
|
|
749
|
+
[
|
|
750
|
+
MODEL,
|
|
751
|
+
[VENDOR, "Nvidia"],
|
|
752
|
+
[TYPE, TABLET]
|
|
753
|
+
],
|
|
754
|
+
[/(sprint) (\w+)/i],
|
|
755
|
+
[
|
|
756
|
+
VENDOR,
|
|
757
|
+
MODEL,
|
|
758
|
+
[TYPE, MOBILE]
|
|
759
|
+
],
|
|
760
|
+
[/(kin\.[onetw]{3})/i],
|
|
761
|
+
[
|
|
762
|
+
[
|
|
763
|
+
MODEL,
|
|
764
|
+
/\./g,
|
|
765
|
+
" "
|
|
766
|
+
],
|
|
767
|
+
[VENDOR, MICROSOFT],
|
|
768
|
+
[TYPE, MOBILE]
|
|
769
|
+
],
|
|
770
|
+
[/droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i],
|
|
771
|
+
[
|
|
772
|
+
MODEL,
|
|
773
|
+
[VENDOR, ZEBRA],
|
|
774
|
+
[TYPE, TABLET]
|
|
775
|
+
],
|
|
776
|
+
[/droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i],
|
|
777
|
+
[
|
|
778
|
+
MODEL,
|
|
779
|
+
[VENDOR, ZEBRA],
|
|
780
|
+
[TYPE, MOBILE]
|
|
781
|
+
],
|
|
782
|
+
[/smart-tv.+(samsung)/i],
|
|
783
|
+
[VENDOR, [TYPE, SMARTTV]],
|
|
784
|
+
[/hbbtv.+maple;(\d+)/i],
|
|
785
|
+
[
|
|
786
|
+
[
|
|
787
|
+
MODEL,
|
|
788
|
+
/^/,
|
|
789
|
+
"SmartTV"
|
|
790
|
+
],
|
|
791
|
+
[VENDOR, SAMSUNG],
|
|
792
|
+
[TYPE, SMARTTV]
|
|
793
|
+
],
|
|
794
|
+
[/(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i],
|
|
795
|
+
[[VENDOR, LG], [TYPE, SMARTTV]],
|
|
796
|
+
[/(apple) ?tv/i],
|
|
797
|
+
[
|
|
798
|
+
VENDOR,
|
|
799
|
+
[MODEL, `${APPLE} TV`],
|
|
800
|
+
[TYPE, SMARTTV]
|
|
801
|
+
],
|
|
802
|
+
[/crkey/i],
|
|
803
|
+
[
|
|
804
|
+
[MODEL, `${CHROME}cast`],
|
|
805
|
+
[VENDOR, GOOGLE],
|
|
806
|
+
[TYPE, SMARTTV]
|
|
807
|
+
],
|
|
808
|
+
[/droid.+aft(\w+)( bui|\))/i],
|
|
809
|
+
[
|
|
810
|
+
MODEL,
|
|
811
|
+
[VENDOR, AMAZON],
|
|
812
|
+
[TYPE, SMARTTV]
|
|
813
|
+
],
|
|
814
|
+
[/\(dtv[);].+(aquos)/i, /(aquos-tv[\w ]+)\)/i],
|
|
815
|
+
[
|
|
816
|
+
MODEL,
|
|
817
|
+
[VENDOR, SHARP],
|
|
818
|
+
[TYPE, SMARTTV]
|
|
819
|
+
],
|
|
820
|
+
[/(bravia[\w ]+)( bui|\))/i],
|
|
821
|
+
[
|
|
822
|
+
MODEL,
|
|
823
|
+
[VENDOR, SONY],
|
|
824
|
+
[TYPE, SMARTTV]
|
|
825
|
+
],
|
|
826
|
+
[/(mitv-\w{5}) bui/i],
|
|
827
|
+
[
|
|
828
|
+
MODEL,
|
|
829
|
+
[VENDOR, XIAOMI],
|
|
830
|
+
[TYPE, SMARTTV]
|
|
831
|
+
],
|
|
832
|
+
[/Hbbtv.*(technisat) (.*);/i],
|
|
833
|
+
[
|
|
834
|
+
VENDOR,
|
|
835
|
+
MODEL,
|
|
836
|
+
[TYPE, SMARTTV]
|
|
837
|
+
],
|
|
838
|
+
[/\b(roku)[\dx]*[)/]((?:dvp-)?[\d.]*)/i, /hbbtv\/\d+\.\d+\.\d+ +\([\w+ ]*; *(\w[^;]*);([^;]*)/i],
|
|
839
|
+
[
|
|
840
|
+
[VENDOR, trim],
|
|
841
|
+
[MODEL, trim],
|
|
842
|
+
[TYPE, SMARTTV]
|
|
843
|
+
],
|
|
844
|
+
[/\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i],
|
|
845
|
+
[[TYPE, SMARTTV]],
|
|
846
|
+
[/(ouya)/i, /(nintendo) ([wids3utch]+)/i],
|
|
847
|
+
[
|
|
848
|
+
VENDOR,
|
|
849
|
+
MODEL,
|
|
850
|
+
[TYPE, CONSOLE]
|
|
851
|
+
],
|
|
852
|
+
[/droid.+; (shield) bui/i],
|
|
853
|
+
[
|
|
854
|
+
MODEL,
|
|
855
|
+
[VENDOR, "Nvidia"],
|
|
856
|
+
[TYPE, CONSOLE]
|
|
857
|
+
],
|
|
858
|
+
[/(playstation [345portablevi]+)/i],
|
|
859
|
+
[
|
|
860
|
+
MODEL,
|
|
861
|
+
[VENDOR, SONY],
|
|
862
|
+
[TYPE, CONSOLE]
|
|
863
|
+
],
|
|
864
|
+
[/\b(xbox(?: one)?(?!; xbox))[); ]/i],
|
|
865
|
+
[
|
|
866
|
+
MODEL,
|
|
867
|
+
[VENDOR, MICROSOFT],
|
|
868
|
+
[TYPE, CONSOLE]
|
|
869
|
+
],
|
|
870
|
+
[/((pebble))app/i],
|
|
871
|
+
[
|
|
872
|
+
VENDOR,
|
|
873
|
+
MODEL,
|
|
874
|
+
[TYPE, WEARABLE]
|
|
875
|
+
],
|
|
876
|
+
[/(watch)(?: ?os[,/]|\d,\d\/)[\d.]+/i],
|
|
877
|
+
[
|
|
878
|
+
MODEL,
|
|
879
|
+
[VENDOR, APPLE],
|
|
880
|
+
[TYPE, WEARABLE]
|
|
881
|
+
],
|
|
882
|
+
[/droid.+; (glass) \d/i],
|
|
883
|
+
[
|
|
884
|
+
MODEL,
|
|
885
|
+
[VENDOR, GOOGLE],
|
|
886
|
+
[TYPE, WEARABLE]
|
|
887
|
+
],
|
|
888
|
+
[/droid.+; (wt63?0{2,3})\)/i],
|
|
889
|
+
[
|
|
890
|
+
MODEL,
|
|
891
|
+
[VENDOR, ZEBRA],
|
|
892
|
+
[TYPE, WEARABLE]
|
|
893
|
+
],
|
|
894
|
+
[/(quest( \d| pro)?)/i],
|
|
895
|
+
[
|
|
896
|
+
MODEL,
|
|
897
|
+
[VENDOR, FACEBOOK],
|
|
898
|
+
[TYPE, WEARABLE]
|
|
899
|
+
],
|
|
900
|
+
[/(tesla)(?: qtcarbrowser|\/[-\w.]+)/i],
|
|
901
|
+
[VENDOR, [TYPE, EMBEDDED]],
|
|
902
|
+
[/(aeobc)\b/i],
|
|
903
|
+
[
|
|
904
|
+
MODEL,
|
|
905
|
+
[VENDOR, AMAZON],
|
|
906
|
+
[TYPE, EMBEDDED]
|
|
907
|
+
],
|
|
908
|
+
[/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+? mobile safari/i],
|
|
909
|
+
[MODEL, [TYPE, MOBILE]],
|
|
910
|
+
[/droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i],
|
|
911
|
+
[MODEL, [TYPE, TABLET]],
|
|
912
|
+
[/\b((tablet|tab)[;/]|focus\/\d(?!.+mobile))/i],
|
|
913
|
+
[[TYPE, TABLET]],
|
|
914
|
+
[/(phone|mobile(?:[;/]| [ \w/.]*safari)|pda(?=.+windows ce))/i],
|
|
915
|
+
[[TYPE, MOBILE]],
|
|
916
|
+
[/(android[-\w. ]{0,9});.+buil/i],
|
|
917
|
+
[MODEL, [VENDOR, "Generic"]]
|
|
918
|
+
],
|
|
919
|
+
engine: [
|
|
920
|
+
[/windows.+ edge\/([\w.]+)/i],
|
|
921
|
+
[VERSION, [NAME, `${EDGE}HTML`]],
|
|
922
|
+
[/webkit\/537\.36.+chrome\/(?!27)([\w.]+)/i],
|
|
923
|
+
[VERSION, [NAME, "Blink"]],
|
|
924
|
+
[
|
|
925
|
+
/(presto)\/([\w.]+)/i,
|
|
926
|
+
/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w.]+)/i,
|
|
927
|
+
/ekioh(flow)\/([\w.]+)/i,
|
|
928
|
+
/(khtml|tasman|links)[/ ]\(?([\w.]+)/i,
|
|
929
|
+
/(icab)[/ ]([23]\.[\d.]+)/i,
|
|
930
|
+
/\b(libweb)/i
|
|
931
|
+
],
|
|
932
|
+
[NAME, VERSION],
|
|
933
|
+
[/rv:([\w.]{1,9})\b.+(gecko)/i],
|
|
934
|
+
[VERSION, NAME]
|
|
935
|
+
],
|
|
936
|
+
os: [
|
|
937
|
+
[/microsoft (windows) (vista|xp)/i],
|
|
938
|
+
[NAME, VERSION],
|
|
939
|
+
[/(windows (?:phone(?: os)?|mobile))[/ ]?([.\w ]*)/i],
|
|
940
|
+
[NAME, [
|
|
941
|
+
VERSION,
|
|
942
|
+
strMapper,
|
|
943
|
+
windowsVersionMap
|
|
944
|
+
]],
|
|
945
|
+
[
|
|
946
|
+
/windows nt 6\.2; (arm)/i,
|
|
947
|
+
/windows[/ ]?([ntce\d. ]+\w)(?!.+xbox)/i,
|
|
948
|
+
/(?:win(?=[39n])|win 9x )([nt\d.]+)/i
|
|
949
|
+
],
|
|
950
|
+
[[
|
|
951
|
+
VERSION,
|
|
952
|
+
strMapper,
|
|
953
|
+
windowsVersionMap
|
|
954
|
+
], [NAME, "Windows"]],
|
|
955
|
+
[
|
|
956
|
+
/ip[honead]{2,4}\b(?:.*os (\w+) like mac|; opera)/i,
|
|
957
|
+
/(?:ios;fbsv\/|iphone.+ios[/ ])([\d.]+)/i,
|
|
958
|
+
/cfnetwork\/.+darwin/i
|
|
959
|
+
],
|
|
960
|
+
[[
|
|
961
|
+
VERSION,
|
|
962
|
+
/_/g,
|
|
963
|
+
"."
|
|
964
|
+
], [NAME, "iOS"]],
|
|
965
|
+
[/(mac os x) ?([\w. ]*)/i, /(macintosh|mac_powerpc\b)(?!.+haiku)/i],
|
|
966
|
+
[[NAME, MAC_OS], [
|
|
967
|
+
VERSION,
|
|
968
|
+
/_/g,
|
|
969
|
+
"."
|
|
970
|
+
]],
|
|
971
|
+
[/droid ([\w.]+)\b.+(android[- ]x86|harmonyos)/i],
|
|
972
|
+
[VERSION, NAME],
|
|
973
|
+
[
|
|
974
|
+
/(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-/ ]?([\w.]*)/i,
|
|
975
|
+
/(blackberry)\w*\/([\w.]*)/i,
|
|
976
|
+
/(tizen|kaios)[/ ]([\w.]+)/i,
|
|
977
|
+
/\((series40);/i
|
|
978
|
+
],
|
|
979
|
+
[NAME, VERSION],
|
|
980
|
+
[/\(bb(10);/i],
|
|
981
|
+
[VERSION, [NAME, BLACKBERRY]],
|
|
982
|
+
[/(?:symbian ?os|symbos|s60(?=;)|series60)[-/ ]?([\w.]*)/i],
|
|
983
|
+
[VERSION, [NAME, "Symbian"]],
|
|
984
|
+
[/mozilla\/[\d.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w.]+)/i],
|
|
985
|
+
[VERSION, [NAME, `${FIREFOX} OS`]],
|
|
986
|
+
[/web0s;.+rt(tv)/i, /\b(?:hp)?wos(?:browser)?\/([\w.]+)/i],
|
|
987
|
+
[VERSION, [NAME, "webOS"]],
|
|
988
|
+
[/watch(?: ?os[,/]|\d,\d\/)([\d.]+)/i],
|
|
989
|
+
[VERSION, [NAME, "watchOS"]],
|
|
990
|
+
[/crkey\/([\d.]+)/i],
|
|
991
|
+
[VERSION, [NAME, `${CHROME}cast`]],
|
|
992
|
+
[/(cros) \w+(?:\)| ([\w.]+)\b)/i],
|
|
993
|
+
[[NAME, CHROMIUM_OS], VERSION],
|
|
994
|
+
[
|
|
995
|
+
/panasonic;(viera)/i,
|
|
996
|
+
/(netrange)mmh/i,
|
|
997
|
+
/(nettv)\/(\d+\.[\w.]+)/i,
|
|
998
|
+
/(nintendo|playstation) ([wids345portablevuch]+)/i,
|
|
999
|
+
/(xbox); +xbox ([^);]+)/i,
|
|
1000
|
+
/\b(joli|palm)\b ?(?:os)?\/?([\w.]*)/i,
|
|
1001
|
+
/(mint)[/() ]?(\w*)/i,
|
|
1002
|
+
/(mageia|vectorlinux)[; ]/i,
|
|
1003
|
+
/([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,
|
|
1004
|
+
/(hurd|linux) ?([\w.]*)/i,
|
|
1005
|
+
/(gnu) ?([\w.]*)/i,
|
|
1006
|
+
/\b([-e-hrntopcs]{0,5}bsd|dragonfly)[/ ]?(?!amd|[ix346]{1,2}86)([\w.]*)/i,
|
|
1007
|
+
/(haiku) (\w+)/i
|
|
1008
|
+
],
|
|
1009
|
+
[NAME, VERSION],
|
|
1010
|
+
[/(sunos) ?([\w.]*)/i],
|
|
1011
|
+
[[NAME, "Solaris"], VERSION],
|
|
1012
|
+
[
|
|
1013
|
+
/((?:open)?solaris)[-/ ]?([\w.]*)/i,
|
|
1014
|
+
/(aix) ((\d)(?=[.) ])[\w.])*/i,
|
|
1015
|
+
/\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i,
|
|
1016
|
+
/(unix) ?([\w.]*)/i
|
|
1017
|
+
],
|
|
1018
|
+
[NAME, VERSION]
|
|
1019
|
+
]
|
|
1020
|
+
};
|
|
1021
|
+
function isExtensionsInput(input) {
|
|
1022
|
+
return typeof input === "object" && input !== null;
|
|
1023
|
+
}
|
|
1024
|
+
Object.freeze(enumerize([
|
|
1025
|
+
NAME,
|
|
1026
|
+
VERSION,
|
|
1027
|
+
MAJOR
|
|
1028
|
+
]));
|
|
1029
|
+
Object.freeze(enumerize([ARCHITECTURE]));
|
|
1030
|
+
Object.freeze(enumerize([
|
|
1031
|
+
MODEL,
|
|
1032
|
+
VENDOR,
|
|
1033
|
+
TYPE,
|
|
1034
|
+
CONSOLE,
|
|
1035
|
+
MOBILE,
|
|
1036
|
+
SMARTTV,
|
|
1037
|
+
TABLET,
|
|
1038
|
+
WEARABLE,
|
|
1039
|
+
EMBEDDED
|
|
1040
|
+
]));
|
|
1041
|
+
Object.freeze(enumerize([NAME, VERSION]));
|
|
1042
|
+
Object.freeze(enumerize([NAME, VERSION]));
|
|
1043
|
+
function getRuntimeNavigator() {
|
|
1044
|
+
if (typeof window === "undefined" || !window.navigator) return void 0;
|
|
1045
|
+
return window.navigator;
|
|
1046
|
+
}
|
|
1047
|
+
function normalizeUA(ua) {
|
|
1048
|
+
return ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
|
|
1049
|
+
}
|
|
1050
|
+
function createDefaultParserContext(uastring) {
|
|
1051
|
+
if (typeof uastring === "string") return {
|
|
1052
|
+
ua: normalizeUA(uastring),
|
|
1053
|
+
isSelfNavigator: false,
|
|
1054
|
+
navigator: void 0,
|
|
1055
|
+
userAgentData: void 0,
|
|
1056
|
+
regexMap: regexes
|
|
1057
|
+
};
|
|
1058
|
+
const navigator = getRuntimeNavigator();
|
|
1059
|
+
const ua = normalizeUA(navigator && navigator.userAgent ? navigator.userAgent : EMPTY);
|
|
1060
|
+
return {
|
|
1061
|
+
ua,
|
|
1062
|
+
isSelfNavigator: Boolean(navigator && navigator.userAgent === ua),
|
|
1063
|
+
navigator,
|
|
1064
|
+
userAgentData: navigator?.userAgentData,
|
|
1065
|
+
regexMap: regexes
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
function createParserContext(uastringOrExtensions, extensions) {
|
|
1069
|
+
if (!extensions && !isExtensionsInput(uastringOrExtensions)) return createDefaultParserContext(uastringOrExtensions);
|
|
1070
|
+
const navigator = getRuntimeNavigator();
|
|
1071
|
+
const uastring = isExtensionsInput(uastringOrExtensions) ? void 0 : uastringOrExtensions;
|
|
1072
|
+
const resolvedExtensions = isExtensionsInput(uastringOrExtensions) ? uastringOrExtensions : extensions;
|
|
1073
|
+
const ua = normalizeUA(uastring || (navigator && navigator.userAgent ? navigator.userAgent : EMPTY));
|
|
1074
|
+
const userAgentData = navigator?.userAgentData;
|
|
1075
|
+
return {
|
|
1076
|
+
ua,
|
|
1077
|
+
isSelfNavigator: Boolean(navigator && navigator.userAgent === ua),
|
|
1078
|
+
navigator,
|
|
1079
|
+
userAgentData,
|
|
1080
|
+
regexMap: resolvedExtensions ? extend(regexes, resolvedExtensions) : regexes
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
function parseBrowserFromContext(context) {
|
|
1084
|
+
const browser = {
|
|
1085
|
+
name: void 0,
|
|
1086
|
+
version: void 0,
|
|
1087
|
+
major: void 0
|
|
1088
|
+
};
|
|
1089
|
+
rgxMapper(context.ua, context.regexMap.browser, browser);
|
|
1090
|
+
browser.major = majorize(browser.version);
|
|
1091
|
+
if (context.isSelfNavigator && context.navigator?.brave && typeof context.navigator.brave.isBrave === "function") browser.name = "Brave";
|
|
1092
|
+
return browser;
|
|
1093
|
+
}
|
|
1094
|
+
function parseCPUFromContext(context) {
|
|
1095
|
+
const cpu = { architecture: void 0 };
|
|
1096
|
+
rgxMapper(context.ua, context.regexMap.cpu, cpu);
|
|
1097
|
+
return cpu;
|
|
1098
|
+
}
|
|
1099
|
+
function parseDeviceFromContext(context) {
|
|
1100
|
+
const device = {
|
|
1101
|
+
vendor: void 0,
|
|
1102
|
+
model: void 0,
|
|
1103
|
+
type: void 0
|
|
1104
|
+
};
|
|
1105
|
+
rgxMapper(context.ua, context.regexMap.device, device);
|
|
1106
|
+
if (context.isSelfNavigator && !device.type && context.userAgentData?.mobile) device.type = MOBILE;
|
|
1107
|
+
if (context.isSelfNavigator && device.model === "Macintosh" && context.navigator && typeof context.navigator.standalone !== "undefined" && context.navigator.maxTouchPoints && context.navigator.maxTouchPoints > 2) {
|
|
1108
|
+
device.model = "iPad";
|
|
1109
|
+
device.type = TABLET;
|
|
1110
|
+
}
|
|
1111
|
+
return device;
|
|
1112
|
+
}
|
|
1113
|
+
function parseEngineFromContext(context) {
|
|
1114
|
+
const engine = {
|
|
1115
|
+
name: void 0,
|
|
1116
|
+
version: void 0
|
|
1117
|
+
};
|
|
1118
|
+
rgxMapper(context.ua, context.regexMap.engine, engine);
|
|
1119
|
+
return engine;
|
|
1120
|
+
}
|
|
1121
|
+
function parseOSFromContext(context) {
|
|
1122
|
+
const os = {
|
|
1123
|
+
name: void 0,
|
|
1124
|
+
version: void 0
|
|
1125
|
+
};
|
|
1126
|
+
rgxMapper(context.ua, context.regexMap.os, os);
|
|
1127
|
+
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);
|
|
1128
|
+
return os;
|
|
1129
|
+
}
|
|
1130
|
+
function parseUA(uastringOrExtensions, extensions) {
|
|
1131
|
+
let context;
|
|
1132
|
+
let browserCache;
|
|
1133
|
+
let engineCache;
|
|
1134
|
+
let osCache;
|
|
1135
|
+
let deviceCache;
|
|
1136
|
+
let cpuCache;
|
|
1137
|
+
const getContext = () => context ||= createParserContext(uastringOrExtensions, extensions);
|
|
1138
|
+
return {
|
|
1139
|
+
get ua() {
|
|
1140
|
+
return getContext().ua;
|
|
1141
|
+
},
|
|
1142
|
+
get browser() {
|
|
1143
|
+
browserCache ||= parseBrowserFromContext(getContext());
|
|
1144
|
+
return browserCache;
|
|
1145
|
+
},
|
|
1146
|
+
get engine() {
|
|
1147
|
+
engineCache ||= parseEngineFromContext(getContext());
|
|
1148
|
+
return engineCache;
|
|
1149
|
+
},
|
|
1150
|
+
get os() {
|
|
1151
|
+
osCache ||= parseOSFromContext(getContext());
|
|
1152
|
+
return osCache;
|
|
1153
|
+
},
|
|
1154
|
+
get device() {
|
|
1155
|
+
deviceCache ||= parseDeviceFromContext(getContext());
|
|
1156
|
+
return deviceCache;
|
|
1157
|
+
},
|
|
1158
|
+
get cpu() {
|
|
1159
|
+
cpuCache ||= parseCPUFromContext(getContext());
|
|
1160
|
+
return cpuCache;
|
|
1161
|
+
}
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
//#endregion
|
|
1165
|
+
//#region src/node/auth/state.ts
|
|
1166
|
+
/**
|
|
1167
|
+
* Format a raw `navigator.userAgent` string into the short display label
|
|
1168
|
+
* shown for a trusted device (e.g. "Chrome 120 | macOS 14 desktop").
|
|
1169
|
+
*
|
|
1170
|
+
* The client used to parse+format this itself, but that pulled
|
|
1171
|
+
* `ua-parser-modern` into the browser bundle for a label nothing else on
|
|
1172
|
+
* the client needs — the client now sends the raw string and parsing
|
|
1173
|
+
* happens here, at the server ingress, keeping the persisted label format
|
|
1174
|
+
* identical.
|
|
1175
|
+
*/
|
|
1176
|
+
function describeUA(userAgent) {
|
|
1177
|
+
const info = parseUA(userAgent);
|
|
1178
|
+
return [
|
|
1179
|
+
info.browser.name,
|
|
1180
|
+
info.browser.version,
|
|
1181
|
+
"|",
|
|
1182
|
+
info.os.name,
|
|
1183
|
+
info.os.version,
|
|
1184
|
+
info.device.type
|
|
1185
|
+
].filter((i) => i).join(" ");
|
|
1186
|
+
}
|
|
1187
|
+
/** Number of decimal digits in a human-typed one-time authentication code. */
|
|
1188
|
+
const TEMP_AUTH_CODE_LENGTH = 6;
|
|
1189
|
+
/**
|
|
1190
|
+
* How long an authentication code stays valid after it is (re)generated. A
|
|
1191
|
+
* 6-digit code only has ~20 bits of entropy, so a short lifetime plus the
|
|
1192
|
+
* attempt cap below are what keep it brute-force resistant.
|
|
1193
|
+
*/
|
|
1194
|
+
const TEMP_AUTH_CODE_TTL = 5 * 6e4;
|
|
1195
|
+
/** Failed attempts allowed against a single code before it is rotated. */
|
|
1196
|
+
const TEMP_AUTH_MAX_ATTEMPTS = 5;
|
|
1197
|
+
let tempAuthCode = generateTempCode();
|
|
1198
|
+
let tempAuthCodeExpiresAt = Date.now() + TEMP_AUTH_CODE_TTL;
|
|
1199
|
+
let tempAuthFailedAttempts = 0;
|
|
1200
|
+
function generateTempCode() {
|
|
1201
|
+
return randomDigits(TEMP_AUTH_CODE_LENGTH);
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* The current one-time authentication code. Display this to the user (e.g. in
|
|
1205
|
+
* the dev-server terminal) so they can type it into the browser to authenticate.
|
|
1206
|
+
*/
|
|
1207
|
+
function getTempAuthCode() {
|
|
1208
|
+
return tempAuthCode;
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Rotate the authentication code, resetting its expiry window and failed-attempt
|
|
1212
|
+
* counter. Call this when a new authentication flow begins (e.g. when an
|
|
1213
|
+
* untrusted client starts authenticating) so the displayed code is freshly
|
|
1214
|
+
* valid for its full TTL.
|
|
1215
|
+
*/
|
|
1216
|
+
function refreshTempAuthCode() {
|
|
1217
|
+
tempAuthCode = generateTempCode();
|
|
1218
|
+
tempAuthCodeExpiresAt = Date.now() + TEMP_AUTH_CODE_TTL;
|
|
1219
|
+
tempAuthFailedAttempts = 0;
|
|
1220
|
+
return tempAuthCode;
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Build a "magic link" authentication URL that embeds a one-time code (OTP) in
|
|
1224
|
+
* the URL **fragment**. Opening it authenticates the client without typing —
|
|
1225
|
+
* print it on startup (devframe stays headless, so the host prints its own
|
|
1226
|
+
* banner). Defaults to the current code; the link is subject to the same TTL.
|
|
1227
|
+
*
|
|
1228
|
+
* The code rides the fragment (`#devframe_otp=…`), not the query string, so it
|
|
1229
|
+
* is never sent to the server, written to an access log, or leaked in a
|
|
1230
|
+
* `Referer` header — the browser client reads it locally (see
|
|
1231
|
+
* `consumeOtpFromUrl`). Any existing fragment parameters are preserved.
|
|
1232
|
+
*/
|
|
1233
|
+
function buildOtpAuthUrl(baseUrl, code = tempAuthCode) {
|
|
1234
|
+
const url = new URL(baseUrl);
|
|
1235
|
+
const fragment = new URLSearchParams(url.hash.replace(/^#/, ""));
|
|
1236
|
+
fragment.set(DEVFRAME_OTP_URL_PARAM, code);
|
|
1237
|
+
url.hash = fragment.toString();
|
|
1238
|
+
return url.href;
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Re-authenticate a connection that presents a previously-issued bearer token.
|
|
1242
|
+
* Returns `true` and marks the session trusted when the token is known.
|
|
1243
|
+
*
|
|
1244
|
+
* Used by the `anonymous:devframe:auth` handler so a client that already
|
|
1245
|
+
* authenticated (token persisted in the browser) is trusted on reconnect
|
|
1246
|
+
* without entering the code again.
|
|
1247
|
+
*/
|
|
1248
|
+
function verifyAuthToken(token, session, storage) {
|
|
1249
|
+
if (!token || !storage.value().trusted[token]) return false;
|
|
1250
|
+
session.meta.clientAuthToken = token;
|
|
1251
|
+
session.meta.isTrusted = true;
|
|
1252
|
+
return true;
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Exchange a one-time authentication code for a fresh, node-issued bearer token.
|
|
1256
|
+
*
|
|
1257
|
+
* On success this mints a high-entropy token, records it in the trusted store,
|
|
1258
|
+
* marks the calling session trusted, rotates the code, and returns the token
|
|
1259
|
+
* for the client to persist. Returns `null` on any failure.
|
|
1260
|
+
*
|
|
1261
|
+
* Because the code is short and human-typed, verification is hardened against
|
|
1262
|
+
* brute force: it enforces a time-to-live, compares in constant time, and
|
|
1263
|
+
* rotates the code after {@link TEMP_AUTH_MAX_ATTEMPTS} failed attempts so an
|
|
1264
|
+
* attacker cannot keep guessing against the same code.
|
|
1265
|
+
*/
|
|
1266
|
+
function exchangeTempAuthCode(code, session, info, storage) {
|
|
1267
|
+
if (Date.now() > tempAuthCodeExpiresAt) {
|
|
1268
|
+
refreshTempAuthCode();
|
|
1269
|
+
return null;
|
|
1270
|
+
}
|
|
1271
|
+
if (!timingSafeEqual(code, tempAuthCode)) {
|
|
1272
|
+
tempAuthFailedAttempts += 1;
|
|
1273
|
+
if (tempAuthFailedAttempts >= TEMP_AUTH_MAX_ATTEMPTS) refreshTempAuthCode();
|
|
1274
|
+
return null;
|
|
1275
|
+
}
|
|
1276
|
+
const authToken = randomToken();
|
|
1277
|
+
storage.mutate((state) => {
|
|
1278
|
+
state.trusted[authToken] = {
|
|
1279
|
+
authToken,
|
|
1280
|
+
ua: describeUA(info.ua),
|
|
1281
|
+
origin: info.origin,
|
|
1282
|
+
timestamp: Date.now()
|
|
1283
|
+
};
|
|
1284
|
+
});
|
|
1285
|
+
session.meta.clientAuthToken = authToken;
|
|
1286
|
+
session.meta.isTrusted = true;
|
|
1287
|
+
refreshTempAuthCode();
|
|
1288
|
+
return authToken;
|
|
1289
|
+
}
|
|
1290
|
+
//#endregion
|
|
1291
|
+
export { verifyAuthToken as a, refreshTempAuthCode as i, exchangeTempAuthCode as n, getTempAuthCode as r, buildOtpAuthUrl as t };
|