js-style-kit 0.6.1 → 0.7.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.
Files changed (64) hide show
  1. package/README.md +5 -0
  2. package/dist/index.d.ts +11 -5
  3. package/dist/index.js +48 -7
  4. package/dist/index.js.map +1 -1
  5. package/package.json +8 -5
  6. package/src/eslint/base/README.md +186 -0
  7. package/src/eslint/base/config.ts +37 -0
  8. package/src/eslint/base/rules.ts +444 -0
  9. package/src/eslint/base/types.ts +20 -0
  10. package/src/eslint/constants.ts +52 -0
  11. package/src/eslint/convex/README.md +30 -0
  12. package/src/eslint/convex/config.ts +34 -0
  13. package/src/eslint/convex/rules.ts +8 -0
  14. package/src/eslint/convex/types.ts +8 -0
  15. package/src/eslint/ignores.ts +31 -0
  16. package/src/eslint/import/README.md +397 -0
  17. package/src/eslint/import/config.ts +48 -0
  18. package/src/eslint/import/rules.ts +81 -0
  19. package/src/eslint/index.ts +259 -0
  20. package/src/eslint/jsdoc/README.md +399 -0
  21. package/src/eslint/jsdoc/config.ts +29 -0
  22. package/src/eslint/jsdoc/rules.ts +81 -0
  23. package/src/eslint/jsdoc/types.ts +56 -0
  24. package/src/eslint/nextjs/config.ts +25 -0
  25. package/src/eslint/nextjs/rules.ts +25 -0
  26. package/src/eslint/nextjs/types.ts +27 -0
  27. package/src/eslint/perfectionist/README.md +454 -0
  28. package/src/eslint/perfectionist/config.ts +25 -0
  29. package/src/eslint/perfectionist/rules.ts +39 -0
  30. package/src/eslint/prefer-arrow-function/config.ts +33 -0
  31. package/src/eslint/prefer-arrow-function/types.ts +13 -0
  32. package/src/eslint/process-custom-rules.ts +72 -0
  33. package/src/eslint/query/README.md +254 -0
  34. package/src/eslint/query/config.ts +27 -0
  35. package/src/eslint/query/rules.ts +11 -0
  36. package/src/eslint/query/types.ts +11 -0
  37. package/src/eslint/react/README.md +416 -0
  38. package/src/eslint/react/config.ts +65 -0
  39. package/src/eslint/react/rules.ts +188 -0
  40. package/src/eslint/react/types.ts +26 -0
  41. package/src/eslint/react-refresh/config.ts +28 -0
  42. package/src/eslint/react-refresh/rules.ts +48 -0
  43. package/src/eslint/storybook/README.md +424 -0
  44. package/src/eslint/storybook/config.ts +57 -0
  45. package/src/eslint/testing/README.md +436 -0
  46. package/src/eslint/testing/config.ts +90 -0
  47. package/src/eslint/testing/jest-rules.ts +47 -0
  48. package/src/eslint/testing/vitest-rules.ts +42 -0
  49. package/src/eslint/turbo/README.md +380 -0
  50. package/src/eslint/turbo/config.ts +26 -0
  51. package/src/eslint/turbo/types.ts +7 -0
  52. package/src/eslint/types.ts +29 -0
  53. package/src/eslint/typescript/README.md +229 -0
  54. package/src/eslint/typescript/config.ts +48 -0
  55. package/src/eslint/typescript/rules.ts +137 -0
  56. package/src/eslint/typescript/types.ts +35 -0
  57. package/src/eslint/unicorn/README.md +497 -0
  58. package/src/eslint/unicorn/config.ts +36 -0
  59. package/src/eslint/unicorn/rules.ts +86 -0
  60. package/src/index.ts +3 -0
  61. package/src/modules.d.ts +5 -0
  62. package/src/prettier/README.md +413 -0
  63. package/src/prettier/index.ts +110 -0
  64. package/src/utils/is-type.ts +60 -0
@@ -0,0 +1,397 @@
1
+ # Import Configuration
2
+
3
+ Comprehensive import/export validation and organization powered by `eslint-plugin-import-x`. A faster alternative to `eslint-plugin-import`.
4
+
5
+ [← Back to main README](../../../README.md)
6
+
7
+ ## Overview
8
+
9
+ Import configuration is **enabled by default** and provides:
10
+
11
+ - Import/export validation and error detection
12
+ - Duplicate import prevention
13
+ - Path validation and optimization
14
+ - Circular dependency detection
15
+ - TypeScript-aware import resolution
16
+
17
+ ## Quick Start
18
+
19
+ The import configuration is automatically enabled when you use `eslintConfig()`:
20
+
21
+ ```js
22
+ import { eslintConfig } from "js-style-kit";
23
+
24
+ export default eslintConfig(); // Import rules enabled by default
25
+ ```
26
+
27
+ ### Disable Import Validation
28
+
29
+ Disable import validation by passing `import: false` to `eslintConfig()`:
30
+
31
+ ```js
32
+ export default eslintConfig({
33
+ import: false,
34
+ });
35
+ ```
36
+
37
+ ## Key Features
38
+
39
+ ### Import Validation
40
+
41
+ Ensures all imports are valid and resolvable:
42
+
43
+ ```js
44
+ // ✅ Good
45
+ import { useState } from "react";
46
+ import { formatDate } from "./utils";
47
+ import type { User } from "./types";
48
+
49
+ // ❌ Bad - unresolved import
50
+ import { missing } from "./nonexistent";
51
+
52
+ // ❌ Bad - importing from wrong export
53
+ import { nonExistent } from "react";
54
+ ```
55
+
56
+ **Rules:**
57
+
58
+ - `import-x/named` - Validates named imports exist (JS only)
59
+ - `import-x/default` - Validates default imports exist (JS only)
60
+ - `import-x/namespace` - Validates namespace imports (JS only)
61
+ - `import-x/no-unresolved` - Ensures imports can be resolved (JS only)
62
+
63
+ **Note:** In TypeScript projects, these validations are handled by TypeScript itself.
64
+
65
+ ### Duplicate Prevention
66
+
67
+ Prevents duplicate and redundant imports:
68
+
69
+ ```js
70
+ // ✅ Good
71
+ import { useState, useEffect } from "react";
72
+
73
+ // ❌ Bad - duplicate imports
74
+ import { useState } from "react";
75
+ import { useEffect } from "react";
76
+ ```
77
+
78
+ **Rules:**
79
+
80
+ - `import-x/no-duplicates` - Merges duplicate imports from the same module
81
+
82
+ ### Import Organization
83
+
84
+ Enforces clean import structure:
85
+
86
+ ```js
87
+ // ✅ Good
88
+ import React from "react";
89
+ import { useState } from "react";
90
+
91
+ const MyComponent = () => {
92
+ /* ... */
93
+ };
94
+
95
+ // ❌ Bad - import after code
96
+ const MyComponent = () => {
97
+ /* ... */
98
+ };
99
+
100
+ import React from "react"; // Import must come first
101
+ ```
102
+
103
+ **Rules:**
104
+
105
+ - `import-x/first` - Imports must come before other statements
106
+ - `import-x/newline-after-import` - Requires newline after last import (fixable)
107
+
108
+ ### Path Validation
109
+
110
+ Ensures clean, maintainable import paths:
111
+
112
+ ```js
113
+ // ✅ Good
114
+ import { helper } from "./utils/helper";
115
+ import { config } from "@/config";
116
+
117
+ // ❌ Bad - absolute path
118
+ import { helper } from "/Users/name/project/src/utils/helper";
119
+
120
+ // ❌ Bad - importing from package's internal path
121
+ import { Button } from "../../node_modules/ui-library/dist/button";
122
+
123
+ // ❌ Bad - self import
124
+ import { something } from "./current-file";
125
+
126
+ // ❌ Bad - unnecessary path segments
127
+ import { helper } from "./utils/../helper";
128
+ ```
129
+
130
+ **Rules:**
131
+
132
+ - `import-x/no-absolute-path` - Disallows absolute filesystem paths
133
+ - `import-x/no-relative-packages` - Prevents relative imports of packages
134
+ - `import-x/no-self-import` - Prevents importing from the same file
135
+ - `import-x/no-useless-path-segments` - Removes unnecessary path segments
136
+
137
+ ### Circular Dependencies
138
+
139
+ Detects circular dependencies that can cause issues:
140
+
141
+ ```js
142
+ // ❌ Bad
143
+ // user.ts
144
+ import { Post } from "./post";
145
+ export class User { posts: Post[] }
146
+
147
+ // post.ts
148
+ import { User } from "./user"; // ❌ Circular dependency
149
+ export class Post { author: User }
150
+
151
+ // ✅ Good - use type-only import to break cycle
152
+ // post.ts
153
+ import type { User } from "./user";
154
+ export class Post { author: User }
155
+ ```
156
+
157
+ **Rules:**
158
+
159
+ - `import-x/no-cycle` - Warns on circular dependencies
160
+
161
+ ### Dependency Management
162
+
163
+ Validates package usage:
164
+
165
+ ```js
166
+ // ✅ Good - importing from dependencies
167
+ import React from "react"; // Listed in package.json
168
+
169
+ // ❌ Bad - importing package not in dependencies
170
+ import express from "express"; // Not in package.json
171
+ ```
172
+
173
+ **Rules:**
174
+
175
+ - `import-x/no-extraneous-dependencies` - Ensures imports are in `package.json`
176
+
177
+ ### Export Best Practices
178
+
179
+ Enforces safe export patterns:
180
+
181
+ ```js
182
+ // ✅ Good
183
+ export const API_KEY = "abc123";
184
+ export const config = { url: "..." };
185
+
186
+ // ❌ Bad - mutable export
187
+ export let count = 0; // Can be reassigned externally
188
+
189
+ // ❌ Bad - named as default
190
+ export { user as default };
191
+ import user from "./user"; // Confusing
192
+ ```
193
+
194
+ **Rules:**
195
+
196
+ - `import-x/no-mutable-exports` - Prevents `export let`
197
+ - `import-x/no-named-as-default` - Warns when default export has same name as named export
198
+ - `import-x/no-named-as-default-member` - Warns on accessing named exports from default
199
+
200
+ ## TypeScript Integration
201
+
202
+ When TypeScript is enabled, the configuration automatically adjusts:
203
+
204
+ ```js
205
+ export default eslintConfig({
206
+ typescript: true, // Enabled by default
207
+ });
208
+ ```
209
+
210
+ **TypeScript mode:**
211
+
212
+ - ✅ Uses `eslint-import-resolver-typescript` for path resolution
213
+ - ✅ Supports TypeScript path aliases (`@/`, `~/`, etc.)
214
+ - ✅ Disables redundant validation rules (TypeScript handles them)
215
+ - ✅ Validates type-only imports
216
+ - ✅ Supports Bun runtime resolution
217
+
218
+ ### Path Aliases
219
+
220
+ ```ts
221
+ // tsconfig.json
222
+ {
223
+ "compilerOptions": {
224
+ "paths": {
225
+ "@/*": ["./src/*"],
226
+ "~/*": ["./"]
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ ```ts
233
+ // ✅ Works with TypeScript resolver
234
+ import { Button } from "@/components/Button";
235
+ import { config } from "~/config";
236
+ ```
237
+
238
+ ## Examples
239
+
240
+ ### JavaScript Project
241
+
242
+ ```js
243
+ // utils.js
244
+ export const formatDate = (date) => {
245
+ /* ... */
246
+ };
247
+ export const parseDate = (str) => {
248
+ /* ... */
249
+ };
250
+
251
+ // app.js
252
+ import { formatDate, parseDate } from "./utils"; // ✅ Combined import
253
+
254
+ formatDate(new Date());
255
+ ```
256
+
257
+ ### TypeScript Project
258
+
259
+ ```ts
260
+ // types.ts
261
+ export interface User {
262
+ id: string;
263
+ name: string;
264
+ }
265
+
266
+ // user-service.ts
267
+ import type { User } from "./types"; // ✅ Type-only import
268
+
269
+ export const getUser = (): User => {
270
+ /* ... */
271
+ };
272
+ ```
273
+
274
+ ### Breaking Circular Dependencies
275
+
276
+ ```ts
277
+ // Before - circular dependency
278
+ // user.ts
279
+ import { Post } from "./post";
280
+ export interface User {
281
+ posts: Post[];
282
+ }
283
+
284
+ // post.ts
285
+ import { User } from "./user"; // ❌ Circular
286
+ export interface Post {
287
+ author: User;
288
+ }
289
+
290
+ // After - using type-only import
291
+ // user.ts
292
+ import type { Post } from "./post";
293
+ export interface User {
294
+ posts: Post[];
295
+ }
296
+
297
+ // post.ts
298
+ import type { User } from "./user"; // ✅ Type-only breaks cycle
299
+ export interface Post {
300
+ author: User;
301
+ }
302
+ ```
303
+
304
+ ### Monorepo Packages
305
+
306
+ ```ts
307
+ // package.json in workspace
308
+ {
309
+ "dependencies": {
310
+ "@myorg/shared": "workspace:*"
311
+ }
312
+ }
313
+
314
+ // ✅ Good - importing workspace package
315
+ import { Button } from "@myorg/shared";
316
+
317
+ // ❌ Bad - relative import to other package
318
+ import { Button } from "../../shared/src/Button";
319
+ ```
320
+
321
+ ## Customization
322
+
323
+ Override specific import rules:
324
+
325
+ ```js
326
+ export default eslintConfig({
327
+ rules: {
328
+ // Allow circular dependencies in some cases
329
+ "import-x/no-cycle": "off",
330
+
331
+ // Error on extraneous dependencies instead of warn
332
+ "import-x/no-extraneous-dependencies": "error",
333
+
334
+ // Allow default exports with same name as named export
335
+ "import-x/no-named-as-default": "off",
336
+ },
337
+ });
338
+ ```
339
+
340
+ ### Custom Import Ordering
341
+
342
+ While this config handles import validation, use the [Perfectionist](../perfectionist/README.md) configuration for import sorting:
343
+
344
+ ```js
345
+ export default eslintConfig({
346
+ // Import validation + sorting
347
+ perfectionist: true, // Sorts imports alphabetically
348
+ });
349
+ ```
350
+
351
+ ## Common Issues
352
+
353
+ ### Unresolved imports in monorepo
354
+
355
+ Make sure TypeScript is enabled and `tsconfig.json` includes proper path mappings:
356
+
357
+ ```json
358
+ {
359
+ "compilerOptions": {
360
+ "baseUrl": ".",
361
+ "paths": {
362
+ "@myorg/*": ["packages/*/src"]
363
+ }
364
+ }
365
+ }
366
+ ```
367
+
368
+ ### False positives on dynamic imports
369
+
370
+ Dynamic imports are supported:
371
+
372
+ ```js
373
+ const module = await import(`./modules/${name}`); // ✅ OK
374
+ ```
375
+
376
+ ### Type imports not working
377
+
378
+ Ensure TypeScript is enabled in the config:
379
+
380
+ ```js
381
+ export default eslintConfig({
382
+ typescript: true, // Required for type-only import validation
383
+ });
384
+ ```
385
+
386
+ ## Related Configurations
387
+
388
+ - [Perfectionist](../perfectionist/README.md) - Auto-sorts imports
389
+ - [TypeScript](../typescript/README.md) - TypeScript configuration
390
+ - [Base](../base/README.md) - Base ESLint rules
391
+
392
+ ## Learn More
393
+
394
+ - [eslint-plugin-import-x](https://github.com/un-ts/eslint-plugin-import-x)
395
+ - [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript)
396
+ - [ES Module Imports](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)
397
+ - [Main README](../../../README.md)
@@ -0,0 +1,48 @@
1
+ import type { ESLint } from "eslint";
2
+
3
+ import tsParser from "@typescript-eslint/parser";
4
+ import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
5
+ import importXPlugin from "eslint-plugin-import-x";
6
+
7
+ import type { EslintConfigObject, EslintRuleConfig } from "../types.js";
8
+
9
+ import { configNames } from "../constants.js";
10
+ import { importRules } from "./rules.js";
11
+
12
+ /**
13
+ * Creates an ESLint configuration for Import.
14
+ *
15
+ * @param typescript - Whether TypeScript is being used in the project. When true, some rules are adjusted to be more TypeScript-friendly.
16
+ * @param customRules - Optional object containing custom rules to override or add to the Import configuration.
17
+ * @returns ESLint configuration object for Import
18
+ */
19
+ export const importConfig = (
20
+ typescript: boolean,
21
+ customRules?: Record<string, EslintRuleConfig>,
22
+ ): EslintConfigObject => ({
23
+ languageOptions: {
24
+ ecmaVersion: "latest",
25
+ parser: tsParser,
26
+ sourceType: "module",
27
+ },
28
+ name: configNames.import,
29
+ plugins: {
30
+ "import-x": importXPlugin as unknown as ESLint.Plugin,
31
+ },
32
+ rules: {
33
+ ...importRules(typescript),
34
+ ...(customRules ?? {}),
35
+ },
36
+ settings: {
37
+ "import-x/resolver": {
38
+ node: true,
39
+ typescript,
40
+ },
41
+ "import-x/resolver-next": [
42
+ createTypeScriptImportResolver({
43
+ alwaysTryTypes: true,
44
+ bun: true,
45
+ }),
46
+ ],
47
+ },
48
+ });
@@ -0,0 +1,81 @@
1
+ import type { EslintRuleConfig } from "../types.js";
2
+
3
+ type ImportRules = Record<`import-x/${string}`, EslintRuleConfig>;
4
+
5
+ /**
6
+ * Creates a configuration object for import ESLint rules.
7
+ *
8
+ * @param typescript - Whether to include TypeScript-specific rules.
9
+ * @returns A configuration object for import ESLint rules.
10
+ */
11
+ export const importRules = (typescript: boolean): ImportRules => ({
12
+ // these rules are better handled by typescript
13
+ ...(!typescript ?
14
+ {
15
+ "import-x/default": "warn",
16
+ "import-x/export": "warn",
17
+ "import-x/named": "warn",
18
+ "import-x/namespace": "warn",
19
+ "import-x/no-unresolved": "warn",
20
+ }
21
+ : {}),
22
+ /**
23
+ * Disallow non-import statements appearing before import statements.
24
+ *
25
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/first.md
26
+ */
27
+ "import-x/first": "warn",
28
+ /**
29
+ * Require a newline after the last import-x/require.
30
+ *
31
+ * 🔧 Fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/newline-after-import.md
32
+ */
33
+ "import-x/newline-after-import": "warn",
34
+ /**
35
+ * Disallow import of modules using absolute paths.
36
+ *
37
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-absolute-path.md
38
+ */
39
+ "import-x/no-absolute-path": "warn",
40
+ /**
41
+ * Disallow cyclical dependencies between modules.
42
+ *
43
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-cycle.md
44
+ */
45
+ "import-x/no-cycle": "warn",
46
+ "import-x/no-duplicates": "warn",
47
+ /**
48
+ * Disallow the use of extraneous packages.
49
+ *
50
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-extraneous-dependencies.md
51
+ */
52
+ "import-x/no-extraneous-dependencies": ["warn", { includeTypes: true }],
53
+ /**
54
+ * Disallow mutable exports.
55
+ *
56
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-mutable-exports.md
57
+ */
58
+ "import-x/no-mutable-exports": "warn",
59
+ // red flags (thus, warnings)
60
+ "import-x/no-named-as-default": "warn",
61
+ "import-x/no-named-as-default-member": "warn",
62
+ /**
63
+ * Disallow importing packages through relative paths.
64
+ *
65
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-relative-packages.md
66
+ */
67
+ "import-x/no-relative-packages": "warn",
68
+
69
+ /**
70
+ * Disallow a module from importing itself.
71
+ *
72
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-self-import.md
73
+ */
74
+ "import-x/no-self-import": "warn",
75
+ /**
76
+ * Ensures that there are no useless path segments.
77
+ *
78
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-useless-path-segments.md
79
+ */
80
+ "import-x/no-useless-path-segments": ["warn"],
81
+ });