Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-08-19 04:39:40 +02:00
padre 44ca9ffc30
commit 2796185f36
Se han modificado 4 ficheros con 265 adiciones y 3 borrados

Ver fichero

@@ -11,7 +11,10 @@
"test": "jest", "test": "jest",
"lint": "eslint src/", "lint": "eslint src/",
"prepublishOnly": "npm test && npm run lint", "prepublishOnly": "npm test && npm run lint",
"postinstall": "echo 'Thanks for installing alepm! Run: alepm --help to get started.'" "postinstall": "echo 'Thanks for installing alepm! Run: alepm --help to get started.'",
"hello": "echo 'Hello from alepm!'",
"date": "date",
"version": "echo 'alepm version:' && node -e \"console.log(require('./package.json').version)\""
}, },
"keywords": [ "keywords": [
"package-manager", "package-manager",

Ver fichero

@@ -105,6 +105,21 @@ program
} }
}); });
// Run command
program
.command('run <script>')
.description('Run a script from package.json')
.option('--silent', 'Suppress output from npm scripts')
.option('--if-present', 'Don\'t error if script is missing')
.action(async (script, options) => {
try {
await pm.runScript(script, options);
} catch (error) {
console.error(chalk.red(`Error: ${error.message}`));
process.exit(1);
}
});
// Cache commands // Cache commands
program program
.command('cache') .command('cache')

Ver fichero

@@ -15,7 +15,7 @@ const ConfigManager = require('../utils/config-manager');
const Logger = require('../utils/logger'); const Logger = require('../utils/logger');
class PackageManager { class PackageManager {
constructor() { constructor(options = {}) {
this.cache = new CacheManager(); this.cache = new CacheManager();
this.security = new SecurityManager(); this.security = new SecurityManager();
this.storage = new BinaryStorage(); this.storage = new BinaryStorage();
@@ -29,7 +29,7 @@ class PackageManager {
this.resolver.setRegistry(this.registry); this.resolver.setRegistry(this.registry);
this.resolver.setLockManager(this.lock); this.resolver.setLockManager(this.lock);
this.projectRoot = this.findProjectRoot(); this.projectRoot = options.projectRoot || this.findProjectRoot();
this.globalRoot = path.join(require('os').homedir(), '.alepm'); this.globalRoot = path.join(require('os').homedir(), '.alepm');
this.initialized = false; this.initialized = false;
@@ -596,6 +596,115 @@ class PackageManager {
} }
} }
async runScript(scriptName, options = {}) {
await this.ensureInitialized();
const packageJsonPath = path.join(this.projectRoot, 'package.json');
if (!await fs.pathExists(packageJsonPath)) {
throw new Error('No package.json found in current directory');
}
const packageJson = await fs.readJson(packageJsonPath);
if (!packageJson.scripts) {
if (options.ifPresent) {
console.log(chalk.yellow('No scripts section found in package.json'));
return;
}
throw new Error('No scripts section found in package.json');
}
const script = packageJson.scripts[scriptName];
if (!script) {
if (options.ifPresent) {
console.log(chalk.yellow(`Script "${scriptName}" not found`));
return;
}
// Show available scripts
const availableScripts = Object.keys(packageJson.scripts);
console.log(chalk.red(`Script "${scriptName}" not found.`));
if (availableScripts.length > 0) {
console.log(chalk.blue('Available scripts:'));
availableScripts.forEach(name => {
console.log(chalk.gray(` ${name}: ${packageJson.scripts[name]}`));
});
}
throw new Error(`Script "${scriptName}" not found`);
}
console.log(chalk.blue(`Running script: ${scriptName}`));
console.log(chalk.gray(`> ${script}`));
console.log('');
const { spawn } = require('child_process');
return new Promise((resolve, reject) => {
// Determine shell based on OS
const isWindows = process.platform === 'win32';
const shell = isWindows ? 'cmd' : 'sh';
const shellFlag = isWindows ? '/c' : '-c';
const childProcess = spawn(shell, [shellFlag, script], {
cwd: this.projectRoot,
stdio: options.silent ? 'pipe' : 'inherit',
shell: true,
env: {
...process.env,
// Add node_modules/.bin to PATH
PATH: `${path.join(this.projectRoot, 'node_modules', '.bin')}${path.delimiter}${process.env.PATH}`
}
});
// Handle silent mode
if (options.silent) {
let stdout = '';
let stderr = '';
if (childProcess.stdout) {
childProcess.stdout.on('data', (data) => {
stdout += data.toString();
});
}
if (childProcess.stderr) {
childProcess.stderr.on('data', (data) => {
stderr += data.toString();
});
}
childProcess.on('close', (code) => {
if (code === 0) {
if (stdout.trim()) {
console.log(stdout.trim());
}
resolve();
} else {
if (stderr.trim()) {
console.error(stderr.trim());
}
reject(new Error(`Script "${scriptName}" exited with code ${code}`));
}
});
} else {
childProcess.on('close', (code) => {
if (code === 0) {
console.log(chalk.green(`✓ Script "${scriptName}" completed successfully`));
resolve();
} else {
reject(new Error(`Script "${scriptName}" exited with code ${code}`));
}
});
}
childProcess.on('error', (error) => {
reject(new Error(`Failed to run script "${scriptName}": ${error.message}`));
});
});
}
async verifyLock() { async verifyLock() {
const spinner = ora('Verifying lock file...').start(); const spinner = ora('Verifying lock file...').start();

135
tests/run-command.test.js Archivo normal
Ver fichero

@@ -0,0 +1,135 @@
const fs = require('fs-extra');
const path = require('path');
const PackageManager = require('../src/core/package-manager');
describe('Run Command', () => {
let tempDir;
let packageManager;
beforeEach(async () => {
tempDir = path.join(__dirname, 'temp-run-test');
await fs.ensureDir(tempDir);
packageManager = new PackageManager({ projectRoot: tempDir });
});
afterEach(async () => {
if (await fs.pathExists(tempDir)) {
await fs.remove(tempDir);
}
});
test('should run a simple script successfully', async () => {
const packageJson = {
name: 'test-package',
version: '1.0.0',
scripts: {
hello: 'echo "Hello World"'
}
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
// This should not throw
await packageManager.runScript('hello');
});
test('should fail when script does not exist', async () => {
const packageJson = {
name: 'test-package',
version: '1.0.0',
scripts: {
hello: 'echo "Hello World"'
}
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
await expect(packageManager.runScript('nonexistent')).rejects.toThrow(
'Script "nonexistent" not found'
);
});
test('should not fail when script does not exist with ifPresent option', async () => {
const packageJson = {
name: 'test-package',
version: '1.0.0',
scripts: {
hello: 'echo "Hello World"'
}
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
// This should not throw
await packageManager.runScript('nonexistent', { ifPresent: true });
});
test('should fail when package.json does not exist', async () => {
// Override ensureInitialized to prevent auto-creation
const originalEnsureInitialized = packageManager.ensureInitialized;
packageManager.ensureInitialized = async () => {};
await expect(packageManager.runScript('hello')).rejects.toThrow(
'No package.json found in current directory'
);
// Restore original method
packageManager.ensureInitialized = originalEnsureInitialized;
});
test('should fail when package.json has no scripts section', async () => {
const packageJson = {
name: 'test-package',
version: '1.0.0'
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
await expect(packageManager.runScript('hello')).rejects.toThrow(
'No scripts section found in package.json'
);
});
test('should not fail when package.json has no scripts section with ifPresent option', async () => {
const packageJson = {
name: 'test-package',
version: '1.0.0'
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
// This should not throw
await packageManager.runScript('hello', { ifPresent: true });
});
test('should run script with silent option', async () => {
const packageJson = {
name: 'test-package',
version: '1.0.0',
scripts: {
hello: 'echo "Hello World"'
}
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
// This should not throw
await packageManager.runScript('hello', { silent: true });
});
test('should handle script that exits with error code', async () => {
const packageJson = {
name: 'test-package',
version: '1.0.0',
scripts: {
fail: 'nonexistentcommand123456' // This command doesn't exist
}
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
await expect(packageManager.runScript('fail')).rejects.toThrow(
'Script "fail" exited with code 127'
);
});
});