Comparar commits
18 Commits
83419364ab
...
master
| Autor | SHA1 | Fecha | |
|---|---|---|---|
| 511b545ffb | |||
|
76e9c939e2
|
|||
| 6c575750ff | |||
|
9eb10395ad
|
|||
|
e46dd6a16a
|
|||
|
30d2b35bda
|
|||
| 2fccf3fd48 | |||
|
fdeb3b2a2c
|
|||
| a92b2496e1 | |||
|
05836dadd2
|
|||
| a6dc54c045 | |||
|
d2044f85c5
|
|||
| dfb39d8772 | |||
|
2796185f36
|
|||
|
44ca9ffc30
|
|||
| b52ad0d2ea | |||
|
ba2a9b08da
|
|||
| 5b5393ddb5 |
16
package.json
16
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "alepm",
|
"name": "alepm",
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"description": "Advanced and secure Node.js package manager with binary storage, intelligent caching, and comprehensive security features",
|
"description": "Advanced and secure Node.js package manager with binary storage, intelligent caching, and comprehensive security features",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -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",
|
||||||
@@ -48,21 +51,14 @@
|
|||||||
"IMPLEMENTATION.md"
|
"IMPLEMENTATION.md"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "^2.2.0",
|
|
||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
"commander": "^11.1.0",
|
"commander": "^11.1.0",
|
||||||
"crypto": "^1.0.1",
|
|
||||||
"debug": "^4.4.1",
|
|
||||||
"express": "^5.1.0",
|
|
||||||
"fs-extra": "^11.3.1",
|
"fs-extra": "^11.3.1",
|
||||||
"inquirer": "^8.2.6",
|
"inquirer": "^8.2.6",
|
||||||
"listr2": "^6.6.1",
|
|
||||||
"lodash": "^4.17.21",
|
|
||||||
"node-fetch": "^2.6.12",
|
"node-fetch": "^2.6.12",
|
||||||
"ora": "^5.4.1",
|
"ora": "^5.4.1",
|
||||||
"semver": "^7.7.2",
|
"semver": "^7.7.2",
|
||||||
"tar": "^6.2.1",
|
"tar": "^6.2.1"
|
||||||
"lodash.debounce": "^4.0.8"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.45.0",
|
"eslint": "^8.45.0",
|
||||||
|
|||||||
27
src/cache/cache-manager.js
vendido
27
src/cache/cache-manager.js
vendido
@@ -11,13 +11,15 @@ class CacheManager {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.cacheDir = path.join(require('os').homedir(), '.alepm', 'cache');
|
this.cacheDir = path.join(require('os').homedir(), '.alepm', 'cache');
|
||||||
this.metadataFile = path.join(this.cacheDir, 'metadata.json');
|
this.metadataFile = path.join(this.cacheDir, 'metadata.json');
|
||||||
this.init();
|
this._initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
|
if (this._initialized) return;
|
||||||
|
|
||||||
await fs.ensureDir(this.cacheDir);
|
await fs.ensureDir(this.cacheDir);
|
||||||
|
|
||||||
if (!fs.existsSync(this.metadataFile)) {
|
if (!await fs.pathExists(this.metadataFile)) {
|
||||||
await this.saveMetadata({
|
await this.saveMetadata({
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
entries: {},
|
entries: {},
|
||||||
@@ -25,9 +27,12 @@ class CacheManager {
|
|||||||
lastCleanup: Date.now()
|
lastCleanup: Date.now()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(packageName, version) {
|
async get(packageName, version) {
|
||||||
|
await this.init();
|
||||||
const key = this.generateKey(packageName, version);
|
const key = this.generateKey(packageName, version);
|
||||||
const metadata = await this.loadMetadata();
|
const metadata = await this.loadMetadata();
|
||||||
|
|
||||||
@@ -38,7 +43,7 @@ class CacheManager {
|
|||||||
const entry = metadata.entries[key];
|
const entry = metadata.entries[key];
|
||||||
const filePath = path.join(this.cacheDir, entry.file);
|
const filePath = path.join(this.cacheDir, entry.file);
|
||||||
|
|
||||||
if (!fs.existsSync(filePath)) {
|
if (!await fs.pathExists(filePath)) {
|
||||||
// Remove stale entry
|
// Remove stale entry
|
||||||
delete metadata.entries[key];
|
delete metadata.entries[key];
|
||||||
await this.saveMetadata(metadata);
|
await this.saveMetadata(metadata);
|
||||||
@@ -67,6 +72,7 @@ class CacheManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async has(packageName, version) {
|
async has(packageName, version) {
|
||||||
|
await this.init();
|
||||||
const key = this.generateKey(packageName, version);
|
const key = this.generateKey(packageName, version);
|
||||||
const metadata = await this.loadMetadata();
|
const metadata = await this.loadMetadata();
|
||||||
|
|
||||||
@@ -78,7 +84,7 @@ class CacheManager {
|
|||||||
const filePath = path.join(this.cacheDir, entry.file);
|
const filePath = path.join(this.cacheDir, entry.file);
|
||||||
|
|
||||||
// Check if file exists
|
// Check if file exists
|
||||||
if (!fs.existsSync(filePath)) {
|
if (!await fs.pathExists(filePath)) {
|
||||||
// Remove stale entry
|
// Remove stale entry
|
||||||
delete metadata.entries[key];
|
delete metadata.entries[key];
|
||||||
await this.saveMetadata(metadata);
|
await this.saveMetadata(metadata);
|
||||||
@@ -89,6 +95,7 @@ class CacheManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async store(packageName, version, data) {
|
async store(packageName, version, data) {
|
||||||
|
await this.init();
|
||||||
const key = this.generateKey(packageName, version);
|
const key = this.generateKey(packageName, version);
|
||||||
const metadata = await this.loadMetadata();
|
const metadata = await this.loadMetadata();
|
||||||
|
|
||||||
@@ -117,7 +124,7 @@ class CacheManager {
|
|||||||
if (metadata.entries[key]) {
|
if (metadata.entries[key]) {
|
||||||
const oldEntry = metadata.entries[key];
|
const oldEntry = metadata.entries[key];
|
||||||
const oldFilePath = path.join(this.cacheDir, oldEntry.file);
|
const oldFilePath = path.join(this.cacheDir, oldEntry.file);
|
||||||
if (fs.existsSync(oldFilePath)) {
|
if (await fs.pathExists(oldFilePath)) {
|
||||||
await fs.remove(oldFilePath);
|
await fs.remove(oldFilePath);
|
||||||
metadata.totalSize -= oldEntry.size;
|
metadata.totalSize -= oldEntry.size;
|
||||||
}
|
}
|
||||||
@@ -135,6 +142,7 @@ class CacheManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async remove(packageName, version) {
|
async remove(packageName, version) {
|
||||||
|
await this.init();
|
||||||
const key = this.generateKey(packageName, version);
|
const key = this.generateKey(packageName, version);
|
||||||
const metadata = await this.loadMetadata();
|
const metadata = await this.loadMetadata();
|
||||||
|
|
||||||
@@ -145,7 +153,7 @@ class CacheManager {
|
|||||||
const entry = metadata.entries[key];
|
const entry = metadata.entries[key];
|
||||||
const filePath = path.join(this.cacheDir, entry.file);
|
const filePath = path.join(this.cacheDir, entry.file);
|
||||||
|
|
||||||
if (fs.existsSync(filePath)) {
|
if (await fs.pathExists(filePath)) {
|
||||||
await fs.remove(filePath);
|
await fs.remove(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,13 +165,14 @@ class CacheManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async clean() {
|
async clean() {
|
||||||
|
await this.init();
|
||||||
const metadata = await this.loadMetadata();
|
const metadata = await this.loadMetadata();
|
||||||
let cleanedSize = 0;
|
let cleanedSize = 0;
|
||||||
|
|
||||||
for (const [, entry] of Object.entries(metadata.entries)) {
|
for (const [, entry] of Object.entries(metadata.entries)) {
|
||||||
const filePath = path.join(this.cacheDir, entry.file);
|
const filePath = path.join(this.cacheDir, entry.file);
|
||||||
|
|
||||||
if (fs.existsSync(filePath)) {
|
if (await fs.pathExists(filePath)) {
|
||||||
await fs.remove(filePath);
|
await fs.remove(filePath);
|
||||||
cleanedSize += entry.size;
|
cleanedSize += entry.size;
|
||||||
}
|
}
|
||||||
@@ -182,6 +191,7 @@ class CacheManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async verify() {
|
async verify() {
|
||||||
|
await this.init();
|
||||||
const metadata = await this.loadMetadata();
|
const metadata = await this.loadMetadata();
|
||||||
const corrupted = [];
|
const corrupted = [];
|
||||||
const missing = [];
|
const missing = [];
|
||||||
@@ -189,7 +199,7 @@ class CacheManager {
|
|||||||
for (const [key, entry] of Object.entries(metadata.entries)) {
|
for (const [key, entry] of Object.entries(metadata.entries)) {
|
||||||
const filePath = path.join(this.cacheDir, entry.file);
|
const filePath = path.join(this.cacheDir, entry.file);
|
||||||
|
|
||||||
if (!fs.existsSync(filePath)) {
|
if (!await fs.pathExists(filePath)) {
|
||||||
missing.push(key);
|
missing.push(key);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -220,6 +230,7 @@ class CacheManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getStats() {
|
async getStats() {
|
||||||
|
await this.init();
|
||||||
const metadata = await this.loadMetadata();
|
const metadata = await this.loadMetadata();
|
||||||
const entries = Object.values(metadata.entries);
|
const entries = Object.values(metadata.entries);
|
||||||
|
|
||||||
|
|||||||
15
src/cli.js
15
src/cli.js
@@ -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')
|
||||||
|
|||||||
La diferencia del archivo ha sido suprimido porque es demasiado grande
Cargar Diff
135
tests/run-command.test.js
Archivo normal
135
tests/run-command.test.js
Archivo normal
@@ -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'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
Referencia en una nueva incidencia
Block a user