@heetmehta18/autodev 0.1.5 → 0.1.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.
Files changed (2) hide show
  1. package/bin/index.js +93 -34
  2. package/package.json +1 -1
package/bin/index.js CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { spawnSync } = require('child_process');
3
+ const { spawnSync, execSync } = require('child_process');
4
4
  const path = require('path');
5
5
  const fs = require('fs');
6
6
  const os = require('os');
7
- const { execSync } = require('child_process');
7
+ const https = require('https');
8
+ const http = require('http');
8
9
 
9
10
  // Determine OS & Arch mapping
10
11
  const platformMap = {
@@ -29,12 +30,24 @@ if (!platform || !arch) {
29
30
  const ext = platform === 'windows' ? 'zip' : 'tar.gz';
30
31
  const binaryName = platform === 'windows' ? 'autodev.exe' : 'autodev';
31
32
 
32
- // Version mapped to package.json
33
+ // Version: prefer the latest GitHub release tag; fall back to package.json
33
34
  const pkgJson = require('../package.json');
34
- const version = `v${pkgJson.version}`; // E.g., v0.1.0
35
+ const fallbackVersion = `v${pkgJson.version}`;
36
+
37
+ function getLatestReleaseTag() {
38
+ try {
39
+ const out = execSync(
40
+ 'curl -fsSL https://api.github.com/repos/HEETMEHTA18/autodev/releases/latest',
41
+ { encoding: 'utf8', timeout: 10000 }
42
+ );
43
+ const match = out.match(/"tag_name"\s*:\s*"([^"]+)"/);
44
+ if (match && match[1]) return match[1];
45
+ } catch (_) { /* fall through */ }
46
+ return fallbackVersion;
47
+ }
35
48
 
36
49
  // Resolve target paths
37
- const binDir = path.join(__dirname, '..', 'bin');
50
+ const binDir = __dirname;
38
51
  const binaryPath = path.join(binDir, binaryName);
39
52
 
40
53
  // Development fallback paths
@@ -54,9 +67,43 @@ for (const devPath of devPaths) {
54
67
  }
55
68
  }
56
69
 
57
- function downloadBinary() {
70
+ /**
71
+ * Download a file using Node.js built-in https module (follows redirects).
72
+ * This avoids issues with curl/wget not being available or behaving
73
+ * differently in sandboxed npx environments.
74
+ */
75
+ function download(url, destPath, maxRedirects = 5) {
76
+ return new Promise((resolve, reject) => {
77
+ if (maxRedirects <= 0) return reject(new Error('Too many redirects'));
78
+
79
+ const client = url.startsWith('https') ? https : http;
80
+ client.get(url, (res) => {
81
+ // Follow redirects (GitHub releases return 302)
82
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
83
+ return download(res.headers.location, destPath, maxRedirects - 1)
84
+ .then(resolve)
85
+ .catch(reject);
86
+ }
87
+
88
+ if (res.statusCode !== 200) {
89
+ return reject(new Error(`HTTP ${res.statusCode} from ${url}`));
90
+ }
91
+
92
+ const fileStream = fs.createWriteStream(destPath);
93
+ res.pipe(fileStream);
94
+ fileStream.on('finish', () => {
95
+ fileStream.close();
96
+ resolve();
97
+ });
98
+ fileStream.on('error', reject);
99
+ }).on('error', reject);
100
+ });
101
+ }
102
+
103
+ async function downloadBinary() {
104
+ const version = getLatestReleaseTag();
58
105
  console.log(`\n[autodev] Native binary not found. Downloading AutoDev ${version} for ${platform}/${arch}...`);
59
-
106
+
60
107
  if (!fs.existsSync(binDir)) {
61
108
  fs.mkdirSync(binDir, { recursive: true });
62
109
  }
@@ -64,27 +111,28 @@ function downloadBinary() {
64
111
  // Construct download URL
65
112
  const archiveName = `autodev_${platform}_${arch}`;
66
113
  const archiveFile = `${archiveName}.${ext}`;
67
- // Using the user's repository URL
68
114
  const url = `https://github.com/HEETMEHTA18/autodev/releases/download/${version}/${archiveFile}`;
69
-
70
- const tempFile = path.join(os.tmpdir(), archiveFile);
71
-
72
- // Download using curl / wget / powershell
115
+
116
+ const tempFile = path.join(os.tmpdir(), `autodev_download_${Date.now()}.${ext}`);
117
+
118
+ // Download using Node.js built-in HTTPS (handles redirects properly)
73
119
  try {
74
- if (process.platform === 'win32') {
75
- execSync(`powershell -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '${url}' -OutFile '${tempFile}'"`, { stdio: 'inherit' });
76
- } else {
77
- if (spawnSync('command', ['-v', 'curl'], { shell: true }).status === 0) {
78
- execSync(`curl -fsSL "${url}" -o "${tempFile}"`, { stdio: 'inherit' });
79
- } else if (spawnSync('command', ['-v', 'wget'], { shell: true }).status === 0) {
80
- execSync(`wget -q "${url}" -O "${tempFile}"`, { stdio: 'inherit' });
81
- } else {
82
- throw new Error('Neither curl nor wget was found on the system path.');
83
- }
120
+ console.log(`[autodev] Downloading from: ${url}`);
121
+ await download(url, tempFile);
122
+
123
+ // Verify the file was actually downloaded
124
+ if (!fs.existsSync(tempFile)) {
125
+ throw new Error('Download completed but file not found on disk.');
84
126
  }
127
+ const stat = fs.statSync(tempFile);
128
+ if (stat.size < 1000) {
129
+ throw new Error(`Downloaded file is too small (${stat.size} bytes), likely an error page.`);
130
+ }
131
+ console.log(`[autodev] Downloaded ${(stat.size / 1024 / 1024).toFixed(1)} MB`);
85
132
  } catch (err) {
86
133
  console.error(`\n[autodev] Error downloading release asset: ${err.message}`);
87
- console.error(`Please verify that the release version ${version} exists and has compiled assets.`);
134
+ console.error(`[autodev] URL: ${url}`);
135
+ console.error(`[autodev] Please verify that the release version ${version} exists and has compiled assets.`);
88
136
  process.exit(1);
89
137
  }
90
138
 
@@ -100,30 +148,41 @@ function downloadBinary() {
100
148
  } else {
101
149
  execSync(`tar -xzf "${tempFile}" -C "${binDir}"`, { stdio: 'inherit' });
102
150
  }
103
-
151
+
104
152
  // Clean up temp archive
105
153
  if (fs.existsSync(tempFile)) {
106
154
  fs.unlinkSync(tempFile);
107
155
  }
108
-
156
+
109
157
  // Set execution permissions on Linux/macOS
110
- if (process.platform !== 'win32') {
158
+ if (process.platform !== 'win32' && fs.existsSync(binaryPath)) {
111
159
  fs.chmodSync(binaryPath, 0o755);
112
160
  }
113
161
  console.log(`[autodev] Installation successful.\n`);
114
162
  } catch (err) {
163
+ // Clean up temp file on error too
164
+ if (fs.existsSync(tempFile)) {
165
+ fs.unlinkSync(tempFile);
166
+ }
115
167
  console.error(`\n[autodev] Error extracting archive: ${err.message}`);
116
168
  process.exit(1);
117
169
  }
118
170
  }
119
171
 
120
- // If no local dev binary is found and the packaged binary is missing, download it
121
- if (activeBinaryPath === binaryPath && !fs.existsSync(binaryPath)) {
122
- downloadBinary();
123
- }
172
+ async function main() {
173
+ // If no local dev binary is found and the packaged binary is missing, download it
174
+ if (activeBinaryPath === binaryPath && !fs.existsSync(binaryPath)) {
175
+ await downloadBinary();
176
+ }
124
177
 
125
- // Forward execution
126
- const args = process.argv.slice(2);
127
- const result = spawnSync(activeBinaryPath, args, { stdio: 'inherit' });
178
+ // Forward execution
179
+ const args = process.argv.slice(2);
180
+ const result = spawnSync(activeBinaryPath, args, { stdio: 'inherit' });
128
181
 
129
- process.exit(result.status ?? 0);
182
+ process.exit(result.status ?? 0);
183
+ }
184
+
185
+ main().catch((err) => {
186
+ console.error(`[autodev] Fatal error: ${err.message}`);
187
+ process.exit(1);
188
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heetmehta18/autodev",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "The App Store for Developers. Install languages, frameworks, and databases with a single command.",
5
5
  "main": "bin/index.js",
6
6
  "bin": {