colana 1.0.0-beta.21 → 1.0.0-beta.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/bin/colana.js +72 -14
- package/package.json +1 -1
package/bin/colana.js
CHANGED
|
@@ -136,12 +136,63 @@ function runInstall(cmd) {
|
|
|
136
136
|
const proc = spawn(parts[0], parts.slice(1), {
|
|
137
137
|
stdio: 'inherit',
|
|
138
138
|
env: { ...process.env },
|
|
139
|
+
...(process.platform === 'win32' && { shell: true }),
|
|
139
140
|
});
|
|
140
141
|
proc.on('close', (code) => resolve(code === 0));
|
|
141
142
|
proc.on('error', () => resolve(false));
|
|
142
143
|
});
|
|
143
144
|
}
|
|
144
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Spawn a binary with an explicit args array (needed when arguments contain spaces,
|
|
148
|
+
* e.g. winget --override "..." where the value must stay as one argument).
|
|
149
|
+
*/
|
|
150
|
+
function runInstallArgs(binary, args) {
|
|
151
|
+
return new Promise((resolve) => {
|
|
152
|
+
// No shell: true here — winget/xcode-select are real executables, not .cmd files.
|
|
153
|
+
// shell: true would cause cmd.exe to split quoted --override values into separate args.
|
|
154
|
+
const proc = spawn(binary, args, {
|
|
155
|
+
stdio: 'inherit',
|
|
156
|
+
env: { ...process.env },
|
|
157
|
+
});
|
|
158
|
+
proc.on('close', (code) => resolve(code === 0));
|
|
159
|
+
proc.on('error', () => resolve(false));
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Attempt to auto-install C/C++ build tools needed for native npm modules.
|
|
165
|
+
* Returns true if tools were installed (or install was triggered), false otherwise.
|
|
166
|
+
*/
|
|
167
|
+
async function tryInstallBuildTools() {
|
|
168
|
+
const platform = process.platform;
|
|
169
|
+
|
|
170
|
+
if (platform === 'win32') {
|
|
171
|
+
// Try winget (available on Windows 10 21H2+ / Windows 11)
|
|
172
|
+
if (commandExistsSync('winget')) {
|
|
173
|
+
print(` ${c.muted}Installing Visual Studio Build Tools via winget...${c.reset}`);
|
|
174
|
+
const ok = await runInstallArgs('winget', [
|
|
175
|
+
'install', 'Microsoft.VisualStudio.2022.BuildTools',
|
|
176
|
+
'--override', '--add Microsoft.VisualStudio.Workload.VCTools --passive --norestart',
|
|
177
|
+
'--accept-source-agreements', '--accept-package-agreements',
|
|
178
|
+
]);
|
|
179
|
+
return ok;
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (platform === 'darwin') {
|
|
185
|
+
print(` ${c.muted}Installing Xcode Command Line Tools...${c.reset}`);
|
|
186
|
+
// xcode-select --install opens a system dialog; returns non-zero if already installed
|
|
187
|
+
const ok = await runInstallArgs('xcode-select', ['--install']);
|
|
188
|
+
// Even if xcode-select exits non-zero (already installed), the tools may be present
|
|
189
|
+
return ok;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Linux — requires sudo, skip auto-install
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
145
196
|
// ---------------------------------------------------------------------------
|
|
146
197
|
// Doctor Checks (standalone + used by wizard)
|
|
147
198
|
// ---------------------------------------------------------------------------
|
|
@@ -398,23 +449,30 @@ async function installProvider(provider) {
|
|
|
398
449
|
if (success) {
|
|
399
450
|
print(` ${icons.pass} ${provider.name} installed`);
|
|
400
451
|
} else {
|
|
401
|
-
|
|
402
|
-
// Platform-specific hints for native module failures (npm packages may need C/C++ build tools)
|
|
452
|
+
// For npm packages, try auto-installing build tools and retrying
|
|
403
453
|
if (provider.runtime === 'npm') {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
print(`
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
print(`
|
|
414
|
-
|
|
454
|
+
print(` ${c.muted}Build tools may be needed. Attempting automatic install...${c.reset}`);
|
|
455
|
+
const toolsInstalled = await tryInstallBuildTools();
|
|
456
|
+
|
|
457
|
+
if (toolsInstalled) {
|
|
458
|
+
print(` ${c.muted}Retrying ${provider.name} install...${c.reset}`);
|
|
459
|
+
success = await runInstall(provider.installCmd);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (success) {
|
|
463
|
+
print(` ${icons.pass} ${provider.name} installed`);
|
|
464
|
+
return;
|
|
415
465
|
}
|
|
466
|
+
|
|
467
|
+
// Build tools auto-install failed or not available — show minimal fallback
|
|
468
|
+
print(` ${icons.fail} ${c.error}Installation failed.${c.reset}`);
|
|
469
|
+
if (process.platform === 'linux') {
|
|
470
|
+
print(` ${c.muted}Build tools required:${c.reset} ${c.cmd}sudo apt install python3 build-essential${c.reset}`);
|
|
471
|
+
}
|
|
472
|
+
} else {
|
|
473
|
+
print(` ${icons.fail} ${c.error}Installation failed.${c.reset}`);
|
|
416
474
|
}
|
|
417
|
-
print(` ${c.muted}
|
|
475
|
+
print(` ${c.muted}Install manually:${c.reset} ${provider.installCmd}`);
|
|
418
476
|
}
|
|
419
477
|
}
|
|
420
478
|
|