zosenlink-node-client 1.0.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/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # ZosenLink Node Client
2
+
3
+ `zosenlink-node-client` is a minimal managed frpc wrapper for Node.js hosts. It accepts exactly one positional argument: the activation key.
4
+
5
+ ```bash
6
+ ./zosenlink-node-client <activation-key>
7
+ ```
8
+
9
+ The platform URL is fixed to `http://39.106.140.106`. Runtime status events are emitted to stdout as JSON Lines, one object per line, so Node.js can listen to `child.stdout`.
10
+
11
+ Example:
12
+
13
+ ```js
14
+ import { spawn } from "node:child_process";
15
+
16
+ const child = spawn("./zosenlink-node-client", ["dev-activation-key"]);
17
+
18
+ child.stdout.on("data", (chunk) => {
19
+ for (const line of chunk.toString().trim().split("\n")) {
20
+ if (!line) continue;
21
+ console.log(JSON.parse(line));
22
+ }
23
+ });
24
+
25
+ child.stderr.on("data", (chunk) => {
26
+ console.error(chunk.toString());
27
+ });
28
+ ```
29
+
30
+ NPM wrapper example:
31
+
32
+ ```js
33
+ const { startZosenLinkClient } = require("zosenlink-node-client");
34
+
35
+ const child = startZosenLinkClient("dev-activation-key", {
36
+ onEvent(event) {
37
+ console.log(event);
38
+ }
39
+ });
40
+
41
+ child.stderr.on("data", (chunk) => {
42
+ process.stderr.write(chunk);
43
+ });
44
+ ```
45
+
46
+ The npm package expects platform binaries under:
47
+
48
+ ```text
49
+ bin/
50
+ darwin-arm64/zosenlink-node-client
51
+ darwin-x64/zosenlink-node-client
52
+ linux-x64/zosenlink-node-client
53
+ win32-x64/zosenlink-node-client.exe
54
+ ```
55
+
56
+ Build examples:
57
+
58
+ ```bash
59
+ cd apps/zosenlink-node-client
60
+ GOOS=darwin GOARCH=arm64 CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o bin/darwin-arm64/zosenlink-node-client .
61
+ GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o bin/darwin-x64/zosenlink-node-client .
62
+ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o bin/linux-x64/zosenlink-node-client .
63
+ GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o bin/win32-x64/zosenlink-node-client.exe .
64
+
65
+ # Optional artifact build path used by the repo:
66
+ go build -trimpath -ldflags='-s -w' -o ../../artifacts/zosenlink-node-client-darwin-arm64/zosenlink-node-client .
67
+ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o ../../artifacts/zosenlink-node-client-linux-amd64/zosenlink-node-client .
68
+ GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o ../../artifacts/zosenlink-node-client-win64/zosenlink-node-client.exe .
69
+ ```
package/bin/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # Platform Binaries
2
+
3
+ Place built `zosenlink-node-client` binaries in platform-specific folders:
4
+
5
+ ```text
6
+ bin/
7
+ darwin-arm64/zosenlink-node-client
8
+ darwin-x64/zosenlink-node-client
9
+ linux-x64/zosenlink-node-client
10
+ win32-x64/zosenlink-node-client.exe
11
+ ```
12
+
13
+ `index.js` resolves the executable from `process.platform` and `process.arch`.
package/index.js ADDED
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const fs = require("node:fs");
5
+ const path = require("node:path");
6
+ const { execFileSync, spawn } = require("node:child_process");
7
+
8
+ const ARCH_MAP = {
9
+ x64: "x64",
10
+ arm64: "arm64"
11
+ };
12
+
13
+ function platformKey(platform = process.platform, arch = process.arch) {
14
+ return `${platform}-${ARCH_MAP[arch] || arch}`;
15
+ }
16
+
17
+ function executableName(platform = process.platform) {
18
+ return platform === "win32" ? "zosenlink-node-client.exe" : "zosenlink-node-client";
19
+ }
20
+
21
+ function executablePath(options = {}) {
22
+ const platform = options.platform || process.platform;
23
+ const arch = options.arch || process.arch;
24
+ return path.join(__dirname, "bin", platformKey(platform, arch), executableName(platform));
25
+ }
26
+
27
+ function assertActivationKey(activationKey) {
28
+ const key = String(activationKey || "").trim();
29
+ if (!key) {
30
+ throw new Error("activationKey is required");
31
+ }
32
+ return key;
33
+ }
34
+
35
+ function assertExecutable(file) {
36
+ if (!fs.existsSync(file)) {
37
+ throw new Error(`Missing zosenlink-node-client binary: ${file}`);
38
+ }
39
+ if (process.platform !== "win32") {
40
+ fs.chmodSync(file, 0o755);
41
+ }
42
+ if (process.platform === "darwin") {
43
+ removeMacQuarantine(file);
44
+ }
45
+ }
46
+
47
+ function removeMacQuarantine(file) {
48
+ try {
49
+ execFileSync("/usr/bin/xattr", ["-p", "com.apple.quarantine", file], {
50
+ stdio: ["ignore", "pipe", "pipe"]
51
+ });
52
+ } catch (error) {
53
+ if (error && (error.status === 1 || error.code === 1)) return;
54
+ throw error;
55
+ }
56
+
57
+ try {
58
+ execFileSync("/usr/bin/xattr", ["-d", "com.apple.quarantine", file], {
59
+ stdio: ["ignore", "pipe", "pipe"]
60
+ });
61
+ } catch (error) {
62
+ if (error && (error.status === 1 || error.code === 1)) return;
63
+ throw error;
64
+ }
65
+ }
66
+
67
+ function startZosenLinkClient(activationKey, options = {}) {
68
+ const key = assertActivationKey(activationKey);
69
+ const file = options.executable || executablePath(options);
70
+ assertExecutable(file);
71
+
72
+ const child = spawn(file, [key], {
73
+ cwd: path.dirname(file),
74
+ windowsHide: true,
75
+ stdio: ["ignore", "pipe", "pipe"],
76
+ ...options.spawn
77
+ });
78
+
79
+ if (typeof options.onEvent === "function") {
80
+ let stdoutBuffer = "";
81
+ child.stdout.on("data", (chunk) => {
82
+ stdoutBuffer += chunk.toString("utf8");
83
+ let index = stdoutBuffer.indexOf("\n");
84
+ while (index >= 0) {
85
+ const line = stdoutBuffer.slice(0, index).trim();
86
+ stdoutBuffer = stdoutBuffer.slice(index + 1);
87
+ if (line) {
88
+ options.onEvent(JSON.parse(line));
89
+ }
90
+ index = stdoutBuffer.indexOf("\n");
91
+ }
92
+ });
93
+ }
94
+
95
+ return child;
96
+ }
97
+
98
+ module.exports = {
99
+ executablePath,
100
+ platformKey,
101
+ startZosenLinkClient
102
+ };
103
+
104
+ if (require.main === module) {
105
+ const activationKey = process.argv[2];
106
+ const child = startZosenLinkClient(activationKey, {
107
+ onEvent(event) {
108
+ console.log("[zosenlink]", event);
109
+ }
110
+ });
111
+
112
+ child.stderr.on("data", (chunk) => {
113
+ process.stderr.write(chunk);
114
+ });
115
+
116
+ child.on("exit", (code, signal) => {
117
+ console.log(`zosenlink-node-client exited: ${code ?? signal}`);
118
+ });
119
+ }
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "zosenlink-node-client",
3
+ "version": "1.0.0",
4
+ "description": "Node.js wrapper for the ZosenLink managed frpc client.",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "zosenlink-node-client": "./index.js"
8
+ },
9
+ "files": [
10
+ "index.js",
11
+ "bin/README.md",
12
+ "bin/darwin-arm64/zosenlink-node-client",
13
+ "bin/darwin-x64/zosenlink-node-client",
14
+ "bin/linux-x64/zosenlink-node-client",
15
+ "bin/win32-x64/zosenlink-node-client.exe"
16
+ ],
17
+ "engines": {
18
+ "node": ">=16"
19
+ },
20
+ "license": "UNLICENSED"
21
+ }