Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: convert to native ESM module #1038

Merged
merged 12 commits into from Nov 13, 2021
15 changes: 0 additions & 15 deletions .babelrc

This file was deleted.

26 changes: 21 additions & 5 deletions .eslintrc.json
Expand Up @@ -6,19 +6,35 @@
"experimentalObjectRestSpread": true
},
"requireConfigFile": false,
"sourceType": "script"
"sourceType": "module"
},
"env": {
"es6": true,
"node": true
},
"extends": ["eslint:recommended", "prettier"],
"extends": ["eslint:recommended", "plugin:import/recommended", "prettier"],
"plugins": ["node", "import", "prettier"],
"rules": {
"import/order": [
"error",
{
"groups": [
"builtin",
"external",
"internal",
"parent",
"sibling",
"index",
"object",
"type"
],
"newlines-between": "always"
}
],
"no-console": "off",
"node/no-unsupported-features/node-builtins": "off",
"node/no-unsupported-features/es-syntax": ["error", { "version": ">=10.13.0" }],
"node/no-unsupported-features/es-builtins": ["error", { "version": ">=10.13.0" }],
"node/no-unsupported-features/es-builtins": "error",
"node/no-unsupported-features/es-syntax": ["error", { "ignores": ["modules"] }],
"node/no-unsupported-features/node-builtins": "error",
"prettier/prettier": "error"
}
}
5 changes: 1 addition & 4 deletions .github/workflows/codeql.yml
Expand Up @@ -4,10 +4,7 @@ on:
push:
# Run on pushes to specific branches
branches:
- master
- next
- beta
- alpha
- "*"
# Do not run on tags
tags-ignore:
- "*"
Expand Down
16 changes: 10 additions & 6 deletions .github/workflows/main.yml
Expand Up @@ -60,12 +60,6 @@ jobs:
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
# Print current Node.js version
- run: node --version
# Print current npm version
- run: npm --version
# Print current Git version
- run: git --version
# Install node_modules
- uses: actions/cache@v2
id: cache-node_modules
Expand All @@ -76,6 +70,16 @@ jobs:
${{ matrix.os }}-${{ matrix.node }}-${{ hashFiles('**/package-lock.json') }}
- if: steps.cache-node_modules.outputs.cache-hit != 'true'
run: npm ci
# Print current Node.js version
- run: node --version
# Print current npm version
- run: npm --version
# Print current Git version
- run: git --version
# Print lint-staged version
- run: node bin/lint-staged.js --version
# Print lint-staged help text
- run: node bin/lint-staged.js --help
# Run tests
- run: npm test
# Upload coverage artifact from Node.js LTS
Expand Down
3 changes: 3 additions & 0 deletions babel.config.cjs
@@ -0,0 +1,3 @@
module.exports = {
presets: [['@babel/preset-env', { modules: 'cjs', targets: { node: 'current' } }]],
}
37 changes: 14 additions & 23 deletions bin/lint-staged.js
@@ -1,36 +1,27 @@
#!/usr/bin/env node

'use strict'
import fs from 'fs'

const fs = require('fs')
import cmdline from 'commander'
import debug from 'debug'
import supportsColor from 'supports-color'

import lintStaged from '../lib/index.js'
import { CONFIG_STDIN_ERROR } from '../lib/messages.js'

// Force colors for packages that depend on https://www.npmjs.com/package/supports-color
const supportsColor = require('supports-color')
if (supportsColor.stdout) {
process.env.FORCE_COLOR = supportsColor.stdout.level.toString()
}

// Do not terminate main Listr process on SIGINT
process.on('SIGINT', () => {})

const pkg = require('../package.json')
require('please-upgrade-node')(
Object.assign({}, pkg, {
engines: {
node: '>=12.13.0', // First LTS release of 'Erbium'
},
})
)
iiroj marked this conversation as resolved.
Show resolved Hide resolved

const cmdline = require('commander')
const debugLib = require('debug')
const lintStaged = require('../lib')
const { CONFIG_STDIN_ERROR } = require('../lib/messages')

const debug = debugLib('lint-staged:bin')
const packageJson = JSON.parse(fs.readFileSync('package.json'))
const version = packageJson.version

cmdline
.version(pkg.version)
.version(version)
.option('--allow-empty', 'allow empty commits when tasks revert all staged changes', false)
.option('-c, --config [path]', 'path to configuration file, or - to read from stdin')
.option('-d, --debug', 'print additional debug information', false)
Expand All @@ -50,11 +41,11 @@ cmdline
)
.parse(process.argv)

const debugLog = debug('lint-staged:bin')
if (cmdline.debug) {
debugLib.enable('lint-staged*')
debug.enable('lint-staged*')
}

debug('Running `lint-staged@%s`', pkg.version)
debugLog('Running `lint-staged@%s`', version)

/**
* Get the maximum length of a command-line argument string based on current platform
Expand Down Expand Up @@ -89,7 +80,7 @@ const options = {
verbose: !!cmdlineOptions.verbose,
}

debug('Options parsed from command-line:', options)
debugLog('Options parsed from command-line:', options)

if (options.configPath === '-') {
delete options.configPath
Expand Down
15 changes: 15 additions & 0 deletions jest.config.js
@@ -0,0 +1,15 @@
const config = {
collectCoverage: true,
collectCoverageFrom: ['lib/**/*.js'],
moduleDirectories: ['node_modules'],
setupFiles: ['./testSetup.js'],
snapshotSerializers: ['jest-snapshot-serializer-ansi'],
testEnvironment: 'node',
transform: {
'\\.[jt]sx?$': 'babel-jest',
},
/** Also transform ESM packages in `node_modules` */
transformIgnorePatterns: [],
iiroj marked this conversation as resolved.
Show resolved Hide resolved
}

export default config
19 changes: 10 additions & 9 deletions lib/chunkFiles.js
@@ -1,16 +1,17 @@
'use strict'
import path from 'path'

const debug = require('debug')('lint-staged:chunkFiles')
const normalize = require('normalize-path')
const path = require('path')
import debug from 'debug'
import normalize from 'normalize-path'

const debugLog = debug('lint-staged:chunkFiles')

/**
* Chunk array into sub-arrays
* @param {Array} arr
* @param {Number} chunkCount
* @retuns {Array<Array>}
*/
function chunkArray(arr, chunkCount) {
const chunkArray = (arr, chunkCount) => {
okonet marked this conversation as resolved.
Show resolved Hide resolved
if (chunkCount === 1) return [arr]
const chunked = []
let position = 0
Expand All @@ -32,21 +33,21 @@ function chunkArray(arr, chunkCount) {
* @param {Boolean} [opts.relative] whether files are relative to `gitDir` or should be resolved as absolute
* @returns {Array<Array<String>>}
*/
module.exports = function chunkFiles({ files, baseDir, maxArgLength = null, relative = false }) {
export const chunkFiles = ({ files, baseDir, maxArgLength = null, relative = false }) => {
okonet marked this conversation as resolved.
Show resolved Hide resolved
const normalizedFiles = files.map((file) =>
normalize(relative || !baseDir ? file : path.resolve(baseDir, file))
)

if (!maxArgLength) {
debug('Skip chunking files because of undefined maxArgLength')
debugLog('Skip chunking files because of undefined maxArgLength')
return [normalizedFiles] // wrap in an array to return a single chunk
}

const fileListLength = normalizedFiles.join(' ').length
debug(
debugLog(
`Resolved an argument string length of ${fileListLength} characters from ${normalizedFiles.length} files`
)
const chunkCount = Math.min(Math.ceil(fileListLength / maxArgLength), normalizedFiles.length)
debug(`Creating ${chunkCount} chunks for maxArgLength of ${maxArgLength}`)
debugLog(`Creating ${chunkCount} chunks for maxArgLength of ${maxArgLength}`)
return chunkArray(normalizedFiles, chunkCount)
}
16 changes: 7 additions & 9 deletions lib/execGit.js
@@ -1,18 +1,19 @@
'use strict'
import debug from 'debug'
import execa from 'execa'

const debug = require('debug')('lint-staged:git')
const execa = require('execa')
const debugLog = debug('lint-staged:execGit')
okonet marked this conversation as resolved.
Show resolved Hide resolved

/**
* Explicitly never recurse commands into submodules, overriding local/global configuration.
* @see https://git-scm.com/docs/git-config#Documentation/git-config.txt-submodulerecurse
*/
const NO_SUBMODULE_RECURSE = ['-c', 'submodule.recurse=false']

const GIT_GLOBAL_OPTIONS = [...NO_SUBMODULE_RECURSE]
// exported for tests
export const GIT_GLOBAL_OPTIONS = [...NO_SUBMODULE_RECURSE]

module.exports = async function execGit(cmd, options = {}) {
debug('Running git command', cmd)
export const execGit = async (cmd, options = {}) => {
debugLog('Running git command', cmd)
try {
const { stdout } = await execa('git', GIT_GLOBAL_OPTIONS.concat(cmd), {
...options,
Expand All @@ -24,6 +25,3 @@ module.exports = async function execGit(cmd, options = {}) {
throw new Error(all)
}
}

// exported for tests
module.exports.GIT_GLOBAL_OPTIONS = GIT_GLOBAL_OPTIONS
14 changes: 6 additions & 8 deletions lib/figures.js
@@ -1,10 +1,8 @@
const { blue, redBright, yellow } = require('colorette')
const { figures } = require('listr2')
import { blue, redBright, yellow } from 'colorette'
import { figures } from 'listr2'

const { arrowRight, cross, warning } = figures
export const info = blue(figures.arrowRight)

module.exports = {
info: blue(arrowRight),
error: redBright(cross),
warning: yellow(warning),
}
export const error = redBright(figures.cross)

export const warning = yellow(figures.warning)
38 changes: 14 additions & 24 deletions lib/file.js
@@ -1,26 +1,22 @@
'use strict'
import { promises as fs } from 'fs'

const debug = require('debug')('lint-staged:file')
const fs = require('fs')
const { promisify } = require('util')
import debug from 'debug'

const fsReadFile = promisify(fs.readFile)
const fsUnlink = promisify(fs.unlink)
const fsWriteFile = promisify(fs.writeFile)
const debugLog = debug('lint-staged:file')

/**
* Read contents of a file to buffer
* @param {String} filename
* @param {Boolean} [ignoreENOENT=true] — Whether to throw if the file doesn't exist
* @returns {Promise<Buffer>}
*/
const readFile = async (filename, ignoreENOENT = true) => {
debug('Reading file `%s`', filename)
export const readFile = async (filename, ignoreENOENT = true) => {
debugLog('Reading file `%s`', filename)
try {
return await fsReadFile(filename)
return await fs.readFile(filename)
} catch (error) {
if (ignoreENOENT && error.code === 'ENOENT') {
debug("File `%s` doesn't exist, ignoring...", filename)
debugLog("File `%s` doesn't exist, ignoring...", filename)
return null // no-op file doesn't exist
} else {
throw error
Expand All @@ -33,13 +29,13 @@ const readFile = async (filename, ignoreENOENT = true) => {
* @param {String} filename
* @param {Boolean} [ignoreENOENT=true] — Whether to throw if the file doesn't exist
*/
const unlink = async (filename, ignoreENOENT = true) => {
debug('Removing file `%s`', filename)
export const unlink = async (filename, ignoreENOENT = true) => {
debugLog('Removing file `%s`', filename)
try {
await fsUnlink(filename)
await fs.unlink(filename)
} catch (error) {
if (ignoreENOENT && error.code === 'ENOENT') {
debug("File `%s` doesn't exist, ignoring...", filename)
debugLog("File `%s` doesn't exist, ignoring...", filename)
} else {
throw error
}
Expand All @@ -51,13 +47,7 @@ const unlink = async (filename, ignoreENOENT = true) => {
* @param {String} filename
* @param {Buffer} buffer
*/
const writeFile = async (filename, buffer) => {
debug('Writing file `%s`', filename)
await fsWriteFile(filename, buffer)
}

module.exports = {
readFile,
unlink,
writeFile,
export const writeFile = async (filename, buffer) => {
debugLog('Writing file `%s`', filename)
await fs.writeFile(filename, buffer)
}
18 changes: 8 additions & 10 deletions lib/generateTasks.js
@@ -1,10 +1,10 @@
'use strict'
import path from 'path'

const micromatch = require('micromatch')
const normalize = require('normalize-path')
const path = require('path')
import debug from 'debug'
import micromatch from 'micromatch'
import normalize from 'normalize-path'

const debug = require('debug')('lint-staged:gen-tasks')
const debugLog = debug('lint-staged:generateTasks')

/**
* Generates all task commands, and filelist
Expand All @@ -16,8 +16,8 @@ const debug = require('debug')('lint-staged:gen-tasks')
* @param {boolean} [options.files] - Staged filepaths
* @param {boolean} [options.relative] - Whether filepaths to should be relative to gitDir
*/
const generateTasks = ({ config, cwd = process.cwd(), gitDir, files, relative = false }) => {
debug('Generating linter tasks')
export const generateTasks = ({ config, cwd = process.cwd(), gitDir, files, relative = false }) => {
debugLog('Generating linter tasks')

const absoluteFiles = files.map((file) => normalize(path.resolve(gitDir, file)))
const relativeFiles = absoluteFiles.map((file) => normalize(path.relative(cwd, file)))
Expand Down Expand Up @@ -47,10 +47,8 @@ const generateTasks = ({ config, cwd = process.cwd(), gitDir, files, relative =
const fileList = matches.map((file) => normalize(relative ? file : path.resolve(cwd, file)))

const task = { pattern, commands, fileList }
debug('Generated task: \n%O', task)
debugLog('Generated task: \n%O', task)

return task
})
}

module.exports = generateTasks