@kelnishi/satmouse 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/install.js ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * postinstall script — downloads the correct SatMouse binary from GitHub Releases.
5
+ *
6
+ * Platform mapping:
7
+ * darwin-arm64 → SatMouse-macOS-arm64.zip (extracts .app)
8
+ * linux-x64 → satmouse-linux-x64.tar.gz
9
+ * win32-x64 → satmouse-win32-x64.tar.gz
10
+ */
11
+
12
+ import { existsSync, mkdirSync, createWriteStream, unlinkSync, chmodSync } from "node:fs";
13
+ import { execSync } from "node:child_process";
14
+ import { join, dirname } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+ import { get } from "node:https";
17
+
18
+ const __dirname = dirname(fileURLToPath(import.meta.url));
19
+
20
+ const REPO = "kelnishi/SatMouse";
21
+ const VERSION = process.env.SATMOUSE_VERSION || "latest";
22
+
23
+ const PLATFORM_MAP = {
24
+ "darwin-arm64": { asset: "SatMouse-macOS-arm64.zip", binary: "SatMouse.app/Contents/MacOS/satmouse" },
25
+ "linux-x64": { asset: "satmouse-linux-x64.tar.gz", binary: "satmouse" },
26
+ "win32-x64": { asset: "satmouse-win32-x64.tar.gz", binary: "satmouse.exe" },
27
+ };
28
+
29
+ const key = `${process.platform}-${process.arch}`;
30
+ const platformInfo = PLATFORM_MAP[key];
31
+
32
+ if (!platformInfo) {
33
+ console.log(`[satmouse] No prebuilt binary for ${key}. Build from source.`);
34
+ process.exit(0);
35
+ }
36
+
37
+ const binaryDir = join(__dirname, ".cache");
38
+ const binaryPath = join(binaryDir, platformInfo.binary.split("/").pop());
39
+
40
+ if (existsSync(binaryPath)) {
41
+ console.log(`[satmouse] Binary already exists: ${binaryPath}`);
42
+ process.exit(0);
43
+ }
44
+
45
+ async function main() {
46
+ mkdirSync(binaryDir, { recursive: true });
47
+
48
+ // Resolve download URL from GitHub Releases API
49
+ const tag = VERSION === "latest" ? "latest" : `tags/${VERSION}`;
50
+ const apiUrl = `https://api.github.com/repos/${REPO}/releases/${tag}`;
51
+
52
+ console.log(`[satmouse] Fetching release info...`);
53
+ const release = await fetchJSON(apiUrl);
54
+ const asset = release.assets?.find((a) => a.name === platformInfo.asset);
55
+
56
+ if (!asset) {
57
+ console.error(`[satmouse] Asset ${platformInfo.asset} not found in release ${release.tag_name}`);
58
+ console.error(`[satmouse] Download manually from https://github.com/${REPO}/releases`);
59
+ process.exit(1);
60
+ }
61
+
62
+ const archivePath = join(binaryDir, asset.name);
63
+
64
+ console.log(`[satmouse] Downloading ${asset.name} (${formatBytes(asset.size)})...`);
65
+ await download(asset.browser_download_url, archivePath);
66
+
67
+ // Extract
68
+ console.log(`[satmouse] Extracting...`);
69
+ if (asset.name.endsWith(".zip")) {
70
+ execSync(`unzip -o "${archivePath}" -d "${binaryDir}"`, { stdio: "pipe" });
71
+ // For macOS .app bundle, the binary is inside
72
+ const appBinary = join(binaryDir, platformInfo.binary);
73
+ if (existsSync(appBinary) && appBinary !== binaryPath) {
74
+ execSync(`cp "${appBinary}" "${binaryPath}"`, { stdio: "pipe" });
75
+ }
76
+ } else {
77
+ execSync(`tar xzf "${archivePath}" -C "${binaryDir}"`, { stdio: "pipe" });
78
+ }
79
+
80
+ // Make executable
81
+ if (process.platform !== "win32") {
82
+ chmodSync(binaryPath, 0o755);
83
+ }
84
+
85
+ // Clean up archive
86
+ unlinkSync(archivePath);
87
+
88
+ console.log(`[satmouse] Installed to ${binaryPath}`);
89
+ }
90
+
91
+ function fetchJSON(url) {
92
+ return new Promise((resolve, reject) => {
93
+ get(url, { headers: { "User-Agent": "satmouse-npm", Accept: "application/json" } }, (res) => {
94
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
95
+ return fetchJSON(res.headers.location).then(resolve, reject);
96
+ }
97
+ let data = "";
98
+ res.on("data", (chunk) => (data += chunk));
99
+ res.on("end", () => {
100
+ try { resolve(JSON.parse(data)); }
101
+ catch (e) { reject(new Error(`Invalid JSON from ${url}`)); }
102
+ });
103
+ res.on("error", reject);
104
+ }).on("error", reject);
105
+ });
106
+ }
107
+
108
+ function download(url, dest) {
109
+ return new Promise((resolve, reject) => {
110
+ get(url, { headers: { "User-Agent": "satmouse-npm" } }, (res) => {
111
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
112
+ return download(res.headers.location, dest).then(resolve, reject);
113
+ }
114
+ if (res.statusCode !== 200) {
115
+ reject(new Error(`Download failed: HTTP ${res.statusCode}`));
116
+ return;
117
+ }
118
+ const file = createWriteStream(dest);
119
+ res.pipe(file);
120
+ file.on("finish", () => { file.close(); resolve(); });
121
+ file.on("error", reject);
122
+ }).on("error", reject);
123
+ });
124
+ }
125
+
126
+ function formatBytes(bytes) {
127
+ if (bytes < 1024) return `${bytes} B`;
128
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
129
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
130
+ }
131
+
132
+ main().catch((err) => {
133
+ console.error(`[satmouse] Install failed: ${err.message}`);
134
+ console.error(`[satmouse] Download manually from https://github.com/${REPO}/releases`);
135
+ process.exit(1);
136
+ });
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * npx @kelnishi/satmouse
5
+ *
6
+ * Locates and executes the platform-specific SatMouse binary.
7
+ */
8
+
9
+ import { existsSync } from "node:fs";
10
+ import { execFileSync } from "node:child_process";
11
+ import { join, dirname } from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+
14
+ const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ const cacheDir = join(__dirname, ".cache");
16
+
17
+ const binaryName = process.platform === "win32" ? "satmouse.exe" : "satmouse";
18
+ const binaryPath = join(cacheDir, binaryName);
19
+
20
+ if (!existsSync(binaryPath)) {
21
+ console.error("[satmouse] Binary not found. Running install...");
22
+ execFileSync(process.execPath, [join(__dirname, "install.js")], { stdio: "inherit" });
23
+
24
+ if (!existsSync(binaryPath)) {
25
+ console.error("[satmouse] Install failed. Download manually from:");
26
+ console.error(" https://github.com/kelnishi/SatMouse/releases/latest");
27
+ process.exit(1);
28
+ }
29
+ }
30
+
31
+ // Forward all args to the native binary
32
+ try {
33
+ execFileSync(binaryPath, process.argv.slice(2), { stdio: "inherit" });
34
+ } catch (err) {
35
+ process.exit(err.status ?? 1);
36
+ }
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@kelnishi/satmouse",
3
+ "version": "0.1.0",
4
+ "description": "3DConnexion SpaceMouse bridge — run with npx @kelnishi/satmouse",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "satmouse": "bin/satmouse.js"
8
+ },
9
+ "scripts": {
10
+ "postinstall": "node bin/install.js"
11
+ },
12
+ "files": ["bin"],
13
+ "os": ["darwin", "linux", "win32"],
14
+ "cpu": ["arm64", "x64"],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/kelnishi/SatMouse.git",
18
+ "directory": "packages/bridge"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ }
23
+ }