@itsbjoern/roost 0.1.4

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.
Files changed (4) hide show
  1. package/README.md +19 -0
  2. package/bin/roost +35 -0
  3. package/install.js +148 -0
  4. package/package.json +44 -0
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ ## @itsbjoern/roost
2
+
3
+ This is the npm wrapper for the Roost CLI.
4
+
5
+ It downloads a prebuilt `roost` binary from the GitHub Releases of `itsbjoern/roost`
6
+ for your platform and exposes it as the `roost` command.
7
+
8
+ ### Install
9
+
10
+ ```bash
11
+ npm install -g @itsbjoern/roost
12
+ ```
13
+
14
+ Then:
15
+
16
+ ```bash
17
+ roost init
18
+ ```
19
+
package/bin/roost ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const { spawn } = require("child_process");
6
+
7
+ function run() {
8
+ const exeName = process.platform === "win32" ? "roost.exe" : "roost";
9
+ const exePath = path.join(__dirname, exeName);
10
+
11
+ if (!fs.existsSync(exePath)) {
12
+ console.error(
13
+ "roost: binary not found. Try reinstalling:\n" +
14
+ " npm uninstall -g @itsbjoern/roost && npm install -g @itsbjoern/roost\n" +
15
+ "or download a release binary / build from source:\n" +
16
+ " https://github.com/itsbjoern/roost#install"
17
+ );
18
+ process.exit(1);
19
+ }
20
+
21
+ const child = spawn(exePath, process.argv.slice(2), {
22
+ stdio: "inherit",
23
+ });
24
+
25
+ child.on("exit", (code, signal) => {
26
+ if (signal) {
27
+ process.kill(process.pid, signal);
28
+ } else {
29
+ process.exit(code == null ? 1 : code);
30
+ }
31
+ });
32
+ }
33
+
34
+ run();
35
+
package/install.js ADDED
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+
3
+ const https = require("https");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const os = require("os");
7
+ const { pipeline } = require("stream");
8
+ const { promisify } = require("util");
9
+ const tar = require("tar");
10
+
11
+ const streamPipeline = promisify(pipeline);
12
+
13
+ function getTarget() {
14
+ const platform = process.platform;
15
+ const arch = process.arch;
16
+
17
+ if (platform === "linux" && arch === "x64") {
18
+ return "x86_64-unknown-linux-gnu";
19
+ }
20
+
21
+ if (platform === "darwin" && arch === "arm64") {
22
+ return "aarch64-apple-darwin";
23
+ }
24
+
25
+ if (platform === "win32" && arch === "x64") {
26
+ return "x86_64-pc-windows-msvc";
27
+ }
28
+
29
+ return null;
30
+ }
31
+
32
+ async function download(url, dest) {
33
+ await fs.promises.mkdir(path.dirname(dest), { recursive: true });
34
+
35
+ await new Promise((resolve, reject) => {
36
+ const file = fs.createWriteStream(dest);
37
+
38
+ https
39
+ .get(url, (res) => {
40
+ if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
41
+ // Redirect
42
+ https.get(res.headers.location, (res2) => {
43
+ if (res2.statusCode !== 200) {
44
+ reject(
45
+ new Error(`Failed to download binary. HTTP status code: ${res2.statusCode}`)
46
+ );
47
+ return;
48
+ }
49
+ streamPipeline(res2, file).then(resolve).catch(reject);
50
+ }).on("error", reject);
51
+ return;
52
+ }
53
+
54
+ if (res.statusCode !== 200) {
55
+ reject(
56
+ new Error(`Failed to download binary. HTTP status code: ${res.statusCode}`)
57
+ );
58
+ return;
59
+ }
60
+
61
+ streamPipeline(res, file).then(resolve).catch(reject);
62
+ })
63
+ .on("error", reject);
64
+ });
65
+ }
66
+
67
+ async function main() {
68
+ const target = getTarget();
69
+ if (!target) {
70
+ console.error(
71
+ "roost: prebuilt binary is not available for this platform yet.\n" +
72
+ "Supported from npm: linux-x64, darwin-arm64, win32-x64.\n" +
73
+ "You can still install by downloading a release binary or building from source:\n" +
74
+ " https://github.com/itsbjoern/roost#install"
75
+ );
76
+ process.exitCode = 1;
77
+ return;
78
+ }
79
+
80
+ const pkgPath = path.join(__dirname, "package.json");
81
+ let version = null;
82
+ try {
83
+ // eslint-disable-next-line import/no-dynamic-require, global-require
84
+ version = require(pkgPath).version;
85
+ } catch {
86
+ // best-effort; fall back to env if present
87
+ version = process.env.npm_package_version || null;
88
+ }
89
+
90
+ if (!version) {
91
+ console.error("roost: could not determine package version for download URL.");
92
+ process.exitCode = 1;
93
+ return;
94
+ }
95
+
96
+ const tag = `v${version}`;
97
+ const fileName = `roost-${target}.tar.gz`;
98
+ const url = `https://github.com/itsbjoern/roost/releases/download/${tag}/${fileName}`;
99
+
100
+ const tmpDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "roost-"));
101
+ const archivePath = path.join(tmpDir, fileName);
102
+ const binDir = path.join(__dirname, "bin");
103
+
104
+ try {
105
+ console.log(`roost: downloading ${url}`);
106
+ await download(url, archivePath);
107
+
108
+ await fs.promises.mkdir(binDir, { recursive: true });
109
+
110
+ await tar.x({
111
+ file: archivePath,
112
+ cwd: binDir,
113
+ });
114
+
115
+ const exeName = process.platform === "win32" ? "roost.exe" : "roost";
116
+ const binPath = path.join(binDir, exeName);
117
+
118
+ const exists = fs.existsSync(binPath);
119
+ if (!exists) {
120
+ throw new Error(
121
+ `Extracted archive did not contain expected binary at ${binPath}`
122
+ );
123
+ }
124
+
125
+ if (process.platform !== "win32") {
126
+ await fs.promises.chmod(binPath, 0o755);
127
+ }
128
+
129
+ console.log("roost: binary installed.");
130
+ } catch (err) {
131
+ console.error(`roost: failed to install binary from GitHub Releases.\n${err}`);
132
+ console.error(
133
+ "You can download a binary manually or build from source:\n" +
134
+ " https://github.com/itsbjoern/roost#install"
135
+ );
136
+ process.exitCode = 1;
137
+ } finally {
138
+ // best-effort cleanup
139
+ try {
140
+ await fs.promises.rm(tmpDir, { recursive: true, force: true });
141
+ } catch {
142
+ // ignore
143
+ }
144
+ }
145
+ }
146
+
147
+ void main();
148
+
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@itsbjoern/roost",
3
+ "version": "0.1.4",
4
+ "description": "Roost CLI - local HTTPS reverse proxy with automatic cert management",
5
+ "bin": {
6
+ "roost": "bin/roost"
7
+ },
8
+ "scripts": {
9
+ "postinstall": "node install.js"
10
+ },
11
+ "files": [
12
+ "bin/",
13
+ "install.js",
14
+ "README.md"
15
+ ],
16
+ "keywords": [
17
+ "https",
18
+ "tls",
19
+ "ssl",
20
+ "certificates",
21
+ "proxy",
22
+ "local-development",
23
+ "devtools"
24
+ ],
25
+ "author": "Björn Friedrichs (https://bjoernf.com)",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/itsbjoern/roost.git"
30
+ },
31
+ "bugs": {
32
+ "url": "https://github.com/itsbjoern/roost/issues"
33
+ },
34
+ "homepage": "https://github.com/itsbjoern/roost#readme",
35
+ "engines": {
36
+ "node": ">=16"
37
+ },
38
+ "dependencies": {
39
+ "tar": "^7.4.3"
40
+ },
41
+ "publishConfig": {
42
+ "access": "public"
43
+ }
44
+ }