alurkerja-cli 1.0.21 → 1.0.22

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 CHANGED
@@ -14,7 +14,7 @@ const { execSync, spawn } = require('child_process');
14
14
  const os = require('os');
15
15
 
16
16
  const GITLAB_BASE = 'https://gitlab.javan.co.id/alurkerja/on-premises/toolkits/alurkerja-cli';
17
- const GITLAB_TOKEN = 'javan-_P_JrtswtvrZekJDk1Lt'; // GitLab private token
17
+ const GITLAB_TOKEN = 'javan-Lv77immsAVHiT3RnqrKa'; // GitLab private token
18
18
  const VERSION = 'v1.0.0'; // Will be replaced during build
19
19
  const INSTALL_DIR = path.join(os.homedir(), '.alurkerja', 'bin');
20
20
  const BINARY_NAME = os.platform() === 'win32' ? 'alurkerja.exe' : 'alurkerja';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alurkerja-cli",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
4
4
  "description": "Alurkerja CLI - npx wrapper for Go binary",
5
5
  "main": "index.js",
6
6
  "private": false,
package/index.js.backup DELETED
@@ -1,288 +0,0 @@
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
-
10
- const fs = require('fs');
11
- const path = require('path');
12
- const https = require('https');
13
- const { execSync, spawn } = require('child_process');
14
- const os = require('os');
15
-
16
- const GITLAB_BASE = 'https://gitlab.javan.co.id/alurkerja/on-premises/toolkits/alurkerja-cli';
17
- const GITLAB_TOKEN = 'javan-_P_JrtswtvrZekJDk1Lt'; // GitLab private token
18
- const VERSION = 'v1.0.0'; // Will be replaced during build
19
- const INSTALL_DIR = path.join(os.homedir(), '.alurkerja', 'bin');
20
- const BINARY_NAME = os.platform() === 'win32' ? 'alurkerja.exe' : 'alurkerja';
21
- const BINARY_PATH = path.join(INSTALL_DIR, BINARY_NAME);
22
- const CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // 24 hours
23
-
24
- /**
25
- * Detect current platform
26
- */
27
- function detectPlatform() {
28
- const platform = os.platform();
29
- const arch = os.arch();
30
-
31
- let osName;
32
- switch (platform) {
33
- case 'linux': osName = 'linux'; break;
34
- case 'darwin': osName = 'darwin'; break;
35
- case 'win32': osName = 'windows'; break;
36
- default: throw new Error(`Unsupported platform: ${platform}`);
37
- }
38
-
39
- let archName;
40
- switch (arch) {
41
- case 'x64': archName = 'amd64'; break;
42
- case 'arm64': archName = 'arm64'; break;
43
- default: throw new Error(`Unsupported architecture: ${arch}`);
44
- }
45
-
46
- return { os: osName, arch: archName };
47
- }
48
-
49
- /**
50
- * Get the version to download
51
- */
52
- function getVersion() {
53
- return VERSION;
54
- }
55
-
56
- /**
57
- * Download binary from GitLab releases
58
- */
59
- async function downloadBinary(version, platform) {
60
- 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`;
66
-
67
- console.log(`📥 Downloading Alurkerja CLI ${version} for ${platform.os}-${platform.arch}...`);
68
-
69
- // Ensure install directory exists
70
- fs.mkdirSync(INSTALL_DIR, { recursive: true });
71
-
72
- // Use temporary file to avoid ETXTBSY error
73
- const tempPath = `${BINARY_PATH}.tmp`;
74
-
75
- return new Promise((resolve, reject) => {
76
- const file = fs.createWriteStream(tempPath);
77
- let downloadComplete = false;
78
-
79
- const downloadFile = (targetUrl) => {
80
- const url = new URL(targetUrl);
81
- const options = {
82
- hostname: url.hostname,
83
- path: url.pathname + url.search,
84
- headers: {
85
- 'PRIVATE-TOKEN': GITLAB_TOKEN
86
- },
87
- followRedirect: true
88
- };
89
-
90
- const req = https.get(options, (res) => {
91
- if (res.statusCode === 302 || res.statusCode === 301) {
92
- // Follow redirect with PRIVATE-TOKEN header
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;
105
- }
106
-
107
- res.pipe(file);
108
- res.on('end', () => {
109
- downloadComplete = true;
110
- });
111
- });
112
-
113
- req.on('error', (err) => {
114
- if (!downloadComplete) {
115
- file.close();
116
- try { fs.unlinkSync(tempPath); } catch {}
117
- reject(err);
118
- }
119
- });
120
-
121
- req.setTimeout(30000, () => {
122
- if (!downloadComplete) {
123
- req.abort();
124
- file.close();
125
- try { fs.unlinkSync(tempPath); } catch {}
126
- reject(new Error('Download timeout'));
127
- }
128
- });
129
- };
130
-
131
- downloadFile(downloadUrl);
132
-
133
- file.on('error', (err) => {
134
- try { fs.unlinkSync(tempPath); } catch {}
135
- reject(err);
136
- });
137
-
138
- file.on('finish', () => {
139
- file.close((err) => {
140
- if (err) {
141
- try { fs.unlinkSync(tempPath); } catch {}
142
- reject(err);
143
- return;
144
- }
145
-
146
- // Validate the downloaded file
147
- const stats = fs.statSync(tempPath);
148
- if (stats.size < 1000) {
149
- try { fs.unlinkSync(tempPath); } catch {}
150
- reject(new Error(`Download failed: received invalid file (${stats.size} bytes)`));
151
- return;
152
- }
153
-
154
- // Make executable on Unix systems
155
- if (platform.os !== 'windows') {
156
- try {
157
- fs.chmodSync(tempPath, '755');
158
- } catch (err) {
159
- try { fs.unlinkSync(tempPath); } catch {}
160
- reject(new Error(`Failed to make binary executable: ${err.message}`));
161
- return;
162
- }
163
- }
164
-
165
- // Rename temp file to final path
166
- try {
167
- if (fs.existsSync(BINARY_PATH)) {
168
- fs.unlinkSync(BINARY_PATH);
169
- }
170
- fs.renameSync(tempPath, BINARY_PATH);
171
- resolve();
172
- } catch (err) {
173
- try { fs.unlinkSync(tempPath); } catch {}
174
- reject(new Error(`Failed to install binary: ${err.message}`));
175
- }
176
- });
177
- });
178
- });
179
- }
180
-
181
- /**
182
- * Check if binary exists and is executable
183
- */
184
- function binaryExists() {
185
- try {
186
- fs.accessSync(BINARY_PATH, fs.constants.F_OK | fs.constants.X_OK);
187
- return true;
188
- } catch {
189
- return false;
190
- }
191
- }
192
-
193
- /**
194
- * Get version of installed binary
195
- */
196
- function getInstalledVersion() {
197
- try {
198
- const output = execSync(`"${BINARY_PATH}" --version`, { encoding: 'utf8', timeout: 5000 });
199
- const match = output.match(/v?(\d+\.\d+\.\d+)/);
200
- return match ? match[1] : null;
201
- } catch {
202
- return null;
203
- }
204
- }
205
-
206
- /**
207
- * Check if binary file is older than cache duration
208
- */
209
- function isBinaryStale() {
210
- try {
211
- const stats = fs.statSync(BINARY_PATH);
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
- }
217
- }
218
-
219
- /**
220
- * Check if force download flag is present
221
- */
222
- function hasForceDownloadFlag() {
223
- return process.argv.includes('--force-download');
224
- }
225
-
226
- /**
227
- * Execute the Go binary with provided arguments
228
- */
229
- function executeBinary(args) {
230
- const child = spawn(BINARY_PATH, args, {
231
- stdio: 'inherit',
232
- shell: false
233
- });
234
-
235
- child.on('error', (err) => {
236
- console.error(`❌ Failed to execute binary: ${err.message}`);
237
- process.exit(1);
238
- });
239
-
240
- child.on('exit', (code) => {
241
- process.exit(code || 0);
242
- });
243
- }
244
-
245
- /**
246
- * Main bootstrap logic
247
- */
248
- async function bootstrap() {
249
- try {
250
- const platform = detectPlatform();
251
- const version = getVersion();
252
- const installedVersion = getInstalledVersion();
253
- const forceDownload = hasForceDownloadFlag();
254
-
255
- // Check if we need to download the binary
256
- const needsDownload = forceDownload ||
257
- !binaryExists() ||
258
- (installedVersion !== version && version !== 'dev') ||
259
- isBinaryStale();
260
-
261
- if (needsDownload) {
262
- if (forceDownload) {
263
- console.log('🔄 Force download requested...');
264
- }
265
- await downloadBinary(version, platform);
266
- console.log(`✅ Alurkerja CLI ${version} ready!`);
267
- // Small delay to ensure file system sync after download
268
- await new Promise(resolve => setTimeout(resolve, 100));
269
- }
270
-
271
- // Execute the binary with all arguments passed to this script
272
- // Filter out --force-download flag before passing to binary
273
- const args = process.argv.slice(2).filter(arg => arg !== '--force-download');
274
- executeBinary(args);
275
-
276
- } catch (error) {
277
- console.error(`❌ Bootstrap failed: ${error.message}`);
278
- console.log('💡 Try installing directly: curl -fsSL https://alurkerja.com/install.sh | bash');
279
- process.exit(1);
280
- }
281
- }
282
-
283
- // Handle termination signals
284
- process.on('SIGINT', () => process.exit(0));
285
- process.on('SIGTERM', () => process.exit(0));
286
-
287
- // Start bootstrap
288
- bootstrap();
@@ -1,31 +0,0 @@
1
- {
2
- "name": "alurkerja-cli",
3
- "version": "1.0.20",
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
- }