@codfish/eslint-config 0.0.0-PR-124--3ca0d95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # @codfish/eslint-config
2
+
3
+ > Modern ESLint configuration with TypeScript, React, and testing framework support using ESLint v9+ flat config format.
4
+
5
+ [![version](https://img.shields.io/npm/v/@codfish/eslint-config.svg)](http://npm.im/@codfish/eslint-config)
6
+ [![downloads](https://img.shields.io/npm/dm/@codfish/eslint-config.svg)](http://npm-stat.com/charts.html?package=@codfish/eslint-config&from=2015-08-01)
7
+ [![MIT License](https://img.shields.io/npm/l/@codfish/eslint-config.svg)](http://opensource.org/licenses/MIT)
8
+ [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
9
+ [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
10
+
11
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
12
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
13
+ ## Table of Contents
14
+
15
+ - [Features](#features)
16
+ - [Automatic Configuration](#automatic-configuration)
17
+ - [Installation](#installation)
18
+ - [Usage](#usage)
19
+ - [Prettier](#prettier)
20
+ - [With dApps](#with-dapps)
21
+ - [Docker Configuration](#docker-configuration)
22
+ - [Blockchain/dApp Configuration](#blockchaindapp-configuration)
23
+ - [Known issues](#known-issues)
24
+ - [Migration from Legacy Config](#migration-from-legacy-config)
25
+
26
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
27
+
28
+ ## Features
29
+
30
+ - **Modern ESLint v9+ flat config**: Uses the new flat configuration format
31
+ - **Dynamic feature detection**: Automatically configures based on your project's dependencies
32
+ - **TypeScript support**: Full TypeScript linting with modern typescript-eslint parser and rules
33
+ - **React ecosystem**: React, React Hooks, and JSX accessibility rules when React is detected
34
+ - **Test framework agnostic**: Supports Jest and Vitest with automatic detection
35
+ - **Prettier integration**: Built-in Prettier configuration with conflict resolution via eslint-config-prettier
36
+ - **ESM architecture**: Built with ECMAScript modules and full TypeScript typing
37
+ - **Docker support**: Optional configuration for dockerized applications
38
+ - **Blockchain/dApp support**: Optional configuration for decentralized applications
39
+
40
+ ### Automatic Configuration
41
+
42
+ The config automatically detects and configures:
43
+
44
+ - **React**: Includes React, React Hooks, and JSX a11y rules when `react` is installed
45
+ - **Jest**: Configures Jest-specific rules when `jest` is found in dependencies
46
+ - **Vitest**: Configures Vitest-specific rules when `vitest` is detected
47
+ - **Prettier**: Loads your project's Prettier config or falls back to built-in defaults
48
+
49
+ ## Installation
50
+
51
+ Install the package and required peer dependencies:
52
+
53
+ ```sh
54
+ npm i -D @codfish/eslint-config eslint@9
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ Create an `eslint.config.js` file in your project root:
60
+
61
+ ```js
62
+ import { defineConfig } from 'eslint/config';
63
+ import codfish from '@codfish/eslint-config';
64
+
65
+ export default defineConfig([
66
+ {
67
+ files: ['**/*.{js,jsx,ts,tsx}'],
68
+ extends: [codfish],
69
+ // Your overrides here
70
+ },
71
+ ]);
72
+ ```
73
+
74
+ > [!IMPORTANT] If you get ES module errors, you may need to set the `type` field in your `package.json` to `module` or
75
+ > rename your config file to `eslint.config.mjs`.
76
+
77
+ ### Prettier
78
+
79
+ Prettier is automatically run through eslint with the [default configuration](./prettier.js). You can optionally add a
80
+ prettier configuration file in the root of your project and it will take precedence over the
81
+ [built-in config](./prettier.js). You can also choose to extend the Prettier config:
82
+
83
+ **prettier.config.js**
84
+
85
+ ```js
86
+ import codfishConfig from '@codfish/eslint-config/prettier.js';
87
+
88
+ /**
89
+ * @see https://prettier.io/docs/en/configuration.html
90
+ * @type {import("prettier").Config}
91
+ */
92
+ const config = {
93
+ ...codfishConfig,
94
+ // your overrides here
95
+ };
96
+
97
+ export default config;
98
+ ```
99
+
100
+ ### With dApps
101
+
102
+ Similar to the issues with docker, there may be rules you want to adjust for dApp's. This config will set some globals
103
+ as well as ignore missing build artifact imports. While you obviously need those to run your app, sometimes you might
104
+ want to run the linter in a ci/cd environment and build artifacts might not be present.
105
+
106
+ **Note**: The dApp config also includes the `import/no-unresolved` rule found in the docker config.
107
+
108
+ You can also directly import the Prettier config:
109
+
110
+ ```js
111
+ import prettierConfig from '@codfish/eslint-config/prettier';
112
+ export default prettierConfig;
113
+ ```
114
+
115
+ ### Docker Configuration
116
+
117
+ For projects leveraging Docker containers, you may want to disable import resolution errors for `node_modules` if
118
+ packages are only available in the container but you're running the linter locally.
119
+
120
+ ```js
121
+ import codfish from '@codfish/eslint-config';
122
+ import docker from '@codfish/eslint-config/docker';
123
+
124
+ export default defineConfig(
125
+ codfish,
126
+ docker,
127
+
128
+ {
129
+ // Your app-specific overrides
130
+ },
131
+ );
132
+ ```
133
+
134
+ ### Blockchain/dApp Configuration
135
+
136
+ For decentralized applications that use build artifacts and blockchain globals, use the specialized dApp config:
137
+
138
+ ```js
139
+ import codfish from '@codfish/eslint-config';
140
+ import dappConfig from '@codfish/eslint-config/dapp';
141
+
142
+ export default defineConfig(
143
+ codfish,
144
+ dapp,
145
+
146
+ {
147
+ // Your app-specific overrides
148
+ },
149
+ );
150
+ ```
151
+
152
+ The dApp configuration provides:
153
+
154
+ - Blockchain-specific globals (`artifacts`, `contract`, `web3`, etc.)
155
+ - Import resolution handling for smart contract build artifacts
156
+ - Relaxed rules for generated contract files
157
+
158
+ ## Known issues
159
+
160
+ > https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/149
161
+
162
+ When building dynamic classes, the auto sorting of tailwind classes can break things so beware.
163
+
164
+ To avoid this happening you can re-wrap the dynamic class expression like so:
165
+
166
+ ```vue-html
167
+ class="`p-0 ${`tw-border-${accentColor}`}`"
168
+ ```
169
+
170
+ ## Migration from Legacy Config
171
+
172
+ If you're upgrading from an older version that used Airbnb presets:
173
+
174
+ 1. **Update to ESLint v9+**: `npm install --save-dev eslint@9`
175
+ 2. **Switch to flat config**: Replace `.eslintrc.js` with `eslint.config.js`
176
+ 3. **Use import syntax**: Change from `require()` to `import` statements
177
+ 4. **Remove explicit React config**: React support is now automatically detected
178
+ 5. **Update scripts**: Ensure your lint script runs `eslint .` (flat config auto-discovery)
package/commitlint.js ADDED
@@ -0,0 +1,9 @@
1
+ export default {
2
+ extends: ['@commitlint/config-conventional'],
3
+ rules: {
4
+ 'scope-case': [0],
5
+ 'body-max-line-length': [0],
6
+ 'footer-max-line-length': [0],
7
+ 'subject-case': [0],
8
+ },
9
+ };
package/dapp.js ADDED
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from 'eslint/config';
2
+
3
+ export default defineConfig({
4
+ name: 'codfish/dapp',
5
+
6
+ files: ['**/contracts/**/*.{js,ts}', '**/migrations/**/*.{js,ts}', '**/truffle/**/*.{js,ts}'],
7
+
8
+ languageOptions: {
9
+ globals: {
10
+ artifacts: 'readonly',
11
+ assert: 'readonly',
12
+ contract: 'readonly',
13
+ deployer: 'readonly',
14
+ web3: 'readonly',
15
+ },
16
+ },
17
+ });
@@ -0,0 +1,12 @@
1
+ declare namespace _default {
2
+ let _extends: string[];
3
+ export { _extends as extends };
4
+ export let rules: {
5
+ 'scope-case': number[];
6
+ 'body-max-line-length': number[];
7
+ 'footer-max-line-length': number[];
8
+ 'subject-case': number[];
9
+ };
10
+ }
11
+ export default _default;
12
+ //# sourceMappingURL=commitlint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commitlint.d.ts","sourceRoot":"","sources":["../commitlint.js"],"names":[],"mappings":""}
package/dist/dapp.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ declare const _default: import("eslint").Linter.Config<import("eslint").Linter.RulesRecord>[];
2
+ export default _default;
3
+ //# sourceMappingURL=dapp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dapp.d.ts","sourceRoot":"","sources":["../dapp.js"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("eslint").Linter.Config<import("eslint").Linter.RulesRecord>[];
2
+ export default _default;
3
+ //# sourceMappingURL=docker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../docker.js"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("eslint").Linter.Config<import("eslint").Linter.RulesRecord>[];
2
+ export default _default;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.js"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ export default config;
2
+ /**
3
+ * @see https://prettier.io/docs/configuration
4
+ * @type {import("prettier").Config}
5
+ */
6
+ declare const config: import("prettier").Config;
7
+ //# sourceMappingURL=prettier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prettier.d.ts","sourceRoot":"","sources":["../prettier.js"],"names":[],"mappings":";AAAA;;;GAGG;AACH,sBAFU,OAAO,UAAU,EAAE,MAAM,CAqBjC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("eslint").Linter.Config<import("eslint").Linter.RulesRecord>[];
2
+ export default _default;
3
+ //# sourceMappingURL=config-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-files.d.ts","sourceRoot":"","sources":["../../rules/config-files.js"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("eslint").Linter.Config<import("eslint").Linter.RulesRecord>[];
2
+ export default _default;
3
+ //# sourceMappingURL=jest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jest.d.ts","sourceRoot":"","sources":["../../rules/jest.js"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("eslint").Linter.Config<import("eslint").Linter.RulesRecord>[];
2
+ export default _default;
3
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../rules/react.js"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("eslint").Linter.Config<import("eslint").Linter.RulesRecord>[];
2
+ export default _default;
3
+ //# sourceMappingURL=vitest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../../rules/vitest.js"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ export function hasLocalConfig(moduleName: any, searchOptions?: {}): boolean;
2
+ export function hasDep(props: any): boolean;
3
+ export function hasDevDep(props: any): boolean;
4
+ export function hasPeerDep(props: any): boolean;
5
+ export function hasAnyDep(args: any): boolean;
6
+ export function ifAnyDep(deps: any, t: any, f: any): any;
7
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.js"],"names":[],"mappings":"AA4BA,6EAKC;AAfgC,4CAA+D;AAA/D,+CAA+D;AAA/D,gDAA+D;AAMzF,8CAA8E;AAE9E,yDAAmE"}
package/docker.js ADDED
@@ -0,0 +1,13 @@
1
+ import { defineConfig } from 'eslint/config';
2
+
3
+ /**
4
+ * Turns off `import/no-unresolved` errors for node modules in projects using
5
+ * Docker, to avoid false positives.
6
+ */
7
+ export default defineConfig({
8
+ name: 'codfish/docker',
9
+
10
+ rules: {
11
+ 'import/no-unresolved': ['error', { ignore: ['^[^.]+'] }],
12
+ },
13
+ });
package/index.js ADDED
@@ -0,0 +1,136 @@
1
+ import js from '@eslint/js';
2
+ import { defineConfig } from 'eslint/config';
3
+ import prettier from 'eslint-plugin-prettier/recommended';
4
+ import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort';
5
+ import globals from 'globals';
6
+ import tseslint from 'typescript-eslint';
7
+
8
+ import prettierBuiltInConfig from './prettier.js';
9
+ import configFilesConfig from './rules/config-files.js';
10
+ import jestConfig from './rules/jest.js';
11
+ import reactConfig from './rules/react.js';
12
+ import vitestConfig from './rules/vitest.js';
13
+ import { hasLocalConfig, ifAnyDep } from './utils.js';
14
+
15
+ const useBuiltinPrettierConfig = !hasLocalConfig('prettier');
16
+
17
+ /**
18
+ * Modern ESLint configuration with dynamic feature detection
19
+ * Supports TypeScript, React, Jest, Vitest, and Prettier
20
+ */
21
+ export default defineConfig([
22
+ // Base JavaScript configuration
23
+ js.configs.recommended,
24
+
25
+ tseslint.configs.recommended,
26
+
27
+ // Base configuration for all files
28
+ {
29
+ name: 'codfish/base',
30
+
31
+ plugins: {
32
+ 'simple-import-sort': simpleImportSortPlugin,
33
+ },
34
+
35
+ languageOptions: {
36
+ ecmaVersion: 'latest',
37
+ sourceType: 'module',
38
+ globals: {
39
+ ...globals.browser,
40
+ ...globals.node,
41
+ ...globals.es2022,
42
+ },
43
+ },
44
+
45
+ rules: {
46
+ // Custom Grouping: https://github.com/lydell/eslint-plugin-simple-import-sort#custom-grouping
47
+ // Examples: https://github.com/lydell/eslint-plugin-simple-import-sort/blob/main/examples/.eslintrc.js
48
+ 'simple-import-sort/imports': [
49
+ 'error',
50
+ {
51
+ groups: [
52
+ // 1. Node.js builtins prefixed with `node:` or node_modules
53
+ // Exclude relative imports using aliases like `@/` or `@{src|test|tests}` (common ts config paths).
54
+ ['^node:', '^\\u0000', '^(\\w|@(?!src|tests?\\/)\\w)'],
55
+ // All local imports:
56
+ // - Absolute imports and other imports like `@/foo`.
57
+ // - Anything not matched in another group.
58
+ // - Anything that starts with a dot.
59
+ ['^', '^\\.'],
60
+ ],
61
+ },
62
+ ],
63
+ 'simple-import-sort/exports': 'error',
64
+
65
+ // 2. Encouraging `lodash-es` imports per file
66
+ // lodash imports should use `lodash-es` package and should be imported per file.
67
+ // E.G: `import get from 'lodash-es/get'`
68
+ // More details in https://stackoverflow.com/questions/35250500/correct-way-to-import-lodash#answer-35251059
69
+ 'no-restricted-imports': [
70
+ 'error',
71
+ {
72
+ paths: [
73
+ {
74
+ name: 'lodash',
75
+ message: "Please use lodash-es direct import E.G: `import get from 'lodash-es/get'`",
76
+ },
77
+ {
78
+ name: 'lodash-es',
79
+ message: "Please use lodash-es direct import E.G: `import get from 'lodash-es/get'`",
80
+ },
81
+ ],
82
+ patterns: [
83
+ {
84
+ group: ['lodash/*'],
85
+ message: "Please use lodash-es direct import E.G: `import get from 'lodash-es/get'`",
86
+ },
87
+ ],
88
+ },
89
+ ],
90
+ },
91
+ },
92
+
93
+ // Custom ignores
94
+ {
95
+ name: 'codfish/ignores',
96
+
97
+ ignores: [
98
+ '!.github',
99
+ '!.vitepress',
100
+ '**/logs/',
101
+ 'bin/*',
102
+ '**/dist/',
103
+ '**/dist-ssr/',
104
+ '**/cache/',
105
+ '**/coverage/',
106
+ 'cypress/screenshots/',
107
+ 'cypress/videos/',
108
+ 'storybook-static/',
109
+ ],
110
+ },
111
+
112
+ // Configuration files (eslint, prettier, etc.)
113
+ configFilesConfig,
114
+
115
+ // React configuration (dynamic)
116
+ ifAnyDep('react', reactConfig, []),
117
+
118
+ // Jest OR Vitest configuration (dynamic)
119
+ ifAnyDep('jest', jestConfig, []),
120
+
121
+ // Vitest configuration (dynamic)
122
+ ifAnyDep('vitest', vitestConfig, []),
123
+
124
+ // Prettier plugin is responsible for running prettier as an ESLint
125
+ // rule and turning off ESLint rules that might conflict.
126
+ // IMPORTANT: KEEP THIS LAST TO OVERRIDE ESLINT!
127
+ prettier,
128
+
129
+ {
130
+ rules: {
131
+ // Reset prettier rule passing in codfish's prettier config.
132
+ // IMPORTANT: KEEP THIS LAST TO OVERRIDE PRETTIER PLUGIN!
133
+ 'prettier/prettier': useBuiltinPrettierConfig ? ['error', prettierBuiltInConfig] : 'error',
134
+ },
135
+ },
136
+ ]);
package/package.json ADDED
@@ -0,0 +1,118 @@
1
+ {
2
+ "name": "@codfish/eslint-config",
3
+ "version": "0.0.0-PR-124--3ca0d95",
4
+ "description": "Modern ESLint configuration with TypeScript, React, and testing framework support.",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./index.js"
12
+ },
13
+ "./prettier": {
14
+ "types": "./dist/prettier.d.ts",
15
+ "default": "./prettier.js"
16
+ },
17
+ "./dapp": {
18
+ "types": "./dist/dapp.d.ts",
19
+ "default": "./dapp.js"
20
+ },
21
+ "./docker": {
22
+ "types": "./dist/docker.d.ts",
23
+ "default": "./docker.js"
24
+ }
25
+ },
26
+ "scripts": {
27
+ "build": "tsc --emitDeclarationOnly",
28
+ "dev": "tsc --watch",
29
+ "type-check": "tsc --noEmit",
30
+ "lint": "eslint .",
31
+ "fix": "prettier --write \"**/*.{json,css,scss,md}\" && npm run lint -- --fix",
32
+ "prepublishOnly": "npm run build",
33
+ "prepare": "husky"
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/codfish/eslint-config.git"
38
+ },
39
+ "keywords": [
40
+ "eslint",
41
+ "eslintconfig",
42
+ "config",
43
+ "codfish",
44
+ "prettier",
45
+ "javascript",
46
+ "styleguide"
47
+ ],
48
+ "author": "Chris O'Donnell <chris@codfish.dev> (https://www.codfish.dev)",
49
+ "license": "MIT",
50
+ "bugs": {
51
+ "url": "https://github.com/codfish/eslint-config-codfish/issues"
52
+ },
53
+ "homepage": "https://github.com/codfish/eslint-config-codfish#readme",
54
+ "peerDependencies": {
55
+ "eslint": ">= 9"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "typescript": {
59
+ "optional": true
60
+ }
61
+ },
62
+ "engines": {
63
+ "node": ">=20.0.0"
64
+ },
65
+ "files": [
66
+ "dist",
67
+ "rules",
68
+ "index.js",
69
+ "prettier.js",
70
+ "dapp.js",
71
+ "docker.js",
72
+ "utils.js",
73
+ "commitlint.js"
74
+ ],
75
+ "dependencies": {
76
+ "@commitlint/cli": "^19.8.1",
77
+ "@commitlint/config-conventional": "^19.8.1",
78
+ "@eslint/js": "^9.35.0",
79
+ "@vitest/eslint-plugin": "^1.3.10",
80
+ "cosmiconfig": "^9.0.0",
81
+ "eslint-config-prettier": "^10.1.8",
82
+ "eslint-plugin-jest": "^29.0.1",
83
+ "eslint-plugin-jsx-a11y": "^6.10.2",
84
+ "eslint-plugin-prettier": "^5.5.4",
85
+ "eslint-plugin-react": "^7.37.5",
86
+ "eslint-plugin-react-hooks": "^5.2.0",
87
+ "eslint-plugin-simple-import-sort": "^12.1.1",
88
+ "globals": "^16.4.0",
89
+ "lodash.has": "^4.5.2",
90
+ "prettier": "^3.6.2",
91
+ "read-package-up": "^11.0.0"
92
+ },
93
+ "devDependencies": {
94
+ "doctoc": "^2.2.1",
95
+ "eslint": "^9.35.0",
96
+ "husky": "^9.1.7",
97
+ "lint-staged": "^16.1.6",
98
+ "typescript": "^5.9.2",
99
+ "typescript-eslint": "^8.44.0"
100
+ },
101
+ "commitlint": {
102
+ "extends": [
103
+ "./commitlint"
104
+ ]
105
+ },
106
+ "lint-staged": {
107
+ "*.{json,yml}": [
108
+ "prettier --write --config ./prettier.js"
109
+ ],
110
+ "*.md": [
111
+ "prettier --write --config ./prettier.js",
112
+ "doctoc --title '## Table of Contents'"
113
+ ]
114
+ },
115
+ "volta": {
116
+ "node": "24.8.0"
117
+ }
118
+ }
package/prettier.js ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @see https://prettier.io/docs/configuration
3
+ * @type {import("prettier").Config}
4
+ */
5
+ const config = {
6
+ printWidth: 120,
7
+ tabWidth: 2,
8
+ useTabs: false,
9
+ semi: true,
10
+ arrowParens: 'avoid',
11
+ endOfLine: 'lf',
12
+ htmlWhitespaceSensitivity: 'css',
13
+ insertPragma: false,
14
+ jsxSingleQuote: false,
15
+ quoteProps: 'as-needed',
16
+ requirePragma: false,
17
+ singleQuote: true,
18
+ trailingComma: 'all',
19
+ bracketSpacing: true,
20
+ bracketSameLine: false,
21
+ proseWrap: 'always',
22
+ vueIndentScriptAndStyle: false,
23
+ embeddedLanguageFormatting: 'auto',
24
+ };
25
+
26
+ export default config;
@@ -0,0 +1,21 @@
1
+ import { defineConfig } from 'eslint/config';
2
+
3
+ /**
4
+ * Configuration files ESLint rules
5
+ * Allows importing dev dependencies in configuration files
6
+ */
7
+ export default defineConfig({
8
+ name: 'codfish/config-files',
9
+
10
+ files: [
11
+ '*.config.{js,ts}',
12
+ '.eslintrc.{js,ts}',
13
+ '.prettierrc.{js,ts}',
14
+ '.commitlintrc.{js,ts}',
15
+ '.lintstagedrc.{js,ts}',
16
+ ],
17
+
18
+ rules: {
19
+ 'import/no-extraneous-dependencies': 'off',
20
+ },
21
+ });
package/rules/jest.js ADDED
@@ -0,0 +1,24 @@
1
+ import { defineConfig } from 'eslint/config';
2
+ import jest from 'eslint-plugin-jest';
3
+
4
+ /**
5
+ * Jest ESLint configuration for flat config format
6
+ * Includes Jest-specific rules and globals for test files
7
+ */
8
+ export default defineConfig([
9
+ {
10
+ name: 'codfish/jest',
11
+
12
+ files: [
13
+ '**/__tests__/**/*.{js,ts,jsx,tsx}',
14
+ '**/*.{test,spec}.{js,ts,jsx,tsx}',
15
+ '**/jest.config.{js,ts}',
16
+ '**/jest.setup.{js,ts}',
17
+ '**/setupTests.{js,ts}',
18
+ '**/testUtils.{js,ts}',
19
+ 'tests/**/*.{js,ts,jsx,tsx}',
20
+ ],
21
+
22
+ ...jest.configs['flat/recommended'],
23
+ },
24
+ ]);
package/rules/react.js ADDED
@@ -0,0 +1,39 @@
1
+ import { defineConfig } from 'eslint/config';
2
+ import jsxA11y from 'eslint-plugin-jsx-a11y';
3
+ import react from 'eslint-plugin-react';
4
+ import reactHooks from 'eslint-plugin-react-hooks';
5
+ import globals from 'globals';
6
+
7
+ /**
8
+ * React ESLint configuration. Includes React, React Hooks, and JSX accessibility rules.
9
+ *
10
+ * - https://github.com/jsx-eslint/eslint-plugin-react
11
+ * - https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks
12
+ * - https://github.com/jsx-eslint/eslint-plugin-jsx-a11y
13
+ */
14
+ export default defineConfig([
15
+ {
16
+ name: 'codfish/react',
17
+
18
+ files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
19
+
20
+ ...react.configs.flat.recommended,
21
+ ...jsxA11y.flatConfigs.recommended,
22
+
23
+ languageOptions: {
24
+ globals: {
25
+ ...globals.serviceworker,
26
+ ...globals.browser,
27
+ },
28
+ },
29
+ },
30
+
31
+ // React Hooks configuration
32
+ reactHooks.configs['recommended-latest'],
33
+
34
+ {
35
+ rules: {
36
+ 'react-hooks/exhaustive-deps': 'off',
37
+ },
38
+ },
39
+ ]);
@@ -0,0 +1,34 @@
1
+ import vitest from '@vitest/eslint-plugin';
2
+ import { defineConfig } from 'eslint/config';
3
+ import globals from 'globals';
4
+
5
+ /**
6
+ * Vitest ESLint configuration for flat config format
7
+ * Includes Vitest-specific rules and globals for test files
8
+ */
9
+ export default defineConfig([
10
+ {
11
+ files: [
12
+ '**/*.{spec,test}.{js,ts,jsx,tsx}',
13
+ '**/tests/**/*.{js,ts,jsx,tsx}',
14
+ '**/__mocks__/**/*.{js,ts,jsx,tsx}',
15
+ '**/__tests__/**/*.{js,ts,jsx,tsx}',
16
+ ],
17
+
18
+ ...vitest.configs.recommended,
19
+
20
+ name: 'codfish/vitest',
21
+
22
+ languageOptions: {
23
+ globals: {
24
+ ...vitest.environments.env.globals,
25
+ ...globals.node,
26
+ },
27
+ },
28
+
29
+ rules: {
30
+ 'no-console': 'off',
31
+ 'tailwindcss/no-custom-classname': 'off',
32
+ },
33
+ },
34
+ ]);
package/utils.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Utility Methods
3
+ *
4
+ * Credit: Kent C. Dodds
5
+ *
6
+ * @see https://github.com/kentcdodds/kcd-scripts/blob/main/src/utils.js
7
+ */
8
+ import fs from 'node:fs';
9
+ import { cosmiconfigSync } from 'cosmiconfig';
10
+ import has from 'lodash.has';
11
+ import { readPackageUp } from 'read-package-up';
12
+
13
+ const { packageJson: pkg, path: pkgPath } =
14
+ (await readPackageUp({
15
+ cwd: fs.realpathSync(process.cwd()),
16
+ })) || {};
17
+
18
+ const hasPkgProp = props => [props].flat().some(prop => has(pkg, prop));
19
+ const hasPkgSubProp = pkgProp => props => hasPkgProp([props].flat().map(p => `${pkgProp}.${p}`));
20
+
21
+ export const hasDep = hasPkgSubProp('dependencies');
22
+
23
+ export const hasDevDep = hasPkgSubProp('devDependencies');
24
+ export const hasPeerDep = hasPkgSubProp('peerDependencies');
25
+ export const hasAnyDep = args => [hasDep, hasDevDep, hasPeerDep].some(fn => fn(args));
26
+
27
+ export const ifAnyDep = (deps, t, f) => (hasAnyDep([deps].flat()) ? t : f);
28
+
29
+ export function hasLocalConfig(moduleName, searchOptions = {}) {
30
+ const explorerSync = cosmiconfigSync(moduleName, searchOptions);
31
+ const result = explorerSync.search(pkgPath || './');
32
+
33
+ return result !== null;
34
+ }