Marmot (mrm) core utils
Utilities to write codemods for config files (JSON, YAML, INI, Markdown, etc.). Can be used to make tasks for mrm.
Example
Add ESLint to your project:
const { json, lines, packageJson, install } = require('mrm-core');
module.exports = function(config) {
const preset = config('preset', 'tamia');
const packages = ['eslint', `eslint-config-${preset}`];
const eslintrc = json('.eslintrc');
if (!eslintrc.get('extends').startsWith(preset)) {
eslintrc.set('extends', preset).save();
}
lines('.eslintignore').add('node_modules').save();
const pkg = packageJson()
.setScript('lint', 'eslint . --fix')
.setScript('pretest', 'npm run line')
.save();
install(packages);
};
module.exports.description = 'Adds ESLint with a custom preset';
Read more in mrm’s docs, and this talks is already included by default.
You can find more examples here.
You don’t have to use mrm-core with mrm, you can run this tasks from your own code:
const get = require('lodash/get');
const addEslint = require('./tasks/eslint');
const config = {
preset: 'airbnb',
};
const getConfig = (prop, defaultValue) => get(config, prop, defaultValue);
addEslint(getConfig);
Installation
npm install --save-dev mrm-core
API
Work with files
- Do not overwrite original files, .
- All functions (except getters) can be chained.
save()
will create file if it doesn’t exist or update it with new data.save()
will write file to disk only if the new content is different from the original file.
JSON
API:
const { json } = require('mrm-core')
const file = json('file name', { default: 'values' })
file.exists()
file.get()
file.get('key.subkey', 'default value')
file.set('key.subkey', 'value')
file.set({ key: value })
file.unset('key.subkey')
file.merge({ key: value })
file.save()
Example:
json('.eslintrc')
.merge({
extends: 'eslint-config-recommended',
})
.save();
YAML
API:
const { yaml } = require('mrm-core')
const file = yaml('file name', { default: 'values' })
file.exists()
file.get()
file.get('key.subkey', 'default value')
file.set('key.subkey', 'value')
file.set({ key: value })
file.unset('key.subkey')
file.merge({ key: value })
file.save()
Example:
yaml('.travis.yml')
.set('language', 'node_js')
.set('node_js', [4, 6])
.save();
INI
API:
const { ini } = require('mrm-core')
const file = ini('file name', 'comment')
file.exists()
file.get()
file.get('section name')
file.set('section name', { key: value })
file.unset('section name')
file.save()
Example:
const { ini } = require('mrm-core');
ini('.editorconfig', 'editorconfig.org')
.set('root', true)
.set('*', {
indent_style: 'tab',
end_of_line: 'lf'
})
.save();
Result:
root = true
[*]
indent_style = tab
end_of_line = lf
Plain text separated by new line
API:
const { lines } = require('mrm-core')
const file = lines('file name', ['default', 'values'])
file.exists()
file.get()
file.add('new')
file.add(['new', 'lines'])
file.remove('new')
file.remove(['new', 'lines'])
file.save()
Example:
lines('.eslintignore')
.add('node_modules')
.save();
Markdown
Note: use template
function to create Markdown files.
API:
const { markdown } = require('mrm-core')
const file = markdown('file name')
file.exists()
file.get()
file.addBadge('image URL', 'link URL', 'alt text')
file.save()
Example:
const name = 'pizza';
markdown('Readme.md')
.addBadge(
`https://travis-ci.org/${config('github')}/${name}.svg`,
`https://travis-ci.org/${config('github')}/${name}`,
'Build Status'
)
.save();
Plain text templates
Templates use ES6 template literals syntax.
API:
const { template } = require('mrm-core')
const file = template('file name', 'template file name')
file.exists()
file.get()
file.apply({ key: 'value' })
file.save()
Example:
template('License.md', path.join(__dirname, 'License.md'))
.apply(config(), {
year: (new Date()).getFullYear(),
})
.save();
Template:
The MIT License
===============
Copyright ${year} ${name} (${url}), contributors
Permission is hereby granted, free of charge, to any person obtaining...
Special files
package.json
API:
const { packageJson } = require('mrm-core')
const file = packageJson({ default: 'values' })
file.exists()
file.get()
file.getScript('test')
file.setScript('test', 'jest')
file.appendScript('test', 'jest')
file.prependScript('test', 'jest')
file.removeScript('test')
file.removeScript(/^mocha|ava$/)
file.removeScript('test', /b/)
file.save()
Example:
packageJson()
.appendScript('lint', 'eslint . --ext .js --fix')
.save();
File system helpers
const { copyFiles, makeDirs } = require('mrm-core')
copyFiles('source dir', 'file name')
copyFiles('source dir', ['file name 1', 'file name 2'])
copyFiles('source dir', 'file name', { overwrite: false })
makeDirs('dir name')
makeDirs(['dir name 1', 'dir name 2'])
Install and uninstall npm packages
Installs npm package(s) and saves them to package.json
if they aren’t installed yet.
const { install } = require('mrm-core')
install('eslint')
install(['tamia', 'lodash'], { dev: false })
Uninstalls npm package(s) and removes them from package.json
:
const { uninstall } = require('mrm-core')
uninstall('eslint')
uninstall(['tamia', 'lodash'], { dev: false })
Custom error class: MrmError
Use this class to notify user about expected errors in your tasks. It will be printed without a stack trace and will abort task.
const { MrmError } = require('mrm-core')
if (!fs.existsSync('.travis.yml')) {
throw new MrmError('Run travis task first');
}
Change log
The change log can be found on the Releases page.
Contributing
Everyone is welcome to contribute. Please take a moment to review the contributing guidelines.
Authors and license
Artem Sapegin and contributors.
MIT License, see the included License.md file.