infynon 0.2.5 → 0.2.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "infynon",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "Thin npm installer for the proprietary INFYNON CLI binary releases.",
5
5
  "bin": {
6
6
  "infynon": "run.js",
package/postinstall.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
 
4
+ const crypto = require("crypto");
4
5
  const https = require("https");
5
6
  const fs = require("fs");
6
7
  const path = require("path");
@@ -10,6 +11,8 @@ const REPO = "d4rkNinja/infynon-cli";
10
11
  const VERSION = require("./package.json").version;
11
12
  const BIN_DIR = path.join(__dirname, "bin");
12
13
  const BIN_PATH = path.join(BIN_DIR, process.platform === "win32" ? "infynon.exe" : "infynon");
14
+ const TEMP_BIN_PATH = BIN_PATH + ".download-" + process.pid;
15
+ const TEMP_CHECKSUMS_PATH = BIN_PATH + ".checksums-" + process.pid + ".txt";
13
16
 
14
17
  function getTarget() {
15
18
  if (process.platform === "win32" && process.arch === "x64") return { target: "x86_64-pc-windows-msvc", ext: ".exe" };
@@ -23,14 +26,24 @@ function getTarget() {
23
26
  function downloadFile(url, dest, redirects) {
24
27
  redirects = redirects === undefined ? 0 : redirects;
25
28
  if (redirects > 5) {
26
- throw new Error("Too many redirects while downloading binary");
29
+ return Promise.reject(new Error("Too many redirects while downloading binary"));
27
30
  }
28
31
 
29
32
  return new Promise(function (resolve, reject) {
30
33
  https
31
34
  .get(url, { headers: { "User-Agent": "infynon-npm-installer" } }, function (res) {
32
- if (res.statusCode === 301 || res.statusCode === 302) {
33
- return downloadFile(res.headers.location, dest, redirects + 1)
35
+ if (res.statusCode >= 300 && res.statusCode < 400) {
36
+ res.resume();
37
+ if (!res.headers.location) {
38
+ return reject(new Error("Redirect response did not include a Location header"));
39
+ }
40
+ let nextUrl;
41
+ try {
42
+ nextUrl = new URL(res.headers.location, url).toString();
43
+ } catch (err) {
44
+ return reject(err);
45
+ }
46
+ return downloadFile(nextUrl, dest, redirects + 1)
34
47
  .then(resolve)
35
48
  .catch(reject);
36
49
  }
@@ -48,6 +61,12 @@ function downloadFile(url, dest, redirects) {
48
61
  file.on("finish", function () {
49
62
  file.close(resolve);
50
63
  });
64
+ res.on("error", function (err) {
65
+ file.close(function () {
66
+ fs.unlink(dest, function () {});
67
+ reject(err);
68
+ });
69
+ });
51
70
  res.pipe(file);
52
71
  })
53
72
  .on("error", function (err) {
@@ -57,6 +76,36 @@ function downloadFile(url, dest, redirects) {
57
76
  });
58
77
  }
59
78
 
79
+ function removeQuietly(filePath) {
80
+ try {
81
+ fs.rmSync(filePath, { force: true });
82
+ } catch (_) {}
83
+ }
84
+
85
+ function checksumForAsset(checksumsText, assetName) {
86
+ const lines = checksumsText.split(/\r?\n/);
87
+ for (const line of lines) {
88
+ const match = line.match(/^([a-fA-F0-9]{64})\s+[* ]?(.+)$/);
89
+ if (!match) continue;
90
+ if (path.basename(match[2].trim()) === assetName) {
91
+ return match[1].toLowerCase();
92
+ }
93
+ }
94
+ throw new Error("checksums.txt does not include " + assetName);
95
+ }
96
+
97
+ function sha256File(filePath) {
98
+ return crypto.createHash("sha256").update(fs.readFileSync(filePath)).digest("hex");
99
+ }
100
+
101
+ function verifyChecksum(checksumsPath, filePath, assetName) {
102
+ const expected = checksumForAsset(fs.readFileSync(checksumsPath, "utf8"), assetName);
103
+ const actual = sha256File(filePath);
104
+ if (actual !== expected) {
105
+ throw new Error("SHA-256 mismatch for " + assetName);
106
+ }
107
+ }
108
+
60
109
  function verifyBinary() {
61
110
  const result = spawnSync(BIN_PATH, ["--version"], {
62
111
  encoding: "utf8",
@@ -72,6 +121,15 @@ function verifyBinary() {
72
121
  (detail ? ": " + detail : " with exit code " + result.status)
73
122
  );
74
123
  }
124
+ const versionFields = String((result.stdout || "") + " " + (result.stderr || ""))
125
+ .trim()
126
+ .split(/\s+/)
127
+ .map(function (field) {
128
+ return field.replace(/^v/, "");
129
+ });
130
+ if (versionFields.indexOf(VERSION) === -1) {
131
+ throw new Error("Downloaded binary did not report version " + VERSION);
132
+ }
75
133
  }
76
134
 
77
135
  async function main() {
@@ -88,6 +146,7 @@ async function main() {
88
146
  const tag = "v" + VERSION;
89
147
  const assetName = "infynon-" + info.target + info.ext;
90
148
  const url = "https://github.com/" + REPO + "/releases/download/" + tag + "/" + assetName;
149
+ const checksumsUrl = "https://github.com/" + REPO + "/releases/download/" + tag + "/checksums.txt";
91
150
 
92
151
  if (!fs.existsSync(BIN_DIR)) {
93
152
  fs.mkdirSync(BIN_DIR, { recursive: true });
@@ -96,11 +155,21 @@ async function main() {
96
155
  console.log("[infynon] Downloading " + assetName + " from " + tag + " release...");
97
156
 
98
157
  try {
99
- await downloadFile(url, BIN_PATH);
158
+ removeQuietly(TEMP_BIN_PATH);
159
+ removeQuietly(TEMP_CHECKSUMS_PATH);
160
+ await downloadFile(url, TEMP_BIN_PATH);
161
+ await downloadFile(checksumsUrl, TEMP_CHECKSUMS_PATH);
162
+ verifyChecksum(TEMP_CHECKSUMS_PATH, TEMP_BIN_PATH, assetName);
163
+ removeQuietly(BIN_PATH);
164
+ fs.renameSync(TEMP_BIN_PATH, BIN_PATH);
100
165
  } catch (err) {
166
+ removeQuietly(TEMP_BIN_PATH);
167
+ removeQuietly(TEMP_CHECKSUMS_PATH);
101
168
  console.error("[infynon] Download failed: " + err.message);
102
169
  console.error("[infynon] Manual install: https://github.com/" + REPO + "/releases/tag/" + tag);
103
170
  process.exit(1);
171
+ } finally {
172
+ removeQuietly(TEMP_CHECKSUMS_PATH);
104
173
  }
105
174
 
106
175
  if (process.platform !== "win32") {
@@ -110,7 +179,7 @@ async function main() {
110
179
  try {
111
180
  verifyBinary();
112
181
  } catch (err) {
113
- fs.unlink(BIN_PATH, function () {});
182
+ removeQuietly(BIN_PATH);
114
183
  console.error("[infynon] Binary verification failed: " + err.message);
115
184
  console.error("[infynon] Reinstall after the release asset is corrected: npm install -g infynon");
116
185
  process.exit(1);
package/preuninstall.js CHANGED
@@ -3,54 +3,9 @@
3
3
 
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
- const os = require("os");
7
6
 
8
- // Mirror the same path logic as src/firewall/config.rs → config_dir()
9
- const INFYNON_DIR = path.join(os.homedir(), ".infynon");
7
+ const BIN_DIR = path.join(__dirname, "bin");
10
8
 
11
- // Files/dirs managed by infynon that live outside the npm package
12
- const MANAGED_PATHS = [
13
- { p: path.join(INFYNON_DIR, "infynon.toml"), label: "firewall config" },
14
- { p: path.join(INFYNON_DIR, "eagle-eye.toml"), label: "eagle eye config" },
15
- { p: path.join(INFYNON_DIR, "access.jsonl"), label: "access log" },
16
- { p: path.join(INFYNON_DIR, "blocked.jsonl"), label: "blocked log" },
17
- { p: path.join(INFYNON_DIR, "sbom.json"), label: "SBOM" },
18
- ];
19
-
20
- console.log("\n[infynon] Cleaning up...\n");
21
-
22
- let removed = 0;
23
-
24
- for (const { p, label } of MANAGED_PATHS) {
25
- if (fs.existsSync(p)) {
26
- try {
27
- fs.rmSync(p, { force: true });
28
- console.log(" removed " + label + " (" + p + ")");
29
- removed++;
30
- } catch (err) {
31
- console.warn(" skipped " + label + " — " + err.message);
32
- }
33
- }
34
- }
35
-
36
- // Remove ~/.infynon/ itself if it is now empty
37
- if (fs.existsSync(INFYNON_DIR)) {
38
- try {
39
- const remaining = fs.readdirSync(INFYNON_DIR);
40
- if (remaining.length === 0) {
41
- fs.rmdirSync(INFYNON_DIR);
42
- console.log(" removed ~/.infynon/ directory");
43
- } else {
44
- console.log(
45
- " kept ~/.infynon/ — " + remaining.length +
46
- " user file(s) remain: " + remaining.join(", ")
47
- );
48
- }
49
- } catch (_) {}
50
- }
51
-
52
- if (removed === 0) {
53
- console.log(" nothing to clean up.\n");
54
- } else {
55
- console.log("\n[infynon] Clean uninstall complete.\n");
9
+ if (fs.existsSync(BIN_DIR)) {
10
+ fs.rmSync(BIN_DIR, { recursive: true, force: true });
56
11
  }
package/run.js CHANGED
@@ -21,6 +21,16 @@ if (!fs.existsSync(BIN_PATH)) {
21
21
  }
22
22
 
23
23
  function runBinary(args) {
24
+ if (process.platform === "win32") {
25
+ const estimatedLength = BIN_PATH.length + args.reduce(function (total, arg) {
26
+ return total + String(arg).length + 3;
27
+ }, 0);
28
+ if (estimatedLength > 30000) {
29
+ return {
30
+ error: new Error("command line is too long for Windows process creation; reduce arguments or use file-based package-manager input"),
31
+ };
32
+ }
33
+ }
24
34
  return spawnSync(BIN_PATH, args, {
25
35
  stdio: "inherit",
26
36
  windowsHide: false,