restflow-cli 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/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # RestFlow CLI npm Package
2
+
3
+ This package provides the RestFlow CLI binary for multiple platforms.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g restflow-cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ After installation, the `restflow` command will be available:
14
+
15
+ ```bash
16
+ restflow --help
17
+ restflow daemon start
18
+ restflow claude -p "Hello, world!"
19
+ ```
20
+
21
+ ## Supported Platforms
22
+
23
+ - macOS (Intel & Apple Silicon)
24
+ - Linux (x64 & ARM64)
25
+ - Windows (x64)
26
+
27
+ ## Links
28
+
29
+ - [GitHub Repository](https://github.com/lhwzds/restflow)
30
+ - [Documentation](https://docs.restflow.ai)
package/bin/restflow ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawn } = require("child_process");
4
+ const path = require("path");
5
+
6
+ const binaryName = process.platform === "win32" ? "restflow.exe" : "restflow";
7
+ const binaryPath = path.join(__dirname, binaryName);
8
+
9
+ const child = spawn(binaryPath, process.argv.slice(2), {
10
+ stdio: "inherit",
11
+ });
12
+
13
+ child.on("exit", (code) => {
14
+ process.exit(code || 0);
15
+ });
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "restflow-cli",
3
+ "version": "0.1.0",
4
+ "description": "RestFlow CLI - AI assistant that can execute workflows",
5
+ "keywords": [
6
+ "ai",
7
+ "workflow",
8
+ "cli",
9
+ "automation",
10
+ "agent",
11
+ "mcp"
12
+ ],
13
+ "author": "Huaiwu Li",
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/lhwzds/restflow.git"
18
+ },
19
+ "homepage": "https://github.com/lhwzds/restflow",
20
+ "bugs": {
21
+ "url": "https://github.com/lhwzds/restflow/issues"
22
+ },
23
+ "bin": {
24
+ "restflow": "bin/restflow"
25
+ },
26
+ "scripts": {
27
+ "postinstall": "node scripts/install.js",
28
+ "test": "node scripts/install.test.js"
29
+ },
30
+ "engines": {
31
+ "node": ">=16"
32
+ },
33
+ "os": [
34
+ "darwin",
35
+ "linux",
36
+ "win32"
37
+ ],
38
+ "cpu": [
39
+ "x64",
40
+ "arm64"
41
+ ],
42
+ "files": [
43
+ "bin",
44
+ "scripts"
45
+ ]
46
+ }
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env node
2
+
3
+ const https = require("https");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const crypto = require("crypto");
7
+ const { execSync } = require("child_process");
8
+
9
+ const VERSION = require("../package.json").version;
10
+ const REPO = "lhwzds/restflow";
11
+
12
+ const PLATFORM_MAP = {
13
+ darwin: {
14
+ x64: "x86_64-apple-darwin",
15
+ arm64: "aarch64-apple-darwin",
16
+ },
17
+ linux: {
18
+ x64: "x86_64-unknown-linux-gnu",
19
+ arm64: "aarch64-unknown-linux-gnu",
20
+ },
21
+ win32: {
22
+ x64: "x86_64-pc-windows-msvc",
23
+ },
24
+ };
25
+
26
+ function getPlatformTarget() {
27
+ const platform = process.platform;
28
+ const arch = process.arch;
29
+
30
+ const targets = PLATFORM_MAP[platform];
31
+ if (!targets) {
32
+ throw new Error(`Unsupported platform: ${platform}`);
33
+ }
34
+
35
+ const target = targets[arch];
36
+ if (!target) {
37
+ throw new Error(`Unsupported architecture: ${arch} on ${platform}`);
38
+ }
39
+
40
+ return target;
41
+ }
42
+
43
+ function getDownloadUrl(target) {
44
+ const ext = process.platform === "win32" ? "zip" : "tar.gz";
45
+ return `https://github.com/${REPO}/releases/download/cli-v${VERSION}/restflow-${target}.${ext}`;
46
+ }
47
+
48
+ function getChecksumUrl() {
49
+ return `https://github.com/${REPO}/releases/download/cli-v${VERSION}/checksums.txt`;
50
+ }
51
+
52
+ function download(url) {
53
+ return new Promise((resolve, reject) => {
54
+ https
55
+ .get(url, (response) => {
56
+ if (response.statusCode === 302 || response.statusCode === 301) {
57
+ download(response.headers.location).then(resolve).catch(reject);
58
+ return;
59
+ }
60
+
61
+ if (response.statusCode !== 200) {
62
+ reject(new Error(`Failed to download ${url}: ${response.statusCode}`));
63
+ return;
64
+ }
65
+
66
+ const chunks = [];
67
+ response.on("data", (chunk) => chunks.push(chunk));
68
+ response.on("end", () => resolve(Buffer.concat(chunks)));
69
+ response.on("error", reject);
70
+ })
71
+ .on("error", reject);
72
+ });
73
+ }
74
+
75
+ function computeSha256(buffer) {
76
+ return crypto.createHash("sha256").update(buffer).digest("hex");
77
+ }
78
+
79
+ function parseChecksums(text) {
80
+ const map = new Map();
81
+ for (const line of text.split("\n")) {
82
+ const trimmed = line.trim();
83
+ if (!trimmed) continue;
84
+ const parts = trimmed.split(/\s+/);
85
+ if (parts.length < 2) continue;
86
+ const hash = parts[0];
87
+ const filename = parts[1].replace(/^\*?/, "");
88
+ map.set(filename, hash);
89
+ }
90
+ return map;
91
+ }
92
+
93
+ async function verifyChecksum(buffer, filename) {
94
+ const checksumUrl = getChecksumUrl();
95
+ const checksumText = (await download(checksumUrl)).toString("utf8");
96
+ const checksums = parseChecksums(checksumText);
97
+ const expected = checksums.get(filename);
98
+ if (!expected) {
99
+ throw new Error(`Checksum not found for ${filename}`);
100
+ }
101
+ const actual = computeSha256(buffer);
102
+ if (actual !== expected) {
103
+ throw new Error(`Checksum mismatch for ${filename}`);
104
+ }
105
+ }
106
+
107
+ async function extractTarGz(buffer, destDir) {
108
+ const tmpFile = path.join(destDir, "tmp.tar.gz");
109
+ fs.writeFileSync(tmpFile, buffer);
110
+
111
+ try {
112
+ execSync(`tar -xzf "${tmpFile}" -C "${destDir}"`, { stdio: "inherit" });
113
+ } finally {
114
+ fs.unlinkSync(tmpFile);
115
+ }
116
+ }
117
+
118
+ async function extractZip(buffer, destDir) {
119
+ const tmpZip = path.join(destDir, "tmp.zip");
120
+ fs.writeFileSync(tmpZip, buffer);
121
+
122
+ try {
123
+ if (process.platform === "win32") {
124
+ execSync(`powershell -command "Expand-Archive -Path '${tmpZip}' -DestinationPath '${destDir}' -Force"`, {
125
+ stdio: "inherit",
126
+ });
127
+ } else {
128
+ execSync(`unzip -o "${tmpZip}" -d "${destDir}"`, { stdio: "inherit" });
129
+ }
130
+ } finally {
131
+ fs.unlinkSync(tmpZip);
132
+ }
133
+ }
134
+
135
+ async function main() {
136
+ try {
137
+ const target = getPlatformTarget();
138
+ const url = getDownloadUrl(target);
139
+ const binDir = path.join(__dirname, "..", "bin");
140
+ const filename = path.basename(url);
141
+
142
+ console.log(`Downloading restflow for ${target}...`);
143
+ console.log(`URL: ${url}`);
144
+
145
+ const buffer = await download(url);
146
+ await verifyChecksum(buffer, filename);
147
+
148
+ if (!fs.existsSync(binDir)) {
149
+ fs.mkdirSync(binDir, { recursive: true });
150
+ }
151
+
152
+ if (process.platform === "win32") {
153
+ await extractZip(buffer, binDir);
154
+ } else {
155
+ await extractTarGz(buffer, binDir);
156
+ }
157
+
158
+ const binaryName = process.platform === "win32" ? "restflow.exe" : "restflow";
159
+ const binaryPath = path.join(binDir, binaryName);
160
+
161
+ if (process.platform !== "win32") {
162
+ fs.chmodSync(binaryPath, 0o755);
163
+ }
164
+
165
+ console.log(`restflow installed successfully!`);
166
+ } catch (error) {
167
+ console.error(`Failed to install restflow: ${error.message}`);
168
+ process.exit(1);
169
+ }
170
+ }
171
+
172
+ if (require.main === module) {
173
+ main();
174
+ }
175
+
176
+ module.exports = {
177
+ computeSha256,
178
+ parseChecksums,
179
+ };
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+
3
+ const assert = require("assert");
4
+ const { computeSha256, parseChecksums } = require("./install");
5
+
6
+ function testComputeSha256() {
7
+ const hash = computeSha256(Buffer.from("abc", "utf8"));
8
+ assert.strictEqual(
9
+ hash,
10
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
11
+ );
12
+ }
13
+
14
+ function testParseChecksums() {
15
+ const text = `
16
+ ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad restflow-x86_64-apple-darwin.tar.gz
17
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 restflow-x86_64-pc-windows-msvc.zip
18
+ `;
19
+ const map = parseChecksums(text);
20
+ assert.strictEqual(
21
+ map.get("restflow-x86_64-apple-darwin.tar.gz"),
22
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
23
+ );
24
+ assert.strictEqual(
25
+ map.get("restflow-x86_64-pc-windows-msvc.zip"),
26
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
27
+ );
28
+ }
29
+
30
+ function main() {
31
+ testComputeSha256();
32
+ testParseChecksums();
33
+ console.log("install.js tests passed");
34
+ }
35
+
36
+ main();