dataset-cli 1.0.4 → 1.0.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 +1 -1
- package/scripts/install.js +109 -27
package/package.json
CHANGED
package/scripts/install.js
CHANGED
|
@@ -3,15 +3,15 @@ const fs = require('fs');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const https = require('https');
|
|
6
|
+
const crypto = require('crypto');
|
|
6
7
|
|
|
7
|
-
// 1. Fixed Map to match your release.yml naming exactly
|
|
8
8
|
const platformMap = {
|
|
9
9
|
'darwin-x64': 'darwin-amd64',
|
|
10
10
|
'darwin-arm64': 'darwin-arm64',
|
|
11
11
|
'linux-x64': 'linux-amd64',
|
|
12
12
|
'linux-arm64': 'linux-arm64',
|
|
13
13
|
'win32-x64': 'windows-amd64.exe',
|
|
14
|
-
'win32-arm64': 'windows-arm64.exe'
|
|
14
|
+
'win32-arm64': 'windows-arm64.exe'
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const platform = `${os.platform()}-${os.arch()}`;
|
|
@@ -19,6 +19,7 @@ const suffix = platformMap[platform];
|
|
|
19
19
|
|
|
20
20
|
if (!suffix) {
|
|
21
21
|
console.error(`❌ Unsupported platform: ${platform}`);
|
|
22
|
+
console.error('Supported platforms: darwin-x64, darwin-arm64, linux-x64, linux-arm64, win32-x64, win32-arm64');
|
|
22
23
|
process.exit(1);
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -26,47 +27,128 @@ const installDir = path.join(__dirname, '..', 'bin');
|
|
|
26
27
|
const fullBinaryName = `dataset-cli-${suffix}`;
|
|
27
28
|
const destPath = path.join(installDir, os.platform() === 'win32' ? 'dataset-cli.exe' : 'dataset-cli');
|
|
28
29
|
|
|
29
|
-
// 2. Clear previous failed attempts
|
|
30
30
|
if (!fs.existsSync(installDir)) {
|
|
31
31
|
fs.mkdirSync(installDir, { recursive: true });
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
// 3. Get version from package.json
|
|
35
34
|
const packageJson = require(path.join(__dirname, '..', 'package.json'));
|
|
36
35
|
const version = packageJson.version;
|
|
37
36
|
const repo = 'darshan192004/cli-project';
|
|
38
37
|
const downloadUrl = `https://github.com/${repo}/releases/download/v${version}/${fullBinaryName}`;
|
|
38
|
+
const checksumUrl = `https://github.com/${repo}/releases/download/v${version}/${fullBinaryName}.sha256`;
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
const MAX_RETRIES = 3;
|
|
41
|
+
const RETRY_DELAY = 1000;
|
|
41
42
|
|
|
42
|
-
function
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
46
|
-
return download(res.headers.location);
|
|
47
|
-
}
|
|
43
|
+
function delay(ms) {
|
|
44
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
45
|
+
}
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
async function downloadFile(url, isChecksum = false) {
|
|
48
|
+
let lastError;
|
|
49
|
+
|
|
50
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
51
|
+
try {
|
|
52
|
+
const result = await new Promise((resolve, reject) => {
|
|
53
|
+
https.get(url, (res) => {
|
|
54
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
55
|
+
return resolve(downloadFile(res.headers.location, isChecksum));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (res.statusCode !== 200) {
|
|
59
|
+
reject(new Error(`HTTP ${res.statusCode}`));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const chunks = [];
|
|
64
|
+
res.on('data', chunk => chunks.push(chunk));
|
|
65
|
+
res.on('end', () => {
|
|
66
|
+
const data = Buffer.concat(chunks);
|
|
67
|
+
if (isChecksum) {
|
|
68
|
+
resolve(data.toString('utf8').trim());
|
|
69
|
+
} else {
|
|
70
|
+
resolve(data);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
res.on('error', reject);
|
|
74
|
+
}).on('error', reject);
|
|
75
|
+
});
|
|
76
|
+
return result;
|
|
77
|
+
} catch (err) {
|
|
78
|
+
lastError = err;
|
|
79
|
+
if (attempt < MAX_RETRIES) {
|
|
80
|
+
const waitTime = RETRY_DELAY * attempt;
|
|
81
|
+
console.log(`⚠️ Attempt ${attempt} failed, retrying in ${waitTime}ms...`);
|
|
82
|
+
await delay(waitTime);
|
|
83
|
+
}
|
|
53
84
|
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
throw lastError;
|
|
88
|
+
}
|
|
54
89
|
|
|
55
|
-
|
|
56
|
-
|
|
90
|
+
function verifyChecksum(filePath, expectedChecksum) {
|
|
91
|
+
const fileBuffer = fs.readFileSync(filePath);
|
|
92
|
+
const hash = crypto.createHash('sha256').update(fileBuffer).digest('hex');
|
|
93
|
+
|
|
94
|
+
const parts = expectedChecksum.split(/\s+/);
|
|
95
|
+
const checksumParts = parts[0];
|
|
96
|
+
|
|
97
|
+
if (hash !== checksumParts) {
|
|
98
|
+
console.error('❌ Checksum verification failed!');
|
|
99
|
+
console.error(`Expected: ${checksumParts}`);
|
|
100
|
+
console.error(`Got: ${hash}`);
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
57
105
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
106
|
+
async function install() {
|
|
107
|
+
console.log(`☁️ Downloading dataset-cli v${version} for ${platform}...`);
|
|
108
|
+
|
|
109
|
+
let checksum;
|
|
110
|
+
try {
|
|
111
|
+
checksum = await downloadFile(checksumUrl, true);
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.warn(`⚠️ Warning: Could not download checksum file: ${err.message}`);
|
|
114
|
+
console.warn('Proceeding without checksum verification...');
|
|
115
|
+
checksum = null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const binaryData = await downloadFile(downloadUrl);
|
|
120
|
+
|
|
121
|
+
fs.writeFileSync(destPath, binaryData);
|
|
122
|
+
|
|
123
|
+
if (checksum && !verifyChecksum(destPath, checksum)) {
|
|
124
|
+
fs.unlinkSync(destPath);
|
|
125
|
+
console.error('❌ Installation failed: checksum mismatch');
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (os.platform() !== 'win32') {
|
|
130
|
+
try {
|
|
62
131
|
fs.chmodSync(destPath, 0o755);
|
|
132
|
+
} catch (chmodErr) {
|
|
133
|
+
console.warn(`⚠️ Warning: Could not set executable permissions: ${chmodErr.message}`);
|
|
63
134
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const stat = fs.statSync(destPath);
|
|
138
|
+
if (stat.size === 0) {
|
|
139
|
+
fs.unlinkSync(destPath);
|
|
140
|
+
console.error('❌ Installation failed: downloaded file is empty');
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.log(`✅ Success! Installed to ${destPath}`);
|
|
145
|
+
console.log(` Size: ${(stat.size / 1024 / 1024).toFixed(2)} MB`);
|
|
146
|
+
|
|
147
|
+
} catch (err) {
|
|
148
|
+
console.error(`❌ Download failed: ${err.message}`);
|
|
149
|
+
console.error(`URL attempted: ${downloadUrl}`);
|
|
68
150
|
process.exit(1);
|
|
69
|
-
}
|
|
151
|
+
}
|
|
70
152
|
}
|
|
71
153
|
|
|
72
|
-
|
|
154
|
+
install();
|