@backendsystems/nibble 0.4.0 → 0.4.1
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/install.js +100 -29
- package/package.json +2 -2
package/bin/install.js
CHANGED
|
@@ -1,49 +1,120 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const os = require('os');
|
|
3
6
|
const path = require('path');
|
|
4
|
-
const
|
|
7
|
+
const crypto = require('crypto');
|
|
8
|
+
const tar = require('tar');
|
|
5
9
|
|
|
6
10
|
const PROJECT = 'nibble';
|
|
7
11
|
const OWNER = 'backendsystems';
|
|
8
12
|
const ROOT = path.resolve(__dirname, '..');
|
|
9
13
|
const VENDOR_DIR = path.join(ROOT, 'vendor');
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (os === 'win32') {
|
|
23
|
-
osTarget = 'windows';
|
|
24
|
-
}
|
|
14
|
+
const { version } = require(path.join(ROOT, 'package.json'));
|
|
15
|
+
|
|
16
|
+
const platformMap = { linux: 'linux', darwin: 'darwin', win32: 'windows' };
|
|
17
|
+
const archMap = { x64: 'amd64', arm64: 'arm64' };
|
|
18
|
+
|
|
19
|
+
const osPlatform = platformMap[process.platform];
|
|
20
|
+
const osArch = archMap[process.arch];
|
|
21
|
+
|
|
22
|
+
if (!osPlatform || !osArch) {
|
|
23
|
+
console.error(`Unsupported platform: ${process.platform}/${process.arch}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
const tag = `v${version}`;
|
|
28
|
+
const base = `https://github.com/${OWNER}/${PROJECT}/releases/download/${tag}`;
|
|
29
|
+
const archiveName = `${PROJECT}_${osPlatform}_${osArch}.tar.gz`;
|
|
30
|
+
const binName = process.platform === 'win32' ? `${PROJECT}.exe` : PROJECT;
|
|
31
|
+
const destPath = path.join(VENDOR_DIR, binName);
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
function download(url, dest) {
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
const file = fs.createWriteStream(dest);
|
|
36
|
+
function get(url) {
|
|
37
|
+
https.get(url, (res) => {
|
|
38
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
39
|
+
return get(res.headers.location);
|
|
40
|
+
}
|
|
41
|
+
if (res.statusCode !== 200) {
|
|
42
|
+
return reject(new Error(`HTTP ${res.statusCode} downloading ${url}`));
|
|
43
|
+
}
|
|
44
|
+
res.pipe(file);
|
|
45
|
+
file.on('finish', () => file.close(resolve));
|
|
46
|
+
file.on('error', reject);
|
|
47
|
+
}).on('error', reject);
|
|
33
48
|
}
|
|
34
|
-
|
|
49
|
+
get(url);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function fetch(url) {
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
function get(url) {
|
|
56
|
+
https.get(url, (res) => {
|
|
57
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
58
|
+
return get(res.headers.location);
|
|
59
|
+
}
|
|
60
|
+
if (res.statusCode !== 200) {
|
|
61
|
+
return reject(new Error(`HTTP ${res.statusCode} fetching ${url}`));
|
|
62
|
+
}
|
|
63
|
+
const chunks = [];
|
|
64
|
+
res.on('data', c => chunks.push(c));
|
|
65
|
+
res.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
66
|
+
res.on('error', reject);
|
|
67
|
+
}).on('error', reject);
|
|
68
|
+
}
|
|
69
|
+
get(url);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
35
72
|
|
|
36
|
-
|
|
73
|
+
function sha256File(filePath) {
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
const hash = crypto.createHash('sha256');
|
|
76
|
+
fs.createReadStream(filePath)
|
|
77
|
+
.on('data', d => hash.update(d))
|
|
78
|
+
.on('end', () => resolve(hash.digest('hex')))
|
|
79
|
+
.on('error', reject);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function parseChecksum(checksumsTxt, filename) {
|
|
84
|
+
for (const line of checksumsTxt.split('\n')) {
|
|
85
|
+
const [hash, name] = line.trim().split(/\s+/);
|
|
86
|
+
if (name === filename) return hash;
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
37
89
|
}
|
|
38
90
|
|
|
39
91
|
async function main() {
|
|
40
|
-
console.log(`Installing ${PROJECT} ${
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
92
|
+
console.log(`Installing ${PROJECT} ${version} for ${osPlatform}/${osArch}...`);
|
|
93
|
+
fs.mkdirSync(VENDOR_DIR, { recursive: true });
|
|
94
|
+
|
|
95
|
+
const checksumsTxt = await fetch(`${base}/checksums.txt`);
|
|
96
|
+
const expectedHash = parseChecksum(checksumsTxt, archiveName);
|
|
97
|
+
if (!expectedHash) {
|
|
98
|
+
throw new Error(`No checksum found for ${archiveName} in checksums.txt`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const tmpFile = path.join(os.tmpdir(), archiveName);
|
|
102
|
+
try {
|
|
103
|
+
await download(`${base}/${archiveName}`, tmpFile);
|
|
104
|
+
|
|
105
|
+
const actualHash = await sha256File(tmpFile);
|
|
106
|
+
if (actualHash !== expectedHash) {
|
|
107
|
+
throw new Error(`Checksum mismatch for ${archiveName}: expected ${expectedHash}, got ${actualHash}`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
await tar.extract({ file: tmpFile, cwd: VENDOR_DIR, filter: p => p === binName });
|
|
111
|
+
console.log(`Installed ${PROJECT} to ${destPath}`);
|
|
112
|
+
} finally {
|
|
113
|
+
try { fs.unlinkSync(tmpFile); } catch {}
|
|
114
|
+
}
|
|
44
115
|
}
|
|
45
116
|
|
|
46
117
|
main().catch((err) => {
|
|
47
|
-
console.error(
|
|
118
|
+
console.error(`${PROJECT} install failed: ${err.message}`);
|
|
48
119
|
process.exit(1);
|
|
49
120
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backendsystems/nibble",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Fast local network scanner with hardware identification and a terminal UI",
|
|
5
5
|
"bin": {
|
|
6
6
|
"nibble": "bin/nibble.js"
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"postinstall": "node bin/install.js"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"
|
|
12
|
+
"tar": "^7.0.0"
|
|
13
13
|
},
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|