@wtasnorg/node-lib 0.0.6 → 0.0.8
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/changelog.txt +14 -0
- package/dev_checklist.txt +56 -0
- package/docs/README.md +8 -34
- package/docs/docs.json +1538 -0
- package/docs/functions/createFindDirectories.md +2 -2
- package/docs/functions/hello.md +2 -2
- package/docs/functions/parseUserAgent.md +42 -0
- package/docs/functions/pojo.md +4 -4
- package/docs/interfaces/FileSystemDependencies.md +9 -9
- package/docs/interfaces/FindDirectoriesOptions.md +8 -8
- package/docs/interfaces/UserAgentInfo.md +61 -0
- package/eslint.config.js +52 -0
- package/gen-docs/001_commands.txt +44 -0
- package/gen-docs/001_coverage.txt +43 -0
- package/gen-docs/001_env.txt +33 -0
- package/gen-docs/001_lint.txt +40 -0
- package/gen-docs/001_state.txt +58 -0
- package/gen-docs/002_api.txt +34 -0
- package/gen-docs/002_deps.txt +46 -0
- package/gen-docs/002_errors.txt +34 -0
- package/gen-docs/002_naming.txt +36 -0
- package/gen-docs/002_notes.txt +20 -0
- package/gen-docs/002_purity.txt +36 -0
- package/gen-docs/002_scope.txt +28 -0
- package/gen-docs/002_srp.txt +34 -0
- package/gen-sec/001_commands.txt +65 -0
- package/gen-sec/001_env.txt +28 -0
- package/gen-sec/001_findings.txt +63 -0
- package/gen-sec/001_inventory.txt +41 -0
- package/gen-sec/001_owasp.txt +78 -0
- package/gen-sec/001_scope.txt +44 -0
- package/package.json +10 -3
- package/{README.md → readme.txt} +3 -1
- package/src/find.d.ts +4 -4
- package/src/find.js +13 -7
- package/src/find.test.js +2 -6
- package/src/find.test.ts +3 -11
- package/src/find.ts +13 -13
- package/src/index.d.ts +4 -2
- package/src/index.js +2 -1
- package/src/index.ts +6 -2
- package/src/pojo.d.ts +2 -2
- package/src/pojo.js +2 -2
- package/src/pojo.test.js +1 -3
- package/src/pojo.test.ts +2 -1
- package/src/pojo.ts +3 -3
- package/src/user-agent.d.ts +48 -0
- package/src/user-agent.js +189 -0
- package/src/user-agent.test.d.ts +2 -0
- package/src/user-agent.test.js +54 -0
- package/src/user-agent.test.ts +60 -0
- package/src/user-agent.ts +199 -0
- package/test_report +26 -0
- package/typedoc.json +6 -2
- package/DEV_CHECKLIST.md +0 -15
- package/docs/_media/LICENSE +0 -21
- package/docs/globals.md +0 -16
package/src/find.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { resolve, join } from "node:path";
|
|
2
2
|
|
|
3
3
|
interface FileSystemDependencies {
|
|
4
|
-
readdir: (
|
|
5
|
-
stat: (
|
|
4
|
+
readdir: (_path: string, _opts: { withFileTypes: true }) => Promise<{ name: string; isDirectory(): boolean; }[]>;
|
|
5
|
+
stat: (_path: string) => Promise<{ isDirectory(): boolean }>;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
interface FindDirectoriesOptions {
|
|
9
9
|
maxDepth?: number;
|
|
10
10
|
followSymlinks?: boolean;
|
|
11
|
-
allowlist?: string[] | ((
|
|
12
|
-
blocklist?: string[] | ((
|
|
11
|
+
allowlist?: string[] | ((_absPath: string, _name: string) => boolean);
|
|
12
|
+
blocklist?: string[] | ((_absPath: string, _name: string) => boolean);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -38,7 +38,7 @@ function createFindDirectories(deps: FileSystemDependencies) {
|
|
|
38
38
|
function isAllowed(absPath: string, name: string): boolean {
|
|
39
39
|
if (allowlist) {
|
|
40
40
|
if (Array.isArray(allowlist)) {
|
|
41
|
-
if (!allowlist.includes(name)) return false;
|
|
41
|
+
if (!allowlist.includes(name)) { return false; }
|
|
42
42
|
} else if (!allowlist(absPath, name)) {
|
|
43
43
|
return false;
|
|
44
44
|
}
|
|
@@ -49,7 +49,7 @@ function createFindDirectories(deps: FileSystemDependencies) {
|
|
|
49
49
|
function isBlocked(absPath: string, name: string): boolean {
|
|
50
50
|
if (blocklist) {
|
|
51
51
|
if (Array.isArray(blocklist)) {
|
|
52
|
-
if (blocklist.includes(name)) return true;
|
|
52
|
+
if (blocklist.includes(name)) { return true; }
|
|
53
53
|
} else if (blocklist(absPath, name)) {
|
|
54
54
|
return true;
|
|
55
55
|
}
|
|
@@ -58,19 +58,19 @@ function createFindDirectories(deps: FileSystemDependencies) {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
async function walk(currentPath: string, depth: number): Promise<void> {
|
|
61
|
-
if (depth > maxDepth) return;
|
|
61
|
+
if (depth > maxDepth) { return; }
|
|
62
62
|
|
|
63
63
|
const entries = await readdir(currentPath, { withFileTypes: true });
|
|
64
64
|
|
|
65
65
|
for (const entry of entries) {
|
|
66
66
|
const childPath = resolve(join(currentPath, entry.name));
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
const isDirectory = entry.isDirectory();
|
|
69
69
|
|
|
70
|
-
if (!isDirectory) continue;
|
|
70
|
+
if (!isDirectory) { continue; }
|
|
71
71
|
|
|
72
|
-
if (isBlocked(childPath, entry.name)) continue;
|
|
73
|
-
if (!isAllowed(childPath, entry.name)) continue;
|
|
72
|
+
if (isBlocked(childPath, entry.name)) { continue; }
|
|
73
|
+
if (!isAllowed(childPath, entry.name)) { continue; }
|
|
74
74
|
|
|
75
75
|
results.push(childPath);
|
|
76
76
|
|
|
@@ -91,9 +91,9 @@ function createFindDirectories(deps: FileSystemDependencies) {
|
|
|
91
91
|
|
|
92
92
|
export {
|
|
93
93
|
createFindDirectories,
|
|
94
|
-
}
|
|
94
|
+
};
|
|
95
95
|
|
|
96
96
|
export type {
|
|
97
97
|
FileSystemDependencies,
|
|
98
98
|
FindDirectoriesOptions,
|
|
99
|
-
}
|
|
99
|
+
};
|
package/src/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { hello } from "./hello.js";
|
|
|
2
2
|
import { pojo } from "./pojo.js";
|
|
3
3
|
import type { FindDirectoriesOptions, FileSystemDependencies } from "./find.js";
|
|
4
4
|
import { createFindDirectories } from "./find.js";
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import type { UserAgentInfo } from "./user-agent.js";
|
|
6
|
+
import { parseUserAgent } from "./user-agent.js";
|
|
7
|
+
export { hello, pojo, createFindDirectories, parseUserAgent };
|
|
8
|
+
export type { FindDirectoriesOptions, FileSystemDependencies, UserAgentInfo, };
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { hello } from "./hello.js";
|
|
2
2
|
import { pojo } from "./pojo.js";
|
|
3
3
|
import { createFindDirectories } from "./find.js";
|
|
4
|
-
|
|
4
|
+
import { parseUserAgent } from "./user-agent.js";
|
|
5
|
+
export { hello, pojo, createFindDirectories, parseUserAgent };
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
package/src/index.ts
CHANGED
|
@@ -2,14 +2,18 @@ import { hello } from "./hello.js";
|
|
|
2
2
|
import { pojo } from "./pojo.js";
|
|
3
3
|
import type { FindDirectoriesOptions, FileSystemDependencies } from "./find.js";
|
|
4
4
|
import { createFindDirectories } from "./find.js";
|
|
5
|
+
import type { UserAgentInfo } from "./user-agent.js";
|
|
6
|
+
import { parseUserAgent } from "./user-agent.js";
|
|
5
7
|
|
|
6
8
|
export {
|
|
7
9
|
hello,
|
|
8
10
|
pojo,
|
|
9
|
-
createFindDirectories
|
|
11
|
+
createFindDirectories,
|
|
12
|
+
parseUserAgent
|
|
10
13
|
};
|
|
11
14
|
|
|
12
15
|
export type {
|
|
13
16
|
FindDirectoriesOptions,
|
|
14
17
|
FileSystemDependencies,
|
|
15
|
-
|
|
18
|
+
UserAgentInfo,
|
|
19
|
+
};
|
package/src/pojo.d.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @template T
|
|
7
7
|
* @param {T} instance - A class instance to convert.
|
|
8
|
-
* @returns {Object<string,
|
|
8
|
+
* @returns {Object<string, unknown>} A plain JavaScript object containing only data fields.
|
|
9
9
|
*/
|
|
10
|
-
declare function pojo<T extends object>(instance: T): Record<string,
|
|
10
|
+
declare function pojo<T extends object>(instance: T): Record<string, unknown>;
|
|
11
11
|
export { pojo };
|
|
12
12
|
//# sourceMappingURL=pojo.d.ts.map
|
package/src/pojo.js
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @template T
|
|
7
7
|
* @param {T} instance - A class instance to convert.
|
|
8
|
-
* @returns {Object<string,
|
|
8
|
+
* @returns {Object<string, unknown>} A plain JavaScript object containing only data fields.
|
|
9
9
|
*/
|
|
10
10
|
function pojo(instance) {
|
|
11
|
-
return Object.fromEntries(Object.entries(instance).filter((
|
|
11
|
+
return Object.fromEntries(Object.entries(instance).filter((entry) => typeof entry[1] !== "function"));
|
|
12
12
|
}
|
|
13
13
|
export { pojo };
|
|
14
14
|
//# sourceMappingURL=pojo.js.map
|
package/src/pojo.test.js
CHANGED
|
@@ -28,9 +28,7 @@ test("pojo() should exclude methods", () => {
|
|
|
28
28
|
test("pojo() should exclude prototype properties", () => {
|
|
29
29
|
class Product {
|
|
30
30
|
id;
|
|
31
|
-
constructor(id) {
|
|
32
|
-
this.id = id;
|
|
33
|
-
}
|
|
31
|
+
constructor(id) { this.id = id; }
|
|
34
32
|
get info() {
|
|
35
33
|
return `Product:${this.id}`;
|
|
36
34
|
}
|
package/src/pojo.test.ts
CHANGED
|
@@ -35,7 +35,8 @@ test("pojo() should exclude methods", () => {
|
|
|
35
35
|
|
|
36
36
|
test("pojo() should exclude prototype properties", () => {
|
|
37
37
|
class Product {
|
|
38
|
-
|
|
38
|
+
id: number;
|
|
39
|
+
constructor(id: number) { this.id = id; }
|
|
39
40
|
|
|
40
41
|
get info() {
|
|
41
42
|
return `Product:${this.id}`;
|
package/src/pojo.ts
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @template T
|
|
7
7
|
* @param {T} instance - A class instance to convert.
|
|
8
|
-
* @returns {Object<string,
|
|
8
|
+
* @returns {Object<string, unknown>} A plain JavaScript object containing only data fields.
|
|
9
9
|
*/
|
|
10
|
-
function pojo<T extends object>(instance: T): Record<string,
|
|
10
|
+
function pojo<T extends object>(instance: T): Record<string, unknown> {
|
|
11
11
|
return Object.fromEntries(
|
|
12
|
-
Object.entries(instance).filter((
|
|
12
|
+
Object.entries(instance).filter((entry) => typeof entry[1] !== "function")
|
|
13
13
|
);
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Information extracted from a user-agent string.
|
|
3
|
+
*/
|
|
4
|
+
export interface UserAgentInfo {
|
|
5
|
+
/**
|
|
6
|
+
* Browser name (e.g., Chrome, Firefox, Safari, Edge, Opera, Other).
|
|
7
|
+
*/
|
|
8
|
+
browser: string;
|
|
9
|
+
/**
|
|
10
|
+
* Browser version (e.g., 120.0.0.0).
|
|
11
|
+
*/
|
|
12
|
+
version: string;
|
|
13
|
+
/**
|
|
14
|
+
* Operating system (e.g., Windows, macOS, Linux, iOS, Android, Other).
|
|
15
|
+
*/
|
|
16
|
+
os: string;
|
|
17
|
+
/**
|
|
18
|
+
* Device type (e.g., Mobile, Tablet, Desktop, Other).
|
|
19
|
+
*/
|
|
20
|
+
device: string;
|
|
21
|
+
/**
|
|
22
|
+
* Rendering engine (e.g., Blink, WebKit, Gecko, Presto, Other).
|
|
23
|
+
*/
|
|
24
|
+
engine: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Parses a user-agent string into a UserAgentInfo object.
|
|
28
|
+
*
|
|
29
|
+
* @param ua - The user-agent string to parse.
|
|
30
|
+
* @returns An object containing the extracted information.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* // Success Example (Chrome on Windows)
|
|
35
|
+
* const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
|
|
36
|
+
* const info = parseUserAgent(ua);
|
|
37
|
+
* // { browser: "Chrome", version: "120.0.0.0", os: "Windows", device: "Desktop", engine: "Blink" }
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* // Error/Fallback Example (Empty string)
|
|
43
|
+
* const info = parseUserAgent("");
|
|
44
|
+
* // { browser: "Other", version: "0", os: "Other", device: "Desktop", engine: "Other" }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseUserAgent(ua: string): UserAgentInfo;
|
|
48
|
+
//# sourceMappingURL=user-agent.d.ts.map
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a user-agent string into a UserAgentInfo object.
|
|
3
|
+
*
|
|
4
|
+
* @param ua - The user-agent string to parse.
|
|
5
|
+
* @returns An object containing the extracted information.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // Success Example (Chrome on Windows)
|
|
10
|
+
* const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
|
|
11
|
+
* const info = parseUserAgent(ua);
|
|
12
|
+
* // { browser: "Chrome", version: "120.0.0.0", os: "Windows", device: "Desktop", engine: "Blink" }
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Error/Fallback Example (Empty string)
|
|
18
|
+
* const info = parseUserAgent("");
|
|
19
|
+
* // { browser: "Other", version: "0", os: "Other", device: "Desktop", engine: "Other" }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function parseUserAgent(ua) {
|
|
23
|
+
if (!ua) {
|
|
24
|
+
return {
|
|
25
|
+
browser: "Other",
|
|
26
|
+
version: "0",
|
|
27
|
+
os: "Other",
|
|
28
|
+
device: "Desktop",
|
|
29
|
+
engine: "Other",
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const browserInfo = detectBrowser(ua);
|
|
33
|
+
return {
|
|
34
|
+
browser: browserInfo.name,
|
|
35
|
+
version: browserInfo.version,
|
|
36
|
+
os: detectOS(ua),
|
|
37
|
+
device: detectDeviceType(ua),
|
|
38
|
+
engine: detectEngine(ua),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Detects the browser name and version from a user-agent string.
|
|
43
|
+
*
|
|
44
|
+
* @param ua - The user-agent string.
|
|
45
|
+
* @returns An object with name and version.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* // Success Example
|
|
50
|
+
* detectBrowser("Mozilla/5.0 ... Firefox/121.0");
|
|
51
|
+
* // { name: "Firefox", version: "121.0" }
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* // Error/Fallback Example
|
|
57
|
+
* detectBrowser("UnknownBot/1.0");
|
|
58
|
+
* // { name: "Other", version: "0" }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
function detectBrowser(ua) {
|
|
62
|
+
let name = "Other";
|
|
63
|
+
let version = "0";
|
|
64
|
+
if (ua.includes("Edg/")) {
|
|
65
|
+
name = "Edge";
|
|
66
|
+
version = ua.split("Edg/")[1]?.split(" ")[0] || "0";
|
|
67
|
+
}
|
|
68
|
+
else if (ua.includes("Chrome/") && !ua.includes("Chromium/")) {
|
|
69
|
+
name = "Chrome";
|
|
70
|
+
version = ua.split("Chrome/")[1]?.split(" ")[0] || "0";
|
|
71
|
+
}
|
|
72
|
+
else if (ua.includes("Safari/") && !ua.includes("Chrome/")) {
|
|
73
|
+
name = "Safari";
|
|
74
|
+
version = ua.split("Version/")[1]?.split(" ")[0] || ua.split("Safari/")[1]?.split(" ")[0] || "0";
|
|
75
|
+
}
|
|
76
|
+
else if (ua.includes("Firefox/")) {
|
|
77
|
+
name = "Firefox";
|
|
78
|
+
version = ua.split("Firefox/")[1]?.split(" ")[0] || "0";
|
|
79
|
+
}
|
|
80
|
+
else if (ua.includes("OPR/") || ua.includes("Opera/")) {
|
|
81
|
+
name = "Opera";
|
|
82
|
+
version = (ua.split("OPR/")[1] || ua.split("Opera/")[1])?.split(" ")[0] || "0";
|
|
83
|
+
}
|
|
84
|
+
return { name, version };
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Detects the operating system from a user-agent string.
|
|
88
|
+
*
|
|
89
|
+
* @param ua - The user-agent string.
|
|
90
|
+
* @returns The operating system name.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* // Success Example
|
|
95
|
+
* detectOS("Mozilla/5.0 (iPhone; ...)");
|
|
96
|
+
* // "iOS"
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* // Error/Fallback Example
|
|
102
|
+
* detectOS("Custom OS");
|
|
103
|
+
* // "Other"
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
function detectOS(ua) {
|
|
107
|
+
if (ua.includes("iPhone") || ua.includes("iPad") || ua.includes("iPod")) {
|
|
108
|
+
return "iOS";
|
|
109
|
+
}
|
|
110
|
+
if (ua.includes("Windows")) {
|
|
111
|
+
return "Windows";
|
|
112
|
+
}
|
|
113
|
+
if (ua.includes("Mac OS X")) {
|
|
114
|
+
return "macOS";
|
|
115
|
+
}
|
|
116
|
+
if (ua.includes("Android")) {
|
|
117
|
+
return "Android";
|
|
118
|
+
}
|
|
119
|
+
if (ua.includes("Linux")) {
|
|
120
|
+
return "Linux";
|
|
121
|
+
}
|
|
122
|
+
return "Other";
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Detects the device type (Desktop, Mobile, Tablet) from a user-agent string.
|
|
126
|
+
*
|
|
127
|
+
* @param ua - The user-agent string.
|
|
128
|
+
* @returns The device type.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* // Success Example
|
|
133
|
+
* detectDeviceType("Mozilla/5.0 (iPad; ...)");
|
|
134
|
+
* // "Tablet"
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* // Error/Fallback Example
|
|
140
|
+
* detectDeviceType("Generic Browser");
|
|
141
|
+
* // "Desktop"
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
function detectDeviceType(ua) {
|
|
145
|
+
if (ua.includes("iPad") || (ua.includes("Android") && !ua.includes("Mobile"))) {
|
|
146
|
+
return "Tablet";
|
|
147
|
+
}
|
|
148
|
+
if (ua.includes("Mobi")) {
|
|
149
|
+
return "Mobile";
|
|
150
|
+
}
|
|
151
|
+
return "Desktop";
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Detects the rendering engine from a user-agent string.
|
|
155
|
+
*
|
|
156
|
+
* @param ua - The user-agent string.
|
|
157
|
+
* @returns The engine name.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```typescript
|
|
161
|
+
* // Success Example
|
|
162
|
+
* detectEngine("Mozilla/5.0 ... AppleWebKit/537.36 ...");
|
|
163
|
+
* // "Blink"
|
|
164
|
+
* ```
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* // Error/Fallback Example
|
|
169
|
+
* detectEngine("Unknown Engine");
|
|
170
|
+
* // "Other"
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
function detectEngine(ua) {
|
|
174
|
+
// Blink check must come first: Chrome/Chromium browsers use AppleWebKit but are Blink-based
|
|
175
|
+
if (ua.includes("Chrome/") && ua.includes("AppleWebKit/")) {
|
|
176
|
+
return "Blink";
|
|
177
|
+
}
|
|
178
|
+
if (ua.includes("AppleWebKit")) {
|
|
179
|
+
return "WebKit";
|
|
180
|
+
}
|
|
181
|
+
if (ua.includes("Gecko/")) {
|
|
182
|
+
return "Gecko";
|
|
183
|
+
}
|
|
184
|
+
if (ua.includes("Presto/")) {
|
|
185
|
+
return "Presto";
|
|
186
|
+
}
|
|
187
|
+
return "Other";
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=user-agent.js.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { parseUserAgent } from "./user-agent.js";
|
|
4
|
+
test("parseUserAgent - Chrome on Windows", () => {
|
|
5
|
+
const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
|
|
6
|
+
const info = parseUserAgent(ua);
|
|
7
|
+
assert.strictEqual(info.browser, "Chrome");
|
|
8
|
+
assert.strictEqual(info.os, "Windows");
|
|
9
|
+
assert.strictEqual(info.device, "Desktop");
|
|
10
|
+
assert.strictEqual(info.version, "120.0.0.0");
|
|
11
|
+
});
|
|
12
|
+
test("parseUserAgent - Firefox on macOS", () => {
|
|
13
|
+
const ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 14.2; rv:121.0) Gecko/20100101 Firefox/121.0";
|
|
14
|
+
const info = parseUserAgent(ua);
|
|
15
|
+
assert.strictEqual(info.browser, "Firefox");
|
|
16
|
+
assert.strictEqual(info.os, "macOS");
|
|
17
|
+
assert.strictEqual(info.version, "121.0");
|
|
18
|
+
assert.strictEqual(info.engine, "Gecko");
|
|
19
|
+
});
|
|
20
|
+
test("parseUserAgent - Safari on iPhone", () => {
|
|
21
|
+
const ua = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1";
|
|
22
|
+
const info = parseUserAgent(ua);
|
|
23
|
+
assert.strictEqual(info.browser, "Safari");
|
|
24
|
+
assert.strictEqual(info.os, "iOS");
|
|
25
|
+
assert.strictEqual(info.device, "Mobile");
|
|
26
|
+
assert.strictEqual(info.version, "17.2");
|
|
27
|
+
});
|
|
28
|
+
test("parseUserAgent - Edge on Windows", () => {
|
|
29
|
+
const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0";
|
|
30
|
+
const info = parseUserAgent(ua);
|
|
31
|
+
assert.strictEqual(info.browser, "Edge");
|
|
32
|
+
assert.strictEqual(info.os, "Windows");
|
|
33
|
+
assert.strictEqual(info.version, "120.0.0.0");
|
|
34
|
+
});
|
|
35
|
+
test("parseUserAgent - Chrome on Android (Mobile)", () => {
|
|
36
|
+
const ua = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36";
|
|
37
|
+
const info = parseUserAgent(ua);
|
|
38
|
+
assert.strictEqual(info.browser, "Chrome");
|
|
39
|
+
assert.strictEqual(info.os, "Android");
|
|
40
|
+
assert.strictEqual(info.device, "Mobile");
|
|
41
|
+
});
|
|
42
|
+
test("parseUserAgent - Android Tablet", () => {
|
|
43
|
+
const ua = "Mozilla/5.0 (Linux; Android 10; SM-T510) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
|
|
44
|
+
const info = parseUserAgent(ua);
|
|
45
|
+
assert.strictEqual(info.browser, "Chrome");
|
|
46
|
+
assert.strictEqual(info.os, "Android");
|
|
47
|
+
assert.strictEqual(info.device, "Tablet");
|
|
48
|
+
});
|
|
49
|
+
test("parseUserAgent - Empty/Null UA", () => {
|
|
50
|
+
const info = parseUserAgent("");
|
|
51
|
+
assert.strictEqual(info.browser, "Other");
|
|
52
|
+
assert.strictEqual(info.device, "Desktop");
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=user-agent.test.js.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { parseUserAgent } from "./user-agent.js";
|
|
4
|
+
|
|
5
|
+
test("parseUserAgent - Chrome on Windows", () => {
|
|
6
|
+
const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
|
|
7
|
+
const info = parseUserAgent(ua);
|
|
8
|
+
assert.strictEqual(info.browser, "Chrome");
|
|
9
|
+
assert.strictEqual(info.os, "Windows");
|
|
10
|
+
assert.strictEqual(info.device, "Desktop");
|
|
11
|
+
assert.strictEqual(info.version, "120.0.0.0");
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("parseUserAgent - Firefox on macOS", () => {
|
|
15
|
+
const ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 14.2; rv:121.0) Gecko/20100101 Firefox/121.0";
|
|
16
|
+
const info = parseUserAgent(ua);
|
|
17
|
+
assert.strictEqual(info.browser, "Firefox");
|
|
18
|
+
assert.strictEqual(info.os, "macOS");
|
|
19
|
+
assert.strictEqual(info.version, "121.0");
|
|
20
|
+
assert.strictEqual(info.engine, "Gecko");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("parseUserAgent - Safari on iPhone", () => {
|
|
24
|
+
const ua = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1";
|
|
25
|
+
const info = parseUserAgent(ua);
|
|
26
|
+
assert.strictEqual(info.browser, "Safari");
|
|
27
|
+
assert.strictEqual(info.os, "iOS");
|
|
28
|
+
assert.strictEqual(info.device, "Mobile");
|
|
29
|
+
assert.strictEqual(info.version, "17.2");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("parseUserAgent - Edge on Windows", () => {
|
|
33
|
+
const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0";
|
|
34
|
+
const info = parseUserAgent(ua);
|
|
35
|
+
assert.strictEqual(info.browser, "Edge");
|
|
36
|
+
assert.strictEqual(info.os, "Windows");
|
|
37
|
+
assert.strictEqual(info.version, "120.0.0.0");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("parseUserAgent - Chrome on Android (Mobile)", () => {
|
|
41
|
+
const ua = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36";
|
|
42
|
+
const info = parseUserAgent(ua);
|
|
43
|
+
assert.strictEqual(info.browser, "Chrome");
|
|
44
|
+
assert.strictEqual(info.os, "Android");
|
|
45
|
+
assert.strictEqual(info.device, "Mobile");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("parseUserAgent - Android Tablet", () => {
|
|
49
|
+
const ua = "Mozilla/5.0 (Linux; Android 10; SM-T510) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
|
|
50
|
+
const info = parseUserAgent(ua);
|
|
51
|
+
assert.strictEqual(info.browser, "Chrome");
|
|
52
|
+
assert.strictEqual(info.os, "Android");
|
|
53
|
+
assert.strictEqual(info.device, "Tablet");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("parseUserAgent - Empty/Null UA", () => {
|
|
57
|
+
const info = parseUserAgent("");
|
|
58
|
+
assert.strictEqual(info.browser, "Other");
|
|
59
|
+
assert.strictEqual(info.device, "Desktop");
|
|
60
|
+
});
|