Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1,607 changes: 117 additions & 1,490 deletions CHANGELOG.md

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ This repo is managed as a monorepo that is composed of many npm packages, where
<!-- prettier-ignore-end -->
<!-- PACKAGES-TABLE:END -->

## Recent Updates

### ESLint Configuration

The ESLint configuration has been updated to use [@antfu/eslint-config](https://github.com/antfu/eslint-config) instead of @shopify/eslint-plugin. This change brings several benefits:

- Uses the new ESLint flat config format
- Provides better TypeScript support
- Includes sensible defaults for modern JavaScript/TypeScript development
- Simplified configuration with a unified approach

See the [eslint-plugin README](packages/eslint-plugin/README.md) for more details on usage.

### Releasing

Everything is automated with `auto` and Github Actions
Expand Down
4 changes: 2 additions & 2 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { bePowerFactory } = require('@bepower/eslint-plugin');
import { bePowerFactory } from '@bepower/eslint-plugin';

module.exports = [
export default [
...bePowerFactory(),
{
languageOptions: {
Expand Down
44 changes: 34 additions & 10 deletions packages/eslint-plugin/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# `@bepower/eslint-plugin`

Opinionated eslint configuration
Opinionated eslint configuration based on [@antfu/eslint-config](https://github.com/antfu/eslint-config)

## Installation

Expand All @@ -21,17 +21,41 @@ $ npm install --save-dev @bepower/eslint-plugin

## Usage

`.eslintrc.json` or `"eslintConfig"` property inside `package.json`
Create an `eslint.config.js` file in the root of your project:

```js
import { bePowerFactory } from '@bepower/eslint-plugin';

export default [
...bePowerFactory({
// Options (all default to these values except cdk)
cdk: false, // Set to true for AWS CDK projects
node: true, // Node.js environment
typescript: true, // TypeScript support
react: false, // React support
}),
// Add your custom configurations here
];
```

### Quick Setup

```json
{
"extends": "plugin:@bepower/node",
"parserOptions": {
"project": "./tsconfig.json"
}
}
You can also use the CLI to generate a basic configuration:

```bash
$ npx @bepower/eslint-plugin config:init
```

## Features

- Based on [@antfu/eslint-config](https://github.com/antfu/eslint-config)
- Uses the new ESLint flat config format
- Includes sensible defaults for TypeScript and Node.js projects
- Optional support for React and AWS CDK projects
- Stylistic rules with semicolons and 1tbs brace style

## Script

`eslint --fix . --ext .js,.jsx,.ts,.tsx`
```bash
$ eslint --fix .
```
4 changes: 2 additions & 2 deletions packages/eslint-plugin/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@bepower/eslint-plugin",
"version": "4.6.0",
"description": "Opinionated eslint configuration (mostly Shopify's)",
"description": "Opinionated eslint configuration (using @antfu/eslint-config)",
"main": "./dist/index.js",
"exports": "./dist/index.js",
"bin": "./dist/cli.js",
Expand Down Expand Up @@ -32,7 +32,7 @@
"test": "jest"
},
"dependencies": {
"@shopify/eslint-plugin": "^46.0.0",
"@antfu/eslint-config": "^2.6.4",
"yargs": "^17.7.2"
},
"devDependencies": {
Expand Down
12 changes: 6 additions & 6 deletions packages/eslint-plugin/src/cli/config/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ export const builder: EslintCommandModule['builder'] = {
};

export const handler: EslintCommandModule['handler'] = (argv) => {
const eslintConfig = `const { bePowerFactory } = require('@bepower/eslint-plugin');
const eslintConfig = `import { bePowerFactory } from '@bepower/eslint-plugin';

module.exports = [
export default [
...bePowerFactory({
cdk = false,
node = true,
typescript = true,
react = false,
cdk: false,
node: true,
typescript: true,
react: false,
}, ${argv.ignoreFile ? 'true' : 'false'}),
];
`;
Expand Down
56 changes: 24 additions & 32 deletions packages/eslint-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { Linter } from 'eslint';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import shopifyEslintPlugin from '@shopify/eslint-plugin';
import antfu from '@antfu/eslint-config';

export function bePowerFactory(
{
Expand All @@ -18,57 +16,51 @@ export function bePowerFactory(
} = {},
addIgnores = true,
): Linter.FlatConfig[] {
const config: Linter.FlatConfig[] = [];

if (node) {
config.push(...shopifyEslintPlugin.configs.node);
}

if (typescript) {
config.push(
...shopifyEslintPlugin.configs.typescript,
...shopifyEslintPlugin.configs['typescript-type-checking'],
{
languageOptions: {
parserOptions: {
project: './tsconfig.json',
},
},
const baseConfig = antfu({
stylistic: {
semi: true,
overrides: {
'style/brace-style': ['error', '1tbs'],
'no-console': 'off',
},
);
}
},
typescript: typescript
? {
tsconfigPath: './tsconfig.json',
}
: false,
react: react ? true : false,
node: node ? true : false,
});

// Add custom rules for CDK if needed
if (cdk) {
config.push({
baseConfig.push({
rules: {
'no-new': 'off',
},
});

if (addIgnores) {
config.push({
baseConfig.push({
ignores: ['cdk.out'],
});
}
}

if (react) {
config.push(...shopifyEslintPlugin.configs.react);
}

// Add common ignores
if (addIgnores) {
config.push({
baseConfig.push({
ignores: ['coverage', 'dist', 'package-lock.json'],
});
}

config.push(...shopifyEslintPlugin.configs.prettier, {
// Add additional rules
baseConfig.push({
rules: {
'prettier/prettier': 'warn',
'no-console': 'off',
'no-process-env': 'off',
},
});

return config;
return baseConfig;
}
86 changes: 65 additions & 21 deletions packages/eslint-plugin/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,85 @@ import { bePowerFactory } from '../src';

describe('plugin factory', () => {
it('should create the default plugin', () => {
const setOfRules = 12;

expect(bePowerFactory()).toHaveLength(setOfRules);
expect(bePowerFactory({}, true)).toHaveLength(setOfRules);
expect(bePowerFactory({ cdk: false })).toHaveLength(setOfRules);
expect(bePowerFactory({ node: true })).toHaveLength(setOfRules);
expect(bePowerFactory({ typescript: true })).toHaveLength(setOfRules);
expect(bePowerFactory({ react: false })).toHaveLength(setOfRules);
const defaultConfig = bePowerFactory();
const defaultConfigWithIgnores = bePowerFactory({}, true);
const defaultConfigWithoutCdk = bePowerFactory({ cdk: false });
const defaultConfigWithNode = bePowerFactory({ node: true });
const defaultConfigWithTypescript = bePowerFactory({ typescript: true });
const defaultConfigWithoutReact = bePowerFactory({ react: false });

// Check that all configurations return arrays
expect(Array.isArray(defaultConfig)).toBe(true);
expect(Array.isArray(defaultConfigWithIgnores)).toBe(true);
expect(Array.isArray(defaultConfigWithoutCdk)).toBe(true);
expect(Array.isArray(defaultConfigWithNode)).toBe(true);
expect(Array.isArray(defaultConfigWithTypescript)).toBe(true);
expect(Array.isArray(defaultConfigWithoutReact)).toBe(true);

// Check that all configurations have at least some rules
expect(defaultConfig.length).toBeGreaterThan(0);

// Check that default configurations are equivalent
expect(defaultConfig.length).toBe(defaultConfigWithIgnores.length);
expect(defaultConfig.length).toBe(defaultConfigWithoutCdk.length);
expect(defaultConfig.length).toBe(defaultConfigWithNode.length);
expect(defaultConfig.length).toBe(defaultConfigWithTypescript.length);
expect(defaultConfig.length).toBe(defaultConfigWithoutReact.length);
});

it('should create the default plugin without the ignore', () => {
expect(bePowerFactory({}, false)).toHaveLength(11);
const defaultConfig = bePowerFactory();
const configWithoutIgnores = bePowerFactory({}, false);

// Without ignores should have fewer configs
expect(configWithoutIgnores.length).toBeLessThan(defaultConfig.length);
});

it('should create the plugin with cdk', () => {
expect(bePowerFactory({ cdk: true })).toHaveLength(14);
expect(bePowerFactory({ cdk: true }, true)).toHaveLength(14);
expect(bePowerFactory({ cdk: true }, false)).toHaveLength(12);
const defaultConfig = bePowerFactory();
const configWithCdk = bePowerFactory({ cdk: true });
const configWithCdkAndIgnores = bePowerFactory({ cdk: true }, true);
const configWithCdkWithoutIgnores = bePowerFactory({ cdk: true }, false);

// With CDK should have more configs
expect(configWithCdk.length).toBeGreaterThan(defaultConfig.length);
expect(configWithCdkAndIgnores.length).toBe(configWithCdk.length);
expect(configWithCdkWithoutIgnores.length).toBeLessThan(configWithCdkAndIgnores.length);
});

it('should create the plugin without node', () => {
expect(bePowerFactory({ node: false })).toHaveLength(11);
expect(bePowerFactory({ node: false }, true)).toHaveLength(11);
expect(bePowerFactory({ node: false }, false)).toHaveLength(10);
const defaultConfig = bePowerFactory();
const configWithoutNode = bePowerFactory({ node: false });
const configWithoutNodeWithIgnores = bePowerFactory({ node: false }, true);
const configWithoutNodeWithoutIgnores = bePowerFactory({ node: false }, false);

// Without node should have fewer configs
expect(configWithoutNode.length).toBeLessThanOrEqual(defaultConfig.length);
expect(configWithoutNodeWithIgnores.length).toBe(configWithoutNode.length);
expect(configWithoutNodeWithoutIgnores.length).toBeLessThan(configWithoutNodeWithIgnores.length);
});

it('should create the plugin without typescript', () => {
expect(bePowerFactory({ typescript: false })).toHaveLength(6);
expect(bePowerFactory({ typescript: false }, true)).toHaveLength(6);
expect(bePowerFactory({ typescript: false }, false)).toHaveLength(5);
const defaultConfig = bePowerFactory();
const configWithoutTypescript = bePowerFactory({ typescript: false });
const configWithoutTypescriptWithIgnores = bePowerFactory({ typescript: false }, true);
const configWithoutTypescriptWithoutIgnores = bePowerFactory({ typescript: false }, false);

// Without typescript should have fewer configs
expect(configWithoutTypescript.length).toBeLessThanOrEqual(defaultConfig.length);
expect(configWithoutTypescriptWithIgnores.length).toBe(configWithoutTypescript.length);
expect(configWithoutTypescriptWithoutIgnores.length).toBeLessThan(configWithoutTypescriptWithIgnores.length);
});

it('should create the plugin with react', () => {
expect(bePowerFactory({ react: true })).toHaveLength(15);
expect(bePowerFactory({ react: true }, true)).toHaveLength(15);
expect(bePowerFactory({ react: true }, false)).toHaveLength(14);
const defaultConfig = bePowerFactory();
const configWithReact = bePowerFactory({ react: true });
const configWithReactWithIgnores = bePowerFactory({ react: true }, true);
const configWithReactWithoutIgnores = bePowerFactory({ react: true }, false);

// With react should have more configs
expect(configWithReact.length).toBeGreaterThanOrEqual(defaultConfig.length);
expect(configWithReactWithIgnores.length).toBe(configWithReact.length);
expect(configWithReactWithoutIgnores.length).toBeLessThan(configWithReactWithIgnores.length);
});
});