@seyuna/cli 0.0.2-dev.1 → 0.0.2-dev.12
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/seyuna +0 -0
- package/index.js +32 -0
- package/install.js +123 -0
- package/package.json +9 -3
- package/deno-wrapper.ts +0 -79
- package/deno.json +0 -13
- package/node-install.js +0 -66
package/bin/seyuna
CHANGED
|
Binary file
|
package/index.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const childProcess = require("child_process");
|
|
3
|
+
|
|
4
|
+
// Lookup table for all platforms and binary distribution packages
|
|
5
|
+
const BINARY_DISTRIBUTION_PACKAGES = {
|
|
6
|
+
darwin: "@seyuna/cli-darwin",
|
|
7
|
+
linux: "@seyuna/cli-linux",
|
|
8
|
+
freebsd: "@seyuna/cli-linux",
|
|
9
|
+
win32: "@seyuna/cli-win32",
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// Windows binaries end with .exe so we need to special case them.
|
|
13
|
+
const binaryName = process.platform === "win32" ? "seyuna.exe" : "seyuna";
|
|
14
|
+
|
|
15
|
+
// Determine package name for this platform
|
|
16
|
+
const platformSpecificPackageName =
|
|
17
|
+
BINARY_DISTRIBUTION_PACKAGES[process.platform];
|
|
18
|
+
|
|
19
|
+
function getBinaryPath() {
|
|
20
|
+
try {
|
|
21
|
+
// Resolving will fail if the optionalDependency was not installed
|
|
22
|
+
return require.resolve(`${platformSpecificPackageName}/bin/${binaryName}`);
|
|
23
|
+
} catch (e) {
|
|
24
|
+
return path.join(__dirname, "..", binaryName);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports.runBinary = function (...args) {
|
|
29
|
+
childProcess.execFileSync(getBinaryPath(), args, {
|
|
30
|
+
stdio: "inherit",
|
|
31
|
+
});
|
|
32
|
+
};
|
package/install.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const zlib = require("zlib");
|
|
4
|
+
const https = require("https");
|
|
5
|
+
|
|
6
|
+
// Lookup table for all platforms and binary distribution packages
|
|
7
|
+
const BINARY_DISTRIBUTION_PACKAGES = {
|
|
8
|
+
darwin: "@seyuna/cli-darwin",
|
|
9
|
+
linux: "@seyuna/cli-linux",
|
|
10
|
+
freebsd: "@seyuna/cli-linux",
|
|
11
|
+
win32: "@seyuna/cli-win32",
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// Adjust the version you want to install.
|
|
15
|
+
const BINARY_DISTRIBUTION_VERSION = "0.0.2-dev.12";
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
// Windows binaries end with .exe so we need to special case them.
|
|
19
|
+
const binaryName = process.platform === "win32" ? "seyuna.exe" : "seyuna";
|
|
20
|
+
|
|
21
|
+
// Determine package name for this platform
|
|
22
|
+
const platformSpecificPackageName =
|
|
23
|
+
BINARY_DISTRIBUTION_PACKAGES[process.platform];
|
|
24
|
+
|
|
25
|
+
// Compute the path we want to emit the fallback binary to
|
|
26
|
+
const fallbackBinaryPath = path.join(__dirname, binaryName);
|
|
27
|
+
|
|
28
|
+
function makeRequest(url) {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
https
|
|
31
|
+
.get(url, (response) => {
|
|
32
|
+
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
33
|
+
const chunks = [];
|
|
34
|
+
response.on("data", (chunk) => chunks.push(chunk));
|
|
35
|
+
response.on("end", () => {
|
|
36
|
+
resolve(Buffer.concat(chunks));
|
|
37
|
+
});
|
|
38
|
+
} else if (
|
|
39
|
+
response.statusCode >= 300 &&
|
|
40
|
+
response.statusCode < 400 &&
|
|
41
|
+
response.headers.location
|
|
42
|
+
) {
|
|
43
|
+
// Follow redirects
|
|
44
|
+
makeRequest(response.headers.location).then(resolve, reject);
|
|
45
|
+
} else {
|
|
46
|
+
reject(
|
|
47
|
+
new Error(
|
|
48
|
+
`npm responded with status code ${response.statusCode} when downloading the package!`
|
|
49
|
+
)
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
.on("error", (error) => {
|
|
54
|
+
reject(error);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function extractFileFromTarball(tarballBuffer, filepath) {
|
|
60
|
+
// Tar archives are organized in 512 byte blocks.
|
|
61
|
+
// Blocks can either be header blocks or data blocks.
|
|
62
|
+
// Header blocks contain file names of the archive in the first 100 bytes, terminated by a null byte.
|
|
63
|
+
// The size of a file is contained in bytes 124-135 of a header block.
|
|
64
|
+
// The following blocks will be data blocks containing the file.
|
|
65
|
+
let offset = 0;
|
|
66
|
+
while (offset < tarballBuffer.length) {
|
|
67
|
+
const header = tarballBuffer.subarray(offset, offset + 512);
|
|
68
|
+
offset += 512;
|
|
69
|
+
|
|
70
|
+
const fileName = header.toString("utf-8", 0, 100).replace(/\0.*/g, "");
|
|
71
|
+
const fileSize = parseInt(
|
|
72
|
+
header.toString("utf-8", 124, 136).replace(/\0.*/g, ""),
|
|
73
|
+
8
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
if (fileName === filepath) {
|
|
77
|
+
return tarballBuffer.subarray(offset, offset + fileSize);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Clamp offset to the uppoer multiple of 512
|
|
81
|
+
offset = (offset + fileSize + 511) & ~511;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function downloadBinaryFromNpm() {
|
|
86
|
+
// Download the tarball of the right binary distribution package
|
|
87
|
+
const tarballDownloadBuffer = await makeRequest(
|
|
88
|
+
`https://registry.npmjs.org/${platformSpecificPackageName}/-/${platformSpecificPackageName}-${BINARY_DISTRIBUTION_VERSION}.tgz`
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const tarballBuffer = zlib.unzipSync(tarballDownloadBuffer);
|
|
92
|
+
|
|
93
|
+
// Extract binary from package and write to disk
|
|
94
|
+
fs.writeFileSync(
|
|
95
|
+
fallbackBinaryPath,
|
|
96
|
+
extractFileFromTarball(tarballBuffer, `package/bin/${binaryName}`)
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// Make binary executable
|
|
100
|
+
fs.chmodSync(fallbackBinaryPath, "755");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function isPlatformSpecificPackageInstalled() {
|
|
104
|
+
try {
|
|
105
|
+
// Resolving will fail if the optionalDependency was not installed
|
|
106
|
+
require.resolve(`${platformSpecificPackageName}/bin/${binaryName}`);
|
|
107
|
+
return true;
|
|
108
|
+
} catch (e) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Skip downloading the binary if it was already installed via optionalDependencies
|
|
114
|
+
if (!isPlatformSpecificPackageInstalled()) {
|
|
115
|
+
console.log(
|
|
116
|
+
"Platform specific package not found. Will manually download binary."
|
|
117
|
+
);
|
|
118
|
+
downloadBinaryFromNpm();
|
|
119
|
+
} else {
|
|
120
|
+
console.log(
|
|
121
|
+
"Platform specific package already installed. Will fall back to manually downloading binary."
|
|
122
|
+
);
|
|
123
|
+
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seyuna/cli",
|
|
3
|
-
"version": "0.0.2-dev.
|
|
3
|
+
"version": "0.0.2-dev.12",
|
|
4
|
+
"main": "./index.js",
|
|
4
5
|
"bin": {
|
|
5
6
|
"seyuna": "./bin/seyuna"
|
|
6
7
|
},
|
|
7
8
|
"scripts": {
|
|
8
|
-
"
|
|
9
|
+
"postinstall": "node ./install.js"
|
|
9
10
|
},
|
|
10
11
|
"description": "Seyuna CLI",
|
|
11
12
|
"author": "Seyuna",
|
|
12
13
|
"license": "MIT",
|
|
13
14
|
"engines": {
|
|
14
15
|
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"optionalDependencies": {
|
|
18
|
+
"@seyuna/cli-darwin": "0.0.2-dev.12",
|
|
19
|
+
"@seyuna/cli-linux": "0.0.2-dev.12",
|
|
20
|
+
"@seyuna/cli-win32": "0.0.2-dev.12"
|
|
15
21
|
}
|
|
16
|
-
}
|
|
22
|
+
}
|
package/deno-wrapper.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env -S deno run --allow-run --allow-read --allow-write --allow-net
|
|
2
|
-
|
|
3
|
-
import { join, dirname } from "jsr:@std/path@^0.224.0";
|
|
4
|
-
import { ensureDir, existsSync } from "jsr:@std/fs@^0.224.0";
|
|
5
|
-
|
|
6
|
-
// Get version from deno.json
|
|
7
|
-
async function getVersion(): Promise<string> {
|
|
8
|
-
const text = await Deno.readTextFile("deno.json");
|
|
9
|
-
const config = JSON.parse(text);
|
|
10
|
-
return config.version;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Download a file from a URL to a destination path
|
|
14
|
-
async function downloadFile(url: string, dest: string): Promise<void> {
|
|
15
|
-
const res = await fetch(url);
|
|
16
|
-
if (!res.ok || !res.body) {
|
|
17
|
-
throw new Error(`Failed to download ${url}: ${res.status} ${res.statusText}`);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
await ensureDir(dirname(dest));
|
|
21
|
-
const file = await Deno.open(dest, { create: true, write: true, truncate: true });
|
|
22
|
-
await res.body.pipeTo(file.writable);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Main execution
|
|
26
|
-
async function main() {
|
|
27
|
-
const platform = Deno.build.os; // "windows", "linux", or "darwin"
|
|
28
|
-
const binName = platform === "windows" ? "seyuna.exe" : "seyuna";
|
|
29
|
-
const binPath = join(Deno.cwd(), "bin", binName);
|
|
30
|
-
|
|
31
|
-
if (!existsSync(binPath)) {
|
|
32
|
-
console.log("seyuna binary not found, downloading...");
|
|
33
|
-
|
|
34
|
-
const version = await getVersion();
|
|
35
|
-
|
|
36
|
-
let target: string;
|
|
37
|
-
switch (platform) {
|
|
38
|
-
case "windows":
|
|
39
|
-
target = "seyuna-windows.exe";
|
|
40
|
-
break;
|
|
41
|
-
case "darwin":
|
|
42
|
-
target = "seyuna-macos";
|
|
43
|
-
break;
|
|
44
|
-
case "linux":
|
|
45
|
-
target = "seyuna-linux";
|
|
46
|
-
break;
|
|
47
|
-
default:
|
|
48
|
-
console.error(`Unsupported platform: ${platform}`);
|
|
49
|
-
Deno.exit(1);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const releaseUrl = `https://github.com/seyuna-corp/seyuna-cli/releases/download/v${version}/${target}`;
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
await downloadFile(releaseUrl, binPath);
|
|
56
|
-
if (platform !== "windows") {
|
|
57
|
-
await Deno.chmod(binPath, 0o755);
|
|
58
|
-
}
|
|
59
|
-
console.log(`seyuna CLI v${version} installed to ${binPath}`);
|
|
60
|
-
} catch (err) {
|
|
61
|
-
console.error("Installation failed:", err);
|
|
62
|
-
Deno.exit(1);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Forward all arguments to the actual binary
|
|
67
|
-
const process = Deno.run({
|
|
68
|
-
cmd: [binPath, ...Deno.args],
|
|
69
|
-
stdin: "inherit",
|
|
70
|
-
stdout: "inherit",
|
|
71
|
-
stderr: "inherit",
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
const status = await process.status();
|
|
75
|
-
process.close();
|
|
76
|
-
Deno.exit(status.code);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
await main();
|
package/deno.json
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@seyuna/cli",
|
|
3
|
-
"version": "0.0.2-dev.1",
|
|
4
|
-
"description": "Seyuna CLI",
|
|
5
|
-
"bin": {
|
|
6
|
-
"seyuna": "./deno-wrapper.ts"
|
|
7
|
-
},
|
|
8
|
-
"exports": "./deno-wrapper.ts",
|
|
9
|
-
"license": "MIT",
|
|
10
|
-
"tasks": {
|
|
11
|
-
"install": "deno run --allow-write --allow-net deno-install.ts"
|
|
12
|
-
}
|
|
13
|
-
}
|
package/node-install.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { mkdir, chmod, readFile } from "fs/promises";
|
|
2
|
-
import { createWriteStream } from "fs";
|
|
3
|
-
import { Readable } from "stream";
|
|
4
|
-
import path from "path";
|
|
5
|
-
import { fileURLToPath } from "url";
|
|
6
|
-
import process from "process";
|
|
7
|
-
|
|
8
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
|
|
10
|
-
async function downloadFile(url, dest) {
|
|
11
|
-
const res = await fetch(url);
|
|
12
|
-
if (!res.ok) {
|
|
13
|
-
throw new Error(`Failed to download ${url}: ${res.status} ${res.statusText}`);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
await mkdir(path.dirname(dest), { recursive: true });
|
|
17
|
-
|
|
18
|
-
const readable = Readable.fromWeb(res.body);
|
|
19
|
-
const fileStream = createWriteStream(dest);
|
|
20
|
-
|
|
21
|
-
return new Promise((resolve, reject) => {
|
|
22
|
-
readable.pipe(fileStream);
|
|
23
|
-
readable.on("error", reject);
|
|
24
|
-
fileStream.on("finish", resolve);
|
|
25
|
-
fileStream.on("error", reject);
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async function getVersion() {
|
|
30
|
-
const pkgPath = path.join(__dirname, "package.json");
|
|
31
|
-
const pkgJson = await readFile(pkgPath, "utf8");
|
|
32
|
-
return JSON.parse(pkgJson).version;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async function main() {
|
|
36
|
-
const version = await getVersion();
|
|
37
|
-
|
|
38
|
-
const platform = process.platform;
|
|
39
|
-
let target;
|
|
40
|
-
if (platform === "win32") {
|
|
41
|
-
target = "seyuna-windows.exe";
|
|
42
|
-
} else if (platform === "darwin") {
|
|
43
|
-
target = "seyuna-macos";
|
|
44
|
-
} else if (platform === "linux") {
|
|
45
|
-
target = "seyuna-linux";
|
|
46
|
-
} else {
|
|
47
|
-
console.error(`Unsupported platform: ${platform}`);
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const releaseUrl = `https://github.com/seyuna-corp/seyuna-cli/releases/download/v${version}/${target}`;
|
|
52
|
-
const dest = path.join(__dirname, "bin", platform === "win32" ? "seyuna.exe" : "seyuna");
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
await downloadFile(releaseUrl, dest);
|
|
56
|
-
if (platform !== "win32") {
|
|
57
|
-
await chmod(dest, 0o755);
|
|
58
|
-
}
|
|
59
|
-
console.log(`seyuna CLI v${version} installed to ${dest}`);
|
|
60
|
-
} catch (err) {
|
|
61
|
-
console.error(err);
|
|
62
|
-
process.exit(1);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
main();
|