Skip to content

Commit

Permalink
feat: expose single configs as named exports (#218)
Browse files Browse the repository at this point in the history
Co-authored-by: Egill Sveinbjörnsson <egilsster@users.noreply.github.com>
Co-authored-by: Christofer Splittorff <cbt@qlik.com>
  • Loading branch information
3 people authored Nov 28, 2024
1 parent c8e1d23 commit 807ebd8
Show file tree
Hide file tree
Showing 40 changed files with 17,324 additions and 282 deletions.
5 changes: 5 additions & 0 deletions .changeset/strong-paws-laugh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@qlik/eslint-config": minor
---

Exposing single configs as named exports. Can be import as `import { recommendedJS, recommendedTS } from "@qlik/eslint-config"`
8 changes: 1 addition & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,17 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0 ## Needed for Changesets to find `main` branch

## https://github.com/changesets/changesets/issues/517
- name: Create git reference to main branch (for Changesets)
if: ${{ github.event.pull_request.title != 'Version Packages' }}
run: git pull --force --no-tags origin main:main

- uses: pnpm/action-setup@v3

- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm

- run: pnpm install

- run: pnpm exec changeset status --since=main

- run: pnpm format:check

- run: pnpm lint
- run: pnpm test
27 changes: 27 additions & 0 deletions .github/workflows/update-eslint-configs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Update ESLint Test Configs

on:
workflow_dispatch:

jobs:
update-configs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Git Config
run: |
git config user.name "github-action"
git config user.email "github-action@noreply.github.com"
- uses: pnpm/action-setup@v3

- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm

- run: pnpm install

- name: Update Configs
run: ./packages/eslint-config/test/update-configs.sh
10 changes: 9 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
{
"eslint.workingDirectories": ["test/test-react-svelte", "test/test-react", "test/test-base"]
"eslint.workingDirectories": [
"packages/browserslist-config",
"packages/eslint-config",
"packages/prettier-config",
"packages/tsconfig",
"test/test-react-svelte",
"test/test-react",
"test/test-base"
]
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"format:write": "turbo run format:write",
"lint": "turbo run lint",
"prepare-release": "changeset",
"publish-packages": "changeset publish"
"publish-packages": "changeset publish",
"test": "turbo run test"
},
"prettier": "@qlik/prettier-config",
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions packages/eslint-config/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test/generated
68 changes: 63 additions & 5 deletions packages/eslint-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@ export default qlik.compose(

### v1 notable changes

- Updates [`@typescript-eslint/typescript-eslint`](https://github.com/typescript-eslint/typescript-eslint) to v8, this brings a few new rules. See article for v8 <https://typescript-eslint.io/blog/announcing-typescript-eslint-v8>
- Moves from [`eslint-plugin-import`](https://github.com/import-js/eslint-plugin-import) to [`eslint-plugin-import-x`](https://github.com/un-ts/eslint-plugin-import-x). If you reference any of the `import/` rules you'll need to replace `import/` with `import-x/`.
- Updates [`@typescript-eslint/typescript-eslint`](https://github.com/typescript-eslint/typescript-eslint) to v8, this brings
a few new rules. See article for v8 <https://typescript-eslint.io/blog/announcing-typescript-eslint-v8>
- Moves from [`eslint-plugin-import`](https://github.com/import-js/eslint-plugin-import) to [`eslint-plugin-import-x`](https://github.com/un-ts/eslint-plugin-import-x).
If you reference any of the `import/` rules you'll need to replace `import/` with `import-x/`.
- Some stylistic rules have been disabled (for example `function` vs arrow functions)

## Usage

These configs works on both TypeScript and JavaSript out of the box. (as long as the file endings are any of `.js, .jsx, .mjs, .cjs, .ts, .tsx, .cts, .mts`)
The default exports configs works on both TypeScript and JavaSript out of the box. (as long as the file endings are any of `.js, .jsx, .mjs, .cjs, .ts, .tsx, .cts, .mts`).
The configs are eslint flat config arrays populated with configs that has appropriate file endings attached to them. Designed
to diminish the amount of configuration needed in an `eslint.config.js` file.

To get started, create `eslint.config.js` (if your package json has `"type": "module"`), otherwise create `eslint.config.mjs`.
If you are not building your project with TypeScript (using Webpack or Vite for example), then tell TypeScript to include
Expand Down Expand Up @@ -137,7 +141,61 @@ export default qlik.compose(
);
```

A config can be extended if needed. For example if the default file patterns needs to be altered.
## Using the named exports configs

The different configs are also accessible through named imports. These configs can be used in specific scenarios where more
control of the configs are needed. The `extend` property can be used to apply a config on certain file patterns.

Example only use javascript rules with react

```js
import qlik, { recommendedJS, reactJS } from "@qlik/eslint-config";

export default qlik.compose(
reactJS
)
```

with typescript support

```js
import qlik, { recommendedJS, reactJS } from "@qlik/eslint-config";

export default qlik.compose(
reactJS,
reactTS
)
```

This is equal to:

```js
import qlik from "@qlik/eslint-config";

export default qlik.compose(
...qlik.configs.react
)
```

The single configs can be useful together with the `extend` property. Below shows an example of a config
that wants to use lint rules for node environment on a part of the code base.

```js
import qlik, { esmJS } from "@qlik/eslint-config";

export default qlik.compose(
// apply recommended config to all files
...qlik.configs.recommended,
// set node esm config on .js files inside the tools folder
{
files: ["tools/**/*.js"],
extend: [esmJS],
},
)

```

Example of changing the default file patterns on the vitest config.

```js
// @ts-check
Expand All @@ -148,7 +206,7 @@ export default qlik.compose(
{
// adds vitest lint rules on the specified files with an altered rule
files: ['**/my_tests_are_here/*.spec.ts']
extends [qlik.configs.vitest],
extend: [qlik.configs.vitest],
rules: {
"vitest/max-nested-describe": [
"error",
Expand Down
11 changes: 10 additions & 1 deletion packages/eslint-config/eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import eslint from "@eslint/js";
import vitestPlugin from "@vitest/eslint-plugin";
import tseslint from "typescript-eslint";

export default tseslint.config(eslint.configs.recommended, ...tseslint.configs.recommended);
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
// test files
{
files: ["**/__tests__/**/*.{js,jsx,ts,tsx}"],
...vitestPlugin.configs.recommended,
},
);
3 changes: 2 additions & 1 deletion packages/eslint-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"check-types": "tsc --noEmit",
"format:check": "prettier --check '**' --ignore-unknown",
"format:write": "prettier --write '**' --ignore-unknown",
"lint": "eslint ."
"lint": "eslint .",
"test": "vitest run && ./test/verify-configs.sh"
},
"prettier": "@qlik/prettier-config",
"dependencies": {
Expand Down
55 changes: 31 additions & 24 deletions packages/eslint-config/src/configs/cjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,54 @@
import globals from "globals";
import { mergeConfigs } from "../utils/config.js";
import { recommendedJS, recommendedTS } from "./recommended.js";
import rules from "./rules/index.js";
import nodeRules from "./rules/node.js";

/**
* @satisfies {import("../types/index.js").ESLintFlatConfig['rules']}
*/
const cjsRules = {
...nodeRules,
// modify rules for node commonjs here
};

/**
* @type {import("../types/index.js").ESLintFlatConfig}
*/
const cjsJS = mergeConfigs(recommendedJS, {
name: "node-cjs-js",
files: ["**/*.{js,cjs}"],
languageOptions: {
globals: globals.node,
sourceType: "commonjs",
const cjsJS = mergeConfigs(
// base it on the recommended javascript config
recommendedJS,
// add qlik's recommended node commonjs config for javascript
{
name: "node-cjs-js",
files: ["**/*.{js,cjs}"],
languageOptions: {
globals: globals.node,
sourceType: "commonjs",
},
rules: cjsRules,
},
rules: {
...rules.nodeRules,
...cjsRules,
},
});
);

/**
* @type {import("../types/index.js").ESLintFlatConfig}
*/
const cjsTS = mergeConfigs(recommendedTS, {
name: "node-cjs-ts",
files: ["**/*.{ts,cts}"],
languageOptions: {
globals: globals.node,
sourceType: "commonjs",
},
rules: {
...rules.nodeRules,
...cjsRules,
// modify ts specific rules for node here
const cjsTS = mergeConfigs(
// base it on the recommended typescript config
recommendedTS,
// add qlik's recommended node commonjs config for typescript
{
name: "node-cjs-ts",
files: ["**/*.{ts,cts}"],
languageOptions: {
globals: globals.node,
sourceType: "commonjs",
},
rules: {
...cjsRules,
// modify ts specific rules for node here
},
},
});
);

export default [cjsJS, cjsTS];
export { cjsJS, cjsTS };
54 changes: 32 additions & 22 deletions packages/eslint-config/src/configs/esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,55 @@
import globals from "globals";
import { mergeConfigs } from "../utils/config.js";
import { recommendedJS, recommendedTS } from "./recommended.js";
import nodeRules from "./rules/node.js";

/**
* @satisfies {import("../types/index.js").ESLintFlatConfig["rules"]}
*/
const nodeEsmRules = {
// modify rules for node esm here
...nodeRules,
"import-x/extensions": ["error", "ignorePackages"],
// modify rules for node esm here
};

/**
* @type {import("../types/index.js").ESLintFlatConfig}
*/
const esmJS = mergeConfigs(recommendedJS, {
name: "node-esm-js",
files: ["**/*.{js,mjs}"],
languageOptions: {
globals: globals.node,
sourceType: "module",
const esmJS = mergeConfigs(
// base it on the recommended javascript config
recommendedJS,
// add qlik's recommended node esm config for javascript
{
name: "node-esm-js",
files: ["**/*.{js,mjs}"],
languageOptions: {
globals: globals.node,
sourceType: "module",
},
rules: nodeEsmRules,
},
rules: {
...nodeEsmRules,
},
});
);

/**
* @type {import("../types/index.js").ESLintFlatConfig}
*/
const esmTS = mergeConfigs(recommendedTS, {
name: "node-esm-ts",
files: ["**/*.{ts,mts}"],
languageOptions: {
globals: globals.node,
sourceType: "module",
},
rules: {
...nodeEsmRules,
// modify ts specific rules for node esm here
const esmTS = mergeConfigs(
// base it on the recommended typescript config
recommendedTS,
// add qlik's recommended node esm config for typescript
{
name: "node-esm-ts",
files: ["**/*.{ts,mts}"],
languageOptions: {
globals: globals.node,
sourceType: "module",
},
rules: {
...nodeEsmRules,
// modify typescript specific rules for node esm here if needed
},
},
});
);

export default [esmJS, esmTS];
export { esmJS, esmTS };
25 changes: 14 additions & 11 deletions packages/eslint-config/src/configs/jest.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,26 @@
import jestPlugin from "eslint-plugin-jest";
import testingLibraryPlugin from "eslint-plugin-testing-library";
import { mergeConfigs } from "../utils/config.js";
import rules from "./rules/index.js";

/**
* @type {import("../types/index.js").ESLintFlatConfig}
* config for jest https://github.com/jest-community/eslint-plugin-jest
*/
const jest = mergeConfigs(jestPlugin.configs["flat/recommended"], {
name: "jest-js",
files: ["**/__test__/**/*.{js,jsx,ts,tsx}", "**/__tests__/**/*.{js,jsx,ts,tsx}"],
plugins: {
"testing-library": testingLibraryPlugin,
const jest = mergeConfigs(
// base it on the recommended jest config
jestPlugin.configs["flat/recommended"],
// add testing-library plugin recommended config for react
testingLibraryPlugin.configs["flat/react"],
// add qlik's recommended jest config
{
name: "jest",
files: ["**/__test__/**/*.{js,jsx,ts,tsx}", "**/__tests__/**/*.{js,jsx,ts,tsx}"],
rules: {
// ...testingLibraryRules,
// modify rules from eslint-plugin-jest here
},
},
rules: {
...rules.testingLibraryRules,
// modify rules from eslint-plugin-jest here
},
});
);

export default [jest];
export { jest };
Loading

0 comments on commit 807ebd8

Please sign in to comment.