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

Add tsdx lint command #99

Merged
merged 34 commits into from
Aug 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a53365a
feat(lint): Add tsdx lint command
sam-kvale-sap May 11, 2019
c2d5ff8
feat(lint): process.exit(1) when errorCount > 0
sam-kvale-sap May 11, 2019
b34a8f4
style(lint): Fix lint errors that failed the CI build
sam-kvale-sap May 11, 2019
641f5fb
feat(lint): Play nicely with pretty-quick husky hook
sam-kvale-sap May 11, 2019
87d26f6
feat(lint): Install eslint-prettier dependencies, remove tslint devDeps
sam-kvale-sap May 11, 2019
2009b77
feat(lint): Add jsx linting support for React by default
sam-kvale-sap May 11, 2019
ec9ee11
fix(lint): Fix local ignore-pattern
sam-kvale-sap May 11, 2019
dcf82df
feat(lint): Use @typescript-eslint/no-unused-vars instead of typescri…
sam-kvale-sap May 13, 2019
9467d40
Merge branch 'master' into feat/linting-command
swyxio May 17, 2019
5f82e13
Update lockfile
jaredpalmer May 30, 2019
6be8bc4
Merge branch 'master' into pr/skvale/99
jaredpalmer May 30, 2019
17a1f6c
Merge branch 'master' into pr/skvale/99
jaredpalmer May 30, 2019
97e97c2
Add pre-commit lint hook
jaredpalmer May 30, 2019
6fafc73
Specify no-unused-locals in tsconfig
jaredpalmer May 30, 2019
0794e13
feat(lint): Extend react-app from eslint-config-react-app
sam-kvale-sap May 30, 2019
eae9bac
test(lint): Tests no longer failed from spacing violations
sam-kvale-sap May 30, 2019
63cb7eb
feat(lint): Could just extend react-app instead of overriding anything
sam-kvale-sap May 30, 2019
42fb986
feat(lint): Use prettier eslint for tsdx as an opt-in
sam-kvale-sap May 30, 2019
4332881
feat(lint): Optionally use prettier with --prettier flag
sam-kvale-sap May 30, 2019
12f2e99
feat(lint): Specify how to customize the lint rules in the README
sam-kvale-sap May 30, 2019
92adf03
feat(lint): Use prettier by default again
sam-kvale-sap May 31, 2019
eb2fe5b
Merge branch 'master' into feat/linting-command
sam-kvale-sap Jun 22, 2019
3f57f61
feat(lint): Use eslint@6
sam-kvale-sap Jun 22, 2019
4197482
chore(lockfile): Commit updated lockfile
sam-kvale-sap Jun 22, 2019
257a196
feat(lint): Update to @typescript-eslint/{parser,eslint-plugin} v1.11.0
sam-kvale-sap Jun 24, 2019
83c753d
chore(deps): Bump eslint and @typescript-eslint
sam-kvale-sap Jul 12, 2019
1604e99
Merge branch 'master' into feat/linting-command
sam-kvale-sap Jul 12, 2019
a51795a
Merge branch 'master' into feat/linting-command
sam-kvale-sap Jul 27, 2019
9d595a5
feat(lint): Bump deps and simplify createEslintConfig
sam-kvale-sap Aug 10, 2019
215cd93
feat(lint): Simplify written eslintrc
sam-kvale-sap Aug 10, 2019
530b8b5
chore(docs): Remove wrongfully merged README addition
sam-kvale-sap Aug 10, 2019
fe37a21
chore(yarn.lock): Fix merge issue with the babel/core version
sam-kvale-sap Aug 10, 2019
65ea74f
feat(lint): Bump eslint-config-react-app dep
sam-kvale-sap Aug 13, 2019
00584a1
feat(lint): Last small updates
sam-kvale-sap Aug 14, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ jobs:
name: Build
command: yarn build

- run:
name: Lint
command: yarn lint:post-build

- run:
name: Run tests
command: yarn test --runInBand --no-cache --coverage
Expand Down
7 changes: 7 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
extends: [
'react-app',
'prettier/@typescript-eslint',
'plugin:prettier/recommended',
],
};
33 changes: 31 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,23 @@ Despite all the recent hype, setting up a new TypeScript (x React) library can b
- [`npm start` or `yarn start`](#npm-start-or-yarn-start)
- [`npm run build` or `yarn build`](#npm-run-build-or-yarn-build)
- [`npm test` or `yarn test`](#npm-test-or-yarn-test)
- [`npm run lint` or `yarn lint`](#npm-run-lint-or-yarn-lint)
- [Optimizations](#optimizations)
- [Development-only Expressions + Treeshaking](#development-only-expressions--treeshaking)
- [Rollup Treeshaking](#rollup-treeshaking)
- [Advanced `babel-plugin-dev-expressions`](#advanced-babel-plugin-dev-expressions)
- [`__DEV__`](#__dev__)
- [`__DEV__`](#dev)
- [`invariant`](#invariant)
- [`warning`](#warning)
- [Using lodash](#using-lodash)
- [Hosting extracted errors](#hosting-extracted-errors)
- [Error extraction](#error-extraction)
- [Inspiration](#inspiration)
- [Comparison to Microbundle](#comparison-to-microbundle)
- [API Reference](#api-reference)
- [`tsdx watch`](#tsdx-watch)
- [`tsdx build`](#tsdx-build)
- [`tsdx test`](#tsdx-test)
- [`tsdx lint`](#tsdx-lint)
- [Author](#author)
- [License](#license)

Expand Down Expand Up @@ -77,6 +79,11 @@ The package is optimized and bundled with Rollup into multiple formats (CommonJS
Runs the test watcher (Jest) in an interactive mode.
By default, runs tests related to files changed since the last commit.

### `npm run lint` or `yarn lint`

Runs Eslint with Prettier on .ts and .tsx files.
If you want to customize eslint you can add an `eslint` block to your package.json, or you can run `yarn lint --write-file` and edit the generated `.eslintrc.js` file.

## Optimizations

Aside from just bundling your module into different formats, TSDX comes with some optimizations for your convenience. They yield objectively better code and smaller bundle sizes.
Expand Down Expand Up @@ -343,6 +350,28 @@ Examples

This runs Jest v24.x in watch mode. See [https://jestjs.io](https://jestjs.io) for options. If you are using the React template, jest uses the flag `--env=jsdom` by default.

### `tsdx lint`

```shell
Description
Run eslint with Prettier

Usage
$ tsdx lint [options]

Options
--fix Fixes fixable errors and warnings
--ignore-pattern Ignore a pattern
--write-file Write the config file locally
-h, --help Displays this message

Examples
$ tsdx lint src
$ tsdx lint src --fix
$ tsdx lint src test --ignore-pattern test/foo.ts
$ tsdx lint src --write-file
```

## Author

- [Jared Palmer](https://twitter.com/jaredpalmer)
Expand Down
24 changes: 18 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
"scripts": {
"prepare": "tsc -p tsconfig.json",
"build": "tsc -p tsconfig.json",
"lint": "yarn build && yarn lint:post-build",
"lint:post-build": "node dist/index.js lint src test --ignore-pattern 'test/tests/lint'",
"test": "jest --config ./test/jest.config.json"
},
"files": [
Expand All @@ -35,6 +37,8 @@
"@babel/plugin-proposal-class-properties": "^7.4.4",
"@babel/polyfill": "^7.4.4",
"@babel/preset-env": "^7.4.4",
"@typescript-eslint/eslint-plugin": "^1.13.0",
"@typescript-eslint/parser": "^1.13.0",
"ansi-escapes": "^3.2.0",
"asyncro": "^3.0.0",
"babel-plugin-annotate-pure-calls": "^0.4.0",
Expand All @@ -47,6 +51,15 @@
"chalk": "^2.4.2",
"cross-env": "5.2.0",
"enquirer": "^2.3.0",
"eslint": "^6.1.0",
"eslint-config-prettier": "^6.0.0",
"eslint-config-react-app": "^5.0.1",
"eslint-plugin-flowtype": "^4.2.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-react": "^7.14.3",
"eslint-plugin-react-hooks": "^1.7.0",
"execa": "^1.0.0",
"fs-extra": "^8.0.1",
"jest": "^24.8.0",
Expand All @@ -55,6 +68,7 @@
"mkdirp": "^0.5.1",
"ora": "^3.4.0",
"pascal-case": "^2.0.1",
"prettier": "^1.18.2",
"progress-estimator": "^0.2.2",
"rollup": "^1.12.0",
"rollup-plugin-babel": "^4.3.2",
Expand All @@ -74,32 +88,30 @@
"devDependencies": {
"@types/ansi-escapes": "^4.0.0",
"@types/camelcase": "^5.2.0",
"@types/eslint": "^4.16.8",
"@types/execa": "^0.9.0",
"@types/fs-extra": "^8.0.0",
"@types/jest": "^24.0.15",
"@types/mkdirp": "^0.5.2",
"@types/ms": "^0.7.30",
"@types/node": "^12.0.2",
"@types/ora": "^3.2.0",
"@types/react": "^16.8.17",
"@types/rollup-plugin-json": "^3.0.2",
"@types/rollup-plugin-sourcemaps": "^0.4.2",
"husky": "^2.3.0",
"prettier": "^1.17.1",
"pretty-quick": "^1.10.0",
"ps-tree": "^1.2.0",
"react": "^16.8.6",
"shelljs": "^0.8.3",
"tslint": "^5.16.0",
"tslint-config-palmerhq": "^1.0.2",
"tslint-config-prettier": "^1.18.0",
"tslint-react": "^4.0.0",
"typescript": "^3.4.5"
},
"peerDependencies": {
"typescript": "3"
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged"
"pre-commit": "pretty-quick --staged --pattern '!test/tests/lint/**' && yarn lint"
}
},
"prettier": {
Expand Down
41 changes: 41 additions & 0 deletions src/createEslintConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import fs from 'fs';
import path from 'path';
import { CLIEngine } from 'eslint';

interface CreateEslintConfigArgs {
rootDir: string;
writeFile: boolean;
}
export function createEslintConfig({
rootDir,
writeFile,
}: CreateEslintConfigArgs): CLIEngine.Options['baseConfig'] {
const config = {
extends: [
'react-app',
'prettier/@typescript-eslint',
'plugin:prettier/recommended',
],
};

if (writeFile) {
const file = path.join(rootDir, '.eslintrc.js');
if (fs.existsSync(file)) {
console.error(
'Error trying to save the Eslint configuration file:',
`${file} already exists.`
);
} else {
try {
fs.writeFileSync(
file,
`module.exports = ${JSON.stringify(config, null, 2)}`
);
} catch (e) {
console.error(e);
}
}
}

return config;
}
3 changes: 0 additions & 3 deletions src/createJestConfig.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import fs from 'fs';
import path from 'path';

export function createJestConfig(
_: (relativePath: string) => void,
rootDir: string
Expand Down
1 change: 1 addition & 0 deletions src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ declare module 'ora';
declare module 'sade';
declare module 'tiny-glob/sync';
declare module 'ansi-escapes';
declare module 'eslint-config-react-app';

// Patch Babel
// @see line 226 of https://unpkg.com/@babel/core@7.4.4/lib/index.js
Expand Down
6 changes: 2 additions & 4 deletions src/errors/extractErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';

import fs from 'fs-extra';
import * as babylon from 'babylon';
import traverse from 'babel-traverse';
Expand Down Expand Up @@ -137,8 +135,8 @@ function ErrorProd(code) {
url += '&args[]=' + encodeURIComponent(arguments[i]);
}
return new Error(
\`Minified ${prettyName} error #\$\{code\}; visit \$\{url\} for the full message or \` +
'use the non-minified dev environment for full errors and additional \' +
\`Minified ${prettyName} error #$\{code}; visit $\{url} for the full message or \` +
'use the non-minified dev environment for full errors and additional ' +
'helpful warnings. '
);
}
Expand Down
1 change: 0 additions & 1 deletion src/errors/invertObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export function invertObject(
const result: Dict = {};
const mapKeys = Object.keys(targetObj);

// eslint-disable-next-line no-for-of-loops/no-for-of-loops
for (const originalKey of mapKeys) {
const originalVal = targetObj[originalKey];

Expand Down
48 changes: 45 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import chalk from 'chalk';
import util from 'util';
import * as fs from 'fs-extra';
import jest from 'jest';
import { CLIEngine } from 'eslint';
import logError from './logError';
import path from 'path';
import mkdirp from 'mkdirp';
Expand All @@ -24,8 +25,8 @@ import { paths } from './constants';
import * as Messages from './messages';
import { createRollupConfig } from './createRollupConfig';
import { createJestConfig } from './createJestConfig';
import { createEslintConfig } from './createEslintConfig';
import { resolveApp, safePackageName, clearConsole } from './utils';
import * as Output from './output';
import { concatAllArray } from 'jpjs';
import getInstallCmd from './getInstallCmd';
import getInstallArgs from './getInstallArgs';
Expand All @@ -44,6 +45,7 @@ let appPackageJson: {
name: string;
source?: string;
jest?: any;
eslint?: any;
};
try {
appPackageJson = fs.readJSONSync(resolveApp('package.json'));
Expand Down Expand Up @@ -417,7 +419,7 @@ prog
.describe(
'Run jest test runner in watch mode. Passes through all flags directly to Jest'
)
.action(async (opts: any) => {
.action(async () => {
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'test';
process.env.NODE_ENV = 'test';
Expand All @@ -441,8 +443,48 @@ prog
})
);

const [_skipTheWordTest, ...argsToPassToJestCli] = argv;
const [, ...argsToPassToJestCli] = argv;
jest.run(argsToPassToJestCli);
});

prog
.command('lint')
.describe('Run eslint with Prettier')
.example('lint src test')
.option('--fix', 'Fixes fixable errors and warnings')
.example('lint src test --fix')
.option('--ignore-pattern', 'Ignore a pattern')
.example('lint src test --ignore-pattern test/foobar.ts')
.option('--write-file', 'Write the config file locally')
.example('lint src test --write-file')
.action(
async (opts: {
fix: boolean;
'ignore-pattern': string;
'write-file': boolean;
_: string[];
}) => {
const cli = new CLIEngine({
baseConfig: {
...createEslintConfig({
rootDir: paths.appRoot,
writeFile: opts['write-file'],
}),
...appPackageJson.eslint,
},
extensions: ['.ts', '.tsx'],
fix: opts.fix,
ignorePattern: opts['ignore-pattern'],
});
const report = cli.executeOnFiles(opts['_']);
if (opts.fix) {
CLIEngine.outputFixes(report);
}
console.log(cli.getFormatter()(report.results));
if (report.errorCount) {
process.exit(1);
}
}
);

prog.parse(process.argv);
1 change: 1 addition & 0 deletions test/tests/lint/file-with-lint-errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const foo () => !!'bar';
5 changes: 5 additions & 0 deletions test/tests/lint/file-with-prettier-lint-errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const foo = ( ) =>
!! ('bar')
;


1 change: 1 addition & 0 deletions test/tests/lint/file-without-lint-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const foo = () => !!'bar';
5 changes: 5 additions & 0 deletions test/tests/lint/react-file-with-lint-errors.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react';

export const Foobar = (props: any) => {
return <<div {...props}>foobar</div>;
};
5 changes: 5 additions & 0 deletions test/tests/lint/react-file-without-lint-error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react';

export const Foobar = (props: any) => {
return <div {...props}>foobar </div>;
};
Loading