const pify = require('pify');
const fs = require('fs');
const path = require('path');
const Registry = require('winreg');
const notify = require('../notify');
const {cliScriptPath, cliLinkPath} = require('../config/paths');
const readlink = pify(fs.readlink);
const symlink = pify(fs.symlink);
const checkInstall = () => {
return readlink(cliLinkPath)
.then(link => link === cliScriptPath)
.catch(err => {
if (err.code === 'ENOENT') {
return false;
}
throw err;
});
};
const addSymlink = () => {
return checkInstall().then(isInstalled => {
if (isInstalled) {
console.log('Hyper CLI already in PATH');
return Promise.resolve();
}
console.log('Linking HyperCLI');
return symlink(cliScriptPath, cliLinkPath);
});
};
const addBinToUserPath = () => {
return new Promise((resolve, reject) => {
const envKey = new Registry({hive: 'HKCU', key: '\\Environment'});
envKey.values((err, items) => {
if (err) {
reject(err);
return;
}
const binPath = path.dirname(cliScriptPath);
const basePath = path.resolve(binPath, '../../..');
const pathItem = items.find(item => item.name.toUpperCase() === 'PATH');
let newPathValue = binPath;
const pathItemName = pathItem ? pathItem.name : 'PATH';
if (pathItem) {
const pathParts = pathItem.value.split(';');
const existingPath = pathParts.find(pathPart => pathPart === binPath);
if (existingPath) {
console.log('Hyper CLI already in PATH');
resolve();
return;
}
newPathValue = pathParts
.filter(pathPart => !pathPart.startsWith(basePath))
.concat([binPath])
.join(';');
}
console.log('Adding HyperCLI path (registry)');
envKey.set(pathItemName, Registry.REG_SZ, newPathValue, error => {
if (error) {
reject(error);
return;
}
resolve();
});
});
});
};
const logNotify = (withNotification, ...args) => {
console.log(...args);
withNotification && notify(...args);
};
exports.installCLI = withNotification => {
if (process.platform === 'win32') {
addBinToUserPath()
.then(() =>
logNotify(
withNotification,
'Hyper CLI installed',
'You may need to restart your computer to complete this installation process.'
)
)
.catch(err =>
logNotify(withNotification, 'Hyper CLI installation failed', `Failed to add Hyper CLI path to user PATH ${err}`)
);
} else if (process.platform === 'darwin') {
addSymlink()
.then(() => logNotify(withNotification, 'Hyper CLI installed', `Symlink created at ${cliLinkPath}`))
.catch(err => {
const error =
err.code === 'EEXIST' || err.code === 'EINVAL'
? `File already exists: ${cliLinkPath}`
: `Symlink creation failed: ${err.code}`;
console.error(err);
logNotify(withNotification, 'Hyper CLI installation failed', error);
});
} else {
withNotification &&
notify('Hyper CLI installation', 'Command is added in PATH only at package installation. Please reinstall.');
}
};