@gaia-react/lint 1.0.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/dist/index.js ADDED
@@ -0,0 +1,904 @@
1
+ // src/configs/base.ts
2
+ import eslintComments from "@eslint-community/eslint-plugin-eslint-comments";
3
+ import js from "@eslint/js";
4
+ import { configs, plugins, rules } from "eslint-config-airbnb-extended";
5
+ import preferArrowFunctions from "eslint-plugin-prefer-arrow-functions";
6
+ import lodashUnderscore from "eslint-plugin-you-dont-need-lodash-underscore";
7
+ var jsConfig = [
8
+ // ESLint recommended config
9
+ {
10
+ name: "js/config",
11
+ ...js.configs.recommended
12
+ },
13
+ // Stylistic plugin
14
+ plugins.stylistic,
15
+ // Import X plugin
16
+ plugins.importX,
17
+ // Airbnb base recommended config
18
+ ...configs.base.recommended,
19
+ // Strict import rules
20
+ rules.base.importsStrict
21
+ ];
22
+ var jsCustomConfig = [
23
+ {
24
+ name: "js-custom",
25
+ rules: {
26
+ "consistent-return": "off",
27
+ curly: ["error", "all"],
28
+ "max-params": "error",
29
+ "no-param-reassign": "off",
30
+ // handled by sonarjs
31
+ "no-undef": "off",
32
+ "no-unused-vars": "off"
33
+ // handled by sonarjs
34
+ }
35
+ },
36
+ {
37
+ files: ["**/*.test.ts?(x)", "**/*.stories.ts?(x)"],
38
+ name: "test-files/all",
39
+ rules: {
40
+ "guard-for-in": "off",
41
+ "max-params": "off",
42
+ "no-await-in-loop": "off",
43
+ "no-plusplus": "off",
44
+ "no-restricted-syntax": "off"
45
+ }
46
+ },
47
+ {
48
+ files: [".playwright/**/*.ts?(x)"],
49
+ name: "playwright/all",
50
+ rules: {
51
+ "no-await-in-loop": "off",
52
+ "no-restricted-syntax": "off"
53
+ }
54
+ }
55
+ ];
56
+ var typescriptConfig = [
57
+ // TypeScript ESLint plugin
58
+ plugins.typescriptEslint,
59
+ // Airbnb base TypeScript config
60
+ ...configs.base.typescript,
61
+ // Strict TypeScript rules
62
+ rules.typescript.typescriptEslintStrict,
63
+ rules.typescript.stylistic,
64
+ // Airbnb React TypeScript config
65
+ ...configs.react.typescript,
66
+ {
67
+ files: ["./*.ts"],
68
+ name: "root-ts-files",
69
+ rules: {
70
+ "global-require": "off",
71
+ "no-void": "off"
72
+ }
73
+ },
74
+ {
75
+ files: ["**/*.ts?(x)"],
76
+ name: "no-void",
77
+ rules: {
78
+ "no-void": ["error", { allowAsStatement: true }]
79
+ }
80
+ }
81
+ ];
82
+ var tsEslintConfig = [
83
+ {
84
+ files: ["**/*.ts?(x)"],
85
+ name: "typescript/config",
86
+ rules: {
87
+ "@typescript-eslint/array-type": ["error", { default: "array" }],
88
+ "@typescript-eslint/ban-ts-comment": "off",
89
+ "@typescript-eslint/consistent-type-definitions": ["error", "type"],
90
+ "@typescript-eslint/consistent-type-imports": "error",
91
+ "@typescript-eslint/explicit-module-boundary-types": "off",
92
+ "@typescript-eslint/method-signature-style": "error",
93
+ "@typescript-eslint/no-confusing-void-expression": [
94
+ "error",
95
+ { ignoreArrowShorthand: true }
96
+ ],
97
+ "@typescript-eslint/no-floating-promises": [
98
+ "error",
99
+ { ignoreIIFE: true, ignoreVoid: true }
100
+ ],
101
+ "@typescript-eslint/no-misused-promises": [
102
+ "error",
103
+ { checksVoidReturn: false }
104
+ ],
105
+ "@typescript-eslint/no-non-null-assertion": "off",
106
+ "@typescript-eslint/no-throw-literal": "off",
107
+ "@typescript-eslint/no-unnecessary-boolean-literal-compare": "error",
108
+ "@typescript-eslint/no-unnecessary-condition": "error",
109
+ "@typescript-eslint/no-unnecessary-type-parameters": "off",
110
+ "@typescript-eslint/no-unsafe-assignment": "error",
111
+ "@typescript-eslint/no-unsafe-return": "error",
112
+ "@typescript-eslint/only-throw-error": "off",
113
+ "@typescript-eslint/prefer-nullish-coalescing": "error",
114
+ "@typescript-eslint/prefer-promise-reject-errors": "off",
115
+ "@typescript-eslint/restrict-template-expressions": [
116
+ "error",
117
+ { allowBoolean: true, allowNumber: true }
118
+ ],
119
+ "@typescript-eslint/return-await": "off",
120
+ "@typescript-eslint/unbound-method": "off"
121
+ }
122
+ },
123
+ {
124
+ files: ["app/hooks/**/*", "app/routes/**/*", "app/sessions.server/**/*"],
125
+ name: "typescript/only-throw-error",
126
+ rules: {
127
+ "@typescript-eslint/only-throw-error": "off"
128
+ }
129
+ },
130
+ {
131
+ files: ["app/utils/**", "app/services/**", "app/hooks/**"],
132
+ name: "typescript/explicit-return-types",
133
+ rules: {
134
+ "@typescript-eslint/explicit-module-boundary-types": "error"
135
+ }
136
+ },
137
+ {
138
+ files: ["**/*.test.ts?(x)", "**/*.stories.ts?(x)"],
139
+ name: "typescript/test-files",
140
+ rules: {
141
+ "@typescript-eslint/no-explicit-any": "off",
142
+ "@typescript-eslint/no-unsafe-assignment": "off",
143
+ "@typescript-eslint/no-unsafe-member-access": "off"
144
+ }
145
+ },
146
+ {
147
+ files: ["test/**/*.ts?(x)"],
148
+ name: "typescript/test-config",
149
+ rules: {
150
+ "@typescript-eslint/no-var-requires": "off",
151
+ "no-plusplus": "off"
152
+ }
153
+ },
154
+ {
155
+ files: ["**/*.d.ts"],
156
+ name: "typescript/type-definitions",
157
+ rules: {
158
+ "@typescript-eslint/consistent-type-definitions": "off",
159
+ "@typescript-eslint/method-signature-style": "error",
160
+ "@typescript-eslint/no-unused-vars": "off"
161
+ }
162
+ }
163
+ ];
164
+ var importXConfig = [
165
+ {
166
+ name: "import-x-all-files",
167
+ rules: {
168
+ "import-x/consistent-type-specifier-style": ["error", "prefer-top-level"],
169
+ "import-x/extensions": "off",
170
+ "import-x/no-anonymous-default-export": [
171
+ "error",
172
+ {
173
+ allowArray: true,
174
+ allowLiteral: true,
175
+ allowObject: true
176
+ }
177
+ ],
178
+ "import-x/no-namespace": "off",
179
+ "import-x/no-rename-default": "off",
180
+ "import-x/no-useless-path-segments": "off",
181
+ "import-x/order": "off",
182
+ "import-x/prefer-default-export": "off"
183
+ }
184
+ },
185
+ {
186
+ files: ["./*.ts"],
187
+ name: "import-x/root-ts-files",
188
+ rules: {
189
+ "import-x/no-extraneous-dependencies": "off",
190
+ "import-x/no-unresolved": "error",
191
+ "import-x/prefer-default-export": "off"
192
+ }
193
+ },
194
+ {
195
+ files: ["**/*.test.ts?(x)", "**/*.stories.ts?(x)"],
196
+ name: "import-x/test-files",
197
+ rules: {
198
+ "import-x/extensions": "off",
199
+ "import-x/no-extraneous-dependencies": "off"
200
+ }
201
+ },
202
+ {
203
+ files: ["app/**/!(*.test|*.stories).ts?(x)"],
204
+ name: "import-x/app-test-files",
205
+ rules: {
206
+ "import-x/no-unresolved": "error"
207
+ }
208
+ },
209
+ {
210
+ files: ["app/**/hooks/*.ts?(x)"],
211
+ name: "import-x/hooks",
212
+ rules: {
213
+ "import-x/no-default-export": "error"
214
+ }
215
+ },
216
+ {
217
+ files: ["test/**/*.ts?(x)"],
218
+ name: "import-x/test-config-files",
219
+ rules: {
220
+ "import-x/no-extraneous-dependencies": "off",
221
+ "import-x/prefer-default-export": "off"
222
+ }
223
+ },
224
+ {
225
+ files: [".storybook/**/*.ts?(x)", ".playwright/**/*.ts?(x)"],
226
+ name: "import-x/storybook-playwright",
227
+ rules: {
228
+ "import-x/no-extraneous-dependencies": "off",
229
+ "import-x/no-unresolved": "off"
230
+ }
231
+ }
232
+ ];
233
+ var eslintCommentsConfig = [
234
+ {
235
+ name: "eslint-comments",
236
+ plugins: {
237
+ "eslint-comments": eslintComments
238
+ },
239
+ rules: {
240
+ "eslint-comments/disable-enable-pair": "off",
241
+ "eslint-comments/no-unused-disable": "error"
242
+ }
243
+ }
244
+ ];
245
+ var preferArrowFunctionsConfig = [
246
+ {
247
+ name: "prefer-arrow",
248
+ plugins: {
249
+ "prefer-arrow-functions": preferArrowFunctions
250
+ },
251
+ rules: {
252
+ "prefer-arrow-functions/prefer-arrow-functions": "error"
253
+ }
254
+ },
255
+ {
256
+ files: ["**/*.d.ts"],
257
+ name: "ts-definition-files/prefer-arrow-off",
258
+ rules: {
259
+ "prefer-arrow-functions/prefer-arrow-functions": "off"
260
+ }
261
+ }
262
+ ];
263
+ var lodashUnderscoreConfig = [
264
+ {
265
+ name: "you-dont-need-lodash-underscore",
266
+ plugins: {
267
+ "you-dont-need-lodash-underscore": lodashUnderscore
268
+ },
269
+ rules: {
270
+ ...lodashUnderscore.configs.compatible.rules
271
+ }
272
+ }
273
+ ];
274
+ var base = [
275
+ ...jsConfig,
276
+ ...jsCustomConfig,
277
+ ...typescriptConfig,
278
+ ...tsEslintConfig,
279
+ ...importXConfig,
280
+ ...eslintCommentsConfig,
281
+ ...preferArrowFunctionsConfig,
282
+ ...lodashUnderscoreConfig
283
+ ];
284
+
285
+ // src/configs/react.ts
286
+ import { configs as configs2, plugins as plugins2 } from "eslint-config-airbnb-extended";
287
+ var react = [
288
+ // React plugin
289
+ plugins2.react,
290
+ // React hooks plugin
291
+ plugins2.reactHooks,
292
+ // React JSX A11y plugin
293
+ plugins2.reactA11y,
294
+ // Airbnb React recommended config
295
+ ...configs2.react.recommended,
296
+ {
297
+ name: "react-custom",
298
+ rules: {
299
+ "jsx-a11y/control-has-associated-label": "off",
300
+ "jsx-a11y/no-autofocus": "off",
301
+ "react/boolean-prop-naming": [
302
+ "error",
303
+ {
304
+ propTypeNames: ["bool", "mutuallyExclusiveTrueProps"],
305
+ rule: "^((can|has|hide|is|show)[A-Z]([A-Za-z0-9]?)+|(checked|disabled|hide|required|show))"
306
+ }
307
+ ],
308
+ "react/function-component-definition": "off",
309
+ "react/jsx-boolean-value": ["error", "always"],
310
+ "react/jsx-curly-brace-presence": "error",
311
+ "react/jsx-filename-extension": "off",
312
+ "react/jsx-fragments": "error",
313
+ // off by default because it doesn't handle props onXyz function names correctly
314
+ // turn this on from time to time to check for misnamed handlers elsewhere
315
+ "react/jsx-handler-names": ["off", { checkLocalVariables: true }],
316
+ "react/jsx-newline": ["error", { prevent: true }],
317
+ "react/jsx-no-useless-fragment": ["error", { allowExpressions: true }],
318
+ "react/no-children-prop": "off",
319
+ "react/no-danger": "off",
320
+ "react/prop-types": "off",
321
+ "react/react-in-jsx-scope": "off",
322
+ "react/require-default-props": "off"
323
+ }
324
+ },
325
+ {
326
+ files: ["**/routes/**/*.tsx"],
327
+ name: "react-router/routes",
328
+ rules: {
329
+ "no-empty-pattern": "off",
330
+ "react/display-name": "off"
331
+ }
332
+ },
333
+ {
334
+ files: ["**/*.test.ts?(x)", "**/*.stories.ts?(x)"],
335
+ name: "react/test-files",
336
+ rules: {
337
+ "react/jsx-props-no-spreading": "off"
338
+ }
339
+ }
340
+ ];
341
+
342
+ // src/configs/style-hygiene.ts
343
+ import canonical from "eslint-plugin-canonical";
344
+ import checkFile from "eslint-plugin-check-file";
345
+ import perfectionist from "eslint-plugin-perfectionist";
346
+ import unicorn from "eslint-plugin-unicorn";
347
+ import unusedImports from "eslint-plugin-unused-imports";
348
+ var canonicalConfig = [
349
+ canonical.configs["flat/recommended"],
350
+ {
351
+ name: "canonical",
352
+ rules: {
353
+ "canonical/destructuring-property-newline": "off",
354
+ "canonical/filename-match-exported": "error",
355
+ "canonical/id-match": "off",
356
+ "canonical/import-specifier-newline": "off"
357
+ }
358
+ },
359
+ {
360
+ files: ["**/*.tsx", "**/hooks/*.ts?(x)"],
361
+ name: "canonical/sort-react-dependencies",
362
+ rules: {
363
+ "canonical/sort-react-dependencies": "error"
364
+ }
365
+ },
366
+ {
367
+ files: [
368
+ "app/root.tsx",
369
+ "app/entry.server.tsx",
370
+ "app/**/tests/*",
371
+ "test/**/*.ts?(x)",
372
+ "**/*.stories.tsx",
373
+ "**/routes/**/*.tsx",
374
+ "**/hooks/*.ts?(x)",
375
+ ".storybook/**/*.ts?(x)",
376
+ ".playwright/**/*.ts?(x)"
377
+ ],
378
+ name: "canonical/filename-match-exported-disabled",
379
+ rules: {
380
+ "canonical/filename-match-exported": "off"
381
+ }
382
+ }
383
+ ];
384
+ var perfectionistConfig = [
385
+ perfectionist.configs["recommended-natural"],
386
+ {
387
+ name: "perfectionist",
388
+ rules: {
389
+ "perfectionist/sort-imports": [
390
+ "error",
391
+ {
392
+ customGroups: [
393
+ {
394
+ elementNamePattern: "^react$",
395
+ groupName: "react-type",
396
+ selector: "type"
397
+ },
398
+ {
399
+ elementNamePattern: "^react$",
400
+ groupName: "react"
401
+ },
402
+ {
403
+ elementNamePattern: "^react-.+",
404
+ groupName: "react-other-type",
405
+ selector: "type"
406
+ },
407
+ {
408
+ elementNamePattern: "^react-.+",
409
+ groupName: "react-other"
410
+ }
411
+ ],
412
+ groups: [
413
+ "react-type",
414
+ "react",
415
+ "react-other-type",
416
+ "react-other",
417
+ ["type-external", "external"],
418
+ ["type-builtin", "builtin"],
419
+ ["type-internal", "internal"],
420
+ ["type-parent", "parent"],
421
+ ["type-sibling", "sibling"],
422
+ ["type-index", "index"],
423
+ "unknown",
424
+ "style",
425
+ "side-effect",
426
+ "side-effect-style"
427
+ ],
428
+ newlinesBetween: 0,
429
+ type: "natural"
430
+ }
431
+ ],
432
+ "perfectionist/sort-jsx-props": [
433
+ "error",
434
+ {
435
+ customGroups: [
436
+ {
437
+ elementNamePattern: ["^key$", "^ref$"],
438
+ groupName: "reserved"
439
+ }
440
+ ],
441
+ groups: ["reserved"],
442
+ type: "natural"
443
+ }
444
+ ]
445
+ }
446
+ }
447
+ ];
448
+ var unicornConfig = [
449
+ unicorn.configs.recommended,
450
+ {
451
+ name: "unicorn",
452
+ rules: {
453
+ "unicorn/consistent-destructuring": "error",
454
+ "unicorn/consistent-template-literal-escape": "off",
455
+ "unicorn/filename-case": "off",
456
+ "unicorn/new-for-builtins": "off",
457
+ "unicorn/no-array-callback-reference": "off",
458
+ "unicorn/no-array-for-each": "off",
459
+ "unicorn/no-array-reduce": "off",
460
+ "unicorn/no-nested-ternary": "off",
461
+ "unicorn/no-null": "off",
462
+ "unicorn/no-useless-undefined": "off",
463
+ "unicorn/prefer-export-from": "off",
464
+ "unicorn/prefer-global-this": "off",
465
+ "unicorn/prefer-set-has": "off",
466
+ "unicorn/prefer-switch": "off",
467
+ "unicorn/prefer-ternary": "off",
468
+ "unicorn/prevent-abbreviations": [
469
+ "error",
470
+ {
471
+ ignore: [
472
+ "acc",
473
+ "ctx",
474
+ "e2e",
475
+ "env",
476
+ "obj",
477
+ "prev",
478
+ "req",
479
+ "res",
480
+ /args/i,
481
+ /fn/i,
482
+ /param/i,
483
+ /params/i,
484
+ /props/i,
485
+ /ref/i,
486
+ /src/i,
487
+ /utils/i
488
+ ]
489
+ }
490
+ ],
491
+ "unicorn/text-encoding-identifier-case": "off"
492
+ }
493
+ },
494
+ {
495
+ files: ["./*.ts"],
496
+ name: "unicorn/root-ts-files",
497
+ rules: {
498
+ "unicorn/prefer-module": "off",
499
+ "unicorn/prevent-abbreviations": "off"
500
+ }
501
+ }
502
+ ];
503
+ var unusedImportsConfig = [
504
+ {
505
+ name: "unused-imports",
506
+ plugins: {
507
+ "unused-imports": unusedImports
508
+ },
509
+ rules: {
510
+ "@typescript-eslint/no-unused-vars": "off",
511
+ "no-unused-vars": "off",
512
+ "sonarjs/no-unused-vars": "off",
513
+ "sonarjs/unused-import": "off",
514
+ "unused-imports/no-unused-imports": "error",
515
+ "unused-imports/no-unused-vars": [
516
+ "error",
517
+ {
518
+ args: "after-used",
519
+ argsIgnorePattern: "^_",
520
+ ignoreRestSiblings: true,
521
+ vars: "all",
522
+ varsIgnorePattern: "^_"
523
+ }
524
+ ]
525
+ }
526
+ },
527
+ {
528
+ files: ["**/*.d.ts"],
529
+ name: "unused-imports/ts-definition-files",
530
+ rules: {
531
+ "unused-imports/no-unused-vars": "off"
532
+ }
533
+ }
534
+ ];
535
+ var checkFileConfig = [
536
+ {
537
+ plugins: {
538
+ "check-file": checkFile
539
+ }
540
+ },
541
+ {
542
+ files: ["app/**/*"],
543
+ name: "check-file",
544
+ rules: {
545
+ "check-file/filename-naming-convention": [
546
+ "error",
547
+ {
548
+ // React hook files must be camelCase (to match the hook name)
549
+ "**/hooks/*.{ts,tsx}": "CAMEL_CASE",
550
+ "app/state/*.tsx": "KEBAB_CASE",
551
+ // React component files must be named index.tsx
552
+ "app/{components,pages}/**/!(assets|hooks|state|tests|utils)/*.tsx": "index+()",
553
+ // Generally, non-component files must be named kebab-case
554
+ "app/{components,pages}/**/!(hooks)/*.ts": "KEBAB_CASE",
555
+ // Non-component files inside specific components folders must be kebab-case
556
+ "app/{components,pages}/**/(assets|state|tests|utils)/*.{ts,tsx}": "KEBAB_CASE",
557
+ "test/**/*.ts?(x)": "KEBAB_CASE"
558
+ },
559
+ {
560
+ ignoreMiddleExtensions: true
561
+ }
562
+ ],
563
+ "check-file/folder-match-with-fex": [
564
+ "error",
565
+ {
566
+ // require stories and test files to be inside tests folders
567
+ "*.(stories|test).{ts,tsx}": "app/**/tests/"
568
+ }
569
+ ],
570
+ "check-file/folder-naming-convention": [
571
+ "error",
572
+ {
573
+ // enforce PascalCase component folders, and allow assets, hooks, tests, and utils subfolders
574
+ "app/components/**/": "(assets|hooks|state|tests|utils|[A-Z][a-zA-Z0-9]*)"
575
+ }
576
+ ]
577
+ }
578
+ },
579
+ {
580
+ files: ["test/**/*.*"],
581
+ name: "check-file/test-files",
582
+ rules: {
583
+ "check-file/filename-naming-convention": [
584
+ "error",
585
+ {
586
+ "test/**/*.ts?(x)": "KEBAB_CASE"
587
+ },
588
+ {
589
+ ignoreMiddleExtensions: true
590
+ }
591
+ ]
592
+ }
593
+ }
594
+ ];
595
+ var styleHygiene = [
596
+ ...canonicalConfig,
597
+ ...perfectionistConfig,
598
+ ...unicornConfig,
599
+ ...unusedImportsConfig,
600
+ ...checkFileConfig
601
+ ];
602
+
603
+ // src/configs/guardrails.ts
604
+ import noRelativeImportPaths from "eslint-plugin-no-relative-import-paths";
605
+ import sonarjs from "eslint-plugin-sonarjs";
606
+
607
+ // src/plugins/no-enum.ts
608
+ var noEnumRule = {
609
+ create: (context) => ({
610
+ TSEnumDeclaration: (node) => {
611
+ context.report({ messageId: "noEnum", node });
612
+ }
613
+ }),
614
+ meta: {
615
+ docs: { description: "Disallow TypeScript enums" },
616
+ messages: {
617
+ noEnum: "Do not use TypeScript enums. Use an object with `as const` instead."
618
+ },
619
+ schema: [],
620
+ type: "problem"
621
+ }
622
+ };
623
+ var plugin = {
624
+ meta: {
625
+ name: "no-enum",
626
+ version: "0.1.0"
627
+ },
628
+ rules: {
629
+ "no-enum": noEnumRule
630
+ }
631
+ };
632
+ var no_enum_default = plugin;
633
+
634
+ // src/plugins/no-switch.ts
635
+ var noSwitchRule = {
636
+ create: (context) => ({
637
+ SwitchStatement: (node) => {
638
+ context.report({ messageId: "noSwitch", node });
639
+ }
640
+ }),
641
+ meta: {
642
+ docs: { description: "Disallow switch statements" },
643
+ messages: {
644
+ noSwitch: "Do not use switch statements. Use an object map or if/else instead."
645
+ },
646
+ schema: [],
647
+ type: "problem"
648
+ }
649
+ };
650
+ var plugin2 = {
651
+ meta: {
652
+ name: "no-switch",
653
+ version: "0.1.0"
654
+ },
655
+ rules: {
656
+ "no-switch": noSwitchRule
657
+ }
658
+ };
659
+ var no_switch_default = plugin2;
660
+
661
+ // src/configs/guardrails.ts
662
+ var sonarConfig = [
663
+ sonarjs.configs.recommended,
664
+ {
665
+ name: "sonarjs",
666
+ rules: {
667
+ "sonarjs/cognitive-complexity": "error",
668
+ "sonarjs/fixme-tag": "off",
669
+ "sonarjs/no-commented-code": "off",
670
+ "sonarjs/no-nested-conditional": "off",
671
+ "sonarjs/no-nested-functions": "off",
672
+ "sonarjs/no-selector-parameter": "off",
673
+ "sonarjs/regex-complexity": "off",
674
+ "sonarjs/todo-tag": "off"
675
+ }
676
+ },
677
+ {
678
+ files: ["**/*.tsx", "**/hooks/*.ts?(x)"],
679
+ name: "sonarjs/react-files",
680
+ rules: {
681
+ "sonarjs/cognitive-complexity": "off",
682
+ "sonarjs/function-return-type": "off"
683
+ }
684
+ },
685
+ {
686
+ files: ["**/*.test.ts?(x)", "**/*.stories.ts?(x)"],
687
+ name: "sonarjs/test-files",
688
+ rules: {
689
+ "sonarjs/no-duplicate-string": "off",
690
+ "sonarjs/no-identical-functions": "off"
691
+ }
692
+ },
693
+ {
694
+ files: ["app/languages/**/*.ts", "eslint.config.mjs"],
695
+ name: "sonarjs/credential-checks",
696
+ rules: {
697
+ "sonarjs/no-hardcoded-credentials": "off",
698
+ "sonarjs/no-hardcoded-passwords": "off"
699
+ }
700
+ }
701
+ ];
702
+ var noEnumConfig = [
703
+ {
704
+ files: ["**/*.ts?(x)"],
705
+ name: "no-enum",
706
+ plugins: { "no-enum": no_enum_default },
707
+ rules: {
708
+ "no-enum/no-enum": "error"
709
+ }
710
+ }
711
+ ];
712
+ var noSwitchConfig = [
713
+ {
714
+ files: ["**/*.ts?(x)", "**/*.js?(x)"],
715
+ name: "no-switch",
716
+ plugins: { "no-switch": no_switch_default },
717
+ rules: { "no-switch/no-switch": "error" }
718
+ }
719
+ ];
720
+ var noRelativeImportPathsConfig = [
721
+ {
722
+ name: "no-relative-import-paths",
723
+ plugins: {
724
+ "no-relative-import-paths": noRelativeImportPaths
725
+ },
726
+ rules: {
727
+ "no-relative-import-paths/no-relative-import-paths": [
728
+ "error",
729
+ {
730
+ allowedDepth: 2,
731
+ allowSameFolder: true,
732
+ prefix: "~",
733
+ rootDir: "app"
734
+ }
735
+ ]
736
+ }
737
+ }
738
+ ];
739
+ var guardrails = [
740
+ ...sonarConfig,
741
+ ...noEnumConfig,
742
+ ...noSwitchConfig,
743
+ ...noRelativeImportPathsConfig
744
+ ];
745
+
746
+ // src/configs/testing.ts
747
+ import vitest from "@vitest/eslint-plugin";
748
+ import jestDom from "eslint-plugin-jest-dom";
749
+ import testingLibrary from "eslint-plugin-testing-library";
750
+ var testing = [
751
+ {
752
+ files: ["*.test.ts?(x)", "*.stories.ts?(x)", "test/**/*.ts?(x)"],
753
+ name: "vitest",
754
+ plugins: {
755
+ "jest-dom": jestDom,
756
+ vitest
757
+ },
758
+ rules: {
759
+ ...jestDom.configs["flat/recommended"].rules,
760
+ ...vitest.configs.recommended.rules
761
+ }
762
+ },
763
+ {
764
+ ...testingLibrary.configs["flat/react"],
765
+ files: ["**/*.test.ts?(x)"],
766
+ name: "testing-library"
767
+ }
768
+ ];
769
+
770
+ // src/configs/storybook.ts
771
+ import storybookPlugin from "eslint-plugin-storybook";
772
+ var storybook = [
773
+ ...storybookPlugin.configs["flat/recommended"]
774
+ ];
775
+
776
+ // src/configs/playwright.ts
777
+ import playwrightPlugin from "eslint-plugin-playwright";
778
+ var playwright = [
779
+ {
780
+ name: "playwright",
781
+ ...playwrightPlugin.configs["flat/recommended"],
782
+ files: [".playwright/**/*.ts?(x)"]
783
+ }
784
+ ];
785
+
786
+ // src/configs/prettier.ts
787
+ import { rules as prettierConfigRules } from "eslint-config-prettier";
788
+ import prettierPlugin from "eslint-plugin-prettier";
789
+ var prettier = [
790
+ {
791
+ name: "prettier/plugin/config",
792
+ plugins: { prettier: prettierPlugin }
793
+ },
794
+ {
795
+ name: "prettier/config",
796
+ rules: {
797
+ ...prettierConfigRules,
798
+ "@stylistic/padding-line-between-statements": [
799
+ "error",
800
+ {
801
+ blankLine: "always",
802
+ next: ["block-like", "export", "return", "throw"],
803
+ prev: "*"
804
+ }
805
+ ],
806
+ "@stylistic/quotes": [
807
+ "error",
808
+ "single",
809
+ {
810
+ allowTemplateLiterals: "avoidEscape",
811
+ avoidEscape: true
812
+ }
813
+ ],
814
+ "@stylistic/spaced-comment": "off",
815
+ "prettier/prettier": ["error", { endOfLine: "auto" }]
816
+ }
817
+ }
818
+ ];
819
+
820
+ // src/configs/better-tailwind.ts
821
+ import betterTailwindPlugin from "eslint-plugin-better-tailwindcss";
822
+ var betterTailwind = (opts) => [
823
+ {
824
+ name: "better-tailwindcss",
825
+ plugins: {
826
+ "better-tailwindcss": betterTailwindPlugin
827
+ },
828
+ rules: {
829
+ "better-tailwindcss/enforce-canonical-classes": "error",
830
+ "better-tailwindcss/enforce-consistent-important-position": "error",
831
+ "better-tailwindcss/enforce-consistent-variable-syntax": "error",
832
+ "better-tailwindcss/enforce-shorthand-classes": "error",
833
+ "better-tailwindcss/no-conflicting-classes": "error",
834
+ "better-tailwindcss/no-deprecated-classes": "error",
835
+ "better-tailwindcss/no-unknown-classes": [
836
+ "error",
837
+ { ignore: opts.ignore ?? [] }
838
+ ]
839
+ },
840
+ settings: {
841
+ "better-tailwindcss": {
842
+ detectComponentClasses: true,
843
+ entryPoint: opts.entryPoint
844
+ }
845
+ }
846
+ }
847
+ ];
848
+
849
+ // src/configs/ignores.ts
850
+ import { includeIgnoreFile } from "@eslint/compat";
851
+ import path from "path";
852
+ var defaultIgnores = [
853
+ ".storybook",
854
+ ".playwright",
855
+ "/.react-router/**",
856
+ ".claude/**/*.js",
857
+ ".claude/**/*.cjs",
858
+ "scripts",
859
+ "public/**",
860
+ "**/*.css",
861
+ "**/*.svg",
862
+ "**/*.md"
863
+ ];
864
+ var ignores = (opts) => {
865
+ const out = [];
866
+ if (opts?.gitignore) {
867
+ const resolved = path.isAbsolute(opts.gitignore) ? opts.gitignore : path.resolve(process.cwd(), opts.gitignore);
868
+ out.push(includeIgnoreFile(resolved));
869
+ }
870
+ out.push({
871
+ ignores: [...defaultIgnores, ...opts?.extra ?? []],
872
+ name: "ignored-files"
873
+ });
874
+ return out;
875
+ };
876
+
877
+ // src/index.ts
878
+ var gaiaLint = {
879
+ base,
880
+ react,
881
+ styleHygiene,
882
+ guardrails,
883
+ testing,
884
+ storybook,
885
+ playwright,
886
+ prettier,
887
+ betterTailwind,
888
+ ignores
889
+ };
890
+ var index_default = gaiaLint;
891
+ export {
892
+ base,
893
+ betterTailwind,
894
+ index_default as default,
895
+ guardrails,
896
+ ignores,
897
+ playwright,
898
+ prettier,
899
+ react,
900
+ storybook,
901
+ styleHygiene,
902
+ testing
903
+ };
904
+ //# sourceMappingURL=index.js.map