diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 18531b3..441975c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,13 +10,10 @@ jobs: fail-fast: false matrix: node-version: - - 14 - - 12 - - 10 - - 8 + - 16 steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - run: npm install diff --git a/cli.js b/cli.js index 6075c37..a983671 100755 --- a/cli.js +++ b/cli.js @@ -1,7 +1,7 @@ #!/usr/bin/env node -'use strict'; -const createXo = require('.'); +import process from 'node:process'; +import createXo from './index.js'; createXo({ - args: process.argv.slice(2) + args: process.argv.slice(2), }); diff --git a/index.js b/index.js index 8a77f22..7d198fa 100644 --- a/index.js +++ b/index.js @@ -1,20 +1,18 @@ -'use strict'; -const path = require('path'); -const minimist = require('minimist'); -const arrify = require('arrify'); -const argv = require('the-argv'); -const pathExists = require('path-exists'); -const readPkgUp = require('read-pkg-up'); -const writePkg = require('write-pkg'); -const execa = require('execa'); -const hasYarn = require('has-yarn'); +import process from 'node:process'; +import path from 'node:path'; +import fs from 'node:fs'; +import minimist from 'minimist'; +import {readPackageUpSync} from 'read-pkg-up'; +import {writePackageSync} from 'write-pkg'; +import execa from 'execa'; +import hasYarn from 'has-yarn'; const DEFAULT_TEST_SCRIPT = 'echo "Error: no test specified" && exit 1'; const PLURAL_OPTIONS = [ 'env', 'global', - 'ignore' + 'ignore', ]; const CONFIG_FILES = [ @@ -26,7 +24,7 @@ const CONFIG_FILES = [ '.jshintrc', '.jscsrc', '.jscs.json', - '.jscs.yaml' + '.jscs.yaml', ]; const buildTestScript = test => { @@ -43,7 +41,7 @@ const buildTestScript = test => { }; const warnConfigFile = packageCwd => { - const files = CONFIG_FILES.filter(file => pathExists.sync(path.join(packageCwd, file))); + const files = CONFIG_FILES.filter(file => fs.existsSync(path.join(packageCwd, file))); if (files.length === 0) { return; @@ -52,33 +50,38 @@ const warnConfigFile = packageCwd => { console.log(`${files.join(' & ')} can probably be deleted now that you're using XO.`); }; -module.exports = async (options = {}) => { - const packageResult = readPkgUp.sync({ +export default async function createXo(options = {}) { + const { + packageJson = {}, + path: packagePath = path.resolve(options.cwd || '', 'package.json'), + } = readPackageUpSync({ cwd: options.cwd, - normalize: false + normalize: false, }) || {}; - const packageJson = packageResult.package || {}; - const packagePath = packageResult.path || path.resolve(options.cwd || '', 'package.json'); + const packageCwd = path.dirname(packagePath); packageJson.scripts = packageJson.scripts || {}; packageJson.scripts.test = buildTestScript(packageJson.scripts.test); - const cli = minimist(options.args || argv()); + const cli = minimist(options.args || process.argv.slice(2)); delete cli._; for (const option of PLURAL_OPTIONS) { if (cli[option]) { - cli[`${option}s`] = arrify(cli[option]); + cli[`${option}s`] = [cli[option]].flat(); delete cli[option]; } } if (Object.keys(cli).length > 0) { - packageJson.xo = {...packageJson.xo, ...cli}; + packageJson.xo = { + ...packageJson.xo, + ...cli, + }; } - writePkg.sync(packagePath, packageJson); + writePackageSync(packagePath, packageJson); const post = () => { warnConfigFile(packageCwd); @@ -107,4 +110,4 @@ module.exports = async (options = {}) => { await execa('npm', ['install', '--save-dev', 'xo'], {cwd: packageCwd}); post(); -}; +} diff --git a/license b/license index e7af2f7..fa7ceba 100644 --- a/license +++ b/license @@ -1,6 +1,6 @@ MIT License -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) Sindre Sorhus (https://sindresorhus.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/package.json b/package.json index d110163..72ba915 100644 --- a/package.json +++ b/package.json @@ -4,18 +4,21 @@ "description": "Add XO to your project", "license": "MIT", "repository": "xojs/create-xo", + "funding": "https://github.com/xojs/create-xo?sponsor=1", "author": { "name": "Sindre Sorhus", "email": "sindresorhus@gmail.com", - "url": "sindresorhus.com" + "url": "https://sindresorhus.com" }, + "type": "module", + "bin": "./cli.js", + "exports": "./index.js", "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "scripts": { "test": "xo && ava" }, - "bin": "cli.js", "files": [ "index.js", "cli.js" @@ -32,19 +35,16 @@ "xo" ], "dependencies": { - "arrify": "^2.0.1", - "execa": "^1.0.0", - "has-yarn": "^2.1.0", - "minimist": "^1.1.3", - "path-exists": "^4.0.0", - "read-pkg-up": "^6.0.0", - "the-argv": "^1.0.0", - "write-pkg": "^4.0.0" + "execa": "^5.1.1", + "has-yarn": "^3.0.0", + "minimist": "^1.2.5", + "read-pkg-up": "^9.0.0", + "write-pkg": "^5.0.0" }, "devDependencies": { - "ava": "^2.4.0", - "dot-prop": "^5.1.0", - "temp-write": "^4.0.0", - "xo": "^0.25.3" + "ava": "^3.15.0", + "dot-prop": "^6.0.1", + "temp-write": "^5.0.0", + "xo": "^0.45.0" } } diff --git a/readme.md b/readme.md index 7be09e6..9cb6731 100644 --- a/readme.md +++ b/readme.md @@ -2,30 +2,26 @@ > Add [XO](https://github.com/xojs/xo) to your project - ## CLI -``` -$ npm init xo [options] +```sh +npm init xo [options] ``` Example: +```sh +npm init xo --space --no-semicolon ``` -$ npm init xo --space --no-semicolon -``` - ## API ### Usage ```js -const createXo = require('create-xo'); +import createXo from 'create-xo'; -(async () => { - await createXo(); -})(); +await createXo(); ``` ### createXo(options?) @@ -38,19 +34,19 @@ Type: `object` #### cwd -Type: `string`
+Type: `string`\ Default: `process.cwd()` -Current working directory. +The current working directory. #### args -Type: `string[]`
+Type: `string[]`\ Default: CLI arguments *(`process.argv.slice(2)`)* -Options to put in [XO's config](https://www.npmjs.com/package/xo#config) in `package.json`. +The options to put in [XO's config](https://www.npmjs.com/package/xo#config) in `package.json`. -For instance, with the arguments `['--space', '--env=node']` the following will be put in `package.json`: +For instance, with the arguments `['--space', '--env=node']`, the following will be put in `package.json`: ```json { diff --git a/test.js b/test.js index 727491b..6095159 100644 --- a/test.js +++ b/test.js @@ -1,11 +1,12 @@ -import path from 'path'; -import fs from 'fs'; +import path from 'node:path'; +import fs from 'node:fs'; +import process from 'node:process'; import tempWrite from 'temp-write'; import dotProp from 'dot-prop'; import test from 'ava'; -import createXo from '.'; +import createXo from './index.js'; -const originalArgv = process.argv.slice(); +const originalArgv = [...process.argv]; const {get} = dotProp; async function run(pkg) { @@ -13,7 +14,7 @@ async function run(pkg) { await createXo({ cwd: path.dirname(filepath), - skipInstall: true + skipInstall: true, }); return JSON.parse(fs.readFileSync(filepath, 'utf8')); @@ -28,8 +29,8 @@ test('empty package.json', async t => { test('has scripts', async t => { const pkg = await run({ scripts: { - start: '' - } + start: '', + }, }); t.is(get(pkg, 'scripts.test'), 'xo'); @@ -39,8 +40,8 @@ test('has scripts', async t => { test('has default test', async t => { const pkg = await run({ scripts: { - test: 'echo "Error: no test specified" && exit 1' - } + test: 'echo "Error: no test specified" && exit 1', + }, }); t.is(get(pkg, 'scripts.test'), 'xo'); @@ -50,8 +51,8 @@ test('has default test', async t => { test('has only xo', async t => { const pkg = await run({ scripts: { - test: 'xo' - } + test: 'xo', + }, }); t.is(get(pkg, 'scripts.test'), 'xo'); @@ -61,8 +62,8 @@ test('has only xo', async t => { test('has test', async t => { const pkg = await run({ scripts: { - test: 'ava' - } + test: 'ava', + }, }); t.is(get(pkg, 'scripts.test'), 'xo && ava'); @@ -70,12 +71,12 @@ test('has test', async t => { }); test('has cli args', async t => { - process.argv = originalArgv.concat(['--space']); + process.argv = [...originalArgv, '--space']; const pkg = await run({ scripts: { - start: '' - } + start: '', + }, }); process.argv = originalArgv; @@ -84,12 +85,12 @@ test('has cli args', async t => { }); test('has cli args and test', async t => { - process.argv = originalArgv.concat(['--env=node', '--env=browser']); + process.argv = [...originalArgv, '--env=node', '--env=browser']; const pkg = await run({ scripts: { - test: 'ava' - } + test: 'ava', + }, }); process.argv = originalArgv; @@ -99,12 +100,12 @@ test('has cli args and test', async t => { }); test('has cli args and existing config', async t => { - process.argv = originalArgv.concat(['--space']); + process.argv = [...originalArgv, '--space']; const pkg = await run({ xo: { - esnext: true - } + esnext: true, + }, }); process.argv = originalArgv; @@ -118,8 +119,8 @@ test('has existing config without cli args', async t => { const pkg = await run({ xo: { - esnext: true - } + esnext: true, + }, }); process.argv = originalArgv; @@ -128,7 +129,7 @@ test('has existing config without cli args', async t => { }); test('has everything covered when it comes to config', async t => { - process.argv = originalArgv.concat([ + process.argv = [...originalArgv, '--space', '--esnext', '--no-semicolon', @@ -137,8 +138,7 @@ test('has everything covered when it comes to config', async t => { '--global=foo', '--global=bar', '--ignore=foo', - '--ignore=bar' - ]); + '--ignore=bar']; const pkg = await run({});