vaporwaver-ts
Version:
TypeScript version of the Vaporwaver Python library. Vaporwaver is a Python library for generating vaporwave image art.
125 lines • 5.23 kB
JavaScript
import { spawn } from "child_process";
export class DependencyError extends Error {
constructor(message, details = {}) {
super(message);
this.details = details;
this.name = 'DependencyError';
}
}
export class DependencyChecker {
static async checkPython(minVersion = '3.7.0') {
try {
const version = await this.getPythonVersion();
if (!this.isVersionSatisfied(version, minVersion)) {
throw new DependencyError(`Python version ${minVersion} or higher is required. Found: ${version}`);
}
}
catch (error) {
if (error instanceof DependencyError)
throw error;
throw new DependencyError('Python is not installed or not accessible');
}
}
static async checkPythonDependencies() {
try {
const deps = await this.getInstalledPythonPackages();
const required = ['Pillow', 'glitch-this', 'opencv-python'];
const missing = required.filter(dep => !deps.some(installed => installed.toLowerCase().startsWith(dep.toLowerCase())));
if (missing.length > 0) {
// Try to install missing dependencies
await this.installMissingDependencies(missing);
}
}
catch (error) {
throw new DependencyError('Failed to verify Python dependencies', { originalError: error });
}
}
static async getPythonVersion() {
return new Promise((resolve, reject) => {
const python = spawn(this.pythonCommand, ['--version']);
let output = '';
python.stdout.on('data', (data) => { output += data; });
python.stderr.on('data', (data) => { output += data; });
python.on('close', (code) => {
if (code === 0) {
const version = output.match(/(\d+\.\d+\.\d+)/);
if (version) {
resolve(version[1]);
}
else {
reject(new Error('Could not parse Python version'));
}
}
else {
reject(new Error(`Python check failed with code ${code}`));
}
});
});
}
static async getInstalledPythonPackages() {
return new Promise((resolve, reject) => {
const pip = spawn(this.pipCommand, ['freeze']);
let output = '';
pip.stdout.on('data', (data) => { output += data; });
pip.stderr.on('data', () => { });
pip.on('close', (code) => {
if (code === 0) {
resolve(output.split('\n').filter(Boolean));
}
else {
reject(new Error('Failed to get installed packages'));
}
});
});
}
static async installMissingDependencies(packages) {
// Try different installation methods
const methods = [
{ cmd: this.pipCommand, args: ['install', '--user'] },
{ cmd: this.pipCommand, args: ['install'] },
{ cmd: this.pythonCommand, args: ['-m', 'pip', 'install', '--user'] },
{ cmd: this.pythonCommand, args: ['-m', 'pip', 'install'] }
];
for (const method of methods) {
try {
await this.tryInstallMethod(method.cmd, [...method.args, ...packages]);
return; // Installation successful
}
catch (error) {
console.warn(`Installation attempt failed with method ${method.cmd}`, error);
// Continue to next method
}
}
throw new DependencyError('Failed to install Python dependencies. Please install manually:\n' +
`${this.pythonCommand} -m pip install ${packages.join(' ')}`);
}
static async tryInstallMethod(cmd, args) {
return new Promise((resolve, reject) => {
const install = spawn(cmd, args);
let output = '';
install.stdout.on('data', (data) => { output += data; });
install.stderr.on('data', (data) => { output += data; });
install.on('close', (code) => {
if (code === 0) {
resolve();
}
else {
reject(new Error(`Installation failed with code ${code}\n${output}`));
}
});
});
}
static isVersionSatisfied(current, required) {
const parseVersion = (v) => v.split('.').map(Number);
const [currentMajor, currentMinor, currentPatch] = parseVersion(current);
const [reqMajor, reqMinor, reqPatch] = parseVersion(required);
if (currentMajor !== reqMajor)
return currentMajor > reqMajor;
if (currentMinor !== reqMinor)
return currentMinor > reqMinor;
return currentPatch >= reqPatch;
}
}
DependencyChecker.pythonCommand = process.platform === 'win32' ? 'python' : 'python3';
DependencyChecker.pipCommand = process.platform === 'win32' ? 'pip' : 'pip3';
//# sourceMappingURL=dependency-checker.js.map