alurkerja-cli 1.0.0 → 1.0.2
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 +81 -52
- package/index.js.backup +82 -53
- package/package.json +1 -1
- package/package.json.backup +1 -1
package/index.js
CHANGED
|
@@ -13,7 +13,8 @@ const https = require('https');
|
|
|
13
13
|
const { execSync, spawn } = require('child_process');
|
|
14
14
|
const os = require('os');
|
|
15
15
|
|
|
16
|
-
const
|
|
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
18
|
const VERSION = 'v1.0.0'; // Will be replaced during build
|
|
18
19
|
const INSTALL_DIR = path.join(os.homedir(), '.alurkerja', 'bin');
|
|
19
20
|
const BINARY_PATH = path.join(INSTALL_DIR, 'alurkerja');
|
|
@@ -44,87 +45,115 @@ function detectPlatform() {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
|
-
* Get the
|
|
48
|
+
* Get the version to download
|
|
48
49
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return VERSION;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return new Promise((resolve, reject) => {
|
|
55
|
-
const options = {
|
|
56
|
-
hostname: 'api.github.com',
|
|
57
|
-
path: `/repos/${REPO}/releases/latest`,
|
|
58
|
-
headers: { 'User-Agent': 'alurkerja-cli-wrapper' }
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const req = https.get(options, (res) => {
|
|
62
|
-
let data = '';
|
|
63
|
-
res.on('data', chunk => data += chunk);
|
|
64
|
-
res.on('end', () => {
|
|
65
|
-
try {
|
|
66
|
-
const release = JSON.parse(data);
|
|
67
|
-
resolve(release.tag_name);
|
|
68
|
-
} catch (err) {
|
|
69
|
-
reject(new Error('Failed to parse GitHub API response'));
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
req.on('error', reject);
|
|
75
|
-
req.setTimeout(10000, () => {
|
|
76
|
-
req.abort();
|
|
77
|
-
reject(new Error('GitHub API request timeout'));
|
|
78
|
-
});
|
|
79
|
-
});
|
|
50
|
+
function getVersion() {
|
|
51
|
+
return VERSION;
|
|
80
52
|
}
|
|
81
53
|
|
|
82
54
|
/**
|
|
83
|
-
* Download binary from
|
|
55
|
+
* Download binary from GitLab releases
|
|
84
56
|
*/
|
|
85
57
|
async function downloadBinary(version, platform) {
|
|
86
58
|
const binaryName = `alurkerja-${platform.os}-${platform.arch}${platform.os === 'windows' ? '.exe' : ''}`;
|
|
87
|
-
const downloadUrl =
|
|
59
|
+
const downloadUrl = `${GITLAB_BASE}/-/raw/master/dist/${binaryName}`;
|
|
88
60
|
|
|
89
61
|
console.log(`📥 Downloading Alurkerja CLI ${version}...`);
|
|
90
62
|
|
|
91
63
|
// Ensure install directory exists
|
|
92
64
|
fs.mkdirSync(INSTALL_DIR, { recursive: true });
|
|
93
65
|
|
|
66
|
+
// Use temporary file to avoid ETXTBSY error
|
|
67
|
+
const tempPath = `${BINARY_PATH}.tmp`;
|
|
68
|
+
|
|
94
69
|
return new Promise((resolve, reject) => {
|
|
95
|
-
const file = fs.createWriteStream(
|
|
70
|
+
const file = fs.createWriteStream(tempPath);
|
|
71
|
+
|
|
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
|
+
};
|
|
96
80
|
|
|
97
|
-
const req = https.get(
|
|
81
|
+
const req = https.get(options, (res) => {
|
|
98
82
|
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
99
|
-
// Follow redirect
|
|
100
|
-
|
|
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) => {
|
|
101
93
|
redirectRes.pipe(file);
|
|
102
|
-
redirectRes.on('end', resolve);
|
|
103
94
|
});
|
|
104
95
|
}
|
|
105
96
|
|
|
106
97
|
if (res.statusCode !== 200) {
|
|
98
|
+
file.close();
|
|
99
|
+
fs.unlinkSync(tempPath);
|
|
107
100
|
reject(new Error(`Download failed with status ${res.statusCode}`));
|
|
108
101
|
return;
|
|
109
102
|
}
|
|
110
103
|
|
|
111
104
|
res.pipe(file);
|
|
112
|
-
res.on('end', resolve);
|
|
113
105
|
});
|
|
114
106
|
|
|
115
|
-
req.on('error',
|
|
107
|
+
req.on('error', (err) => {
|
|
108
|
+
file.close();
|
|
109
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
110
|
+
reject(err);
|
|
111
|
+
});
|
|
112
|
+
|
|
116
113
|
req.setTimeout(30000, () => {
|
|
117
114
|
req.abort();
|
|
115
|
+
file.close();
|
|
116
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
118
117
|
reject(new Error('Download timeout'));
|
|
119
118
|
});
|
|
120
119
|
|
|
121
|
-
file.on('error',
|
|
120
|
+
file.on('error', (err) => {
|
|
121
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
122
|
+
reject(err);
|
|
123
|
+
});
|
|
124
|
+
|
|
122
125
|
file.on('finish', () => {
|
|
123
|
-
file.close()
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
file.close((err) => {
|
|
127
|
+
if (err) {
|
|
128
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
129
|
+
reject(err);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Make executable on Unix systems before renaming
|
|
134
|
+
if (platform.os !== 'windows') {
|
|
135
|
+
try {
|
|
136
|
+
fs.chmodSync(tempPath, '755');
|
|
137
|
+
} catch (err) {
|
|
138
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
139
|
+
reject(new Error(`Failed to make binary executable: ${err.message}`));
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Rename temp file to final path
|
|
145
|
+
try {
|
|
146
|
+
// Remove old binary if exists
|
|
147
|
+
if (fs.existsSync(BINARY_PATH)) {
|
|
148
|
+
fs.unlinkSync(BINARY_PATH);
|
|
149
|
+
}
|
|
150
|
+
fs.renameSync(tempPath, BINARY_PATH);
|
|
151
|
+
resolve();
|
|
152
|
+
} catch (err) {
|
|
153
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
154
|
+
reject(new Error(`Failed to install binary: ${err.message}`));
|
|
155
|
+
}
|
|
156
|
+
});
|
|
128
157
|
});
|
|
129
158
|
});
|
|
130
159
|
}
|
|
@@ -179,16 +208,16 @@ function executeBinary(args) {
|
|
|
179
208
|
async function bootstrap() {
|
|
180
209
|
try {
|
|
181
210
|
const platform = detectPlatform();
|
|
182
|
-
const
|
|
211
|
+
const version = getVersion();
|
|
183
212
|
const installedVersion = getInstalledVersion();
|
|
184
213
|
|
|
185
214
|
// Check if we need to download the binary
|
|
186
215
|
const needsDownload = !binaryExists() ||
|
|
187
|
-
(installedVersion !==
|
|
216
|
+
(installedVersion !== version && version !== 'dev');
|
|
188
217
|
|
|
189
218
|
if (needsDownload) {
|
|
190
|
-
await downloadBinary(
|
|
191
|
-
console.log(`✅ Alurkerja CLI ${
|
|
219
|
+
await downloadBinary(version, platform);
|
|
220
|
+
console.log(`✅ Alurkerja CLI ${version} ready!`);
|
|
192
221
|
}
|
|
193
222
|
|
|
194
223
|
// Execute the binary with all arguments passed to this script
|
package/index.js.backup
CHANGED
|
@@ -13,8 +13,9 @@ const https = require('https');
|
|
|
13
13
|
const { execSync, spawn } = require('child_process');
|
|
14
14
|
const os = require('os');
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
const
|
|
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
|
|
18
19
|
const INSTALL_DIR = path.join(os.homedir(), '.alurkerja', 'bin');
|
|
19
20
|
const BINARY_PATH = path.join(INSTALL_DIR, 'alurkerja');
|
|
20
21
|
|
|
@@ -44,87 +45,115 @@ function detectPlatform() {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
|
-
* Get the
|
|
48
|
+
* Get the version to download
|
|
48
49
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return VERSION;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return new Promise((resolve, reject) => {
|
|
55
|
-
const options = {
|
|
56
|
-
hostname: 'api.github.com',
|
|
57
|
-
path: `/repos/${REPO}/releases/latest`,
|
|
58
|
-
headers: { 'User-Agent': 'alurkerja-cli-wrapper' }
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const req = https.get(options, (res) => {
|
|
62
|
-
let data = '';
|
|
63
|
-
res.on('data', chunk => data += chunk);
|
|
64
|
-
res.on('end', () => {
|
|
65
|
-
try {
|
|
66
|
-
const release = JSON.parse(data);
|
|
67
|
-
resolve(release.tag_name);
|
|
68
|
-
} catch (err) {
|
|
69
|
-
reject(new Error('Failed to parse GitHub API response'));
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
req.on('error', reject);
|
|
75
|
-
req.setTimeout(10000, () => {
|
|
76
|
-
req.abort();
|
|
77
|
-
reject(new Error('GitHub API request timeout'));
|
|
78
|
-
});
|
|
79
|
-
});
|
|
50
|
+
function getVersion() {
|
|
51
|
+
return VERSION;
|
|
80
52
|
}
|
|
81
53
|
|
|
82
54
|
/**
|
|
83
|
-
* Download binary from
|
|
55
|
+
* Download binary from GitLab releases
|
|
84
56
|
*/
|
|
85
57
|
async function downloadBinary(version, platform) {
|
|
86
58
|
const binaryName = `alurkerja-${platform.os}-${platform.arch}${platform.os === 'windows' ? '.exe' : ''}`;
|
|
87
|
-
const downloadUrl =
|
|
59
|
+
const downloadUrl = `${GITLAB_BASE}/-/raw/master/dist/${binaryName}`;
|
|
88
60
|
|
|
89
61
|
console.log(`📥 Downloading Alurkerja CLI ${version}...`);
|
|
90
62
|
|
|
91
63
|
// Ensure install directory exists
|
|
92
64
|
fs.mkdirSync(INSTALL_DIR, { recursive: true });
|
|
93
65
|
|
|
66
|
+
// Use temporary file to avoid ETXTBSY error
|
|
67
|
+
const tempPath = `${BINARY_PATH}.tmp`;
|
|
68
|
+
|
|
94
69
|
return new Promise((resolve, reject) => {
|
|
95
|
-
const file = fs.createWriteStream(
|
|
70
|
+
const file = fs.createWriteStream(tempPath);
|
|
71
|
+
|
|
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
|
+
};
|
|
96
80
|
|
|
97
|
-
const req = https.get(
|
|
81
|
+
const req = https.get(options, (res) => {
|
|
98
82
|
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
99
|
-
// Follow redirect
|
|
100
|
-
|
|
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) => {
|
|
101
93
|
redirectRes.pipe(file);
|
|
102
|
-
redirectRes.on('end', resolve);
|
|
103
94
|
});
|
|
104
95
|
}
|
|
105
96
|
|
|
106
97
|
if (res.statusCode !== 200) {
|
|
98
|
+
file.close();
|
|
99
|
+
fs.unlinkSync(tempPath);
|
|
107
100
|
reject(new Error(`Download failed with status ${res.statusCode}`));
|
|
108
101
|
return;
|
|
109
102
|
}
|
|
110
103
|
|
|
111
104
|
res.pipe(file);
|
|
112
|
-
res.on('end', resolve);
|
|
113
105
|
});
|
|
114
106
|
|
|
115
|
-
req.on('error',
|
|
107
|
+
req.on('error', (err) => {
|
|
108
|
+
file.close();
|
|
109
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
110
|
+
reject(err);
|
|
111
|
+
});
|
|
112
|
+
|
|
116
113
|
req.setTimeout(30000, () => {
|
|
117
114
|
req.abort();
|
|
115
|
+
file.close();
|
|
116
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
118
117
|
reject(new Error('Download timeout'));
|
|
119
118
|
});
|
|
120
119
|
|
|
121
|
-
file.on('error',
|
|
120
|
+
file.on('error', (err) => {
|
|
121
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
122
|
+
reject(err);
|
|
123
|
+
});
|
|
124
|
+
|
|
122
125
|
file.on('finish', () => {
|
|
123
|
-
file.close()
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
file.close((err) => {
|
|
127
|
+
if (err) {
|
|
128
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
129
|
+
reject(err);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Make executable on Unix systems before renaming
|
|
134
|
+
if (platform.os !== 'windows') {
|
|
135
|
+
try {
|
|
136
|
+
fs.chmodSync(tempPath, '755');
|
|
137
|
+
} catch (err) {
|
|
138
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
139
|
+
reject(new Error(`Failed to make binary executable: ${err.message}`));
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Rename temp file to final path
|
|
145
|
+
try {
|
|
146
|
+
// Remove old binary if exists
|
|
147
|
+
if (fs.existsSync(BINARY_PATH)) {
|
|
148
|
+
fs.unlinkSync(BINARY_PATH);
|
|
149
|
+
}
|
|
150
|
+
fs.renameSync(tempPath, BINARY_PATH);
|
|
151
|
+
resolve();
|
|
152
|
+
} catch (err) {
|
|
153
|
+
try { fs.unlinkSync(tempPath); } catch {}
|
|
154
|
+
reject(new Error(`Failed to install binary: ${err.message}`));
|
|
155
|
+
}
|
|
156
|
+
});
|
|
128
157
|
});
|
|
129
158
|
});
|
|
130
159
|
}
|
|
@@ -179,16 +208,16 @@ function executeBinary(args) {
|
|
|
179
208
|
async function bootstrap() {
|
|
180
209
|
try {
|
|
181
210
|
const platform = detectPlatform();
|
|
182
|
-
const
|
|
211
|
+
const version = getVersion();
|
|
183
212
|
const installedVersion = getInstalledVersion();
|
|
184
213
|
|
|
185
214
|
// Check if we need to download the binary
|
|
186
215
|
const needsDownload = !binaryExists() ||
|
|
187
|
-
(installedVersion !==
|
|
216
|
+
(installedVersion !== version && version !== 'dev');
|
|
188
217
|
|
|
189
218
|
if (needsDownload) {
|
|
190
|
-
await downloadBinary(
|
|
191
|
-
console.log(`✅ Alurkerja CLI ${
|
|
219
|
+
await downloadBinary(version, platform);
|
|
220
|
+
console.log(`✅ Alurkerja CLI ${version} ready!`);
|
|
192
221
|
}
|
|
193
222
|
|
|
194
223
|
// Execute the binary with all arguments passed to this script
|
package/package.json
CHANGED