js-style-kit 0.6.0 → 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 -77
  4. package/dist/index.js.map +1 -1
  5. package/package.json +36 -33
  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,81 @@
1
+ import type { JsdocRules } from "./types.js";
2
+
3
+ /**
4
+ * Generates ESLint rules configuration for JSDoc comments.
5
+ *
6
+ * @param requireJsdoc - Whether to enforce JSDoc comments on functions and classes. Defaults to false.
7
+ * @param typescript - Whether TypeScript is being used in the project. When true, some rules are adjusted to be more TypeScript-friendly. Defaults to true.
8
+ * @returns An object containing ESLint rules configuration for JSDoc validation and formatting.
9
+ */
10
+ export const jsdocRules = (
11
+ requireJsdoc = false,
12
+ typescript = true,
13
+ ): JsdocRules => ({
14
+ "jsdoc/check-access": "warn",
15
+ "jsdoc/check-alignment": "warn",
16
+ "jsdoc/check-param-names": [
17
+ "warn",
18
+ {
19
+ checkDestructured: true,
20
+ enableFixer: true,
21
+ },
22
+ ],
23
+ "jsdoc/check-property-names": "warn",
24
+ "jsdoc/check-tag-names": [
25
+ "warn",
26
+ {
27
+ typed: true,
28
+ },
29
+ ],
30
+ "jsdoc/check-types": "warn",
31
+ "jsdoc/check-values": "warn",
32
+ "jsdoc/empty-tags": "warn",
33
+ "jsdoc/implements-on-classes": "warn",
34
+ "jsdoc/multiline-blocks": "warn",
35
+ "jsdoc/no-blank-block-descriptions": "off",
36
+ "jsdoc/no-defaults": "warn",
37
+ "jsdoc/no-multi-asterisks": "warn",
38
+ "jsdoc/no-types": typescript ? "warn" : "off",
39
+ "jsdoc/no-undefined-types": typescript ? "off" : "warn",
40
+ "jsdoc/require-asterisk-prefix": "warn",
41
+ "jsdoc/require-description": requireJsdoc ? "warn" : "off",
42
+ "jsdoc/require-jsdoc":
43
+ requireJsdoc ?
44
+ [
45
+ "warn",
46
+ {
47
+ require: {
48
+ ArrowFunctionExpression: true,
49
+ ClassDeclaration: true,
50
+ ClassExpression: true,
51
+ FunctionDeclaration: true,
52
+ FunctionExpression: true,
53
+ MethodDefinition: true,
54
+ },
55
+ },
56
+ ]
57
+ : "off",
58
+ "jsdoc/require-param": requireJsdoc ? "warn" : "off",
59
+ "jsdoc/require-param-description": "warn",
60
+ "jsdoc/require-param-name": "warn",
61
+ "jsdoc/require-property": requireJsdoc ? "warn" : "off",
62
+ "jsdoc/require-property-description": "warn",
63
+ "jsdoc/require-property-name": "warn",
64
+ "jsdoc/require-returns": requireJsdoc ? "warn" : "off",
65
+ "jsdoc/require-returns-check": "warn",
66
+ "jsdoc/require-returns-description": "warn",
67
+ "jsdoc/require-yields": "warn",
68
+ "jsdoc/require-yields-check": "warn",
69
+ "jsdoc/tag-lines": [
70
+ "warn",
71
+ "never",
72
+ {
73
+ startLines: 1, // Allow 1 line between description and first tag
74
+ tags: {
75
+ param: { lines: "never" }, // Enforce no lines between param tags
76
+ },
77
+ },
78
+ ],
79
+ "jsdoc/text-escaping": "off",
80
+ "jsdoc/valid-types": "warn",
81
+ });
@@ -0,0 +1,56 @@
1
+ import type { EslintRuleConfig } from "../types.js";
2
+
3
+ export type JsdocRules = Record<`jsdoc/${string}`, EslintRuleConfig> & {
4
+ "jsdoc/check-param-names": EslintRuleConfig<{
5
+ allowExtraTrailingParamDocs?: boolean;
6
+ checkDestructured?: boolean;
7
+ checkRestProperty?: boolean;
8
+ checkTypesPattern?: string;
9
+ disableExtraPropertyReporting?: boolean;
10
+ disableMissingParamChecks?: boolean;
11
+ enableFixer?: boolean;
12
+ useDefaultObjectProperties?: boolean;
13
+ }>;
14
+ "jsdoc/require-jsdoc": EslintRuleConfig<{
15
+ checkConstructors?: boolean;
16
+ checkGetters?: boolean;
17
+ checkSetters?: boolean;
18
+ contexts?: (object | string)[];
19
+ enableFixer?: boolean;
20
+ exemptEmptyConstructors?: boolean;
21
+ fixerMessage?: string;
22
+ minLineCount?: number | undefined;
23
+ publicOnly?:
24
+ | boolean
25
+ | {
26
+ ancestorsOnly?: boolean;
27
+ cjs?: boolean;
28
+ esm?: boolean;
29
+ window?: boolean;
30
+ };
31
+ require?: {
32
+ ArrowFunctionExpression?: boolean;
33
+ ClassDeclaration?: boolean;
34
+ ClassExpression?: boolean;
35
+ FunctionDeclaration?: boolean;
36
+ FunctionExpression?: boolean;
37
+ MethodDefinition?: boolean;
38
+ };
39
+ }>;
40
+ "jsdoc/tag-lines": EslintRuleConfig<
41
+ "always" | "any" | "never",
42
+ {
43
+ applyToEndTag?: boolean;
44
+ count?: number;
45
+ endLines?: null | number;
46
+ startLines?: null | number;
47
+ tags?: Record<
48
+ string,
49
+ {
50
+ count?: number;
51
+ lines?: "always" | "any" | "never";
52
+ }
53
+ >;
54
+ }
55
+ >;
56
+ };
@@ -0,0 +1,25 @@
1
+ import nextjs from "eslint-plugin-nextjs";
2
+
3
+ import type { EslintConfigObject, EslintRuleConfig } from "../types.js";
4
+
5
+ import { configNames } from "../constants.js";
6
+ import { nextjsRules } from "./rules.js";
7
+
8
+ /**
9
+ * Creates an ESLint configuration for Next.js.
10
+ *
11
+ * @param customRules - Optional object containing custom rules to override or add to the Next.js configuration.
12
+ * @returns ESLint configuration object for Next.js
13
+ */
14
+ export const nextjsConfig = (
15
+ customRules?: Record<string, EslintRuleConfig>,
16
+ ): EslintConfigObject => ({
17
+ name: configNames.nextjs,
18
+ plugins: {
19
+ nextjs,
20
+ },
21
+ rules: {
22
+ ...nextjsRules,
23
+ ...(customRules ?? {}),
24
+ },
25
+ });
@@ -0,0 +1,25 @@
1
+ import type { NextjsRules } from "./types.js";
2
+
3
+ export const nextjsRules: NextjsRules = {
4
+ "nextjs/google-font-display": "warn",
5
+ "nextjs/google-font-preconnect": "warn",
6
+ "nextjs/inline-script-id": "warn",
7
+ "nextjs/next-script-for-ga": "warn",
8
+ "nextjs/no-assign-module-variable": "warn",
9
+ "nextjs/no-async-client-component": "warn",
10
+ "nextjs/no-before-interactive-script-outside-document": "warn",
11
+ "nextjs/no-css-tags": "warn",
12
+ "nextjs/no-document-import-in-page": "warn",
13
+ "nextjs/no-duplicate-head": "warn",
14
+ "nextjs/no-head-element": "warn",
15
+ "nextjs/no-head-import-in-document": "warn",
16
+ "nextjs/no-html-link-for-pages": "warn",
17
+ "nextjs/no-img-element": "warn",
18
+ "nextjs/no-page-custom-font": "warn",
19
+ "nextjs/no-script-component-in-head": "warn",
20
+ "nextjs/no-styled-jsx-in-document": "warn",
21
+ "nextjs/no-sync-scripts": "warn",
22
+ "nextjs/no-title-in-document-head": "warn",
23
+ "nextjs/no-typos": "warn",
24
+ "nextjs/no-unwanted-polyfillio": "warn",
25
+ };
@@ -0,0 +1,27 @@
1
+ import type { EslintRuleConfig } from "../types.js";
2
+
3
+ // This fixes an index signature issue
4
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
5
+ export type NextjsRules = {
6
+ "nextjs/google-font-display": EslintRuleConfig;
7
+ "nextjs/google-font-preconnect": EslintRuleConfig;
8
+ "nextjs/inline-script-id": EslintRuleConfig;
9
+ "nextjs/next-script-for-ga": EslintRuleConfig;
10
+ "nextjs/no-assign-module-variable": EslintRuleConfig;
11
+ "nextjs/no-async-client-component": EslintRuleConfig;
12
+ "nextjs/no-before-interactive-script-outside-document": EslintRuleConfig;
13
+ "nextjs/no-css-tags": EslintRuleConfig;
14
+ "nextjs/no-document-import-in-page": EslintRuleConfig;
15
+ "nextjs/no-duplicate-head": EslintRuleConfig;
16
+ "nextjs/no-head-element": EslintRuleConfig;
17
+ "nextjs/no-head-import-in-document": EslintRuleConfig;
18
+ "nextjs/no-html-link-for-pages": EslintRuleConfig;
19
+ "nextjs/no-img-element": EslintRuleConfig;
20
+ "nextjs/no-page-custom-font": EslintRuleConfig;
21
+ "nextjs/no-script-component-in-head": EslintRuleConfig;
22
+ "nextjs/no-styled-jsx-in-document": EslintRuleConfig;
23
+ "nextjs/no-sync-scripts": EslintRuleConfig;
24
+ "nextjs/no-title-in-document-head": EslintRuleConfig;
25
+ "nextjs/no-typos": EslintRuleConfig;
26
+ "nextjs/no-unwanted-polyfillio": EslintRuleConfig;
27
+ };
@@ -0,0 +1,454 @@
1
+ # Perfectionist Configuration
2
+
3
+ Automatic code organization through intelligent sorting of imports, objects, types, and more with `eslint-plugin-perfectionist`.
4
+
5
+ [← Back to main README](../../../README.md)
6
+
7
+ ## Overview
8
+
9
+ Perfectionist configuration is **enabled by default** and provides:
10
+
11
+ - Automatic sorting for imports, exports, and named imports
12
+ - Object key and property sorting
13
+ - TypeScript type and interface organization
14
+ - Consistent code structure across your codebase
15
+ - Natural alphabetical ordering (smart number handling)
16
+
17
+ ## Quick Start
18
+
19
+ ```js
20
+ import { eslintConfig } from "js-style-kit";
21
+
22
+ export default eslintConfig({
23
+ sorting: true, // Enabled by default
24
+ });
25
+ ```
26
+
27
+ ## What Gets Sorted
28
+
29
+ Perfectionist automatically organizes:
30
+
31
+ - Import statements
32
+ - Named imports and exports
33
+ - Object literals and properties
34
+ - TypeScript interfaces and types
35
+ - Enums and union types
36
+ - JSX props
37
+ - Classes and decorators
38
+ - Array includes, Maps, and Sets
39
+
40
+ ## Sorting Algorithm
41
+
42
+ All sorting uses **natural ascending order** by default:
43
+
44
+ ```js
45
+ // Natural sort understands numbers
46
+ ["item1", "item2", "item10", "item20"];
47
+ // Not: ["item1", "item10", "item2", "item20"]
48
+
49
+ // Case-insensitive alphabetical
50
+ ["Apple", "banana", "Cherry"];
51
+ ```
52
+
53
+ ## Key Features
54
+
55
+ ### Import Sorting
56
+
57
+ Automatically organizes imports for better readability:
58
+
59
+ ```ts
60
+ // ✅ After auto-fix - properly sorted
61
+ import { useEffect, useState } from "react";
62
+ import { format, parse } from "date-fns";
63
+
64
+ import { Button } from "@/components/Button";
65
+ import { config } from "@/config";
66
+
67
+ import { apiClient } from "./api";
68
+ import { formatDate } from "./utils";
69
+
70
+ // ❌ Before - unsorted
71
+ import { useState, useEffect } from "react";
72
+ import { formatDate } from "./utils";
73
+ import { Button } from "@/components/Button";
74
+ import { parse, format } from "date-fns";
75
+ import { apiClient } from "./api";
76
+ import { config } from "@/config";
77
+ ```
78
+
79
+ **Rules:**
80
+
81
+ - `perfectionist/sort-imports` - Sorts import statements
82
+ - `perfectionist/sort-named-imports` - Sorts named imports within braces
83
+ - `perfectionist/sort-named-exports` - Sorts named exports
84
+ - `perfectionist/sort-exports` - Sorts export statements
85
+
86
+ ### Object Sorting
87
+
88
+ Maintains consistent object key order:
89
+
90
+ ```ts
91
+ // ✅ Good - sorted keys
92
+ const user = {
93
+ age: 30,
94
+ email: "user@example.com",
95
+ id: "123",
96
+ name: "Alice",
97
+ };
98
+
99
+ // ❌ Bad - unsorted keys
100
+ const user = {
101
+ name: "Alice",
102
+ id: "123",
103
+ email: "user@example.com",
104
+ age: 30,
105
+ };
106
+ ```
107
+
108
+ **Rules:**
109
+
110
+ - `perfectionist/sort-objects` - Sorts object literal keys
111
+
112
+ ### TypeScript Types
113
+
114
+ Organizes TypeScript definitions:
115
+
116
+ ```ts
117
+ // ✅ Good - sorted interface properties
118
+ interface User {
119
+ age: number;
120
+ email: string;
121
+ id: string;
122
+ name: string;
123
+ }
124
+
125
+ // ✅ Good - sorted union types
126
+ type Status = "active" | "inactive" | "pending";
127
+
128
+ // ✅ Good - sorted intersection types
129
+ type Combined = Base & Extra & Middle;
130
+
131
+ // ❌ Bad - unsorted
132
+ interface User {
133
+ name: string;
134
+ id: string;
135
+ email: string;
136
+ age: number;
137
+ }
138
+ ```
139
+
140
+ **Rules:**
141
+
142
+ - `perfectionist/sort-interfaces` - Sorts interface properties
143
+ - `perfectionist/sort-object-types` - Sorts type object properties
144
+ - `perfectionist/sort-union-types` - Sorts union type members
145
+ - `perfectionist/sort-intersection-types` - Sorts intersection type members
146
+ - `perfectionist/sort-enums` - Sorts enum members
147
+
148
+ ### JSX Props
149
+
150
+ Maintains consistent prop order:
151
+
152
+ ```tsx
153
+ // ✅ Good - sorted props
154
+ <Button
155
+ className="btn"
156
+ disabled={false}
157
+ onClick={handleClick}
158
+ type="submit"
159
+ >
160
+ Submit
161
+ </Button>
162
+
163
+ // ❌ Bad - unsorted props
164
+ <Button
165
+ onClick={handleClick}
166
+ type="submit"
167
+ className="btn"
168
+ disabled={false}
169
+ >
170
+ Submit
171
+ </Button>
172
+ ```
173
+
174
+ **Rules:**
175
+
176
+ - `perfectionist/sort-jsx-props` - Sorts JSX element props
177
+
178
+ ### Classes
179
+
180
+ Organizes class members and decorators:
181
+
182
+ ```ts
183
+ // ✅ Good - sorted members
184
+ class UserService {
185
+ private cache: Map<string, User>;
186
+ private logger: Logger;
187
+
188
+ constructor(logger: Logger) {
189
+ this.logger = logger;
190
+ this.cache = new Map();
191
+ }
192
+
193
+ getUser(id: string): User {
194
+ /* ... */
195
+ }
196
+ saveUser(user: User): void {
197
+ /* ... */
198
+ }
199
+ }
200
+
201
+ // ✅ Good - sorted decorators
202
+ @Component()
203
+ @Injectable()
204
+ @Module()
205
+ class MyClass {}
206
+ ```
207
+
208
+ **Rules:**
209
+
210
+ - `perfectionist/sort-classes` - Sorts class members
211
+ - `perfectionist/sort-decorators` - Sorts decorators
212
+
213
+ ### Other Collections
214
+
215
+ Sorts various other structures:
216
+
217
+ ```ts
218
+ // ✅ Good - sorted array includes
219
+ const colors = ["blue", "green", "red"];
220
+
221
+ // ✅ Good - sorted Map entries
222
+ const map = new Map([
223
+ ["apple", 1],
224
+ ["banana", 2],
225
+ ["cherry", 3],
226
+ ]);
227
+
228
+ // ✅ Good - sorted Set values
229
+ const set = new Set(["a", "b", "c"]);
230
+
231
+ // ✅ Good - sorted variable declarations
232
+ const a = 1,
233
+ b = 2,
234
+ c = 3;
235
+
236
+ // ✅ Good - sorted switch cases
237
+ switch (value) {
238
+ case "a":
239
+ return 1;
240
+ case "b":
241
+ return 2;
242
+ case "c":
243
+ return 3;
244
+ }
245
+ ```
246
+
247
+ **Rules:**
248
+
249
+ - `perfectionist/sort-array-includes` - Sorts array include calls
250
+ - `perfectionist/sort-maps` - Sorts Map constructor entries
251
+ - `perfectionist/sort-sets` - Sorts Set constructor values
252
+ - `perfectionist/sort-variable-declarations` - Sorts variable declarations
253
+ - `perfectionist/sort-switch-case` - Sorts switch case statements
254
+ - `perfectionist/sort-heritage-clauses` - Sorts class extends/implements
255
+
256
+ ## Complete Example
257
+
258
+ ```ts
259
+ // ✅ Fully sorted code with Perfectionist
260
+ import type { Config, User } from "./types";
261
+
262
+ import { format, parse } from "date-fns";
263
+ import { useEffect, useState } from "react";
264
+
265
+ import { apiClient } from "./api";
266
+
267
+ interface UserProfile {
268
+ age: number;
269
+ avatar?: string;
270
+ email: string;
271
+ id: string;
272
+ name: string;
273
+ role: "admin" | "user";
274
+ }
275
+
276
+ const defaultConfig: Config = {
277
+ apiUrl: "https://api.example.com",
278
+ debug: false,
279
+ timeout: 5000,
280
+ };
281
+
282
+ export const createUser = (data: User): UserProfile => {
283
+ return {
284
+ age: data.age,
285
+ email: data.email,
286
+ id: data.id,
287
+ name: data.name,
288
+ role: data.role,
289
+ };
290
+ };
291
+
292
+ export { apiClient, defaultConfig };
293
+ ```
294
+
295
+ ## Module Sorting
296
+
297
+ Module-level sorting is **disabled by default** as it can be disruptive:
298
+
299
+ ```js
300
+ // perfectionist/sort-modules is "off"
301
+ ```
302
+
303
+ This prevents the plugin from reordering top-level statements like:
304
+
305
+ - Function declarations
306
+ - Class declarations
307
+ - Variable declarations
308
+ - Export statements
309
+
310
+ If you want to enable module sorting:
311
+
312
+ ```js
313
+ export default eslintConfig({
314
+ perfectionist: true,
315
+ rules: {
316
+ "perfectionist/sort-modules": "warn",
317
+ },
318
+ });
319
+ ```
320
+
321
+ ## Customization
322
+
323
+ ### Disable Specific Sorting
324
+
325
+ ```js
326
+ export default eslintConfig({
327
+ perfectionist: true,
328
+ rules: {
329
+ // Disable JSX prop sorting
330
+ "perfectionist/sort-jsx-props": "off",
331
+
332
+ // Disable object sorting
333
+ "perfectionist/sort-objects": "off",
334
+
335
+ // Enable module sorting
336
+ "perfectionist/sort-modules": "warn",
337
+ },
338
+ });
339
+ ```
340
+
341
+ ### File-Specific Overrides
342
+
343
+ ```js
344
+ export default eslintConfig({
345
+ perfectionist: true,
346
+ overrides: [
347
+ {
348
+ files: ["**/*.config.ts"],
349
+ rules: {
350
+ // Don't sort objects in config files
351
+ "perfectionist/sort-objects": "off",
352
+ },
353
+ },
354
+ ],
355
+ });
356
+ ```
357
+
358
+ ## Benefits
359
+
360
+ ### Consistency
361
+
362
+ - Same structure across all files
363
+ - Reduces diff noise in code reviews
364
+ - Easier to find properties and imports
365
+
366
+ ### Maintainability
367
+
368
+ - Clear organization patterns
369
+ - Prevents merge conflicts from ordering
370
+ - Auto-fixes maintain order
371
+
372
+ ### Readability
373
+
374
+ - Natural alphabetical order is easy to scan
375
+ - Grouped related items stay together
376
+ - Predictable structure
377
+
378
+ ## Common Patterns
379
+
380
+ ### React Component
381
+
382
+ ```tsx
383
+ import type { FC, ReactNode } from "react";
384
+
385
+ import { useCallback, useEffect, useState } from "react";
386
+
387
+ interface ButtonProps {
388
+ children: ReactNode;
389
+ className?: string;
390
+ disabled?: boolean;
391
+ onClick?: () => void;
392
+ type?: "button" | "submit";
393
+ }
394
+
395
+ export const Button: FC<ButtonProps> = ({
396
+ children,
397
+ className,
398
+ disabled = false,
399
+ onClick,
400
+ type = "button",
401
+ }) => {
402
+ return (
403
+ <button
404
+ className={className}
405
+ disabled={disabled}
406
+ onClick={onClick}
407
+ type={type}
408
+ >
409
+ {children}
410
+ </button>
411
+ );
412
+ };
413
+ ```
414
+
415
+ ### API Client
416
+
417
+ ```ts
418
+ import type { RequestConfig, Response } from "./types";
419
+
420
+ import { auth } from "./auth";
421
+ import { config } from "./config";
422
+ import { logger } from "./logger";
423
+
424
+ export class ApiClient {
425
+ private baseUrl: string;
426
+ private headers: Record<string, string>;
427
+ private timeout: number;
428
+
429
+ async delete(url: string): Promise<Response> {
430
+ /* ... */
431
+ }
432
+ async get(url: string): Promise<Response> {
433
+ /* ... */
434
+ }
435
+ async post(url: string, data: unknown): Promise<Response> {
436
+ /* ... */
437
+ }
438
+ async put(url: string, data: unknown): Promise<Response> {
439
+ /* ... */
440
+ }
441
+ }
442
+ ```
443
+
444
+ ## Related Configurations
445
+
446
+ - [Import](../import/README.md) - Import validation (works alongside Perfectionist)
447
+ - [TypeScript](../typescript/README.md) - TypeScript type checking
448
+ - [Base](../base/README.md) - Base ESLint rules
449
+
450
+ ## Learn More
451
+
452
+ - [eslint-plugin-perfectionist](https://github.com/azat-io/eslint-plugin-perfectionist)
453
+ - [Natural Sort Algorithm](https://en.wikipedia.org/wiki/Natural_sort_order)
454
+ - [Main README](../../../README.md)
@@ -0,0 +1,25 @@
1
+ import perfectionist from "eslint-plugin-perfectionist";
2
+
3
+ import type { EslintConfigObject, EslintRuleConfig } from "../types.js";
4
+
5
+ import { configNames } from "../constants.js";
6
+ import { perfectionistRules } from "./rules.js";
7
+
8
+ /**
9
+ * Creates an ESLint configuration for Perfectionist.
10
+ *
11
+ * @param customRules - Optional object containing custom rules to override or add to the Perfectionist configuration.
12
+ * @returns ESLint configuration object for Perfectionist
13
+ */
14
+ export const perfectionistConfig = (
15
+ customRules?: Record<string, EslintRuleConfig>,
16
+ ): EslintConfigObject => ({
17
+ name: configNames.perfectionist,
18
+ plugins: {
19
+ perfectionist,
20
+ },
21
+ rules: {
22
+ ...perfectionistRules,
23
+ ...(customRules ?? {}),
24
+ },
25
+ });