Comparing version 2.0.0 to 2.1.0
The MIT License | ||
=============== | ||
Copyright 2016 Artem Sapegin (http://sapegin.me), contributors | ||
Copyright 2017 Artem Sapegin (http://sapegin.me), contributors | ||
@@ -6,0 +6,0 @@ Permission is hereby granted, free of charge, to any person obtaining |
{ | ||
"name": "mrm-core", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"description": "Utilities to make tasks for mrm", | ||
@@ -16,3 +16,3 @@ "author": { | ||
"test": "npm run test:jest", | ||
"lint": "eslint . --fix", | ||
"lint": "eslint . --cache --fix", | ||
"test:jest": "jest", | ||
@@ -34,2 +34,3 @@ "test:watch": "jest --watch", | ||
"js-yaml": "^3.8.4", | ||
"listify": "^1.0.0", | ||
"lodash": "^4.17.4", | ||
@@ -36,0 +37,0 @@ "mkdirp": "^0.5.1", |
@@ -267,2 +267,5 @@ # Marmot (mrm) core utils | ||
file.prependScript('test', 'jest') // Prepend a script with a command: a -> b && a | ||
file.removeScript('test') // Remove script | ||
file.removeScript(/^mocha|ava$/) // Remove all scripts that match a regexp | ||
file.removeScript('test', /b/) // Remove subcommands from a script: a && b -> a | ||
file.save() // Save file | ||
@@ -292,3 +295,3 @@ // All methods of json() work too | ||
### Install npm packages | ||
### Install and uninstall npm packages | ||
@@ -303,2 +306,10 @@ Installs npm package(s) and saves them to `package.json` if they aren’t installed yet. | ||
Uninstalls npm package(s) and removes them from `package.json`: | ||
```js | ||
const { uninstall } = require('mrm-core') | ||
uninstall('eslint') // Uninstall from devDependencies | ||
uninstall(['tamia', 'lodash'], { dev: false }) // Uninstall from dependencies | ||
``` | ||
### Custom error class: `MrmError` | ||
@@ -305,0 +316,0 @@ |
@@ -7,2 +7,3 @@ 'use strict'; | ||
const install = require('../npm').install; | ||
const uninstall = require('../npm').uninstall; | ||
@@ -25,66 +26,147 @@ const modules = ['eslint', 'babel-core']; | ||
it('install() should install an npm packages to devDependencies', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson({}, {}); | ||
install(modules, undefined, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['install', '--save-dev', 'eslint', 'babel-core'], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
describe('install', () => { | ||
it('should install an npm packages to devDependencies', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson({}, {}); | ||
install(modules, undefined, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['install', '--save-dev', 'eslint', 'babel-core'], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
}); | ||
}); | ||
}); | ||
it('install() should install an npm packages to dependencies', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson({}, {}); | ||
install(modules, { dev: false }, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['install', '--save', 'eslint', 'babel-core'], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
it('should install an npm packages to dependencies', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson({}, {}); | ||
install(modules, { dev: false }, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['install', '--save', 'eslint', 'babel-core'], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
}); | ||
}); | ||
}); | ||
it('install() should not install already installed packages', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson({}, { eslint: '*' }); | ||
install(modules, undefined, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['install', '--save-dev', 'babel-core'], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
it('should not install already installed packages', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson({}, { eslint: '*' }); | ||
install(modules, undefined, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['install', '--save-dev', 'babel-core'], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
}); | ||
}); | ||
}); | ||
it('install() should accept the first parameter as a string', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson({}, {}); | ||
install(modules[0], undefined, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['install', '--save-dev', modules[0]], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
it('should accept the first parameter as a string', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson({}, {}); | ||
install(modules[0], undefined, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['install', '--save-dev', modules[0]], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
}); | ||
}); | ||
}); | ||
it('install() should not run npm when there are no new packages', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson( | ||
{}, | ||
{ | ||
eslint: '*', | ||
'babel-core': '*', | ||
} | ||
); | ||
install(modules, undefined, spawn); | ||
expect(spawn).toHaveBeenCalledTimes(0); | ||
}); | ||
it('should not run npm when there are no new packages', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson( | ||
{}, | ||
{ | ||
eslint: '*', | ||
'babel-core': '*', | ||
} | ||
); | ||
install(modules, undefined, spawn); | ||
expect(spawn).toHaveBeenCalledTimes(0); | ||
}); | ||
it('install() should not throw when package.json not found', () => { | ||
const spawn = jest.fn(); | ||
const fn = () => install(modules, undefined, spawn); | ||
expect(fn).not.toThrow(); | ||
it('should not throw when package.json not found', () => { | ||
const spawn = jest.fn(); | ||
const fn = () => install(modules, undefined, spawn); | ||
expect(fn).not.toThrow(); | ||
}); | ||
it('should not throw when package.json has no dependencies section', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson(); | ||
const fn = () => install(modules, undefined, spawn); | ||
expect(fn).not.toThrow(); | ||
}); | ||
}); | ||
it('install() should not throw when package.json has no dependencies section', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson(); | ||
const fn = () => install(modules, undefined, spawn); | ||
expect(fn).not.toThrow(); | ||
describe('uninstall', () => { | ||
it('should uninstall an npm packages from devDependencies', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson( | ||
{}, | ||
{ | ||
eslint: '*', | ||
'babel-core': '*', | ||
} | ||
); | ||
uninstall(modules, undefined, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['uninstall', '--save-dev', 'eslint', 'babel-core'], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
}); | ||
}); | ||
it('should uninstall an npm packages from dependencies', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson( | ||
{ | ||
eslint: '*', | ||
'babel-core': '*', | ||
}, | ||
{} | ||
); | ||
uninstall(modules, { dev: false }, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['uninstall', '--save', 'eslint', 'babel-core'], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
}); | ||
}); | ||
it('should not uninstall not installed packages', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson({}, { eslint: '*' }); | ||
uninstall(modules, undefined, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['uninstall', '--save-dev', 'eslint'], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
}); | ||
}); | ||
it('should accept the first parameter as a string', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson( | ||
{}, | ||
{ | ||
eslint: '*', | ||
} | ||
); | ||
uninstall(modules[0], undefined, spawn); | ||
expect(spawn).toBeCalledWith('npm', ['uninstall', '--save-dev', modules[0]], { | ||
cwd: undefined, | ||
stdio: 'inherit', | ||
}); | ||
}); | ||
it('should not run npm when there are no packages to uninstall', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson({}, {}); | ||
uninstall(modules, undefined, spawn); | ||
expect(spawn).toHaveBeenCalledTimes(0); | ||
}); | ||
it('should not throw when package.json not found', () => { | ||
const spawn = jest.fn(); | ||
const fn = () => uninstall(modules, undefined, spawn); | ||
expect(fn).not.toThrow(); | ||
}); | ||
it('should not throw when package.json has no dependencies section', () => { | ||
const spawn = jest.fn(); | ||
createPackageJson(); | ||
const fn = () => uninstall(modules, undefined, spawn); | ||
expect(fn).not.toThrow(); | ||
}); | ||
}); |
@@ -18,2 +18,3 @@ 'use strict'; | ||
prependScript: expect.any(Function), | ||
removeScript: expect.any(Function), | ||
@@ -50,2 +51,12 @@ // Inherited from json() | ||
}); | ||
it('all methods except getScript should be chainable', () => { | ||
const result = packageJson() | ||
.setScript('test', 'one') | ||
.prependScript('test', 'two') | ||
.appendScript('test', 'three') | ||
.removeScript('test', /one/) | ||
.getScript('test'); | ||
expect(result).toBe('two && three'); | ||
}); | ||
}); | ||
@@ -160,1 +171,78 @@ | ||
}); | ||
describe('removeScript', () => { | ||
it('should remove a command from a script', () => { | ||
const file = packageJson({ | ||
scripts: { | ||
test: 'npm run lint && npm run test:jest', | ||
}, | ||
}); | ||
file.removeScript('test', /lint/); | ||
expect(file.get()).toEqual({ | ||
scripts: { | ||
test: 'npm run test:jest', | ||
}, | ||
}); | ||
}); | ||
it('should not change a script if a command not found', () => { | ||
const test = 'npm run lint && npm run test:jest'; | ||
const file = packageJson({ | ||
scripts: { | ||
test, | ||
}, | ||
}); | ||
file.removeScript('test', /mocha/); | ||
expect(file.get()).toEqual({ | ||
scripts: { | ||
test, | ||
}, | ||
}); | ||
}); | ||
it('should not change anything if a script not found', () => { | ||
const test = 'npm run lint && npm run test:jest'; | ||
const file = packageJson({ | ||
scripts: { | ||
test, | ||
}, | ||
}); | ||
file.removeScript('pizza', /mocha/); | ||
expect(file.get()).toEqual({ | ||
scripts: { | ||
test, | ||
}, | ||
}); | ||
}); | ||
it('should remove the whole script if the second parameter omitted', () => { | ||
const file = packageJson({ | ||
scripts: { | ||
test: 'npm run lint && npm run test:jest', | ||
pizza: 'salami', | ||
}, | ||
}); | ||
file.removeScript('test'); | ||
expect(file.get()).toEqual({ | ||
scripts: { | ||
pizza: 'salami', | ||
}, | ||
}); | ||
}); | ||
it('should remove all scripts that match a regexp', () => { | ||
const file = packageJson({ | ||
scripts: { | ||
test: 'npm run lint && npm run test:jest', | ||
jest: 'jest', | ||
pizza: 'salami', | ||
}, | ||
}); | ||
file.removeScript(/test|jest/); | ||
expect(file.get()).toEqual({ | ||
scripts: { | ||
pizza: 'salami', | ||
}, | ||
}); | ||
}); | ||
}); |
@@ -21,4 +21,2 @@ // @ts-check | ||
} | ||
return pkg.get(addr); | ||
} | ||
@@ -49,3 +47,3 @@ | ||
pkg.set(['scripts', name], command); | ||
return command; | ||
return this; | ||
}, | ||
@@ -61,3 +59,4 @@ | ||
appendScript(name, command) { | ||
return updateScript(pkg, name, command, prevCommand => [prevCommand, command].join(' && ')); | ||
updateScript(pkg, name, command, prevCommand => [prevCommand, command].join(' && ')); | ||
return this; | ||
}, | ||
@@ -73,5 +72,43 @@ | ||
prependScript(name, command) { | ||
return updateScript(pkg, name, command, prevCommand => [command, prevCommand].join(' && ')); | ||
updateScript(pkg, name, command, prevCommand => [command, prevCommand].join(' && ')); | ||
return this; | ||
}, | ||
/** | ||
* Removes a script with a given name (or all script that match a regexp). | ||
* Removes a subcommand (part between &&) from a script that matches a regexp if the match parameter is given. | ||
* | ||
* @param {RegExp|string} name Script name or RegExp | ||
* @param {RegExp} [match] Subcommand RegExp | ||
* @return {string|undefined} Command after update | ||
*/ | ||
removeScript(name, match) { | ||
if (!match) { | ||
if (typeof name === 'string') { | ||
// Remove a script with a given name | ||
pkg.unset(['scripts', name]); | ||
} else { | ||
// Remove all scripts with names matching a regexp | ||
const scriptNames = Object.keys(pkg.get('scripts')); | ||
scriptNames.forEach(script => { | ||
if (script.match(name)) { | ||
pkg.unset(['scripts', script]); | ||
} | ||
}); | ||
} | ||
return this; | ||
} | ||
// No script found with a given name | ||
const command = pkg.get(['scripts', name]); | ||
if (!command) { | ||
return this; | ||
} | ||
// Remove a subcommand from a script | ||
const newCommand = command.split(/\s*&&\s*/).filter(cmd => !cmd.match(match)).join(' && '); | ||
pkg.set(['scripts', name], newCommand); | ||
return this; | ||
}, | ||
}); | ||
}; |
@@ -24,2 +24,8 @@ 'use strict'; | ||
it('should accept default value', () => { | ||
const array = ['one', 'two']; | ||
const file = lines('test.lines', array); | ||
expect(file.get()).toEqual(array); | ||
}); | ||
it('exists() should return true if file exists', () => { | ||
@@ -76,4 +82,15 @@ const file = lines('test.lines'); | ||
expect(fs.readFileSync(filename, 'utf8')).toBe('foo\nbar'); | ||
fs.unlink(filename); | ||
}); | ||
it('should save file without empty lines', () => { | ||
const filename = 'new.lines'; | ||
fs.writeFileSync(filename, 'one\n\n\ntwo\n'); | ||
const file = lines(filename); | ||
file.add(['foo', 'bar']); | ||
file.save(); | ||
expect(fs.readFileSync(filename, 'utf8')).toBe('one\ntwo\nfoo\nbar'); | ||
fs.unlink(filename); | ||
}); | ||
it('should not fail when reading an empty file', () => { | ||
@@ -84,2 +101,3 @@ const filename = 'empty.lines'; | ||
expect(fn).not.toThrow(); | ||
fs.unlink(filename); | ||
}); |
@@ -41,3 +41,3 @@ 'use strict'; | ||
save() { | ||
const content = lines.join('\n'); | ||
const content = lines.filter(value => value.trim()).join('\n'); | ||
core.updateFile(filename, content, originalContent, exists); | ||
@@ -44,0 +44,0 @@ return this; |
@@ -5,2 +5,3 @@ 'use strict'; | ||
const fs = require('./fs'); | ||
const npm = require('./npm'); | ||
const MrmError = require('./error'); | ||
@@ -14,3 +15,2 @@ const ini = require('./formats/ini'); | ||
const packageJson = require('./files/packageJson'); | ||
const install = require('./npm').install; | ||
@@ -23,2 +23,4 @@ module.exports = { | ||
makeDirs: fs.makeDirs, | ||
install: npm.install, | ||
uninstall: npm.uninstall, | ||
MrmError, | ||
@@ -32,3 +34,2 @@ ini, | ||
packageJson, | ||
install, | ||
}; |
@@ -6,3 +6,4 @@ // @ts-check | ||
const castArray = require('lodash/castArray'); | ||
const json = require('./formats/json'); | ||
const listify = require('listify'); | ||
const packageJson = require('./files/packageJson'); | ||
@@ -22,3 +23,3 @@ /** | ||
const pkg = json('package.json', { | ||
const pkg = packageJson({ | ||
dependencies: {}, | ||
@@ -35,6 +36,36 @@ devDependencies: {}, | ||
// eslint-disable-next-line no-console | ||
console.log(`Installing ${newDeps.join(', ')}...`); | ||
runNpm(newDeps, Object.assign({ dev }, options), exec); | ||
console.log(`Installing ${listify(newDeps)}...`); | ||
runNpm(newDeps, { dev }, exec); | ||
} | ||
/* | ||
* Uninstall given npm packages | ||
* | ||
* @param {string|string[]} deps | ||
* @param {Object} [options] | ||
* @param {boolean} [options.dev=true] --save-dev | ||
* @param {Function} [exec] | ||
*/ | ||
function uninstall(deps, options, exec) { | ||
options = options || {}; | ||
deps = castArray(deps); | ||
const dev = options.dev !== false; | ||
const pkg = packageJson({ | ||
dependencies: {}, | ||
devDependencies: {}, | ||
}); | ||
const installed = pkg.get(dev ? 'devDependencies' : 'dependencies') || {}; | ||
const newDeps = deps.filter(dep => installed[dep]); | ||
if (newDeps.length === 0) { | ||
return; | ||
} | ||
// eslint-disable-next-line no-console | ||
console.log(`Uninstalling ${listify(newDeps)}...`); | ||
runNpm(newDeps, { remove: true, dev }, exec); | ||
} | ||
/** | ||
@@ -46,2 +77,3 @@ * Install given npm packages | ||
* @param {boolean} [options.dev=true] --save-dev (--save by default) | ||
* @param {boolean} [options.remove=false] uninstall package (install by default) | ||
* @param {Function} [exec] | ||
@@ -67,2 +99,3 @@ * @return {Object} | ||
install, | ||
uninstall, | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
55409
1596
336
13
+ Addedlistify@^1.0.0
+ Addedlistify@1.0.3(transitive)