7.1.22 • Published 2 years ago

mrm-core v7.1.22

Weekly downloads
21,203
License
MIT
Repository
github
Last release
2 years ago

mrm-core

npm

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}`];

  // .eslintrc
  const eslintrc = json('.eslintrc');
  if (!eslintrc.get('extends').startsWith(preset)) {
    eslintrc.set('extends', preset).save();
  }

  // .eslintignore
  lines('.eslintignore')
    .add('node_modules')
    .save();

  // package.json
  const pkg = packageJson()
    .setScript('lint', 'eslint . --fix')
    .setScript('pretest', 'npm run line')
    .save();

  // Install dependencies
  install(packages);
};
module.exports.description = 'Adds ESLint with a custom preset';

Read more in the docs, and this task is already included by default.

You can find more examples in my dotfiles repository.

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 mrm-core

API

Work with files

  • Do not overwrite original files, unless you want to.
  • 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.
  • save() will try to keep formatting (indentation, end of file new line) of the original file or use style from EditorConfig.

JSON

API:

const { json } = require('mrm-core');
const file = json('file name', { default: 'values' });
file.exists(); // File exists?
file.get(); // Return everything
file.get('key.subkey', 'default value'); // Return value with given address
file.set('key.subkey', 'value'); // Set value by given address
file.set({ key: value }); // Replace JSON with given object
file.unset('key.subkey'); // Remove value by given address
file.merge({ key: value }); // Merge JSON with given object
file.save(); // Save file
file.delete(); // Delete file

Example:

json('.eslintrc')
  .merge({
    extends: 'eslint-config-recommended'
  })
  .save();

YAML

API:

const { yaml } = require('mrm-core');
const file = yaml(
  'file name', // File name
  { default: 'values' }, // Default value
  { version: '1.2' } // Options
);
file.exists(); // File exists?
file.get(); // Return everything
file.get('key.subkey', 'default value'); // Return value with given address
file.set('key.subkey', 'value'); // Set value by given address
file.set({ key: value }); // Replace JSON with given object
file.unset('key.subkey'); // Remove value by given address
file.merge({ key: value }); // Merge JSON with given object
file.save(); // Save file
file.delete(); // Delete file

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 exists?
file.get(); // Return everything
file.get('section name'); // Return section value
file.set('section name', { key: value }); // Set section value
file.unset('section name'); // Remove section
file.save(); // Save file
file.save({ withSpaces: false }); // Disable spaces around =
file.delete(); // Delete file

Example:

const { ini } = require('mrm-core');
ini('.editorconfig', 'editorconfig.org')
  .set('_global', { root: true })
  .set('*', {
    indent_style: 'tab',
    end_of_line: 'lf'
  })
  .save();

Result:

# editorconfig.org
root = true

[*]
indent_style = tab
end_of_line = lf

New line separated text files

API:

const { lines } = require('mrm-core');
const file = lines('file name', ['default', 'values']);
file.exists(); // File exists?
file.get(); // Return everything
file.set(['line 1', 'line 2', 'line 3']); // Set file lines, overwrite existing
file.add('new'); // Add new line
file.add(['new', 'lines']); // Add multiple news lines
file.remove('new'); // Remove line
file.remove(['new', 'lines']); // Remove multiple lines
file.save(); // Save file
file.delete(); // Delete file

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 exists?
file.get(); // Return file content
// Add a badge at the beginning of the file (below header)
file.addBadge('image URL', 'link URL', 'alt text');
// Remove a badge when the predicate function returns true
file.removeBadge(({ imageUrl, linkUrl, altText }) =>
  imageUrl.startsWith('https://travis-ci.org')
);
file.save(); // Save file
file.delete(); // Delete file

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 ECMAScript template literals syntax.

API:

const { template } = require('mrm-core');
const file = template('file name', 'template file name');
file.exists(); // File exists?
file.get(); // Return file content
file.apply({ key: 'value' }); // Replace template tags with given values
file.save(); // Save file
file.delete(); // Delete file

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 exists?
file.get(); // Return everything
file.getScript('test'); // Return script
file.getScript('test', 'eslint'); // Return a subcommand of a script
file.setScript('test', 'eslint --fix'); // Replace a script with a command: a -> b
file.appendScript('test', 'eslint --fix'); // Append command to a script: a -> a && b
file.prependScript('test', 'eslint --fix'); // 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
file.delete(); // Delete file
// All methods of json() work too

Note: subcommand is a command between && in an npm script. For example, prettier --write '**/*.js' && eslint . --fix has two subcommands: prettier… and eslint….

Example:

packageJson()
  .appendScript('lint', 'eslint . --ext .js --fix')
  .save();

File system helpers

const { copyFiles, deleteFiles, makeDirs } = require('mrm-core');
copyFiles('source dir', 'file name'); // Copy file
copyFiles('source dir', ['file name 1', 'file name 2']); // Copy files
copyFiles('source dir', 'file name', { overwrite: false }); // Do not overwrite
deleteFiles('file name 1'); // Delete file or folder
deleteFiles(['file name 1', 'folder name 1']); // Delete files or folders
makeDirs('dir name'); // Create folder
makeDirs(['dir name 1', 'dir name 2']); // Create folders

Install and uninstall npm, Yarn, or pnpm packages

Installs npm package(s) and saves them to package.json if they aren’t installed yet or not satisfying range.

const { install } = require('mrm-core');
install('eslint'); // Install to devDependencies
install(['tamia', 'lodash'], { dev: false }); // Install to dependencies
install({ lodash: '^4.17.3' }); // Install particular version
install(['lodash'], {
  versions: { lodash: '^4.17.3', other: '1.0.0' }
}); // Install particular version
install(['github/repo']); // Install non-registry package without version

Note: Works with all semver ranges, like 1.2.3, ^1.2.0 or >=2.

Uninstalls npm package(s) and removes them from package.json:

const { uninstall } = require('mrm-core');
uninstall('eslint'); // Uninstall from devDependencies
uninstall(['tamia', 'lodash'], { dev: false }); // Uninstall from dependencies

To use Yarn pass yarn: true:

const { install, uninstall } = require('mrm-core');

uninstall(['eslint'], { yarn: true });
install(['standard'], { yarn: true });

With Yarn Berry, pass yarnBerry: true and for pnpm, pass pnpm: true.

Utilities

Infers style (indentation, new line at the end of file) from a source code or reads from the .editorconfig file.

const {
  inferStyle,
  getStyleForFile,
  getIndent,
  format
} = require('mrm-core');
inferStyle('for (;;) {\n  alert(1);\n}\n');
// => { insert_final_newline: true, indent_style: 'space', indent_size: 2 }
getStyleForFile('test.js');
// => { insert_final_newline: false, indent_style: 'tab', indent_size: 'tab' }
getIndent({ indent_style: 'space', indent_size: 2 });
// => '  '
format('alert(1)\n', { insert_final_newline: false });
// => 'alert(1)'
// Only insert_final_newline is supported

Get file extensions list from a command like eslint . --fix --ext .js,.jsx:

const { getExtsFromCommand } = require('mrm-core');
getExtsFromCommand(`eslint . --fix --ext .js,.jsx`, 'ext');
// => ['js', 'jsx']
getExtsFromCommand(`prettier --write '**/*.js'`);
// => ['js']

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');
}

Changelog

The changelog 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.

@ilscc/mrm-presetmrm-task-cocoscreator@infinitebrahmanuniverse/nolb-mr@everything-registry/sub-chunk-2211@puzzleitc/mrm-task-prettiervue-code-style-toolsvite_vue3_ts_ssssdddddyyyy@craft-first/mrm-preset@condor-labs/matchboxstrv-task-eslint@appruut/node-preset@appruut/sun@anpingli/mrm-preset@autots/cra-ts-config@adonisjs/sink@adonisjs/mrm-preset@aiyeola/task-manager@albanbl/mrm-preset@beenary/mrm-preset@azm/mrm-task-editorconfig@azm/mrm-task-eslint@azm/mrm-task-gitignore@azm/mrm-task-koa@azm/mrm-task-prettier@azm/mrm-task-rollup@afifu/setup@bingtsingw/mrm-preset@bhadurian/mrm-preset@betaorbust/scaffold@2digits/cli@20i/mrm-preset@achmadnf18/setup@danielfsousa/create@davidwells/mrm-task-ava@davidwells/mrm-task-typesxxxx-mrm-snowpackxxxx-devtestxxxx-mrm-gitxxxx-mrm-lintxxxx-mrm-presetwebpack-defaults@franklin1992/code_check@forbole/mrm-preset-forbole-rn@henson/mrm-preset@edukat/mrm-preset@koober/mrm-preset@lgfe/mrm-preset@macaw-email/cli@michaeldanilov/mrm-preset-michaeldanilov@ms918/mrm-task-branchclear@ms918/mrm-task-browserlist@ms918/mrm-task-cz@ms918/mrm-task-editorconfig@ms918/mrm-task-eslint@ms918/mrm-task-gitignore@ms918/mrm-task-husky@ms918/mrm-task-license@ms918/mrm-task-lint-staged@ms918/mrm-task-npmrc@ms918/mrm-task-package@ms918/mrm-task-prettier@ms918/mrm-task-readme@marvinroger/dev-core@marvinroger/fusee@nandenjin/mrm-preset@jannajs/lint@johnhom/mrm-preset@homebound/mrm-tasks-gitignore@homebound/mrm-tasks-prettier@homebound/mrm-tasks-typescript@moonwalker/mrm-preset-react@moonwalker/mrm-presets@s21toolkit/shared@open-xchange/mrm-preset@picter/lib-defaults@pinetwork-js/mrm-preset@smarthead/mrm-preset@solid-soda/scripts@speedlo/config@simlabs/mrm-preset-simlabs@releaseband/mrm-preset@rollup-cabal/hull@rollup/hullmrm-preset-defaultmrm-preset-drmikecrowemrm-preset-hwaterkemrm-preset-mbb-testmrm-preset-michaelmrm-preset-nearformmrm-preset-osuresearchmrm-preset-pinnsgmrm-preset-project-init-toolsmrm-preset-rmrmrm-preset-standard-versionmrm-preset-tayloredtechnologymrm-preset-thoroughmrm-preset-zardoymrmmrm-preset-agnosticmrm-preset-appit-rn-test
7.1.19

2 years ago

7.1.18

2 years ago

7.1.22

2 years ago

7.1.20

2 years ago

7.1.21

2 years ago

7.1.17

2 years ago

7.1.15

2 years ago

7.1.16

2 years ago

7.1.14

2 years ago

7.1.13

3 years ago

7.1.11

3 years ago

7.1.12

3 years ago

7.1.10

3 years ago

7.1.7

3 years ago

7.1.9

3 years ago

7.1.8

3 years ago

7.1.3

3 years ago

7.1.2

3 years ago

7.1.1

3 years ago

7.1.0

3 years ago

7.1.6

3 years ago

7.1.5

3 years ago

7.1.4

3 years ago

7.0.0

3 years ago

6.1.7

4 years ago

6.1.6

4 years ago

6.1.4

4 years ago

6.1.3

4 years ago

6.1.5

4 years ago

6.1.2

4 years ago

6.1.1

4 years ago

6.0.0

4 years ago

5.0.0

4 years ago

4.7.0

4 years ago

4.6.0

4 years ago

4.5.0

4 years ago

4.4.0

4 years ago

4.3.0

5 years ago

4.2.2

5 years ago

4.2.1

5 years ago

4.2.0

5 years ago

4.1.3

5 years ago

4.1.2

5 years ago

4.1.1

5 years ago

4.1.0

5 years ago

4.0.3

5 years ago

4.0.2

6 years ago

4.0.1

6 years ago

4.0.0

6 years ago

3.3.4

6 years ago

3.3.3

6 years ago

3.3.2

6 years ago

3.3.1

6 years ago

3.3.0

7 years ago

3.2.0

7 years ago

3.1.3

7 years ago

3.1.2

7 years ago

3.1.1

7 years ago

3.1.0

7 years ago

3.0.3

7 years ago

3.0.2

7 years ago

3.0.1

7 years ago

3.0.0

7 years ago

2.6.0

8 years ago

2.5.1

8 years ago

2.5.0

8 years ago

2.4.0

8 years ago

2.3.1

8 years ago

2.3.0

8 years ago

2.2.2

8 years ago

2.2.1

8 years ago

2.2.0

8 years ago

2.1.3

8 years ago

2.1.2

8 years ago

2.1.1

8 years ago

2.1.0

8 years ago

2.0.0

8 years ago

1.1.0

8 years ago

1.0.2

8 years ago

1.0.1

8 years ago

1.0.0

8 years ago

0.3.2

8 years ago

0.3.1

8 years ago

0.3.0

8 years ago

0.2.2

8 years ago

0.2.1

8 years ago

0.2.0

8 years ago

0.1.1

8 years ago

0.1.0

8 years ago