zeno-config 0.1.0

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,271 @@
1
+ # zeno-config
2
+
3
+ Preconfigured ESLint, Prettier, and TypeScript setup for modern JavaScript and React projects.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **ESLint 9+ flat config** - Modern configuration format
8
+ - ⚛️ **React support** - Comprehensive React, React Hooks, and JSX accessibility rules
9
+ - 📘 **TypeScript ready** - Full TypeScript support with type-aware linting
10
+ - 💅 **Prettier integration** - Seamless formatting with ESLint
11
+ - 🎯 **Node.js optimized** - Specific rules for Node.js projects
12
+ - 🔌 **Modular configs** - Use only what you need
13
+
14
+ ## Requirements
15
+
16
+ - Node.js >= 20
17
+ - ESLint >= 9
18
+
19
+ ## Installation
20
+
21
+ Install the package and its peer dependencies:
22
+
23
+ ```bash
24
+ # Using pnpm (recommended)
25
+
26
+ # Base dependencies
27
+ pnpm add -D zeno-config eslint prettier @eslint/js @stylistic/eslint-plugin eslint-config-prettier eslint-plugin-import-x eslint-plugin-n eslint-plugin-prettier eslint-plugin-unicorn
28
+
29
+ # For React projects, also install:
30
+ pnpm add -D eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y eslint-plugin-react-you-might-not-need-an-effect
31
+
32
+ # For TypeScript projects, also install:
33
+ pnpm add -D typescript typescript-eslint
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ ### ESLint Configuration
39
+
40
+ Create an `eslint.config.js` file in your project root:
41
+
42
+ #### Basic Configuration
43
+
44
+ ```javascript
45
+ import { defineZenoConfig } from 'zeno-config/eslint';
46
+
47
+ export default defineZenoConfig({
48
+ ts: true, // Enable TypeScript support (default: false)
49
+ react: true, // Enable React support (default: false)
50
+ });
51
+ ```
52
+
53
+ #### Required: Empty `.eslintrc` File
54
+
55
+ You must create an empty `.eslintrc` file in your project root for the `import-x/no-unused-modules` rule to work correctly with flat config:
56
+
57
+ ```bash
58
+ touch .eslintrc
59
+ ```
60
+
61
+ This is a workaround for a [known limitation](https://github.com/import-js/eslint-plugin-import/issues/3079) where certain internal ESLint APIs are excluded when using flat config. The file can be empty or contain only `ignorePatterns` if you need to ignore specific files.
62
+
63
+ #### `engines` field in `package.json`
64
+
65
+ Add an `engines` field to your `package.json` with your supported Node.js versions. Some rules for Node.js use this:
66
+
67
+ ```json
68
+ {
69
+ "engines": {
70
+ "node": ">=20"
71
+ }
72
+ }
73
+ ```
74
+
75
+ #### Advanced Configuration
76
+
77
+ ```javascript
78
+ import { defineZenoConfig } from 'zeno-config/eslint';
79
+
80
+ export default defineZenoConfig(
81
+ {
82
+ react: true,
83
+ ts: true,
84
+
85
+ // If using .js extensions for React files, specify React directories
86
+ reactDirs: ['src/client', 'src/components'],
87
+
88
+ // Ignore Node.js rules in specific directories (defaults to reactDirs)
89
+ nodeIgnoreDirs: ['src/client'],
90
+
91
+ // Patterns to ignore for import/no-unresolved rule
92
+ ignoreExports: ['^@/'],
93
+
94
+ // Extensions to ignore for import/extensions rule
95
+ extensionsIgnorePattern: {
96
+ svg: 'always',
97
+ },
98
+
99
+ // Webpack config path for import resolution
100
+ webpackConfig: './webpack.config.js',
101
+ },
102
+ [
103
+ // Your custom config objects
104
+ {
105
+ rules: {
106
+ 'no-console': 'warn',
107
+ },
108
+ },
109
+ ]
110
+ );
111
+ ```
112
+
113
+ ### Prettier Configuration
114
+
115
+ Create a `prettier.config.js` file in your project root:
116
+
117
+ ```javascript
118
+ import zenoConfig from 'zeno-config/prettier';
119
+
120
+ export default zenoConfig;
121
+ ```
122
+
123
+ Or extend it with your own options:
124
+
125
+ ```javascript
126
+ import zenoConfig from 'zeno-config/prettier';
127
+
128
+ export default {
129
+ ...zenoConfig,
130
+ printWidth: 100, // Override specific options
131
+ };
132
+ ```
133
+
134
+ ### TypeScript Configuration
135
+
136
+ For Node.js projects, extend the provided TypeScript config in your `tsconfig.json`:
137
+
138
+ ```json
139
+ {
140
+ "extends": "zeno-config/tsconfig"
141
+ // your tsconfig options
142
+ }
143
+ ```
144
+
145
+ For React projects:
146
+
147
+ ```json
148
+ {
149
+ "extends": "zeno-config/tsconfig-react"
150
+ // your tsconfig options
151
+ }
152
+ ```
153
+
154
+ Example:
155
+
156
+ ```json
157
+ {
158
+ "extends": "zeno-config/tsconfig-react",
159
+ "compilerOptions": {
160
+ "baseUrl": ".", // should match webpack alias settings
161
+ "paths": {
162
+ // should match webpack alias settings
163
+ "@/*": ["src/*"]
164
+ },
165
+
166
+ "allowJs": true,
167
+ "checkJs": false
168
+ },
169
+ "include": ["src/**/*"]
170
+ }
171
+ ```
172
+
173
+ ### File Extensions Helpers
174
+
175
+ Use in your build configs, webpack, etc:
176
+
177
+ ```javascript
178
+ import {
179
+ allExtensions,
180
+ nodeExtensions,
181
+ reactExtensions,
182
+ typescriptExtensions,
183
+ } from 'zeno-config/extensions';
184
+ ```
185
+
186
+ Covers all of the module and commonjs extensions:
187
+
188
+ - **JavaScript**: `.js`, `.mjs`, `.cjs`
189
+ - **JSX**: `.jsx`, `.mjsx`, `.cjsx`
190
+ - **TypeScript**: `.ts`, `.cts`, `.mts`
191
+ - **TSX**: `.tsx`, `.mtsx`, `.ctsx`
192
+
193
+ ### `defineZenoConfig(options, additionalESLintConfig)`
194
+
195
+ | Option | Type | Default | Description |
196
+ | ------------------------- | ---------- | ----------- | ----------------------------------------------------------------------------------- |
197
+ | `react` | `boolean` | `false` | Enable React-specific rules |
198
+ | `ts` | `boolean` | `false` | Enable TypeScript-specific rules |
199
+ | `reactDirs` | `string[]` | `[]` | Directories containing React files (for projects using .js for both React and Node) |
200
+ | `nodeIgnoreDirs` | `string[]` | `[]` | Directories to ignore for Node-specific rules (defaults to `reactDirs` if not set) |
201
+ | `ignoreExports` | `string[]` | `[]` | Export patterns to ignore for import/no-unresolved rule |
202
+ | `extensionsIgnorePattern` | `object` | `{}` | Extension patterns to ignore for import/extensions rule |
203
+ | `webpackConfig` | `string` | `undefined` | Path to webpack config for import resolver |
204
+
205
+ ## Advanced Usage
206
+
207
+ ### Using Internal Configs Directly
208
+
209
+ For advanced use cases, you can import and use the internal configs:
210
+
211
+ ```javascript
212
+ import zenoInternals from 'zeno-config/eslint';
213
+
214
+ const { configs, rules, extensions } = zenoInternals;
215
+
216
+ export default [
217
+ ...configs.getBase(),
218
+ ...configs.getNode(),
219
+ ...configs.getReact(),
220
+ ...configs.getTypescript(),
221
+ // Your custom configs
222
+ ];
223
+ ```
224
+
225
+ ### Accessing Individual Rules
226
+
227
+ ```javascript
228
+ import zenoInternals from 'zeno-config/eslint';
229
+
230
+ const { rules } = zenoInternals;
231
+
232
+ // Use individual rule sets
233
+ const baseRules = rules.getBaseRules();
234
+ const reactRules = rules.getReactPluginRules({ extensions: ['.jsx', '.tsx'] });
235
+ ```
236
+
237
+ ## Defaults
238
+
239
+ ### Ignored Directories
240
+
241
+ The following directories are automatically ignored:
242
+
243
+ - `node_modules/`
244
+ - `dist/`
245
+ - `build/`
246
+ - `coverage/`
247
+
248
+ #### Prettier Settings
249
+
250
+ See [src/prettier.js](src/prettier.js) for the default Prettier configuration.
251
+
252
+ ### TypeScript Settings
253
+
254
+ See the TypeScript configuration files:
255
+
256
+ - [src/tsconfig.base.json](src/tsconfig.base.json) - Base configuration for Node.js projects
257
+ - [src/tsconfig.react.json](src/tsconfig.react.json) - Configuration for React projects (extends base)
258
+
259
+ ### Included Plugins
260
+
261
+ - `@eslint/js` - Core JavaScript rules ([rules](src/eslint/rules/baseRules.js))
262
+ - `@stylistic/eslint-plugin` - Code style rules ([rules](src/eslint/rules/stylisticPluginRules.js))
263
+ - `eslint-plugin-import-x` - Import/export validation ([rules](src/eslint/rules/importPluginRules.js))
264
+ - `eslint-plugin-unicorn` - Additional JavaScript best practices ([rules](src/eslint/rules/unicornPluginRules.js))
265
+ - `eslint-plugin-n` - Node.js specific rules ([rules](src/eslint/rules/nodePluginRules.js))
266
+ - `eslint-plugin-prettier` - Prettier integration
267
+ - `eslint-plugin-react` (optional) - React specific rules ([rules](src/eslint/rules/reactPluginRules.js))
268
+ - `eslint-plugin-react-hooks` (optional) - React Hooks rules ([rules](src/eslint/rules/reactHooksPluginRules.js))
269
+ - `eslint-plugin-jsx-a11y` (optional) - Accessibility rules for JSX ([rules](src/eslint/rules/jsxA11yPluginRules.js))
270
+ - `eslint-plugin-react-you-might-not-need-an-effect` (optional) - React Effect optimization ([rules](src/eslint/rules/reactYouMightNotNeedAnEffectPluginRules.js))
271
+ - `typescript-eslint` (optional) - TypeScript rules ([rules](src/eslint/rules/typescriptPluginRules.js))
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "zeno-config",
3
+ "version": "0.1.0",
4
+ "description": "Opinionated and preconfigured ESLint and Prettier setup",
5
+ "type": "module",
6
+ "packageManager": "pnpm@10.25.0",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
10
+ "scripts": {
11
+ "inspect": "pnpm dlx eslint --inspect-config"
12
+ },
13
+ "exports": {
14
+ "./eslint": {
15
+ "types": "./src/eslint/index.d.ts",
16
+ "default": "./src/eslint/index.js"
17
+ },
18
+ "./prettier": {
19
+ "types": "./src/prettier.d.ts",
20
+ "default": "./src/prettier.js"
21
+ },
22
+ "./tsconfig": "./src/tsconfig.base.json",
23
+ "./tsconfig-react": "./src/tsconfig.react.json",
24
+ "./extensions": {
25
+ "types": "./src/extensions.d.ts",
26
+ "default": "./src/extensions.js"
27
+ }
28
+ },
29
+ "files": [
30
+ "src/**"
31
+ ],
32
+ "peerDependencies": {
33
+ "@eslint/js": "^9.39.2",
34
+ "@stylistic/eslint-plugin": "^5.6.1",
35
+ "eslint": "^9.39.2",
36
+ "eslint-config-prettier": "^10.1.8",
37
+ "eslint-plugin-import-x": "^4.16.1",
38
+ "eslint-plugin-jsx-a11y": "^6.10.2",
39
+ "eslint-plugin-n": "^17.23.1",
40
+ "eslint-plugin-prettier": "^5.5.4",
41
+ "eslint-plugin-react": "^7.37.5",
42
+ "eslint-plugin-react-hooks": "^7.0.1",
43
+ "eslint-plugin-react-you-might-not-need-an-effect": "^0.7.0",
44
+ "eslint-plugin-unicorn": "^62.0.0",
45
+ "prettier": "^3.7.4",
46
+ "typescript": "^5.9.3",
47
+ "typescript-eslint": "^8.50.1"
48
+ },
49
+ "peerDependenciesMeta": {
50
+ "eslint-plugin-jsx-a11y": {
51
+ "optional": true
52
+ },
53
+ "eslint-plugin-react": {
54
+ "optional": true
55
+ },
56
+ "eslint-plugin-react-hooks": {
57
+ "optional": true
58
+ },
59
+ "eslint-plugin-react-you-might-not-need-an-effect": {
60
+ "optional": true
61
+ },
62
+ "typescript": {
63
+ "optional": true
64
+ },
65
+ "typescript-eslint": {
66
+ "optional": true
67
+ }
68
+ },
69
+ "devDependencies": {
70
+ "@eslint/js": "9.39.2",
71
+ "@stylistic/eslint-plugin": "5.6.1",
72
+ "eslint": "9.39.2",
73
+ "eslint-config-prettier": "10.1.8",
74
+ "eslint-plugin-import-x": "4.16.1",
75
+ "eslint-plugin-jsx-a11y": "6.10.2",
76
+ "eslint-plugin-n": "17.23.1",
77
+ "eslint-plugin-prettier": "5.5.4",
78
+ "eslint-plugin-react": "7.37.5",
79
+ "eslint-plugin-react-hooks": "7.0.1",
80
+ "eslint-plugin-react-you-might-not-need-an-effect": "0.7.0",
81
+ "eslint-plugin-unicorn": "62.0.0",
82
+ "prettier": "3.7.4",
83
+ "typescript": "5.9.3",
84
+ "typescript-eslint": "8.50.1"
85
+ },
86
+ "dependencies": {
87
+ "globals": "16.5.0"
88
+ }
89
+ }
@@ -0,0 +1,124 @@
1
+ import { type Linter } from 'eslint';
2
+
3
+ interface BaseConfigOptions {
4
+ /** Export patterns to ignore for import rules */
5
+ ignoreExports?: string[];
6
+ /** Extension patterns to ignore for import rules */
7
+ extensionsIgnorePattern?: Record<string, string>;
8
+ /** Path to webpack config for import resolver */
9
+ webpackConfig?: string;
10
+ }
11
+
12
+ interface NodeConfigOptions {
13
+ /** Additional directories to ignore for Node-specific rules */
14
+ ignoreDirs?: string[];
15
+ }
16
+
17
+ interface ReactConfigOptions {
18
+ /** Directories containing React files (for projects using .js for both React and Node) */
19
+ reactDirs?: string[];
20
+ /** Extension patterns to ignore for import rules */
21
+ extensionsIgnorePattern?: Record<string, string>;
22
+ }
23
+
24
+ interface DefineZenoConfigOptions {
25
+ /** Enable React-specific rules */
26
+ react?: boolean;
27
+ /** Enable TypeScript-specific rules */
28
+ ts?: boolean;
29
+ /** Directories containing React files (for projects using .js for both React and Node) */
30
+ reactDirs?: string[];
31
+ /** Directories to ignore for Node-specific rules */
32
+ nodeIgnoreDirs?: string[];
33
+ /** Export patterns to ignore for import rules */
34
+ ignoreExports?: string[];
35
+ /** Extension patterns to ignore for import rules */
36
+ extensionsIgnorePattern?: Record<string, string>;
37
+ /** Path to webpack config for import resolver */
38
+ webpackConfig?: string;
39
+ }
40
+
41
+ interface Extensions {
42
+ allExtensions: string[];
43
+ allExtensionsString: string;
44
+ nodeExtensions: string[];
45
+ nodeExtensionsString: string;
46
+ reactJsExtensions: string[];
47
+ reactJsExtensionsString: string;
48
+ reactJsExtensionsExtended: string[];
49
+ reactJsExtensionsExtendedString: string;
50
+ reactExtensions: string[];
51
+ reactExtensionsString: string;
52
+ reactExtensionsExtended: string[];
53
+ reactExtensionsExtendedString: string;
54
+ typescriptExtensions: string[];
55
+ typescriptExtensionsString: string;
56
+ }
57
+
58
+ interface Configs {
59
+ getBase: (options?: BaseConfigOptions) => Linter.Config[];
60
+ getReact: (options?: ReactConfigOptions) => Linter.Config[];
61
+ getNode: (options?: NodeConfigOptions) => Linter.Config[];
62
+ getTypescript: () => Linter.Config[];
63
+ }
64
+
65
+ interface Rules {
66
+ getBaseRules: () => Linter.RulesRecord;
67
+ getImportPluginRules: (options?: {
68
+ ignoreExports?: string[];
69
+ extensionsIgnorePattern?: Record<string, string>;
70
+ }) => Linter.RulesRecord;
71
+ getStylisticPluginRules: () => Linter.RulesRecord;
72
+ getUnicornPluginRules: () => Linter.RulesRecord;
73
+ getReactPluginRules: (options?: {
74
+ extensions?: string[];
75
+ }) => Linter.RulesRecord;
76
+ getReactHooksPluginRules: () => Linter.RulesRecord;
77
+ getReactYouMightNotNeedAnEffectPluginRules: () => Linter.RulesRecord;
78
+ getJsxA11yPluginRules: () => Linter.RulesRecord;
79
+ }
80
+
81
+ interface Internals {
82
+ configs: Configs;
83
+ extensions: Extensions;
84
+ rules: Rules;
85
+ }
86
+
87
+ declare const internals: Internals;
88
+
89
+ /**
90
+ * Defines a Zeno ESLint configuration.
91
+ *
92
+ * @param arg1 - Options object or additional config array. If an array, treated as additional config.
93
+ * @param arg2 - Additional ESLint config objects to merge (only used if arg1 is options object).
94
+ * @returns ESLint flat config array.
95
+ *
96
+ * @example
97
+ * // With options object
98
+ * defineZenoConfig({ react: true, ts: true })
99
+ *
100
+ * @example
101
+ * // With additional config
102
+ * defineZenoConfig({ react: true }, [customConfig])
103
+ *
104
+ * @example
105
+ * // With config array only
106
+ * defineZenoConfig([customConfig])
107
+ */
108
+ declare function defineZenoConfig(
109
+ arg1?: DefineZenoConfigOptions | Linter.Config[],
110
+ arg2?: Linter.Config[]
111
+ ): Linter.Config[];
112
+
113
+ export {
114
+ type BaseConfigOptions,
115
+ type Configs,
116
+ type DefineZenoConfigOptions,
117
+ type Extensions,
118
+ type Internals,
119
+ type NodeConfigOptions,
120
+ type ReactConfigOptions,
121
+ type Rules,
122
+ defineZenoConfig,
123
+ };
124
+ export default internals;