From e0ef3c626096403c5528e23c7253d3d90b927304 Mon Sep 17 00:00:00 2001 From: Adam Bergman Date: Wed, 29 Nov 2017 09:40:55 +0100 Subject: [PATCH 01/10] docs(readme): Update README links --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index bdd1e81..52d773f 100644 --- a/README.md +++ b/README.md @@ -122,3 +122,9 @@ Contributions of any kind welcome! ## LICENSE MIT + +[npm]: https://www.npmjs.com/ +[node]: https://nodejs.org +[prs]: http://makeapullrequest.com +[emojis]: https://github.com/kentcdodds/all-contributors#emoji-key +[all-contributors]: https://github.com/kentcdodds/all-contributors From 240fc523e7b4c69ede912f1a1fd2cbbb2a9acc33 Mon Sep 17 00:00:00 2001 From: Adam Bergman Date: Wed, 29 Nov 2017 11:34:35 +0100 Subject: [PATCH 02/10] feat(config): Update config files Update config files to match my projects needs instead of the originals from kcd-scripts --- src/config/__tests__/lintstagedrc.js | 1 + src/config/eslintrc.js | 7 +++---- src/config/jest.config.js | 2 +- src/config/lintstagedrc.js | 14 +++++++------- src/config/prettierignore | 1 + src/config/rollup.config.js | 8 ++++---- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/config/__tests__/lintstagedrc.js b/src/config/__tests__/lintstagedrc.js index 5e29a8b..ce0f853 100644 --- a/src/config/__tests__/lintstagedrc.js +++ b/src/config/__tests__/lintstagedrc.js @@ -1,3 +1,4 @@ +/* eslint-disable no-use-before-define */ import * as utilsMock from '../../utils'; jest.mock('../../utils', () => ({ diff --git a/src/config/eslintrc.js b/src/config/eslintrc.js index e9bac86..dea80a9 100644 --- a/src/config/eslintrc.js +++ b/src/config/eslintrc.js @@ -2,10 +2,9 @@ const { ifAnyDep } = require('../utils'); module.exports = { extends: [ - require.resolve('eslint-config-kentcdodds'), - require.resolve('eslint-config-kentcdodds/jest'), - ifAnyDep('react', require.resolve('eslint-config-kentcdodds/jsx-a11y')), - ifAnyDep('react', require.resolve('eslint-config-kentcdodds/react')), + require.resolve('eslint-config-airbnb-base'), + ifAnyDep('react', require.resolve('eslint-config-airbnb')), + require.resolve('eslint-config-prettier'), ].filter(Boolean), rules: {}, }; diff --git a/src/config/jest.config.js b/src/config/jest.config.js index dab5d7f..11a00a5 100644 --- a/src/config/jest.config.js +++ b/src/config/jest.config.js @@ -16,7 +16,7 @@ const jestConfig = { roots: [fromRoot('src')], testEnvironment: ifAnyDep(['webpack', 'rollup', 'react'], 'jsdom', 'node'), collectCoverageFrom: ['src/**/*.js'], - testMatch: ['**/__tests__/**/*.js'], + testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)(spec|test).js?(x)'], testPathIgnorePatterns: [...ignores], coveragePathIgnorePatterns: [...ignores, 'src/(umd|cjs|esm)-entry.js$'], transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'], diff --git a/src/config/lintstagedrc.js b/src/config/lintstagedrc.js index b4c2587..410e34e 100644 --- a/src/config/lintstagedrc.js +++ b/src/config/lintstagedrc.js @@ -1,6 +1,6 @@ -const { resolveKcdScripts, resolveBin, isOptedOut } = require('../utils'); +const { resolveFransScripts, resolveBin, isOptedOut } = require('../utils'); -const kcdScripts = resolveKcdScripts(); +const fransScripts = resolveFransScripts(); const doctoc = resolveBin('doctoc'); module.exports = { @@ -8,13 +8,13 @@ module.exports = { linters: { 'README.md': [`${doctoc} --maxlevel 3 --notitle`, 'git add'], '.all-contributorsrc': [ - `${kcdScripts} contributors generate`, + `${fransScripts} contributors generate`, 'git add README.md', ], - '**/*.+(js|json|less|css|ts|md)': [ - isOptedOut('autoformat', null, `${kcdScripts} format`), - `${kcdScripts} lint`, - `${kcdScripts} test --findRelatedTests`, + '**/*.+(js|jsx|json|less|scss|sass|css|ts|md)': [ + isOptedOut('autoformat', null, `${fransScripts} format`), + `${fransScripts} lint`, + `${fransScripts} test --findRelatedTests`, isOptedOut('autoformat', null, 'git add'), ].filter(Boolean), }, diff --git a/src/config/prettierignore b/src/config/prettierignore index 5ab667c..5abc85e 100644 --- a/src/config/prettierignore +++ b/src/config/prettierignore @@ -2,5 +2,6 @@ node_modules/ coverage/ dist/ build/ +!src/scripts/build out/ .next/ diff --git a/src/config/rollup.config.js b/src/config/rollup.config.js index 9053e0d..aeb5af4 100644 --- a/src/config/rollup.config.js +++ b/src/config/rollup.config.js @@ -19,10 +19,10 @@ const isNode = parseEnv('BUILD_NODE', false); const name = process.env.BUILD_NAME || capitalize(camelcase(pkg.name)); const defaultGlobals = Object.keys(pkg.peerDependencies || {}).reduce( - (deps, dep) => { - deps[dep] = capitalize(camelcase(dep)); - return deps; - }, + (deps, dep) => + Object.assign({}, deps, { + [dep]: capitalize(camelcase(dep)), + }), {}, ); From 63bf0a56612f2cd845306707a2f74aa9f420cd7d Mon Sep 17 00:00:00 2001 From: Adam Bergman Date: Wed, 29 Nov 2017 11:37:18 +0100 Subject: [PATCH 03/10] feat(scripts): Update scripts Update scripts to match my projects need instead of the original from kcd-scripts --- src/scripts/build/babel.js | 35 +++---- src/scripts/build/index.js | 6 +- src/scripts/build/rollup.js | 139 +++++++++++++++------------ src/scripts/format.js | 2 +- src/scripts/precommit/lint-staged.js | 4 +- src/scripts/validate.js | 11 ++- 6 files changed, 106 insertions(+), 91 deletions(-) diff --git a/src/scripts/build/babel.js b/src/scripts/build/babel.js index 81e6d82..fb0cedd 100644 --- a/src/scripts/build/babel.js +++ b/src/scripts/build/babel.js @@ -1,34 +1,35 @@ -const path = require('path') -const spawn = require('cross-spawn') -const rimraf = require('rimraf') -const {hasPkgProp, fromRoot, resolveBin, hasFile} = require('../../utils') +const path = require('path'); +const spawn = require('cross-spawn'); +const rimraf = require('rimraf'); +const { hasPkgProp, fromRoot, resolveBin, hasFile } = require('../../utils'); -const args = process.argv.slice(2) -const here = p => path.join(__dirname, p) +const args = process.argv.slice(2); +const here = p => path.join(__dirname, p); const useBuiltinConfig = - !args.includes('--presets') && !hasFile('.babelrc') && !hasPkgProp('babel') + !args.includes('--presets') && !hasFile('.babelrc') && !hasPkgProp('babel'); + const config = useBuiltinConfig ? ['--presets', here('../../config/babelrc.js')] - : [] + : []; const ignore = args.includes('--ignore') ? [] - : ['--ignore', '__tests__,__mocks__'] + : ['--ignore', '__tests__,__mocks__']; -const copyFiles = args.includes('--no-copy-files') ? [] : ['--copy-files'] +const copyFiles = args.includes('--no-copy-files') ? [] : ['--copy-files']; -const useSpecifiedOutDir = args.includes('--out-dir') -const outDir = useSpecifiedOutDir ? [] : ['--out-dir', 'dist'] +const useSpecifiedOutDir = args.includes('--out-dir'); +const outDir = useSpecifiedOutDir ? [] : ['--out-dir', 'dist']; if (!useSpecifiedOutDir && !args.includes('--no-clean')) { - rimraf.sync(fromRoot('dist')) + rimraf.sync(fromRoot('dist')); } const result = spawn.sync( - resolveBin('babel-cli', {executable: 'babel'}), + resolveBin('babel-cli', { executable: 'babel' }), [...outDir, ...copyFiles, ...ignore, ...config, 'src'].concat(args), - {stdio: 'inherit'} -) + { stdio: 'inherit' }, +); -process.exit(result.status) +process.exit(result.status); diff --git a/src/scripts/build/index.js b/src/scripts/build/index.js index 9b96498..8ca65b8 100644 --- a/src/scripts/build/index.js +++ b/src/scripts/build/index.js @@ -1,9 +1,9 @@ if (process.argv.includes('--browser')) { - console.error('--browser has been deprecated, use --bundle instead') + console.error('--browser has been deprecated, use --bundle instead'); } if (process.argv.includes('--bundle') || process.argv.includes('--browser')) { - require('./rollup') + require('./rollup'); } else { - require('./babel') + require('./babel'); } diff --git a/src/scripts/build/rollup.js b/src/scripts/build/rollup.js index 7c3e6cb..f52f295 100644 --- a/src/scripts/build/rollup.js +++ b/src/scripts/build/rollup.js @@ -1,75 +1,113 @@ -const path = require('path') -const fs = require('fs') -const spawn = require('cross-spawn') -const mkdirp = require('mkdirp') -const glob = require('glob') -const rimraf = require('rimraf') -const yargsParser = require('yargs-parser') +/* eslint-disable no-use-before-define */ +const path = require('path'); +const fs = require('fs'); +const spawn = require('cross-spawn'); +const mkdirp = require('mkdirp'); +const glob = require('glob'); +const rimraf = require('rimraf'); +const yargsParser = require('yargs-parser'); const { hasFile, resolveBin, fromRoot, getConcurrentlyArgs, -} = require('../../utils') +} = require('../../utils'); -const crossEnv = resolveBin('cross-env') -const rollup = resolveBin('rollup') -const args = process.argv.slice(2) -const here = p => path.join(__dirname, p) -const hereRelative = p => here(p).replace(process.cwd(), '.') -const parsedArgs = yargsParser(args) +const crossEnv = resolveBin('cross-env'); +const rollup = resolveBin('rollup'); +const args = process.argv.slice(2); +const here = p => path.join(__dirname, p); +const hereRelative = p => here(p).replace(process.cwd(), '.'); +const parsedArgs = yargsParser(args); const useBuiltinConfig = - !args.includes('--config') && !hasFile('rollup.config.js') + !args.includes('--config') && !hasFile('rollup.config.js'); const config = useBuiltinConfig ? `--config ${hereRelative('../../config/rollup.config.js')}` - : args.includes('--config') ? '' : '--config' // --config will pick up the rollup.config.js file + : args.includes('--config') ? '' : '--config'; // --config will pick up the rollup.config.js file const environment = parsedArgs.environment ? `--environment ${parsedArgs.environment}` - : '' -const watch = parsedArgs.watch ? '--watch' : '' + : ''; +const watch = parsedArgs.watch ? '--watch' : ''; -let formats = ['esm', 'cjs', 'umd', 'umd.min'] +let formats = ['esm', 'cjs', 'umd', 'umd.min']; if (typeof parsedArgs.bundle === 'string') { - formats = parsedArgs.bundle.split(',') + formats = parsedArgs.bundle.split(','); } -const defaultEnv = 'BUILD_ROLLUP=true' +const defaultEnv = 'BUILD_ROLLUP=true'; const getCommand = (env, ...flags) => [crossEnv, defaultEnv, env, rollup, config, environment, watch, ...flags] .filter(Boolean) - .join(' ') + .join(' '); -const buildPreact = args.includes('--p-react') +const buildPreact = args.includes('--p-react'); const scripts = buildPreact ? getPReactScripts() - : getConcurrentlyArgs(getCommands()) + : getConcurrentlyArgs(getCommands()); -const cleanBuildDirs = !args.includes('--no-clean') +const cleanBuildDirs = !args.includes('--no-clean'); if (cleanBuildDirs) { - rimraf.sync(fromRoot('dist')) + rimraf.sync(fromRoot('dist')); } if (buildPreact) { if (cleanBuildDirs) { - rimraf.sync(fromRoot('preact')) + rimraf.sync(fromRoot('preact')); } - mkdirp.sync(fromRoot('preact')) + mkdirp.sync(fromRoot('preact')); +} + +function getPReactScripts() { + const reactCommands = prefixKeys('react.', getCommands()); + const preactCommands = prefixKeys( + 'preact.', + getCommands('BUILD_PREACT=true'), + ); + return getConcurrentlyArgs(Object.assign(reactCommands, preactCommands)); +} + +function prefixKeys(prefix, object) { + return Object.entries(object).reduce( + (cmds, [key, value]) => + Object.assign({}, cmds, { + [`${prefix}${key}`]: value, + }), + {}, + ); +} + +function getCommands(env = '') { + return formats.reduce((cmds, format) => { + const [formatName, minify = false] = format.split('.'); + const nodeEnv = minify ? 'production' : 'development'; + const sourceMap = formatName === 'umd' ? '--sourcemap' : ''; + const buildMinify = Boolean(minify); + + return Object.assign({}, cmds, { + [format]: getCommand( + `BUILD_FORMAT=${formatName} BUILD_MINIFY=${buildMinify} NODE_ENV=${ + nodeEnv + } ${env}`, + sourceMap, + ), + }); + }, {}); } const result = spawn.sync(resolveBin('concurrently'), scripts, { stdio: 'inherit', -}) +}); if (result.status === 0 && buildPreact && !args.includes('--no-package-json')) { - const preactPkg = fromRoot('preact/package.json') - const preactDir = fromRoot('preact') - const cjsFile = glob.sync(fromRoot('preact/**/*.cjs.js'))[0] - const esmFile = glob.sync(fromRoot('preact/**/*.esm.js'))[0] + const preactPkg = fromRoot('preact/package.json'); + const preactDir = fromRoot('preact'); + const cjsFile = glob.sync(fromRoot('preact/**/*.cjs.js'))[0]; + const esmFile = glob.sync(fromRoot('preact/**/*.esm.js'))[0]; fs.writeFileSync( preactPkg, JSON.stringify( @@ -79,36 +117,9 @@ if (result.status === 0 && buildPreact && !args.includes('--no-package-json')) { module: path.relative(preactDir, esmFile), }, null, - 2 - ) - ) -} - -function getPReactScripts() { - const reactCommands = prefixKeys('react.', getCommands()) - const preactCommands = prefixKeys('preact.', getCommands('BUILD_PREACT=true')) - return getConcurrentlyArgs(Object.assign(reactCommands, preactCommands)) -} - -function prefixKeys(prefix, object) { - return Object.entries(object).reduce((cmds, [key, value]) => { - cmds[`${prefix}${key}`] = value - return cmds - }, {}) -} - -function getCommands(env = '') { - return formats.reduce((cmds, format) => { - const [formatName, minify = false] = format.split('.') - const nodeEnv = minify ? 'production' : 'development' - const sourceMap = formatName === 'umd' ? '--sourcemap' : '' - const buildMinify = Boolean(minify) - cmds[format] = getCommand( - `BUILD_FORMAT=${formatName} BUILD_MINIFY=${buildMinify} NODE_ENV=${nodeEnv} ${env}`, - sourceMap - ) - return cmds - }, {}) + 2, + ), + ); } -process.exit(result.status) +process.exit(result.status); diff --git a/src/scripts/format.js b/src/scripts/format.js index b4f34a2..3bde61e 100644 --- a/src/scripts/format.js +++ b/src/scripts/format.js @@ -33,7 +33,7 @@ const relativeArgs = args.map(a => a.replace(`${process.cwd()}/`, '')); const filesToApply = parsedArgs._.length ? [] - : ['**/*.+(js|json|less|css|ts|md)']; + : ['**/*.+(js|jsx|json|less|scss|css|ts|md)']; const result = spawn.sync( resolveBin('prettier'), diff --git a/src/scripts/precommit/lint-staged.js b/src/scripts/precommit/lint-staged.js index f0633c8..ce25efa 100644 --- a/src/scripts/precommit/lint-staged.js +++ b/src/scripts/precommit/lint-staged.js @@ -27,9 +27,9 @@ function fakeCosmiconfig(...args) { }); }, }; - } else { - return realCosmicConfig(...args); } + + return realCosmicConfig(...args); } if (useBuiltinConfig) { diff --git a/src/scripts/validate.js b/src/scripts/validate.js index cfb2467..aa7f6dd 100644 --- a/src/scripts/validate.js +++ b/src/scripts/validate.js @@ -24,10 +24,13 @@ const scripts = useDefaultScripts : ifScript('test', 'npm run test --silent -- --coverage'), flow: ifScript('flow', 'npm run flow --silent'), } - : validateScripts.split(',').reduce((scriptsToRun, name) => { - scriptsToRun[name] = `npm run ${name} --silent`; - return scriptsToRun; - }, {}); + : validateScripts.split(',').reduce( + (scriptsToRun, name) => + Object.assign({}, scriptsToRun, { + [name]: `npm run ${name} --silent`, + }), + {}, + ); const result = spawn.sync( resolveBin('concurrently'), From 40cebe412654f679e90c9b8fa4f0f00dc5ccb259 Mon Sep 17 00:00:00 2001 From: Adam Bergman Date: Wed, 29 Nov 2017 11:38:42 +0100 Subject: [PATCH 04/10] test: Update tests --- jest.config.js | 7 +++++++ src/__tests__/__snapshots__/index.js.snap | 4 +++- src/__tests__/index.js | 2 ++ src/__tests__/utils.js | 13 ++++++++----- src/scripts/__tests__/__snapshots__/format.js.snap | 6 +++--- src/scripts/__tests__/validate.js | 1 + 6 files changed, 24 insertions(+), 9 deletions(-) diff --git a/jest.config.js b/jest.config.js index d2d22b6..0643260 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,4 +2,11 @@ const { jest: jestConfig } = require('./src/config'); module.exports = Object.assign(jestConfig, { coverageThreshold: null, + testPathIgnorePatterns: [ + '/node_modules/', + '/fixtures/', + '/__tests__/helpers/', + '__mocks__', + 'src/scripts/test.js', + ], }); diff --git a/src/__tests__/__snapshots__/index.js.snap b/src/__tests__/__snapshots__/index.js.snap index 3922bbb..6ffcac7 100644 --- a/src/__tests__/__snapshots__/index.js.snap +++ b/src/__tests__/__snapshots__/index.js.snap @@ -37,7 +37,9 @@ Available Scripts: validate Options: - All options depend on the script. Docs will be improved eventually, but for most scripts you can assume that the args you pass will be forwarded to the respective tool that's being run under the hood. + All options depend on the script. Docs will be improved eventually, but for + most scripts you can assume that the args you pass will be forwarded to the + respective tool that's being run under the hood. May the force be with you. , diff --git a/src/__tests__/index.js b/src/__tests__/index.js index bc28db3..cbb64ed 100644 --- a/src/__tests__/index.js +++ b/src/__tests__/index.js @@ -19,8 +19,10 @@ cases( const originalExit = process.exit; const originalArgv = process.argv; const originalLog = console.log; + process.exit = jest.fn(); console.log = jest.fn(); + try { // tests process.argv = ['node', '../', ...args]; diff --git a/src/__tests__/utils.js b/src/__tests__/utils.js index 0793780..db86019 100644 --- a/src/__tests__/utils.js +++ b/src/__tests__/utils.js @@ -1,9 +1,12 @@ +/* eslint-disable no-use-before-define */ jest.mock('read-pkg-up', () => ({ sync: jest.fn(() => ({ pkg: {}, path: '/blah/package.json' })), })); + jest.mock('which', () => ({ sync: jest.fn(() => {}) })); -let whichSyncMock, readPkgUpSyncMock; +let whichSyncMock; +let readPkgUpSyncMock; beforeEach(() => { jest.resetModules(); @@ -23,17 +26,17 @@ test('appDirectory is the dirname to the package.json', () => { expect(require('../utils').appDirectory).toBe(pkgPath); }); -test('resolveKcdScripts resolves to src/index.js when in the frans-scripts package', () => { +test('resolveFransScripts resolves to src/index.js when in the frans-scripts package', () => { mockPkg({ pkg: { name: 'frans-scripts' } }); - expect(require('../utils').resolveKcdScripts()).toBe( + expect(require('../utils').resolveFransScripts()).toBe( require.resolve('../').replace(process.cwd(), '.'), ); }); -test('resolveKcdScripts resolves to frans-scripts if not in the frans-scripts package', () => { +test('resolveFransScripts resolves to frans-scripts if not in the frans-scripts package', () => { mockPkg({ pkg: { name: 'not-frans-scripts' } }); whichSyncMock.mockImplementationOnce(() => require.resolve('../')); - expect(require('../utils').resolveKcdScripts()).toBe('frans-scripts'); + expect(require('../utils').resolveFransScripts()).toBe('frans-scripts'); }); test(`resolveBin resolves to the full path when it's not in $PATH`, () => { diff --git a/src/scripts/__tests__/__snapshots__/format.js.snap b/src/scripts/__tests__/__snapshots__/format.js.snap index 16d370e..c795e5b 100644 --- a/src/scripts/__tests__/__snapshots__/format.js.snap +++ b/src/scripts/__tests__/__snapshots__/format.js.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`format --config arg can be used for a custom config 1`] = `prettier --ignore-path ./src/config/prettierignore --write **/*.+(js|json|less|css|ts|md) --config ./my-config.js`; +exports[`format --config arg can be used for a custom config 1`] = `prettier --ignore-path ./src/config/prettierignore --write **/*.+(js|jsx|json|less|scss|css|ts|md) --config ./my-config.js`; -exports[`format --ignore-path arg can be used for a custom ignore file 1`] = `prettier --config ./src/config/prettierrc.js --write **/*.+(js|json|less|css|ts|md) --ignore-path ./.myignore`; +exports[`format --ignore-path arg can be used for a custom ignore file 1`] = `prettier --config ./src/config/prettierrc.js --write **/*.+(js|jsx|json|less|scss|css|ts|md) --ignore-path ./.myignore`; -exports[`format --no-write prevents --write argument from being added 1`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore **/*.+(js|json|less|css|ts|md) --no-write`; +exports[`format --no-write prevents --write argument from being added 1`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore **/*.+(js|jsx|json|less|scss|css|ts|md) --no-write`; exports[`format calls prettier CLI with args 1`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore --write my-src/**/*.js`; diff --git a/src/scripts/__tests__/validate.js b/src/scripts/__tests__/validate.js index d63e5fc..718d07b 100644 --- a/src/scripts/__tests__/validate.js +++ b/src/scripts/__tests__/validate.js @@ -1,3 +1,4 @@ +/* eslint-disable no-use-before-define */ import cases from 'jest-in-case'; import { unquoteSerializer } from './helpers/serializers'; From 29c5ab0c15afdfd06568c4354dcaab13e80d23f7 Mon Sep 17 00:00:00 2001 From: Adam Bergman Date: Wed, 29 Nov 2017 11:39:45 +0100 Subject: [PATCH 05/10] feat(Update utils and run-script): Mostly fixing lint errors and formatting with prettier --- src/run-script.js | 108 +++++++++++++++++++++++----------------------- src/utils.js | 40 +++++++++-------- 2 files changed, 77 insertions(+), 71 deletions(-) diff --git a/src/run-script.js b/src/run-script.js index aca8939..189588f 100755 --- a/src/run-script.js +++ b/src/run-script.js @@ -3,37 +3,6 @@ const spawn = require('cross-spawn'); const glob = require('glob'); const [executor, ignoredBin, script, ...args] = process.argv; -if (script) { - spawnScript(); -} else { - const scriptsPath = path.join(__dirname, 'scripts/'); - const scriptsAvailable = glob.sync(path.join(__dirname, 'scripts', '*')); - // `glob.sync` returns paths with unix style path separators even on Windows. - // So we normalize it before attempting to strip out the scripts path. - const scriptsAvailableMessage = scriptsAvailable - .map(path.normalize) - .map(s => - s - .replace(scriptsPath, '') - .replace(/__tests__/, '') - .replace(/\.js$/, ''), - ) - .filter(Boolean) - .join('\n ') - .trim(); - const fullMessage = ` -Usage: ${ignoredBin} [script] [--flags] - -Available Scripts: - ${scriptsAvailableMessage} - -Options: - All options depend on the script. Docs will be improved eventually, but for most scripts you can assume that the args you pass will be forwarded to the respective tool that's being run under the hood. - -May the force be with you. - `.trim(); - console.log(`\n${fullMessage}\n`); -} function getEnv() { // this is required to address an issue in cross-spawn @@ -41,35 +10,13 @@ function getEnv() { return Object.keys(process.env) .filter(key => process.env[key] !== undefined) .reduce( - (envCopy, key) => { - envCopy[key] = process.env[key]; - return envCopy; - }, + (envCopy, key) => Object.assign({}, envCopy, { [key]: process.env[key] }), { [`SCRIPTS_${script.toUpperCase()}`]: true, }, ); } -function spawnScript() { - const relativeScriptPath = path.join(__dirname, './scripts', script); - const scriptPath = attemptResolve(relativeScriptPath); - - if (!scriptPath) { - throw new Error(`Unknown script "${script}".`); - } - const result = spawn.sync(executor, [scriptPath, ...args], { - stdio: 'inherit', - env: getEnv(), - }); - - if (result.signal) { - handleSignal(result); - } else { - process.exit(result.status); - } -} - function handleSignal(result) { if (result.signal === 'SIGKILL') { console.log( @@ -94,3 +41,56 @@ function attemptResolve(...resolveArgs) { return null; } } + +function spawnScript() { + const relativeScriptPath = path.join(__dirname, './scripts', script); + const scriptPath = attemptResolve(relativeScriptPath); + + if (!scriptPath) { + throw new Error(`Unknown script "${script}".`); + } + const result = spawn.sync(executor, [scriptPath, ...args], { + stdio: 'inherit', + env: getEnv(), + }); + + if (result.signal) { + handleSignal(result); + } else { + process.exit(result.status); + } +} + +if (script) { + spawnScript(); +} else { + const scriptsPath = path.join(__dirname, 'scripts/'); + const scriptsAvailable = glob.sync(path.join(__dirname, 'scripts', '*')); + // `glob.sync` returns paths with unix style path separators even on Windows. + // So we normalize it before attempting to strip out the scripts path. + const scriptsAvailableMessage = scriptsAvailable + .map(path.normalize) + .map(s => + s + .replace(scriptsPath, '') + .replace(/__tests__/, '') + .replace(/\.js$/, ''), + ) + .filter(Boolean) + .join('\n ') + .trim(); + const fullMessage = ` +Usage: ${ignoredBin} [script] [--flags] + +Available Scripts: + ${scriptsAvailableMessage} + +Options: + All options depend on the script. Docs will be improved eventually, but for + most scripts you can assume that the args you pass will be forwarded to the + respective tool that's being run under the hood. + +May the force be with you. + `.trim(); + console.log(`\n${fullMessage}\n`); +} diff --git a/src/utils.js b/src/utils.js index 0a97046..600f919 100644 --- a/src/utils.js +++ b/src/utils.js @@ -10,13 +10,6 @@ const { pkg, path: pkgPath } = readPkgUp.sync({ }); const appDirectory = path.dirname(pkgPath); -function resolveKcdScripts() { - if (pkg.name === 'frans-scripts') { - return require.resolve('./').replace(process.cwd(), '.'); - } - return resolveBin('frans-scripts'); -} - // eslint-disable-next-line complexity function resolveBin( modName, @@ -28,6 +21,7 @@ function resolveBin( } catch (_error) { // ignore _error } + try { const modPkgPath = require.resolve(`${modName}/package.json`); const modPkgDir = path.dirname(modPkgPath); @@ -46,6 +40,13 @@ function resolveBin( } } +function resolveFransScripts() { + if (pkg.name === 'frans-scripts') { + return require.resolve('./').replace(process.cwd(), '.'); + } + return resolveBin('frans-scripts'); +} + const fromRoot = (...p) => path.join(appDirectory, ...p); const hasFile = (...p) => fs.existsSync(fromRoot(...p)); const ifFile = (files, t, f) => @@ -71,21 +72,21 @@ const ifDevDep = ifPkgSubProp('devDependencies'); const ifAnyDep = (deps, t, f) => (hasAnyDep(arrify(deps)) ? t : f); const ifScript = ifPkgSubProp('scripts'); -function parseEnv(name, def) { - if (envIsSet(name)) { - return JSON.parse(process.env[name]); - } - return def; -} - function envIsSet(name) { return ( - process.env.hasOwnProperty(name) && + process.env.hasOwnProperty(name) && // eslint-disable-line process.env[name] && process.env[name] !== 'undefined' ); } +function parseEnv(name, def) { + if (envIsSet(name)) { + return JSON.parse(process.env[name]); + } + return def; +} + function getConcurrentlyArgs(scripts, { killOthers = true } = {}) { const colors = [ 'bgBlue', @@ -97,12 +98,15 @@ function getConcurrentlyArgs(scripts, { killOthers = true } = {}) { 'bgBlack', 'bgYellow', ]; + + // eslint-disable-next-line scripts = Object.entries(scripts).reduce((all, [name, script]) => { if (script) { - all[name] = script; + return Object.assign({}, all, { [name]: script }); } return all; }, {}); + const prefixColors = Object.keys(scripts) .reduce( (pColors, _s, i) => @@ -125,6 +129,7 @@ function isOptedOut(key, t = true, f = false) { if (!fs.existsSync(fromRoot('.opt-out'))) { return f; } + const contents = fs.readFileSync(fromRoot('.opt-out'), 'utf-8'); return contents.includes(key) ? t : f; } @@ -133,6 +138,7 @@ function isOptedIn(key, t = true, f = false) { if (!fs.existsSync(fromRoot('.opt-in'))) { return f; } + const contents = fs.readFileSync(fromRoot('.opt-in'), 'utf-8'); return contents.includes(key) ? t : f; } @@ -156,5 +162,5 @@ module.exports = { parseEnv, pkg, resolveBin, - resolveKcdScripts, + resolveFransScripts, }; From c8285634711fea2da296e3f8268b650a0fd725df Mon Sep 17 00:00:00 2001 From: Adam Bergman Date: Wed, 29 Nov 2017 11:42:07 +0100 Subject: [PATCH 06/10] fix: Update entry scripts Add eslint ignore statement due to warning that comes up before the project is built for the first time --- babel.js | 1 + config.js | 1 + eslint.js | 1 + jest.js | 1 + prettier.js | 1 + 5 files changed, 5 insertions(+) diff --git a/babel.js b/babel.js index 953754c..effb31d 100644 --- a/babel.js +++ b/babel.js @@ -1 +1,2 @@ +/* eslint-disable import/no-unresolved */ module.exports = require('./dist/config/babelrc'); diff --git a/config.js b/config.js index 6dc0106..27a8db0 100644 --- a/config.js +++ b/config.js @@ -1 +1,2 @@ +/* eslint-disable import/no-unresolved */ module.exports = require('./dist/config'); diff --git a/eslint.js b/eslint.js index 286e06a..2d3252d 100644 --- a/eslint.js +++ b/eslint.js @@ -1 +1,2 @@ +/* eslint-disable import/no-unresolved */ module.exports = require('./dist/config/eslintrc'); diff --git a/jest.js b/jest.js index 7016985..3a2ce25 100644 --- a/jest.js +++ b/jest.js @@ -1 +1,2 @@ +/* eslint-disable import/no-unresolved */ module.exports = require('./dist/config/jest.config'); diff --git a/prettier.js b/prettier.js index 898d033..9d3170a 100644 --- a/prettier.js +++ b/prettier.js @@ -1 +1,2 @@ +/* eslint-disable import/no-unresolved */ module.exports = require('./dist/config/prettierrc'); From cadd57996db757bb8934bb2d462ab734b5df9a19 Mon Sep 17 00:00:00 2001 From: Adam Bergman Date: Wed, 29 Nov 2017 11:43:11 +0100 Subject: [PATCH 07/10] chore: Add eslint dependencies --- package.json | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index ada22fb..b3dacab 100644 --- a/package.json +++ b/package.json @@ -59,9 +59,13 @@ "cross-env": "^5.1.1", "cross-spawn": "^5.1.0", "doctoc": "^1.3.0", - "eslint": "^4.11.0", - "eslint-config-kentcdodds": "^13.0.1", - "eslint-config-prettier": "^2.8.0", + "eslint": "^4.12.0", + "eslint-config-airbnb": "^16.1.0", + "eslint-config-airbnb-base": "^12.1.0", + "eslint-config-prettier": "^2.9.0", + "eslint-plugin-import": "^2.8.0", + "eslint-plugin-jsx-a11y": "^6.0.2", + "eslint-plugin-react": "^7.5.1", "glob": "^7.1.2", "husky": "^0.14.3", "is-ci": "^1.0.10", @@ -91,8 +95,13 @@ "slash": "^1.0.0" }, "eslintConfig": { - "extends": ["kentcdodds", "kentcdodds/jest"], + "extends": ["airbnb-base", "prettier"], + "env": { + "node": true, + "jest": true + }, "rules": { + "global-require": "off", "no-process-exit": "off", "import/no-dynamic-require": "off", "import/no-unassigned-import": "off", From 4d08a009fdaff32b9ee75b5e02230fc94041166f Mon Sep 17 00:00:00 2001 From: Adam Bergman Date: Wed, 29 Nov 2017 12:06:32 +0100 Subject: [PATCH 08/10] ci: Update CI settings --- .travis.yml | 3 +-- package.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index cb429cb..b2f4e36 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,7 @@ -sudo: false language: node_js cache: directories: - - node_modules + - ~/.npm notifications: email: false node_js: diff --git a/package.json b/package.json index b3dacab..4b10bfc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "frans-scripts", - "version": "0.0.0-semantically-released", + "version": "0.0.0-development", "description": "CLI for common scripts for my projects", "engines": { "node": ">= 8", From 2e07c002a7b349687365eed9200dc2c9241502eb Mon Sep 17 00:00:00 2001 From: Adam Bergman Date: Wed, 29 Nov 2017 12:23:31 +0100 Subject: [PATCH 09/10] build: Update version in package.json Update version in package.json so that the script travis-after-success will run --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b10bfc..b3dacab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "frans-scripts", - "version": "0.0.0-development", + "version": "0.0.0-semantically-released", "description": "CLI for common scripts for my projects", "engines": { "node": ">= 8", From a22d27df879d2e5a5e82c698a28d0063645abb90 Mon Sep 17 00:00:00 2001 From: Adam Bergman Date: Wed, 29 Nov 2017 12:29:12 +0100 Subject: [PATCH 10/10] build: Update version in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b10bfc..b3dacab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "frans-scripts", - "version": "0.0.0-development", + "version": "0.0.0-semantically-released", "description": "CLI for common scripts for my projects", "engines": { "node": ">= 8",