Skip to content

Commit 125a1b1

Browse files
committed
Add architecture detection
1 parent 20c1719 commit 125a1b1

File tree

5 files changed

+200
-18
lines changed

5 files changed

+200
-18
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
node_modules
33
.npmrc
44
test.js
5+
package.json
56
package-lock.json
67

78
# Deno

README.md

+17-5
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22

33
**Cross-Runtime Environment Detection for JavaScript and TypeScript**
44

5-
This package provides a robust, cross runtime, way to determine the current runtime environment (Deno, Bun, Node.js, or browser) along with detailed browser detection.
5+
This package provides a well defined, cross runtime, way to determine details about the current runtime environment (Deno, Bun, Node.js, or browser) along with detailed browser detection.
66

77
Try it out at [jsfiddle.net/ux87tLz4/6/](https://jsfiddle.net/ux87tLz4/6/)
88

9-
**Usage Example**
10-
119
```javascript
12-
import { CurrentProduct, CurrentRuntime, CurrentVersion, Runtime } from "@cross/runtime";
10+
import { CurrentArchitecture, CurrentOS, CurrentProduct, CurrentRuntime, CurrentVersion, Runtime } from "@cross/runtime";
1311

1412
console.log(`Runtime: ${CurrentRuntime}`);
13+
console.log(`OS: ${CurrentOS}`);
14+
console.log(`Architecture: ${CurrentArchitecture}`);
1515
console.log(`Product: ${CurrentProduct}`);
16-
console.log(`Version: ${CurrentVersion}`);
16+
console.log(`Version: ${CurrentVersion}\n`);
1717

1818
if (CurrentRuntime == Runtime.Deno) {
1919
console.log("You're running Deno!");
@@ -22,6 +22,18 @@ if (CurrentRuntime == Runtime.Deno) {
2222
}
2323
```
2424

25+
This script results in something like:
26+
27+
```
28+
Runtime: bun
29+
OS: linux
30+
Architecture: x86_64
31+
Product: bun
32+
Version: 1.0.30
33+
34+
You're not running Deno!
35+
```
36+
2537
**Full Documentation**
2638

2739
For comprehensive documentation, including more advanced usage and examples, please visit the official JSR documentation (if your are not already there):

deno.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cross/runtime",
3-
"version": "0.0.14",
3+
"version": "0.0.15",
44
"exports": "./mod.ts",
55
"fmt": {
66
"lineWidth": 200

mod.test.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { CurrentOS, OperatingSystem } from "./mod.ts";
12
import { CurrentProduct, CurrentRuntime, CurrentVersion, Product, Runtime } from "./mod.ts";
2-
import { assertEquals } from "jsr:@std/assert";
3+
import { assertEquals, assertNotEquals } from "jsr:@std/assert";
34

45
Deno.test("Current runtime is Deno (string)", () => {
56
assertEquals("deno", CurrentRuntime);
@@ -16,3 +17,6 @@ Deno.test("Current product is Deno (enum)", () => {
1617
Deno.test("Current version contains a dot", () => {
1718
assertEquals(true, CurrentVersion?.includes("."));
1819
});
20+
Deno.test("Current operating system is supported", () => {
21+
assertNotEquals(OperatingSystem.Unsupported, CurrentOS);
22+
});

mod.ts

+176-11
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,6 @@ function getBraveVersion() {
4040
return match ? match[2] : "Unknown";
4141
}
4242

43-
function getVivaldiVersion() {
44-
const ua = navigator.userAgent;
45-
const match = ua.match(/Vivaldi\/([0-9]+)\./);
46-
return match ? match[1] : "Unknown";
47-
}
48-
4943
/**
5044
* Enum of supported Runtimes.
5145
* @enum {string}
@@ -58,6 +52,20 @@ export enum Runtime {
5852
Unsupported = "unsupported",
5953
}
6054

55+
/**
56+
* Enum of supported Operating Systems.
57+
* @enum {string}
58+
*/
59+
export enum OperatingSystem {
60+
Windows = "windows",
61+
macOS = "macos",
62+
Linux = "linux",
63+
Android = "android",
64+
Unix = "unix",
65+
iOS = "ios",
66+
Unsupported = "unsupported",
67+
}
68+
6169
/**
6270
* Enum of supported Products.
6371
* @enum {string}
@@ -75,12 +83,23 @@ export enum Product {
7583
Edge = "edge",
7684
Opera = "opera",
7785
Brave = "brave",
78-
Vivaldi = "vivaldi",
7986

8087
// And unsupported
8188
Unsupported = "unsupported",
8289
}
8390

91+
/**
92+
* Enum of common CPU architectures.
93+
* @enum {string}
94+
*/
95+
export enum Architecture {
96+
x86 = "x86",
97+
x64 = "x86_64",
98+
arm = "arm",
99+
arm64 = "arm64",
100+
Unsupported = "unsupported",
101+
}
102+
84103
/**
85104
* Dynamically determines the current runtime environment.
86105
*/
@@ -107,6 +126,80 @@ export function getCurrentRuntime(): Runtime {
107126
}
108127
}
109128

129+
/**
130+
* Dynamically determines the current operating system.
131+
*/
132+
export function getCurrentOS(): OperatingSystem {
133+
const runtime = getCurrentRuntime();
134+
switch (runtime) {
135+
case Runtime.Deno:
136+
switch (Deno.build.os) {
137+
case "darwin":
138+
return OperatingSystem.macOS;
139+
case "windows":
140+
return OperatingSystem.Windows;
141+
case "linux":
142+
return OperatingSystem.Linux;
143+
case "android":
144+
return OperatingSystem.Android;
145+
case "aix":
146+
case "freebsd":
147+
case "illumos":
148+
case "netbsd":
149+
case "solaris":
150+
return OperatingSystem.Unix;
151+
}
152+
return OperatingSystem.Unsupported;
153+
case Runtime.Node:
154+
// @ts-ignore Cross Runtime
155+
switch (process.platform) {
156+
case "darwin":
157+
return OperatingSystem.macOS;
158+
case "win32":
159+
return OperatingSystem.Windows;
160+
case "linux":
161+
return OperatingSystem.Linux;
162+
case "android":
163+
return OperatingSystem.Android;
164+
case "aix":
165+
case "freebsd":
166+
case "openbsd":
167+
case "sunos":
168+
return OperatingSystem.Unix;
169+
}
170+
return OperatingSystem.Unsupported;
171+
case Runtime.Bun:
172+
// @ts-ignore Cross Runtime
173+
switch (process.platform) {
174+
case "darwin":
175+
return OperatingSystem.macOS;
176+
case "win32":
177+
return OperatingSystem.Windows;
178+
case "linux":
179+
return OperatingSystem.Linux;
180+
case "android":
181+
return OperatingSystem.Android;
182+
case "aix":
183+
case "freebsd":
184+
case "openbsd":
185+
case "sunos":
186+
return OperatingSystem.Unix;
187+
}
188+
return OperatingSystem.Unsupported;
189+
case Runtime.Browser: {
190+
if ("userAgent" in navigator) {
191+
const userAgent = navigator.userAgent;
192+
if (userAgent.indexOf("Win") !== -1) return OperatingSystem.Windows;
193+
if (userAgent.indexOf("like Mac") !== -1) return OperatingSystem.iOS;
194+
if (userAgent.indexOf("Mac") !== -1) return OperatingSystem.macOS;
195+
if (userAgent.indexOf("Android") !== -1) return OperatingSystem.Android;
196+
if (userAgent.indexOf("X11") !== -1 || userAgent.indexOf("Linux") !== -1) return OperatingSystem.Linux;
197+
}
198+
}
199+
}
200+
return OperatingSystem.Unsupported;
201+
}
202+
110203
/**
111204
* Dynamically determines the current browser and its version (if applicable).
112205
*/
@@ -126,8 +219,6 @@ export function getCurrentProduct(): Product {
126219
return Product.Opera;
127220
} else if ("brave" in navigator) {
128221
return Product.Brave;
129-
} else if (userAgent.indexOf("Vivaldi") !== -1) {
130-
return Product.Vivaldi;
131222
} else if (userAgent.indexOf("Safari") !== -1 && userAgent.indexOf("Chrome") === -1) {
132223
return Product.Safari;
133224
} else if (userAgent.indexOf("Edg") !== -1) {
@@ -173,13 +264,77 @@ export function getCurrentVersion(): string | undefined {
173264
return getOperaVersion();
174265
case Product.Brave:
175266
return getBraveVersion();
176-
case Product.Vivaldi:
177-
return getVivaldiVersion();
178267
default:
179268
return undefined;
180269
}
181270
}
182271

272+
/**
273+
* Attempts to determine the current CPU architecture of the runtime's environment.
274+
*/
275+
export function getCurrentArchitecture(): Architecture {
276+
const runtime = getCurrentRuntime();
277+
switch (runtime) {
278+
case Runtime.Deno:
279+
if (Deno.build.arch === "x86_64") {
280+
return Architecture.x64;
281+
}
282+
if (Deno.build.arch === "aarch64") {
283+
return Architecture.arm64;
284+
}
285+
if (Deno.build.os === "darwin") {
286+
return Architecture.x64;
287+
}
288+
return Architecture.x86;
289+
case Runtime.Bun:
290+
case Runtime.Node:
291+
// @ts-ignore Cross Runtime
292+
switch (process.arch) {
293+
case "arm":
294+
return Architecture.arm;
295+
case "arm64":
296+
return Architecture.arm64;
297+
case "ia32":
298+
return Architecture.x86;
299+
case "x64":
300+
return Architecture.x64;
301+
case "loong64":
302+
case "mips":
303+
case "mipsel":
304+
case "ppc":
305+
case "ppc64":
306+
case "riscv64":
307+
case "s390":
308+
case "s390x":
309+
return Architecture.Unsupported;
310+
}
311+
return Architecture.Unsupported;
312+
case Runtime.Browser: {
313+
const userAgent = navigator.userAgent;
314+
// @ts-ignore Cross Runtime
315+
const platform = navigator.platform;
316+
// Clues for x86/x64
317+
if (platform.indexOf("Win64") !== -1 || platform.indexOf("x64") !== -1) {
318+
return Architecture.x64;
319+
} else if (platform.indexOf("Win32") !== -1 || platform.indexOf("x86") !== -1) {
320+
return Architecture.x86;
321+
}
322+
// Clues for ARM
323+
if (userAgent.indexOf("arm64") !== -1) {
324+
return Architecture.arm64;
325+
} else if (userAgent.indexOf("arm") !== -1) {
326+
return Architecture.arm;
327+
// @ts-ignore Cross Runtime
328+
} else if (platform.indexOf("iPhone") || platform.indexOf("iPad") || (userAgent.indexOf("Mac") !== -1 && "ontouchend" in document)) {
329+
// Likely aarch64 on newer iOS devices and Apple Silicon Macs
330+
return Architecture.arm64;
331+
}
332+
return Architecture.Unsupported;
333+
}
334+
}
335+
return Architecture.Unsupported;
336+
}
337+
183338
/**
184339
* Static variable containing the current runtime.
185340
*/
@@ -194,3 +349,13 @@ export const CurrentProduct: Product = getCurrentProduct();
194349
* Static variable containing the current product/runtime version.
195350
*/
196351
export const CurrentVersion: string | undefined = getCurrentVersion();
352+
353+
/**
354+
* Static variable containing the current operating system.
355+
*/
356+
export const CurrentOS: string | undefined = getCurrentOS();
357+
358+
/**
359+
* Static variable containing the current operating system.
360+
*/
361+
export const CurrentArchitecture: string | undefined = getCurrentArchitecture();

0 commit comments

Comments
 (0)