alurkerja-cli 1.0.22 → 1.0.23
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/index.js +123 -80
- package/index.js.backup +331 -0
- package/package.json +1 -1
- package/package.json.backup +31 -0
package/index.js
CHANGED
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
*
|
|
6
6
|
* This is a bootstrapper that downloads and executes the Go binary.
|
|
7
7
|
* As per PRD: npx wrapper should NOT contain business logic.
|
|
8
|
+
*
|
|
9
|
+
* Note: Auto-update functionality has been disabled to prevent
|
|
10
|
+
* automatic version checks and downloads on every startup.
|
|
11
|
+
* Binary will only be downloaded if it doesn't exist locally.
|
|
12
|
+
*
|
|
13
|
+
* Downloads from: https://minio-admin.merapi.javan.id/javan-cli/dist/
|
|
8
14
|
*/
|
|
9
15
|
|
|
10
16
|
const fs = require('fs');
|
|
@@ -13,13 +19,11 @@ const https = require('https');
|
|
|
13
19
|
const { execSync, spawn } = require('child_process');
|
|
14
20
|
const os = require('os');
|
|
15
21
|
|
|
16
|
-
const
|
|
17
|
-
const GITLAB_TOKEN = 'javan-Lv77immsAVHiT3RnqrKa'; // GitLab private token
|
|
22
|
+
const MINIO_BASE_URL = 'https://minio-admin.merapi.javan.id/javan-cli/dist';
|
|
18
23
|
const VERSION = 'v1.0.0'; // Will be replaced during build
|
|
19
24
|
const INSTALL_DIR = path.join(os.homedir(), '.alurkerja', 'bin');
|
|
20
25
|
const BINARY_NAME = os.platform() === 'win32' ? 'alurkerja.exe' : 'alurkerja';
|
|
21
26
|
const BINARY_PATH = path.join(INSTALL_DIR, BINARY_NAME);
|
|
22
|
-
const CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
23
27
|
|
|
24
28
|
/**
|
|
25
29
|
* Detect current platform
|
|
@@ -54,15 +58,20 @@ function getVersion() {
|
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
/**
|
|
57
|
-
*
|
|
61
|
+
* Check latest version (simplified - always returns current version)
|
|
62
|
+
*/
|
|
63
|
+
async function getLatestVersion() {
|
|
64
|
+
// Since we moved to direct MinIO URLs, version checking is simplified
|
|
65
|
+
// Always return current package version
|
|
66
|
+
return VERSION;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Download binary from MinIO storage
|
|
58
71
|
*/
|
|
59
72
|
async function downloadBinary(version, platform) {
|
|
60
73
|
const binaryName = `alurkerja-${platform.os}-${platform.arch}${platform.os === 'windows' ? '.exe' : ''}`;
|
|
61
|
-
|
|
62
|
-
// Use GitLab API v4 to get raw file with PRIVATE-TOKEN authentication
|
|
63
|
-
const projectPath = encodeURIComponent('alurkerja/on-premises/toolkits/alurkerja-cli');
|
|
64
|
-
const filePath = encodeURIComponent(`dist/${binaryName}`);
|
|
65
|
-
const downloadUrl = `https://gitlab.javan.co.id/api/v4/projects/${projectPath}/repository/files/${filePath}/raw?ref=master`;
|
|
74
|
+
const downloadUrl = `${MINIO_BASE_URL}/${binaryName}`;
|
|
66
75
|
|
|
67
76
|
console.log(`📥 Downloading Alurkerja CLI ${version} for ${platform.os}-${platform.arch}...`);
|
|
68
77
|
|
|
@@ -76,59 +85,52 @@ async function downloadBinary(version, platform) {
|
|
|
76
85
|
const file = fs.createWriteStream(tempPath);
|
|
77
86
|
let downloadComplete = false;
|
|
78
87
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const redirectUrl = res.headers.location.startsWith('http')
|
|
94
|
-
? res.headers.location
|
|
95
|
-
: `https://${url.hostname}${res.headers.location}`;
|
|
96
|
-
|
|
97
|
-
return downloadFile(redirectUrl);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (res.statusCode !== 200) {
|
|
101
|
-
file.close();
|
|
102
|
-
try { fs.unlinkSync(tempPath); } catch {}
|
|
103
|
-
reject(new Error(`Download failed with status ${res.statusCode}`));
|
|
104
|
-
return;
|
|
88
|
+
const url = new URL(downloadUrl);
|
|
89
|
+
const options = {
|
|
90
|
+
hostname: url.hostname,
|
|
91
|
+
path: url.pathname,
|
|
92
|
+
method: 'GET'
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const req = https.get(options, (res) => {
|
|
96
|
+
// Handle redirects
|
|
97
|
+
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
98
|
+
const redirectUrl = res.headers.location;
|
|
99
|
+
if (redirectUrl) {
|
|
100
|
+
const newUrl = redirectUrl.startsWith('http') ? redirectUrl : `https://${url.hostname}${redirectUrl}`;
|
|
101
|
+
return downloadBinary(version, platform).then(resolve).catch(reject);
|
|
105
102
|
}
|
|
106
|
-
|
|
107
|
-
res.pipe(file);
|
|
108
|
-
res.on('end', () => {
|
|
109
|
-
downloadComplete = true;
|
|
110
|
-
});
|
|
111
|
-
});
|
|
103
|
+
}
|
|
112
104
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
});
|
|
105
|
+
if (res.statusCode !== 200) {
|
|
106
|
+
file.close();
|
|
107
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
108
|
+
reject(new Error(`Download failed with status ${res.statusCode}: ${downloadUrl}`));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
120
111
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
file.close();
|
|
125
|
-
try { fs.unlinkSync(tempPath); } catch {}
|
|
126
|
-
reject(new Error('Download timeout'));
|
|
127
|
-
}
|
|
112
|
+
res.pipe(file);
|
|
113
|
+
res.on('end', () => {
|
|
114
|
+
downloadComplete = true;
|
|
128
115
|
});
|
|
129
|
-
};
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
req.on('error', (err) => {
|
|
119
|
+
if (!downloadComplete) {
|
|
120
|
+
file.close();
|
|
121
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
122
|
+
reject(new Error(`Download failed: ${err.message}`));
|
|
123
|
+
}
|
|
124
|
+
});
|
|
130
125
|
|
|
131
|
-
|
|
126
|
+
req.setTimeout(30000, () => {
|
|
127
|
+
if (!downloadComplete) {
|
|
128
|
+
req.abort();
|
|
129
|
+
file.close();
|
|
130
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
131
|
+
reject(new Error('Download timeout'));
|
|
132
|
+
}
|
|
133
|
+
});
|
|
132
134
|
|
|
133
135
|
file.on('error', (err) => {
|
|
134
136
|
try { fs.unlinkSync(tempPath); } catch {}
|
|
@@ -147,7 +149,7 @@ async function downloadBinary(version, platform) {
|
|
|
147
149
|
const stats = fs.statSync(tempPath);
|
|
148
150
|
if (stats.size < 1000) {
|
|
149
151
|
try { fs.unlinkSync(tempPath); } catch {}
|
|
150
|
-
reject(new Error(`Download failed:
|
|
152
|
+
reject(new Error(`Download failed: invalid file size (${stats.size} bytes)`));
|
|
151
153
|
return;
|
|
152
154
|
}
|
|
153
155
|
|
|
@@ -191,29 +193,19 @@ function binaryExists() {
|
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
/**
|
|
194
|
-
* Get version of installed binary
|
|
196
|
+
* Get version of installed binary (disabled to prevent auto-updates)
|
|
195
197
|
*/
|
|
196
198
|
function getInstalledVersion() {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const match = output.match(/v?(\d+\.\d+\.\d+)/);
|
|
200
|
-
return match ? match[1] : null;
|
|
201
|
-
} catch {
|
|
202
|
-
return null;
|
|
203
|
-
}
|
|
199
|
+
// Always return current version to prevent version-based updates
|
|
200
|
+
return VERSION.replace('v', '');
|
|
204
201
|
}
|
|
205
202
|
|
|
206
203
|
/**
|
|
207
|
-
* Check if binary file is older than cache duration
|
|
204
|
+
* Check if binary file is older than cache duration (disabled to prevent auto-updates)
|
|
208
205
|
*/
|
|
209
206
|
function isBinaryStale() {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const ageMs = Date.now() - stats.mtimeMs;
|
|
213
|
-
return ageMs > CACHE_DURATION_MS;
|
|
214
|
-
} catch {
|
|
215
|
-
return true; // If can't read stats, consider it stale
|
|
216
|
-
}
|
|
207
|
+
// Always return false to prevent time-based updates
|
|
208
|
+
return false;
|
|
217
209
|
}
|
|
218
210
|
|
|
219
211
|
/**
|
|
@@ -223,6 +215,38 @@ function hasForceDownloadFlag() {
|
|
|
223
215
|
return process.argv.includes('--force-download');
|
|
224
216
|
}
|
|
225
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Check if update command is requested
|
|
220
|
+
*/
|
|
221
|
+
function isUpdateCommand() {
|
|
222
|
+
return process.argv.includes('update') && !process.argv.includes('--help');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Show update information
|
|
227
|
+
*/
|
|
228
|
+
async function showUpdateInfo() {
|
|
229
|
+
try {
|
|
230
|
+
const currentVersion = VERSION;
|
|
231
|
+
const latestVersion = await getLatestVersion();
|
|
232
|
+
const forceDownload = hasForceDownloadFlag();
|
|
233
|
+
|
|
234
|
+
console.log(`📋 Current version: ${currentVersion}`);
|
|
235
|
+
console.log(`🔄 Latest version: ${latestVersion}`);
|
|
236
|
+
|
|
237
|
+
if (currentVersion === latestVersion && !forceDownload) {
|
|
238
|
+
console.log('✅ You already have the latest version!');
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
console.log('🔄 Update available!');
|
|
243
|
+
return true;
|
|
244
|
+
} catch (error) {
|
|
245
|
+
console.log(`⚠️ Could not check latest version: ${error.message}`);
|
|
246
|
+
return hasForceDownloadFlag();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
226
250
|
/**
|
|
227
251
|
* Execute the Go binary with provided arguments
|
|
228
252
|
*/
|
|
@@ -249,18 +273,37 @@ async function bootstrap() {
|
|
|
249
273
|
try {
|
|
250
274
|
const platform = detectPlatform();
|
|
251
275
|
const version = getVersion();
|
|
252
|
-
const installedVersion = getInstalledVersion();
|
|
253
276
|
const forceDownload = hasForceDownloadFlag();
|
|
277
|
+
const isUpdate = isUpdateCommand();
|
|
278
|
+
|
|
279
|
+
// Handle update command specially
|
|
280
|
+
if (isUpdate) {
|
|
281
|
+
const shouldUpdate = await showUpdateInfo();
|
|
282
|
+
|
|
283
|
+
if (shouldUpdate || forceDownload) {
|
|
284
|
+
console.log('📥 Downloading latest version...');
|
|
285
|
+
await downloadBinary(version, platform);
|
|
286
|
+
console.log('✅ Update completed successfully!');
|
|
287
|
+
console.log('🎉 Alurkerja CLI has been updated to the latest version');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// For update command, don't continue to execute the binary
|
|
291
|
+
// Show current version and exit
|
|
292
|
+
setTimeout(() => {
|
|
293
|
+
const args = ['--version'];
|
|
294
|
+
executeBinary(args);
|
|
295
|
+
}, 100);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
254
298
|
|
|
255
|
-
//
|
|
256
|
-
const needsDownload = forceDownload ||
|
|
257
|
-
!binaryExists() ||
|
|
258
|
-
(installedVersion !== version && version !== 'dev') ||
|
|
259
|
-
isBinaryStale();
|
|
299
|
+
// Only download if binary doesn't exist or force download is requested
|
|
300
|
+
const needsDownload = forceDownload || !binaryExists();
|
|
260
301
|
|
|
261
302
|
if (needsDownload) {
|
|
262
303
|
if (forceDownload) {
|
|
263
304
|
console.log('🔄 Force download requested...');
|
|
305
|
+
} else {
|
|
306
|
+
console.log('📥 Binary not found, downloading...');
|
|
264
307
|
}
|
|
265
308
|
await downloadBinary(version, platform);
|
|
266
309
|
console.log(`✅ Alurkerja CLI ${version} ready!`);
|
package/index.js.backup
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Alurkerja CLI - npx Wrapper
|
|
5
|
+
*
|
|
6
|
+
* This is a bootstrapper that downloads and executes the Go binary.
|
|
7
|
+
* As per PRD: npx wrapper should NOT contain business logic.
|
|
8
|
+
*
|
|
9
|
+
* Note: Auto-update functionality has been disabled to prevent
|
|
10
|
+
* automatic version checks and downloads on every startup.
|
|
11
|
+
* Binary will only be downloaded if it doesn't exist locally.
|
|
12
|
+
*
|
|
13
|
+
* Downloads from: https://minio-admin.merapi.javan.id/javan-cli/dist/
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const https = require('https');
|
|
19
|
+
const { execSync, spawn } = require('child_process');
|
|
20
|
+
const os = require('os');
|
|
21
|
+
|
|
22
|
+
const MINIO_BASE_URL = 'https://minio-admin.merapi.javan.id/javan-cli/dist';
|
|
23
|
+
const VERSION = 'v1.0.0'; // Will be replaced during build
|
|
24
|
+
const INSTALL_DIR = path.join(os.homedir(), '.alurkerja', 'bin');
|
|
25
|
+
const BINARY_NAME = os.platform() === 'win32' ? 'alurkerja.exe' : 'alurkerja';
|
|
26
|
+
const BINARY_PATH = path.join(INSTALL_DIR, BINARY_NAME);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Detect current platform
|
|
30
|
+
*/
|
|
31
|
+
function detectPlatform() {
|
|
32
|
+
const platform = os.platform();
|
|
33
|
+
const arch = os.arch();
|
|
34
|
+
|
|
35
|
+
let osName;
|
|
36
|
+
switch (platform) {
|
|
37
|
+
case 'linux': osName = 'linux'; break;
|
|
38
|
+
case 'darwin': osName = 'darwin'; break;
|
|
39
|
+
case 'win32': osName = 'windows'; break;
|
|
40
|
+
default: throw new Error(`Unsupported platform: ${platform}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let archName;
|
|
44
|
+
switch (arch) {
|
|
45
|
+
case 'x64': archName = 'amd64'; break;
|
|
46
|
+
case 'arm64': archName = 'arm64'; break;
|
|
47
|
+
default: throw new Error(`Unsupported architecture: ${arch}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return { os: osName, arch: archName };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get the version to download
|
|
55
|
+
*/
|
|
56
|
+
function getVersion() {
|
|
57
|
+
return VERSION;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Check latest version (simplified - always returns current version)
|
|
62
|
+
*/
|
|
63
|
+
async function getLatestVersion() {
|
|
64
|
+
// Since we moved to direct MinIO URLs, version checking is simplified
|
|
65
|
+
// Always return current package version
|
|
66
|
+
return VERSION;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Download binary from MinIO storage
|
|
71
|
+
*/
|
|
72
|
+
async function downloadBinary(version, platform) {
|
|
73
|
+
const binaryName = `alurkerja-${platform.os}-${platform.arch}${platform.os === 'windows' ? '.exe' : ''}`;
|
|
74
|
+
const downloadUrl = `${MINIO_BASE_URL}/${binaryName}`;
|
|
75
|
+
|
|
76
|
+
console.log(`📥 Downloading Alurkerja CLI ${version} for ${platform.os}-${platform.arch}...`);
|
|
77
|
+
|
|
78
|
+
// Ensure install directory exists
|
|
79
|
+
fs.mkdirSync(INSTALL_DIR, { recursive: true });
|
|
80
|
+
|
|
81
|
+
// Use temporary file to avoid ETXTBSY error
|
|
82
|
+
const tempPath = `${BINARY_PATH}.tmp`;
|
|
83
|
+
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
const file = fs.createWriteStream(tempPath);
|
|
86
|
+
let downloadComplete = false;
|
|
87
|
+
|
|
88
|
+
const url = new URL(downloadUrl);
|
|
89
|
+
const options = {
|
|
90
|
+
hostname: url.hostname,
|
|
91
|
+
path: url.pathname,
|
|
92
|
+
method: 'GET'
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const req = https.get(options, (res) => {
|
|
96
|
+
// Handle redirects
|
|
97
|
+
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
98
|
+
const redirectUrl = res.headers.location;
|
|
99
|
+
if (redirectUrl) {
|
|
100
|
+
const newUrl = redirectUrl.startsWith('http') ? redirectUrl : `https://${url.hostname}${redirectUrl}`;
|
|
101
|
+
return downloadBinary(version, platform).then(resolve).catch(reject);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (res.statusCode !== 200) {
|
|
106
|
+
file.close();
|
|
107
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
108
|
+
reject(new Error(`Download failed with status ${res.statusCode}: ${downloadUrl}`));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
res.pipe(file);
|
|
113
|
+
res.on('end', () => {
|
|
114
|
+
downloadComplete = true;
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
req.on('error', (err) => {
|
|
119
|
+
if (!downloadComplete) {
|
|
120
|
+
file.close();
|
|
121
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
122
|
+
reject(new Error(`Download failed: ${err.message}`));
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
req.setTimeout(30000, () => {
|
|
127
|
+
if (!downloadComplete) {
|
|
128
|
+
req.abort();
|
|
129
|
+
file.close();
|
|
130
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
131
|
+
reject(new Error('Download timeout'));
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
file.on('error', (err) => {
|
|
136
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
137
|
+
reject(err);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
file.on('finish', () => {
|
|
141
|
+
file.close((err) => {
|
|
142
|
+
if (err) {
|
|
143
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
144
|
+
reject(err);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Validate the downloaded file
|
|
149
|
+
const stats = fs.statSync(tempPath);
|
|
150
|
+
if (stats.size < 1000) {
|
|
151
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
152
|
+
reject(new Error(`Download failed: invalid file size (${stats.size} bytes)`));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Make executable on Unix systems
|
|
157
|
+
if (platform.os !== 'windows') {
|
|
158
|
+
try {
|
|
159
|
+
fs.chmodSync(tempPath, '755');
|
|
160
|
+
} catch (err) {
|
|
161
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
162
|
+
reject(new Error(`Failed to make binary executable: ${err.message}`));
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Rename temp file to final path
|
|
168
|
+
try {
|
|
169
|
+
if (fs.existsSync(BINARY_PATH)) {
|
|
170
|
+
fs.unlinkSync(BINARY_PATH);
|
|
171
|
+
}
|
|
172
|
+
fs.renameSync(tempPath, BINARY_PATH);
|
|
173
|
+
resolve();
|
|
174
|
+
} catch (err) {
|
|
175
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
176
|
+
reject(new Error(`Failed to install binary: ${err.message}`));
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Check if binary exists and is executable
|
|
185
|
+
*/
|
|
186
|
+
function binaryExists() {
|
|
187
|
+
try {
|
|
188
|
+
fs.accessSync(BINARY_PATH, fs.constants.F_OK | fs.constants.X_OK);
|
|
189
|
+
return true;
|
|
190
|
+
} catch {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Get version of installed binary (disabled to prevent auto-updates)
|
|
197
|
+
*/
|
|
198
|
+
function getInstalledVersion() {
|
|
199
|
+
// Always return current version to prevent version-based updates
|
|
200
|
+
return VERSION.replace('v', '');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Check if binary file is older than cache duration (disabled to prevent auto-updates)
|
|
205
|
+
*/
|
|
206
|
+
function isBinaryStale() {
|
|
207
|
+
// Always return false to prevent time-based updates
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Check if force download flag is present
|
|
213
|
+
*/
|
|
214
|
+
function hasForceDownloadFlag() {
|
|
215
|
+
return process.argv.includes('--force-download');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Check if update command is requested
|
|
220
|
+
*/
|
|
221
|
+
function isUpdateCommand() {
|
|
222
|
+
return process.argv.includes('update') && !process.argv.includes('--help');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Show update information
|
|
227
|
+
*/
|
|
228
|
+
async function showUpdateInfo() {
|
|
229
|
+
try {
|
|
230
|
+
const currentVersion = VERSION;
|
|
231
|
+
const latestVersion = await getLatestVersion();
|
|
232
|
+
const forceDownload = hasForceDownloadFlag();
|
|
233
|
+
|
|
234
|
+
console.log(`📋 Current version: ${currentVersion}`);
|
|
235
|
+
console.log(`🔄 Latest version: ${latestVersion}`);
|
|
236
|
+
|
|
237
|
+
if (currentVersion === latestVersion && !forceDownload) {
|
|
238
|
+
console.log('✅ You already have the latest version!');
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
console.log('🔄 Update available!');
|
|
243
|
+
return true;
|
|
244
|
+
} catch (error) {
|
|
245
|
+
console.log(`⚠️ Could not check latest version: ${error.message}`);
|
|
246
|
+
return hasForceDownloadFlag();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Execute the Go binary with provided arguments
|
|
252
|
+
*/
|
|
253
|
+
function executeBinary(args) {
|
|
254
|
+
const child = spawn(BINARY_PATH, args, {
|
|
255
|
+
stdio: 'inherit',
|
|
256
|
+
shell: false
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
child.on('error', (err) => {
|
|
260
|
+
console.error(`❌ Failed to execute binary: ${err.message}`);
|
|
261
|
+
process.exit(1);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
child.on('exit', (code) => {
|
|
265
|
+
process.exit(code || 0);
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Main bootstrap logic
|
|
271
|
+
*/
|
|
272
|
+
async function bootstrap() {
|
|
273
|
+
try {
|
|
274
|
+
const platform = detectPlatform();
|
|
275
|
+
const version = getVersion();
|
|
276
|
+
const forceDownload = hasForceDownloadFlag();
|
|
277
|
+
const isUpdate = isUpdateCommand();
|
|
278
|
+
|
|
279
|
+
// Handle update command specially
|
|
280
|
+
if (isUpdate) {
|
|
281
|
+
const shouldUpdate = await showUpdateInfo();
|
|
282
|
+
|
|
283
|
+
if (shouldUpdate || forceDownload) {
|
|
284
|
+
console.log('📥 Downloading latest version...');
|
|
285
|
+
await downloadBinary(version, platform);
|
|
286
|
+
console.log('✅ Update completed successfully!');
|
|
287
|
+
console.log('🎉 Alurkerja CLI has been updated to the latest version');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// For update command, don't continue to execute the binary
|
|
291
|
+
// Show current version and exit
|
|
292
|
+
setTimeout(() => {
|
|
293
|
+
const args = ['--version'];
|
|
294
|
+
executeBinary(args);
|
|
295
|
+
}, 100);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Only download if binary doesn't exist or force download is requested
|
|
300
|
+
const needsDownload = forceDownload || !binaryExists();
|
|
301
|
+
|
|
302
|
+
if (needsDownload) {
|
|
303
|
+
if (forceDownload) {
|
|
304
|
+
console.log('🔄 Force download requested...');
|
|
305
|
+
} else {
|
|
306
|
+
console.log('📥 Binary not found, downloading...');
|
|
307
|
+
}
|
|
308
|
+
await downloadBinary(version, platform);
|
|
309
|
+
console.log(`✅ Alurkerja CLI ${version} ready!`);
|
|
310
|
+
// Small delay to ensure file system sync after download
|
|
311
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Execute the binary with all arguments passed to this script
|
|
315
|
+
// Filter out --force-download flag before passing to binary
|
|
316
|
+
const args = process.argv.slice(2).filter(arg => arg !== '--force-download');
|
|
317
|
+
executeBinary(args);
|
|
318
|
+
|
|
319
|
+
} catch (error) {
|
|
320
|
+
console.error(`❌ Bootstrap failed: ${error.message}`);
|
|
321
|
+
console.log('💡 Try installing directly: curl -fsSL https://alurkerja.com/install.sh | bash');
|
|
322
|
+
process.exit(1);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Handle termination signals
|
|
327
|
+
process.on('SIGINT', () => process.exit(0));
|
|
328
|
+
process.on('SIGTERM', () => process.exit(0));
|
|
329
|
+
|
|
330
|
+
// Start bootstrap
|
|
331
|
+
bootstrap();
|
package/package.json
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "alurkerja-cli",
|
|
3
|
+
"version": "1.0.22",
|
|
4
|
+
"description": "Alurkerja CLI - npx wrapper for Go binary",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"private": false,
|
|
7
|
+
"bin": {
|
|
8
|
+
"alurkerja": "./index.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"alurkerja",
|
|
12
|
+
"cli",
|
|
13
|
+
"addon",
|
|
14
|
+
"ci",
|
|
15
|
+
"cd"
|
|
16
|
+
],
|
|
17
|
+
"author": "Alurkerja Team",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=14.0.0"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/alurkerja/alurkerja-cli"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://alurkerja.com",
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {}
|
|
31
|
+
}
|