alurkerja-cli 1.0.2 → 1.0.4

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
@@ -56,7 +56,8 @@ function getVersion() {
56
56
  */
57
57
  async function downloadBinary(version, platform) {
58
58
  const binaryName = `alurkerja-${platform.os}-${platform.arch}${platform.os === 'windows' ? '.exe' : ''}`;
59
- const downloadUrl = `${GITLAB_BASE}/-/raw/master/dist/${binaryName}`;
59
+ // Use GitLab raw file download with correct parameters
60
+ const downloadUrl = `${GITLAB_BASE}/-/raw/master/dist/${binaryName}?ref_type=heads&inline=false`;
60
61
 
61
62
  console.log(`📥 Downloading Alurkerja CLI ${version}...`);
62
63
 
@@ -68,54 +69,59 @@ async function downloadBinary(version, platform) {
68
69
 
69
70
  return new Promise((resolve, reject) => {
70
71
  const file = fs.createWriteStream(tempPath);
72
+ let downloadComplete = false;
71
73
 
72
- const url = new URL(downloadUrl);
73
- const options = {
74
- hostname: url.hostname,
75
- path: url.pathname + url.search,
76
- headers: {
77
- 'PRIVATE-TOKEN': GITLAB_TOKEN
78
- }
79
- };
80
-
81
- const req = https.get(options, (res) => {
82
- if (res.statusCode === 302 || res.statusCode === 301) {
83
- // Follow redirect with token
84
- const redirectUrl = new URL(res.headers.location);
85
- const redirectOptions = {
86
- hostname: redirectUrl.hostname,
87
- path: redirectUrl.pathname + redirectUrl.search,
88
- headers: {
89
- 'PRIVATE-TOKEN': GITLAB_TOKEN
90
- }
91
- };
92
- return https.get(redirectOptions, (redirectRes) => {
93
- redirectRes.pipe(file);
74
+ const downloadFile = (targetUrl) => {
75
+ const url = new URL(targetUrl);
76
+ const options = {
77
+ hostname: url.hostname,
78
+ path: url.pathname + url.search,
79
+ headers: {
80
+ 'PRIVATE-TOKEN': GITLAB_TOKEN
81
+ }
82
+ };
83
+
84
+ const req = https.get(options, (res) => {
85
+ if (res.statusCode === 302 || res.statusCode === 301) {
86
+ // Follow redirect
87
+ const redirectUrl = res.headers.location.startsWith('http')
88
+ ? res.headers.location
89
+ : `https://${url.hostname}${res.headers.location}`;
90
+ return downloadFile(redirectUrl);
91
+ }
92
+
93
+ if (res.statusCode !== 200) {
94
+ file.close();
95
+ try { fs.unlinkSync(tempPath); } catch {}
96
+ reject(new Error(`Download failed with status ${res.statusCode}`));
97
+ return;
98
+ }
99
+
100
+ res.pipe(file);
101
+ res.on('end', () => {
102
+ downloadComplete = true;
94
103
  });
95
- }
104
+ });
96
105
 
97
- if (res.statusCode !== 200) {
98
- file.close();
99
- fs.unlinkSync(tempPath);
100
- reject(new Error(`Download failed with status ${res.statusCode}`));
101
- return;
102
- }
106
+ req.on('error', (err) => {
107
+ if (!downloadComplete) {
108
+ file.close();
109
+ try { fs.unlinkSync(tempPath); } catch {}
110
+ reject(err);
111
+ }
112
+ });
103
113
 
104
- res.pipe(file);
105
- });
106
-
107
- req.on('error', (err) => {
108
- file.close();
109
- try { fs.unlinkSync(tempPath); } catch {}
110
- reject(err);
111
- });
114
+ req.setTimeout(30000, () => {
115
+ if (!downloadComplete) {
116
+ req.abort();
117
+ file.close();
118
+ try { fs.unlinkSync(tempPath); } catch {}
119
+ reject(new Error('Download timeout'));
120
+ }
121
+ });
122
+ };
112
123
 
113
- req.setTimeout(30000, () => {
114
- req.abort();
115
- file.close();
116
- try { fs.unlinkSync(tempPath); } catch {}
117
- reject(new Error('Download timeout'));
118
- });
124
+ downloadFile(downloadUrl);
119
125
 
120
126
  file.on('error', (err) => {
121
127
  try { fs.unlinkSync(tempPath); } catch {}
@@ -130,7 +136,15 @@ async function downloadBinary(version, platform) {
130
136
  return;
131
137
  }
132
138
 
133
- // Make executable on Unix systems before renaming
139
+ // Validate the downloaded file
140
+ const stats = fs.statSync(tempPath);
141
+ if (stats.size < 1000) {
142
+ try { fs.unlinkSync(tempPath); } catch {}
143
+ reject(new Error(`Download failed: received invalid file (${stats.size} bytes)`));
144
+ return;
145
+ }
146
+
147
+ // Make executable on Unix systems
134
148
  if (platform.os !== 'windows') {
135
149
  try {
136
150
  fs.chmodSync(tempPath, '755');
@@ -143,7 +157,6 @@ async function downloadBinary(version, platform) {
143
157
 
144
158
  // Rename temp file to final path
145
159
  try {
146
- // Remove old binary if exists
147
160
  if (fs.existsSync(BINARY_PATH)) {
148
161
  fs.unlinkSync(BINARY_PATH);
149
162
  }
@@ -218,6 +231,8 @@ async function bootstrap() {
218
231
  if (needsDownload) {
219
232
  await downloadBinary(version, platform);
220
233
  console.log(`✅ Alurkerja CLI ${version} ready!`);
234
+ // Small delay to ensure file system sync after download
235
+ await new Promise(resolve => setTimeout(resolve, 100));
221
236
  }
222
237
 
223
238
  // Execute the binary with all arguments passed to this script
package/index.js.backup CHANGED
@@ -56,7 +56,8 @@ function getVersion() {
56
56
  */
57
57
  async function downloadBinary(version, platform) {
58
58
  const binaryName = `alurkerja-${platform.os}-${platform.arch}${platform.os === 'windows' ? '.exe' : ''}`;
59
- const downloadUrl = `${GITLAB_BASE}/-/raw/master/dist/${binaryName}`;
59
+ // Use GitLab raw file download with correct parameters
60
+ const downloadUrl = `${GITLAB_BASE}/-/raw/master/dist/${binaryName}?ref_type=heads&inline=false`;
60
61
 
61
62
  console.log(`📥 Downloading Alurkerja CLI ${version}...`);
62
63
 
@@ -68,54 +69,59 @@ async function downloadBinary(version, platform) {
68
69
 
69
70
  return new Promise((resolve, reject) => {
70
71
  const file = fs.createWriteStream(tempPath);
72
+ let downloadComplete = false;
71
73
 
72
- const url = new URL(downloadUrl);
73
- const options = {
74
- hostname: url.hostname,
75
- path: url.pathname + url.search,
76
- headers: {
77
- 'PRIVATE-TOKEN': GITLAB_TOKEN
78
- }
79
- };
80
-
81
- const req = https.get(options, (res) => {
82
- if (res.statusCode === 302 || res.statusCode === 301) {
83
- // Follow redirect with token
84
- const redirectUrl = new URL(res.headers.location);
85
- const redirectOptions = {
86
- hostname: redirectUrl.hostname,
87
- path: redirectUrl.pathname + redirectUrl.search,
88
- headers: {
89
- 'PRIVATE-TOKEN': GITLAB_TOKEN
90
- }
91
- };
92
- return https.get(redirectOptions, (redirectRes) => {
93
- redirectRes.pipe(file);
74
+ const downloadFile = (targetUrl) => {
75
+ const url = new URL(targetUrl);
76
+ const options = {
77
+ hostname: url.hostname,
78
+ path: url.pathname + url.search,
79
+ headers: {
80
+ 'PRIVATE-TOKEN': GITLAB_TOKEN
81
+ }
82
+ };
83
+
84
+ const req = https.get(options, (res) => {
85
+ if (res.statusCode === 302 || res.statusCode === 301) {
86
+ // Follow redirect
87
+ const redirectUrl = res.headers.location.startsWith('http')
88
+ ? res.headers.location
89
+ : `https://${url.hostname}${res.headers.location}`;
90
+ return downloadFile(redirectUrl);
91
+ }
92
+
93
+ if (res.statusCode !== 200) {
94
+ file.close();
95
+ try { fs.unlinkSync(tempPath); } catch {}
96
+ reject(new Error(`Download failed with status ${res.statusCode}`));
97
+ return;
98
+ }
99
+
100
+ res.pipe(file);
101
+ res.on('end', () => {
102
+ downloadComplete = true;
94
103
  });
95
- }
104
+ });
96
105
 
97
- if (res.statusCode !== 200) {
98
- file.close();
99
- fs.unlinkSync(tempPath);
100
- reject(new Error(`Download failed with status ${res.statusCode}`));
101
- return;
102
- }
106
+ req.on('error', (err) => {
107
+ if (!downloadComplete) {
108
+ file.close();
109
+ try { fs.unlinkSync(tempPath); } catch {}
110
+ reject(err);
111
+ }
112
+ });
103
113
 
104
- res.pipe(file);
105
- });
106
-
107
- req.on('error', (err) => {
108
- file.close();
109
- try { fs.unlinkSync(tempPath); } catch {}
110
- reject(err);
111
- });
114
+ req.setTimeout(30000, () => {
115
+ if (!downloadComplete) {
116
+ req.abort();
117
+ file.close();
118
+ try { fs.unlinkSync(tempPath); } catch {}
119
+ reject(new Error('Download timeout'));
120
+ }
121
+ });
122
+ };
112
123
 
113
- req.setTimeout(30000, () => {
114
- req.abort();
115
- file.close();
116
- try { fs.unlinkSync(tempPath); } catch {}
117
- reject(new Error('Download timeout'));
118
- });
124
+ downloadFile(downloadUrl);
119
125
 
120
126
  file.on('error', (err) => {
121
127
  try { fs.unlinkSync(tempPath); } catch {}
@@ -130,7 +136,15 @@ async function downloadBinary(version, platform) {
130
136
  return;
131
137
  }
132
138
 
133
- // Make executable on Unix systems before renaming
139
+ // Validate the downloaded file
140
+ const stats = fs.statSync(tempPath);
141
+ if (stats.size < 1000) {
142
+ try { fs.unlinkSync(tempPath); } catch {}
143
+ reject(new Error(`Download failed: received invalid file (${stats.size} bytes)`));
144
+ return;
145
+ }
146
+
147
+ // Make executable on Unix systems
134
148
  if (platform.os !== 'windows') {
135
149
  try {
136
150
  fs.chmodSync(tempPath, '755');
@@ -143,7 +157,6 @@ async function downloadBinary(version, platform) {
143
157
 
144
158
  // Rename temp file to final path
145
159
  try {
146
- // Remove old binary if exists
147
160
  if (fs.existsSync(BINARY_PATH)) {
148
161
  fs.unlinkSync(BINARY_PATH);
149
162
  }
@@ -218,6 +231,8 @@ async function bootstrap() {
218
231
  if (needsDownload) {
219
232
  await downloadBinary(version, platform);
220
233
  console.log(`✅ Alurkerja CLI ${version} ready!`);
234
+ // Small delay to ensure file system sync after download
235
+ await new Promise(resolve => setTimeout(resolve, 100));
221
236
  }
222
237
 
223
238
  // Execute the binary with all arguments passed to this script
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alurkerja-cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Alurkerja CLI - npx wrapper for Go binary",
5
5
  "main": "index.js",
6
6
  "private": false,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alurkerja-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Alurkerja CLI - npx wrapper for Go binary",
5
5
  "main": "index.js",
6
6
  "private": false,