@bastidood/eslint-config 0.5.0 → 0.6.1

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 CHANGED
@@ -14,11 +14,9 @@ pnpm add --save-dev @bastidood/eslint-config eslint typescript
14
14
  // eslint.config.ts
15
15
  import { compose } from '@bastidood/eslint-config';
16
16
  import { CORE } from '@bastidood/eslint-config/core';
17
- import { PROMISE } from '@bastidood/eslint-config/promise';
18
- import { UNICORN } from '@bastidood/eslint-config/unicorn';
19
17
  import { defineConfig } from 'eslint/config';
20
18
 
21
- export default defineConfig({ files: ['**/*.ts'] }, compose(CORE, UNICORN, PROMISE));
19
+ export default defineConfig({ files: ['**/*.ts'] }, compose(CORE));
22
20
  ```
23
21
 
24
22
  List `CORE` first.
@@ -28,12 +26,9 @@ List `CORE` first.
28
26
  | Entry point | Contents |
29
27
  | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
30
28
  | `@bastidood/eslint-config` | `compose` |
31
- | `@bastidood/eslint-config/core` | ESLint core, `import`, and `@typescript-eslint` rules |
32
- | `@bastidood/eslint-config/unicorn` | `unicorn` rules |
33
- | `@bastidood/eslint-config/promise` | `promise` rules |
29
+ | `@bastidood/eslint-config/core` | ESLint core, `import`, `jsdoc`, `promise`, `@typescript-eslint`, and `unicorn` rules |
34
30
  | `@bastidood/eslint-config/node` | Node.js rules |
35
31
  | `@bastidood/eslint-config/vitest` | Vitest rules |
36
- | `@bastidood/eslint-config/jsdoc` | JSDoc rules for documentation that TypeScript does not cover |
37
32
  | `@bastidood/eslint-config/tanstack/query` | Enables the slopstopper TanStack Query rules: `prefer-query-key-context`, `no-defaulted-query-key`, `no-standalone-mutate-async`, and `no-mutate-callback-cache-update` |
38
33
  | `@bastidood/eslint-config/tanstack/table` | Enables the slopstopper TanStack Table rules: `prefer-table-atoms`, `require-table-state-pairs`, `no-render-scoped-table-schema`, and `require-exclusive-indeterminate`; bans `stockFeatures` and reading column templates outside `FlexRender` |
39
34
 
@@ -1,3 +1,4 @@
1
+ import { NewResolver } from "eslint-plugin-import-x";
1
2
  import { Linter } from "eslint";
2
3
  export interface RestrictedImportPath {
3
4
  readonly name: string;
@@ -29,24 +30,37 @@ export interface Restrictions {
29
30
  readonly properties?: RestrictedProperty[];
30
31
  readonly syntax?: RestrictedSyntax[];
31
32
  }
33
+ /** An `import-x/resolver-next` resolver. `eslint-import-resolver-typescript` widens `interfaceVersion` to `number`. */
34
+ export interface ImportResolver extends Omit<NewResolver, 'interfaceVersion'> {
35
+ readonly interfaceVersion: number;
36
+ }
32
37
  export interface ScopedRestrictions {
33
38
  readonly files: string[];
34
39
  readonly restrictions: Restrictions;
35
40
  }
36
41
  /**
37
42
  * An entry point: ESLint configuration objects plus the lists that `compose` concatenates, namely the
38
- * restriction lists and the non-standard file extensions that the TypeScript project service must resolve.
39
- * `configs` may nest a configuration list one level deep, such as a plugin's `recommended` list.
43
+ * restriction lists, the non-standard file extensions that the TypeScript project service must resolve, and the
44
+ * `import-x` settings lists. `configs` may nest a configuration list one level deep, such as a plugin's
45
+ * `recommended` list.
40
46
  */
41
47
  export interface Entry {
42
48
  readonly configs?: (Linter.Config | Linter.Config[])[];
43
49
  readonly extraFileExtensions?: string[];
50
+ /** The file extensions that the `import` rules follow, as in `import-x/extensions`. */
51
+ readonly importExtensions?: string[];
52
+ /** The folders whose modules the `import` rules treat as external, as in `import-x/external-module-folders`. */
53
+ readonly importExternalModuleFolders?: string[];
54
+ /** Maps the module name of a parser to the file extensions that it parses, as in `import-x/parsers`. */
55
+ readonly importParsers?: Record<string, string[]>;
56
+ /** The resolvers that the `import` rules try in order, as in `import-x/resolver-next`. */
57
+ readonly importResolvers?: ImportResolver[];
44
58
  readonly restrictions?: Restrictions;
45
59
  readonly scopedRestrictions?: ScopedRestrictions[];
46
60
  }
47
61
  /**
48
- * Compose entry points into one ESLint flat configuration for `extends`. Restriction lists are concatenated
49
- * instead of replaced, and every scoped configuration repeats the top-level restrictions so that it cannot
50
- * drop them.
62
+ * Compose entry points into one ESLint flat configuration for `extends`. Restriction lists, file extension
63
+ * lists, and `import-x` settings lists are concatenated instead of replaced, and every scoped configuration repeats the top-level restrictions
64
+ * so that it cannot drop them.
51
65
  */
52
66
  export declare function compose(...entries: Entry[]): Linter.Config[];
@@ -13,20 +13,20 @@ var RestrictionLists = class RestrictionLists {
13
13
  #properties = ["error"];
14
14
  #syntax = ["error"];
15
15
  append({ importPaths, importPatterns, globals, properties, syntax }) {
16
- appendAll(this.#imports.paths, importPaths);
17
- appendAll(this.#imports.patterns, importPatterns);
18
- appendAll(this.#globals, globals);
19
- appendAll(this.#properties, properties);
20
- appendAll(this.#syntax, syntax);
16
+ appendAll$1(this.#imports.paths, importPaths);
17
+ appendAll$1(this.#imports.patterns, importPatterns);
18
+ appendAll$1(this.#globals, globals);
19
+ appendAll$1(this.#properties, properties);
20
+ appendAll$1(this.#syntax, syntax);
21
21
  }
22
22
  /** Copy these lists so that a scoped override can extend them without changing the top-level rules. */
23
23
  copy() {
24
24
  const copy = new RestrictionLists();
25
- appendAll(copy.#imports.paths, this.#imports.paths);
26
- appendAll(copy.#imports.patterns, this.#imports.patterns);
27
- appendAll(copy.#globals, this.#globals.values().drop(1));
28
- appendAll(copy.#properties, this.#properties.values().drop(1));
29
- appendAll(copy.#syntax, this.#syntax.values().drop(1));
25
+ appendAll$1(copy.#imports.paths, this.#imports.paths);
26
+ appendAll$1(copy.#imports.patterns, this.#imports.patterns);
27
+ appendAll$1(copy.#globals, this.#globals.values().drop(1));
28
+ appendAll$1(copy.#properties, this.#properties.values().drop(1));
29
+ appendAll$1(copy.#syntax, this.#syntax.values().drop(1));
30
30
  return copy;
31
31
  }
32
32
  importsRule() {
@@ -43,23 +43,38 @@ var RestrictionLists = class RestrictionLists {
43
43
  return this.#syntax.length === 1 ? null : this.#syntax;
44
44
  }
45
45
  };
46
- function appendAll(target, items) {
46
+ function appendAll$1(target, items) {
47
47
  if (typeof items === "undefined") return;
48
48
  for (const item of items) target.push(item);
49
49
  }
50
50
  // src/compose/index.ts
51
51
  /**
52
- * Compose entry points into one ESLint flat configuration for `extends`. Restriction lists are concatenated
53
- * instead of replaced, and every scoped configuration repeats the top-level restrictions so that it cannot
54
- * drop them.
52
+ * Compose entry points into one ESLint flat configuration for `extends`. Restriction lists, file extension
53
+ * lists, and `import-x` settings lists are concatenated instead of replaced, and every scoped configuration repeats the top-level restrictions
54
+ * so that it cannot drop them.
55
55
  */
56
56
  function compose(...entries) {
57
57
  const configs = [];
58
58
  const extraFileExtensions = [];
59
+ const importExtensions = [];
60
+ const importExternalModuleFolders = [];
61
+ const importParsers = {};
62
+ const importResolvers = [];
63
+ let hasImportParsers = false;
59
64
  const restrictions = new RestrictionLists();
60
- for (const { configs: entryConfigs, extraFileExtensions: entryExtensions, restrictions: entryRestrictions } of entries) {
65
+ for (const { configs: entryConfigs, extraFileExtensions: entryExtensions, importExtensions: entryImportExtensions, importExternalModuleFolders: entryImportExternalModuleFolders, importParsers: entryImportParsers, importResolvers: entryImportResolvers, restrictions: entryRestrictions } of entries) {
61
66
  appendConfigs(configs, entryConfigs);
62
- if (typeof entryExtensions !== "undefined") for (const extension of entryExtensions) extraFileExtensions.push(extension);
67
+ appendAll(extraFileExtensions, entryExtensions);
68
+ appendAll(importExtensions, entryImportExtensions);
69
+ appendAll(importExternalModuleFolders, entryImportExternalModuleFolders);
70
+ appendAll(importResolvers, entryImportResolvers);
71
+ if (typeof entryImportParsers !== "undefined") for (const parser in entryImportParsers) {
72
+ if (!Object.hasOwn(entryImportParsers, parser)) continue;
73
+ const extensions = importParsers[parser] ?? [];
74
+ appendAll(extensions, entryImportParsers[parser]);
75
+ importParsers[parser] = extensions;
76
+ hasImportParsers = true;
77
+ }
63
78
  if (typeof entryRestrictions !== "undefined") restrictions.append(entryRestrictions);
64
79
  }
65
80
  configs.push({
@@ -82,8 +97,31 @@ function compose(...entries) {
82
97
  name: "@bastidood/eslint-config/project-service",
83
98
  languageOptions: { parserOptions: { extraFileExtensions } }
84
99
  });
100
+ const importSettings = {};
101
+ let hasImportSettings = hasImportParsers;
102
+ if (hasImportParsers) importSettings["import-x/parsers"] = importParsers;
103
+ if (importExtensions.length > 0) {
104
+ importSettings["import-x/extensions"] = importExtensions;
105
+ hasImportSettings = true;
106
+ }
107
+ if (importExternalModuleFolders.length > 0) {
108
+ importSettings["import-x/external-module-folders"] = importExternalModuleFolders;
109
+ hasImportSettings = true;
110
+ }
111
+ if (importResolvers.length > 0) {
112
+ importSettings["import-x/resolver-next"] = importResolvers;
113
+ hasImportSettings = true;
114
+ }
115
+ if (hasImportSettings) configs.push({
116
+ name: "@bastidood/eslint-config/import",
117
+ settings: importSettings
118
+ });
85
119
  return configs;
86
120
  }
121
+ function appendAll(target, items) {
122
+ if (typeof items === "undefined") return;
123
+ for (const item of items) target.push(item);
124
+ }
87
125
  /** Append an entry point's configurations, flattening nested configuration lists one level. */
88
126
  function appendConfigs(target, configs) {
89
127
  if (typeof configs === "undefined") return;
@@ -1,4 +1,4 @@
1
- // ../../node_modules/.pnpm/eslint-plugin-oxlint@1.90.0_oxlint@1.91.0_oxlint-tsgolint@7.0.2005_/node_modules/eslint-plugin-oxlint/dist/generated/rules-by-category.mjs
1
+ // ../../node_modules/.pnpm/eslint-plugin-oxlint@1.92.0_oxlint@1.92.0_oxlint-tsgolint@7.0.2006_/node_modules/eslint-plugin-oxlint/dist/rules-by-category-BNcZTGK2.mjs
2
2
  const pedanticRules = {
3
3
  "accessor-pairs": "off",
4
4
  "array-callback-return": "off",
@@ -436,6 +436,7 @@ const suspiciousRules = {
436
436
  "react/style-prop-object": "off",
437
437
  "@typescript-eslint/no-confusing-non-null-assertion": "off",
438
438
  "@typescript-eslint/no-extraneous-class": "off",
439
+ "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "off",
439
440
  "@typescript-eslint/no-unnecessary-type-constraint": "off",
440
441
  "unicorn/consistent-function-scoping": "off",
441
442
  "unicorn/no-accessor-recursion": "off",
@@ -444,6 +445,7 @@ const suspiciousRules = {
444
445
  "unicorn/no-array-sort": "off",
445
446
  "unicorn/no-confusing-array-with": "off",
446
447
  "unicorn/no-instanceof-builtins": "off",
448
+ "unicorn/no-useless-error-capture-stack-trace": "off",
447
449
  "unicorn/prefer-add-event-listener": "off",
448
450
  "unicorn/require-module-specifiers": "off",
449
451
  "unicorn/require-post-message-target-origin": "off",
@@ -530,7 +532,6 @@ const restrictionRules = {
530
532
  "@typescript-eslint/no-import-type-side-effects": "off",
531
533
  "@typescript-eslint/no-invalid-void-type": "off",
532
534
  "@typescript-eslint/no-namespace": "off",
533
- "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "off",
534
535
  "@typescript-eslint/no-non-null-assertion": "off",
535
536
  "@typescript-eslint/no-require-imports": "off",
536
537
  "@typescript-eslint/no-restricted-types": "off",
@@ -545,7 +546,6 @@ const restrictionRules = {
545
546
  "unicorn/no-length-as-slice-end": "off",
546
547
  "unicorn/no-magic-array-flat-depth": "off",
547
548
  "unicorn/no-process-exit": "off",
548
- "unicorn/no-useless-error-capture-stack-trace": "off",
549
549
  "unicorn/prefer-modern-math-apis": "off",
550
550
  "unicorn/prefer-module": "off",
551
551
  "unicorn/prefer-node-protocol": "off",
@@ -921,7 +921,7 @@ const restrictionTypeAwareRules = {
921
921
  "@typescript-eslint/promise-function-async": "off",
922
922
  "@typescript-eslint/use-unknown-in-catch-callback-variable": "off"
923
923
  };
924
- // ../../node_modules/.pnpm/eslint-plugin-oxlint@1.90.0_oxlint@1.91.0_oxlint-tsgolint@7.0.2005_/node_modules/eslint-plugin-oxlint/dist/generated/rules-by-scope.mjs
924
+ // ../../node_modules/.pnpm/eslint-plugin-oxlint@1.92.0_oxlint@1.92.0_oxlint-tsgolint@7.0.2006_/node_modules/eslint-plugin-oxlint/dist/rules-by-scope-DGVQzOOx.mjs
925
925
  const reactHooksRules = {
926
926
  "react-hooks/capitalized-calls": "off",
927
927
  "react-hooks/error-boundaries": "off",
@@ -1,11 +1,17 @@
1
1
  // ../oxlint/src/core.ts
2
- /** ESLint core, `import`, `oxc`, and type-aware `typescript` rules. Rules that the TypeScript compiler already reports are off. */
2
+ /**
3
+ * ESLint core, `import`, `jsdoc`, `oxc`, `promise`, type-aware `typescript`, and `unicorn` rules. Rules that the
4
+ * TypeScript compiler already reports are off.
5
+ */
3
6
  const CORE = {
4
7
  config: {
5
8
  plugins: [
6
9
  "import",
10
+ "jsdoc",
7
11
  "oxc",
8
- "typescript"
12
+ "promise",
13
+ "typescript",
14
+ "unicorn"
9
15
  ],
10
16
  jsPlugins: [{
11
17
  name: "eslint-js",
@@ -80,13 +86,13 @@ const CORE = {
80
86
  "import/no-amd": "error",
81
87
  "import/no-anonymous-default-export": "error",
82
88
  "import/no-commonjs": "error",
83
- "import/no-cycle": "error",
89
+ "import/no-cycle": ["error", { ignoreExternal: true }],
84
90
  "import/no-default-export": "off",
85
91
  "import/no-dynamic-require": "error",
86
92
  "import/no-empty-named-blocks": "error",
87
93
  "import/no-mutable-exports": "error",
88
94
  "import/no-named-as-default": "error",
89
- "import/no-named-as-default-member": "error",
95
+ "import/no-named-as-default-member": "off",
90
96
  "import/no-named-default": "error",
91
97
  "import/no-named-export": "off",
92
98
  "import/no-namespace": "off",
@@ -96,6 +102,29 @@ const CORE = {
96
102
  "import/no-webpack-loader-syntax": "error",
97
103
  "import/prefer-default-export": "off",
98
104
  "init-declarations": "off",
105
+ "jsdoc/check-access": "off",
106
+ "jsdoc/check-property-names": "off",
107
+ "jsdoc/check-tag-names": ["error", { typed: true }],
108
+ "jsdoc/empty-tags": "error",
109
+ "jsdoc/implements-on-classes": "off",
110
+ "jsdoc/no-blank-blocks": ["error", { enableFixer: true }],
111
+ "jsdoc/no-defaults": "off",
112
+ "jsdoc/require-param": "off",
113
+ "jsdoc/require-param-description": "error",
114
+ "jsdoc/require-param-name": "error",
115
+ "jsdoc/require-param-type": "off",
116
+ "jsdoc/require-property": "off",
117
+ "jsdoc/require-property-description": "off",
118
+ "jsdoc/require-property-name": "off",
119
+ "jsdoc/require-property-type": "off",
120
+ "jsdoc/require-returns": "off",
121
+ "jsdoc/require-returns-description": "error",
122
+ "jsdoc/require-returns-type": "off",
123
+ "jsdoc/require-throws-description": "error",
124
+ "jsdoc/require-throws-type": "off",
125
+ "jsdoc/require-yields": "off",
126
+ "jsdoc/require-yields-description": "error",
127
+ "jsdoc/require-yields-type": "off",
99
128
  "logical-assignment-operators": "error",
100
129
  "max-classes-per-file": "off",
101
130
  "max-lines": "off",
@@ -271,6 +300,17 @@ const CORE = {
271
300
  "prefer-spread": "error",
272
301
  "prefer-template": "error",
273
302
  "preserve-caught-error": "error",
303
+ "promise/always-return": "off",
304
+ "promise/avoid-new": "error",
305
+ "promise/no-callback-in-promise": "off",
306
+ "promise/no-multiple-resolved": "error",
307
+ "promise/no-new-statics": "off",
308
+ "promise/no-promise-in-callback": "error",
309
+ "promise/param-names": "error",
310
+ "promise/prefer-await-to-callbacks": "error",
311
+ "promise/prefer-await-to-then": ["error", { strict: true }],
312
+ "promise/spec-only": "error",
313
+ "promise/valid-params": "off",
274
314
  radix: "error",
275
315
  "require-unicode-regexp": "error",
276
316
  "require-yield": "error",
@@ -440,6 +480,133 @@ const CORE = {
440
480
  "typescript/unified-signatures": "error",
441
481
  "typescript/use-unknown-in-catch-callback-variable": "error",
442
482
  "unicode-bom": "off",
483
+ "unicorn/catch-error-name": "error",
484
+ "unicorn/consistent-assert": "error",
485
+ "unicorn/consistent-date-clone": "error",
486
+ "unicorn/consistent-empty-array-spread": "error",
487
+ "unicorn/consistent-existence-index-check": "error",
488
+ "unicorn/consistent-function-scoping": "error",
489
+ "unicorn/consistent-template-literal-escape": "error",
490
+ "unicorn/custom-error-definition": "error",
491
+ "unicorn/error-message": "error",
492
+ "unicorn/escape-case": "error",
493
+ "unicorn/explicit-length-check": "error",
494
+ "unicorn/explicit-timer-delay": "error",
495
+ "unicorn/filename-case": ["error", { case: "kebabCase" }],
496
+ "unicorn/import-style": "off",
497
+ "unicorn/max-nested-calls": "error",
498
+ "unicorn/new-for-builtins": "error",
499
+ "unicorn/no-abusive-eslint-disable": "error",
500
+ "unicorn/no-accessor-recursion": "error",
501
+ "unicorn/no-array-callback-reference": "error",
502
+ "unicorn/no-array-fill-with-reference-type": "error",
503
+ "unicorn/no-array-for-each": "error",
504
+ "unicorn/no-array-method-this-argument": "error",
505
+ "unicorn/no-array-reverse": "off",
506
+ "unicorn/no-array-sort": "off",
507
+ "unicorn/no-await-expression-member": "error",
508
+ "unicorn/no-await-in-promise-methods": "error",
509
+ "unicorn/no-confusing-array-with": "off",
510
+ "unicorn/no-document-cookie": "error",
511
+ "unicorn/no-empty-file": "error",
512
+ "unicorn/no-hex-escape": "error",
513
+ "unicorn/no-immediate-mutation": "error",
514
+ "unicorn/no-instanceof-array": "error",
515
+ "unicorn/no-instanceof-builtins": ["error", { useErrorIsError: true }],
516
+ "unicorn/no-invalid-fetch-options": "error",
517
+ "unicorn/no-invalid-remove-event-listener": "off",
518
+ "unicorn/no-length-as-slice-end": "error",
519
+ "unicorn/no-lonely-if": "error",
520
+ "unicorn/no-magic-array-flat-depth": "error",
521
+ "unicorn/no-negation-in-equality-check": "error",
522
+ "unicorn/no-new-array": "error",
523
+ "unicorn/no-new-buffer": "error",
524
+ "unicorn/no-object-as-default-parameter": "error",
525
+ "unicorn/no-process-exit": "error",
526
+ "unicorn/no-single-promise-in-promise-methods": "error",
527
+ "unicorn/no-static-only-class": "error",
528
+ "unicorn/no-thenable": "error",
529
+ "unicorn/no-unnecessary-array-flat-depth": "error",
530
+ "unicorn/no-unnecessary-array-splice-count": "error",
531
+ "unicorn/no-unnecessary-await": "off",
532
+ "unicorn/no-unnecessary-slice-end": "error",
533
+ "unicorn/no-unreadable-array-destructuring": "error",
534
+ "unicorn/no-unreadable-iife": "error",
535
+ "unicorn/no-useless-collection-argument": "error",
536
+ "unicorn/no-useless-error-capture-stack-trace": "error",
537
+ "unicorn/no-useless-fallback-in-spread": "error",
538
+ "unicorn/no-useless-iterator-to-array": "error",
539
+ "unicorn/no-useless-length-check": "error",
540
+ "unicorn/no-useless-promise-resolve-reject": "error",
541
+ "unicorn/no-useless-spread": "error",
542
+ "unicorn/no-useless-switch-case": "error",
543
+ "unicorn/no-zero-fractions": "error",
544
+ "unicorn/number-literal-case": "off",
545
+ "unicorn/numeric-separators-style": "error",
546
+ "unicorn/prefer-add-event-listener": "error",
547
+ "unicorn/prefer-array-find": "off",
548
+ "unicorn/prefer-array-flat": "error",
549
+ "unicorn/prefer-array-flat-map": "error",
550
+ "unicorn/prefer-array-index-of": "error",
551
+ "unicorn/prefer-array-some": "error",
552
+ "unicorn/prefer-at": "error",
553
+ "unicorn/prefer-bigint-literals": "error",
554
+ "unicorn/prefer-blob-reading-methods": "error",
555
+ "unicorn/prefer-class-fields": "error",
556
+ "unicorn/prefer-classlist-toggle": "error",
557
+ "unicorn/prefer-code-point": "error",
558
+ "unicorn/prefer-date-now": "error",
559
+ "unicorn/prefer-default-parameters": "error",
560
+ "unicorn/prefer-dom-node-append": "error",
561
+ "unicorn/prefer-dom-node-dataset": "error",
562
+ "unicorn/prefer-dom-node-remove": "error",
563
+ "unicorn/prefer-dom-node-text-content": "error",
564
+ "unicorn/prefer-event-target": "error",
565
+ "unicorn/prefer-export-from": "error",
566
+ "unicorn/prefer-global-this": "error",
567
+ "unicorn/prefer-import-meta-properties": "error",
568
+ "unicorn/prefer-keyboard-event-key": "error",
569
+ "unicorn/prefer-logical-operator-over-ternary": "error",
570
+ "unicorn/prefer-math-min-max": "error",
571
+ "unicorn/prefer-math-trunc": "error",
572
+ "unicorn/prefer-modern-dom-apis": "error",
573
+ "unicorn/prefer-modern-math-apis": "error",
574
+ "unicorn/prefer-module": "error",
575
+ "unicorn/prefer-native-coercion-functions": "error",
576
+ "unicorn/prefer-negative-index": "error",
577
+ "unicorn/prefer-node-protocol": "error",
578
+ "unicorn/prefer-number-coercion": "error",
579
+ "unicorn/prefer-number-properties": ["error", { checkInfinity: true }],
580
+ "unicorn/prefer-object-from-entries": "error",
581
+ "unicorn/prefer-optional-catch-binding": "off",
582
+ "unicorn/prefer-prototype-methods": "error",
583
+ "unicorn/prefer-query-selector": "error",
584
+ "unicorn/prefer-reflect-apply": "off",
585
+ "unicorn/prefer-regexp-test": "error",
586
+ "unicorn/prefer-response-static-json": "error",
587
+ "unicorn/prefer-set-has": "error",
588
+ "unicorn/prefer-set-size": "error",
589
+ "unicorn/prefer-single-call": "error",
590
+ "unicorn/prefer-spread": "error",
591
+ "unicorn/prefer-string-raw": "error",
592
+ "unicorn/prefer-string-replace-all": "error",
593
+ "unicorn/prefer-string-slice": "error",
594
+ "unicorn/prefer-string-starts-ends-with": "off",
595
+ "unicorn/prefer-string-trim-start-end": "error",
596
+ "unicorn/prefer-structured-clone": "error",
597
+ "unicorn/prefer-ternary": "error",
598
+ "unicorn/prefer-top-level-await": "error",
599
+ "unicorn/prefer-type-error": "error",
600
+ "unicorn/relative-url-style": "error",
601
+ "unicorn/require-array-join-separator": "error",
602
+ "unicorn/require-module-attributes": "error",
603
+ "unicorn/require-module-specifiers": "off",
604
+ "unicorn/require-number-to-fixed-digits-argument": "error",
605
+ "unicorn/require-post-message-target-origin": "error",
606
+ "unicorn/switch-case-braces": ["error", "avoid"],
607
+ "unicorn/switch-case-break-position": "error",
608
+ "unicorn/text-encoding-identifier-case": "error",
609
+ "unicorn/throw-new-error": "error",
443
610
  "use-isnan": "off",
444
611
  "valid-typeof": "off",
445
612
  yoda: [
package/dist/core.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Entry } from "./compose/index.mjs";
2
2
  /**
3
- * ESLint core, `import`, and type-aware `@typescript-eslint` rules, generated from the Oxlint `core` entry point. The
4
- * TypeScript project service finds the `tsconfig.json` nearest each file, searching up to the working directory.
3
+ * ESLint core, `import`, `jsdoc`, `promise`, type-aware `@typescript-eslint`, and `unicorn` rules, generated from the
4
+ * Oxlint `core` entry point. The TypeScript project service finds the `tsconfig.json` nearest each file, searching up
5
+ * to the working directory.
5
6
  */
6
7
  export declare const CORE: Entry;
package/dist/core.mjs CHANGED
@@ -1,7 +1,11 @@
1
- import { t as CORE$1 } from "./core-NeXMRUpu.mjs";
2
- import { n as writeEslintRules, r as writeExtensionRules, t as writeCategoryRules } from "./convert-BXtGAZpc.mjs";
1
+ import { t as CORE$1 } from "./core-tXylD6ZH.mjs";
2
+ import { n as writeEslintRules, r as writeExtensionRules, t as writeCategoryRules } from "./convert-BtTj7vbK.mjs";
3
3
  import SLOPSTOPPER from "@bastidood/eslint-plugin-slopstopper";
4
+ import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
4
5
  import { importX } from "eslint-plugin-import-x";
6
+ import jsdocPlugin from "eslint-plugin-jsdoc";
7
+ import promisePlugin from "eslint-plugin-promise";
8
+ import unicornPlugin from "eslint-plugin-unicorn";
5
9
  import tseslint from "typescript-eslint";
6
10
  // src/core.ts
7
11
  const { categories: CATEGORIES, overrides: OVERRIDES, plugins: PLUGINS, rules: OXLINT_RULES } = CORE$1.config;
@@ -25,7 +29,10 @@ for (const { files, rules } of OVERRIDES) {
25
29
  const PLUGIN_DEFINITIONS = {
26
30
  "@typescript-eslint": TYPESCRIPT_ESLINT,
27
31
  import: importX,
28
- slopstopper: SLOPSTOPPER
32
+ jsdoc: jsdocPlugin,
33
+ promise: promisePlugin,
34
+ slopstopper: SLOPSTOPPER,
35
+ unicorn: unicornPlugin
29
36
  };
30
37
  const RESTRICTIONS = {
31
38
  ...CORE$1.restrictions,
@@ -46,8 +53,9 @@ const RESTRICTIONS = {
46
53
  ]
47
54
  };
48
55
  /**
49
- * ESLint core, `import`, and type-aware `@typescript-eslint` rules, generated from the Oxlint `core` entry point. The
50
- * TypeScript project service finds the `tsconfig.json` nearest each file, searching up to the working directory.
56
+ * ESLint core, `import`, `jsdoc`, `promise`, type-aware `@typescript-eslint`, and `unicorn` rules, generated from the
57
+ * Oxlint `core` entry point. The TypeScript project service finds the `tsconfig.json` nearest each file, searching up
58
+ * to the working directory.
51
59
  */
52
60
  const CORE = {
53
61
  configs: [{
@@ -59,6 +67,23 @@ const CORE = {
59
67
  plugins: PLUGIN_DEFINITIONS,
60
68
  rules: RULES
61
69
  }, OVERRIDE_CONFIGS],
70
+ importExtensions: [
71
+ ".ts",
72
+ ".tsx",
73
+ ".cts",
74
+ ".mts",
75
+ ".js",
76
+ ".jsx",
77
+ ".cjs",
78
+ ".mjs"
79
+ ],
80
+ importParsers: { "@typescript-eslint/parser": [
81
+ ".ts",
82
+ ".tsx",
83
+ ".cts",
84
+ ".mts"
85
+ ] },
86
+ importResolvers: [createTypeScriptImportResolver()],
62
87
  restrictions: RESTRICTIONS
63
88
  };
64
89
  export { CORE };
package/dist/node.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { t as CORE } from "./core-NeXMRUpu.mjs";
2
- import { n as writeEslintRules, t as writeCategoryRules } from "./convert-BXtGAZpc.mjs";
1
+ import { t as CORE } from "./core-tXylD6ZH.mjs";
2
+ import { n as writeEslintRules, t as writeCategoryRules } from "./convert-BtTj7vbK.mjs";
3
3
  import nodePlugin from "eslint-plugin-n";
4
4
  // ../oxlint/src/node.ts
5
5
  /** Node.js rules for code that runs on Node.js. */
@@ -1,4 +1,4 @@
1
- import { n as writeEslintRules } from "../convert-BXtGAZpc.mjs";
1
+ import { n as writeEslintRules } from "../convert-BtTj7vbK.mjs";
2
2
  // ../oxlint/src/tanstack/query.ts
3
3
  /** TanStack Query rules that apply to every framework adapter. */
4
4
  const TANSTACK_QUERY$1 = { config: {
@@ -1,4 +1,4 @@
1
- import { n as writeEslintRules } from "../convert-BXtGAZpc.mjs";
1
+ import { n as writeEslintRules } from "../convert-BtTj7vbK.mjs";
2
2
  // ../oxlint/src/tanstack/table.ts
3
3
  const STOCK_FEATURES_MESSAGE = "Register only the features that this table uses in `tableFeatures({...})`. `stockFeatures` hides which features the table depends on and keeps every unused feature in the bundle. Do not suppress this.";
4
4
  const RAW_TEMPLATE_MESSAGE = "Render through `FlexRender` with `cell`, `header`, or `footer` instead of reading the column template. For cells, it renders `aggregatedCell` and skips placeholders, and calling a template directly runs its hooks in the calling component. For a column label, use `column.id` or a label map.";
package/dist/vitest.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { t as CORE } from "./core-NeXMRUpu.mjs";
2
- import { n as writeEslintRules, t as writeCategoryRules } from "./convert-BXtGAZpc.mjs";
1
+ import { t as CORE } from "./core-tXylD6ZH.mjs";
2
+ import { n as writeEslintRules, t as writeCategoryRules } from "./convert-BtTj7vbK.mjs";
3
3
  import vitestPlugin from "@vitest/eslint-plugin";
4
4
  // ../oxlint/src/vitest.ts
5
5
  const MODULE_MOCK_MESSAGE = "A module mock swaps out a dependency that the code under test hides. Make the code honest instead: have it take the stateful or external collaborator (a database, network client, file system, or clock) as a parameter, inject the real one from the entry point, and pass a fake in the test. If a mock is unavoidable, suppress this diagnostic with a reason and mock through `import()` so that the path stays type-checked.";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastidood/eslint-config",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "Strict baseline ESLint configuration generated from @bastidood/oxlint-config.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/BastiDood/slopstopper",
@@ -16,11 +16,8 @@
16
16
  "exports": {
17
17
  ".": "./dist/compose/index.mjs",
18
18
  "./core": "./dist/core.mjs",
19
- "./unicorn": "./dist/unicorn.mjs",
20
- "./promise": "./dist/promise.mjs",
21
19
  "./node": "./dist/node.mjs",
22
20
  "./vitest": "./dist/vitest.mjs",
23
- "./jsdoc": "./dist/jsdoc.mjs",
24
21
  "./tanstack/query": "./dist/tanstack/query.mjs",
25
22
  "./tanstack/table": "./dist/tanstack/table.mjs"
26
23
  },
@@ -31,22 +28,24 @@
31
28
  "access": "public"
32
29
  },
33
30
  "dependencies": {
34
- "@bastidood/eslint-plugin-slopstopper": "^0.4.0",
31
+ "@bastidood/eslint-plugin-slopstopper": "^0.5.1",
35
32
  "@vitest/eslint-plugin": "^1.6.28",
33
+ "eslint-import-resolver-typescript": "^4.4.5",
36
34
  "eslint-plugin-import-x": "^4.17.1",
37
- "eslint-plugin-jsdoc": "^65.4.3",
35
+ "eslint-plugin-jsdoc": "^65.4.4",
38
36
  "eslint-plugin-n": "^18.5.0",
39
37
  "eslint-plugin-promise": "^7.3.0",
40
38
  "eslint-plugin-unicorn": "^79.0.0",
41
39
  "typescript-eslint": "^8.72.1"
42
40
  },
43
41
  "devDependencies": {
44
- "@bastidood/oxlint-config": "0.5.0",
42
+ "@bastidood/oxlint-config": "0.6.1",
45
43
  "@bastidood/tsconfig": "0.1.1",
44
+ "@types/node": "^26.6.6",
46
45
  "@typescript/native": "npm:typescript@^7.0.2",
47
46
  "eslint": "^10.14.0",
48
- "eslint-plugin-oxlint": "^1.90.0",
49
- "tsdown": "^0.23.5",
47
+ "eslint-plugin-oxlint": "^1.92.0",
48
+ "tsdown": "0.23.5",
50
49
  "typescript": "npm:@typescript/typescript6@^6.0.2"
51
50
  },
52
51
  "peerDependencies": {
package/dist/jsdoc.d.mts DELETED
@@ -1,3 +0,0 @@
1
- import { Entry } from "./compose/index.mjs";
2
- /** `eslint-plugin-jsdoc` rules, generated from the Oxlint `jsdoc` entry point. */
3
- export declare const JSDOC: Entry;
package/dist/jsdoc.mjs DELETED
@@ -1,43 +0,0 @@
1
- import { t as CORE } from "./core-NeXMRUpu.mjs";
2
- import { n as writeEslintRules, t as writeCategoryRules } from "./convert-BXtGAZpc.mjs";
3
- import jsdocPlugin from "eslint-plugin-jsdoc";
4
- // ../oxlint/src/jsdoc.ts
5
- const JSDOC$1 = { config: {
6
- plugins: ["jsdoc"],
7
- rules: {
8
- "jsdoc/check-access": "off",
9
- "jsdoc/check-property-names": "off",
10
- "jsdoc/check-tag-names": ["error", { typed: true }],
11
- "jsdoc/empty-tags": "error",
12
- "jsdoc/implements-on-classes": "off",
13
- "jsdoc/no-blank-blocks": ["error", { enableFixer: true }],
14
- "jsdoc/no-defaults": "off",
15
- "jsdoc/require-param": "off",
16
- "jsdoc/require-param-description": "error",
17
- "jsdoc/require-param-name": "error",
18
- "jsdoc/require-param-type": "off",
19
- "jsdoc/require-property": "off",
20
- "jsdoc/require-property-description": "off",
21
- "jsdoc/require-property-name": "off",
22
- "jsdoc/require-property-type": "off",
23
- "jsdoc/require-returns": "off",
24
- "jsdoc/require-returns-description": "error",
25
- "jsdoc/require-returns-type": "off",
26
- "jsdoc/require-throws-description": "error",
27
- "jsdoc/require-throws-type": "off",
28
- "jsdoc/require-yields": "off",
29
- "jsdoc/require-yields-description": "error",
30
- "jsdoc/require-yields-type": "off"
31
- }
32
- } };
33
- // src/jsdoc.ts
34
- const RULES = {};
35
- writeCategoryRules(RULES, CORE.config.categories, JSDOC$1.config.plugins);
36
- writeEslintRules(RULES, JSDOC$1.config.rules);
37
- /** `eslint-plugin-jsdoc` rules, generated from the Oxlint `jsdoc` entry point. */
38
- const JSDOC = { configs: [{
39
- name: "@bastidood/eslint-config/jsdoc",
40
- plugins: { jsdoc: jsdocPlugin },
41
- rules: RULES
42
- }] };
43
- export { JSDOC };
@@ -1,3 +0,0 @@
1
- import { Entry } from "./compose/index.mjs";
2
- /** `eslint-plugin-promise` rules, generated from the Oxlint `promise` entry point. */
3
- export declare const PROMISE: Entry;
package/dist/promise.mjs DELETED
@@ -1,31 +0,0 @@
1
- import { t as CORE } from "./core-NeXMRUpu.mjs";
2
- import { n as writeEslintRules, t as writeCategoryRules } from "./convert-BXtGAZpc.mjs";
3
- import promisePlugin from "eslint-plugin-promise";
4
- // ../oxlint/src/promise.ts
5
- const PROMISE$1 = { config: {
6
- plugins: ["promise"],
7
- rules: {
8
- "promise/always-return": "off",
9
- "promise/avoid-new": "error",
10
- "promise/no-callback-in-promise": "off",
11
- "promise/no-multiple-resolved": "error",
12
- "promise/no-new-statics": "off",
13
- "promise/no-promise-in-callback": "error",
14
- "promise/param-names": "error",
15
- "promise/prefer-await-to-callbacks": "error",
16
- "promise/prefer-await-to-then": ["error", { strict: true }],
17
- "promise/spec-only": "error",
18
- "promise/valid-params": "off"
19
- }
20
- } };
21
- // src/promise.ts
22
- const RULES = {};
23
- writeCategoryRules(RULES, CORE.config.categories, PROMISE$1.config.plugins);
24
- writeEslintRules(RULES, PROMISE$1.config.rules);
25
- /** `eslint-plugin-promise` rules, generated from the Oxlint `promise` entry point. */
26
- const PROMISE = { configs: [{
27
- name: "@bastidood/eslint-config/promise",
28
- plugins: { promise: promisePlugin },
29
- rules: RULES
30
- }] };
31
- export { PROMISE };
@@ -1,3 +0,0 @@
1
- import { Entry } from "./compose/index.mjs";
2
- /** `eslint-plugin-unicorn` rules, generated from the Oxlint `unicorn` entry point. */
3
- export declare const UNICORN: Entry;
package/dist/unicorn.mjs DELETED
@@ -1,147 +0,0 @@
1
- import { t as CORE } from "./core-NeXMRUpu.mjs";
2
- import { n as writeEslintRules, t as writeCategoryRules } from "./convert-BXtGAZpc.mjs";
3
- import unicornPlugin from "eslint-plugin-unicorn";
4
- // ../oxlint/src/unicorn.ts
5
- const UNICORN$1 = { config: {
6
- plugins: ["unicorn"],
7
- rules: {
8
- "unicorn/catch-error-name": "error",
9
- "unicorn/consistent-assert": "error",
10
- "unicorn/consistent-date-clone": "error",
11
- "unicorn/consistent-empty-array-spread": "error",
12
- "unicorn/consistent-existence-index-check": "error",
13
- "unicorn/consistent-function-scoping": "error",
14
- "unicorn/consistent-template-literal-escape": "error",
15
- "unicorn/custom-error-definition": "error",
16
- "unicorn/error-message": "error",
17
- "unicorn/escape-case": "error",
18
- "unicorn/explicit-length-check": "error",
19
- "unicorn/explicit-timer-delay": "error",
20
- "unicorn/filename-case": ["error", { case: "kebabCase" }],
21
- "unicorn/import-style": "off",
22
- "unicorn/max-nested-calls": "error",
23
- "unicorn/new-for-builtins": "error",
24
- "unicorn/no-abusive-eslint-disable": "error",
25
- "unicorn/no-accessor-recursion": "error",
26
- "unicorn/no-array-callback-reference": "error",
27
- "unicorn/no-array-fill-with-reference-type": "error",
28
- "unicorn/no-array-for-each": "error",
29
- "unicorn/no-array-method-this-argument": "error",
30
- "unicorn/no-array-reverse": "off",
31
- "unicorn/no-array-sort": "off",
32
- "unicorn/no-await-expression-member": "error",
33
- "unicorn/no-await-in-promise-methods": "error",
34
- "unicorn/no-confusing-array-with": "off",
35
- "unicorn/no-document-cookie": "error",
36
- "unicorn/no-empty-file": "error",
37
- "unicorn/no-hex-escape": "error",
38
- "unicorn/no-immediate-mutation": "error",
39
- "unicorn/no-instanceof-array": "error",
40
- "unicorn/no-instanceof-builtins": ["error", { useErrorIsError: true }],
41
- "unicorn/no-invalid-fetch-options": "error",
42
- "unicorn/no-invalid-remove-event-listener": "off",
43
- "unicorn/no-length-as-slice-end": "error",
44
- "unicorn/no-lonely-if": "error",
45
- "unicorn/no-magic-array-flat-depth": "error",
46
- "unicorn/no-negation-in-equality-check": "error",
47
- "unicorn/no-new-array": "error",
48
- "unicorn/no-new-buffer": "error",
49
- "unicorn/no-object-as-default-parameter": "error",
50
- "unicorn/no-process-exit": "error",
51
- "unicorn/no-single-promise-in-promise-methods": "error",
52
- "unicorn/no-static-only-class": "error",
53
- "unicorn/no-thenable": "error",
54
- "unicorn/no-unnecessary-array-flat-depth": "error",
55
- "unicorn/no-unnecessary-array-splice-count": "error",
56
- "unicorn/no-unnecessary-await": "off",
57
- "unicorn/no-unnecessary-slice-end": "error",
58
- "unicorn/no-unreadable-array-destructuring": "error",
59
- "unicorn/no-unreadable-iife": "error",
60
- "unicorn/no-useless-collection-argument": "error",
61
- "unicorn/no-useless-error-capture-stack-trace": "error",
62
- "unicorn/no-useless-fallback-in-spread": "error",
63
- "unicorn/no-useless-iterator-to-array": "error",
64
- "unicorn/no-useless-length-check": "error",
65
- "unicorn/no-useless-promise-resolve-reject": "error",
66
- "unicorn/no-useless-spread": "error",
67
- "unicorn/no-useless-switch-case": "error",
68
- "unicorn/no-zero-fractions": "error",
69
- "unicorn/number-literal-case": "off",
70
- "unicorn/numeric-separators-style": "error",
71
- "unicorn/prefer-add-event-listener": "error",
72
- "unicorn/prefer-array-find": "off",
73
- "unicorn/prefer-array-flat": "error",
74
- "unicorn/prefer-array-flat-map": "error",
75
- "unicorn/prefer-array-index-of": "error",
76
- "unicorn/prefer-array-some": "error",
77
- "unicorn/prefer-at": "error",
78
- "unicorn/prefer-bigint-literals": "error",
79
- "unicorn/prefer-blob-reading-methods": "error",
80
- "unicorn/prefer-class-fields": "error",
81
- "unicorn/prefer-classlist-toggle": "error",
82
- "unicorn/prefer-code-point": "error",
83
- "unicorn/prefer-date-now": "error",
84
- "unicorn/prefer-default-parameters": "error",
85
- "unicorn/prefer-dom-node-append": "error",
86
- "unicorn/prefer-dom-node-dataset": "error",
87
- "unicorn/prefer-dom-node-remove": "error",
88
- "unicorn/prefer-dom-node-text-content": "error",
89
- "unicorn/prefer-event-target": "error",
90
- "unicorn/prefer-export-from": "error",
91
- "unicorn/prefer-global-this": "error",
92
- "unicorn/prefer-import-meta-properties": "error",
93
- "unicorn/prefer-keyboard-event-key": "error",
94
- "unicorn/prefer-logical-operator-over-ternary": "error",
95
- "unicorn/prefer-math-min-max": "error",
96
- "unicorn/prefer-math-trunc": "error",
97
- "unicorn/prefer-modern-dom-apis": "error",
98
- "unicorn/prefer-modern-math-apis": "error",
99
- "unicorn/prefer-module": "error",
100
- "unicorn/prefer-native-coercion-functions": "error",
101
- "unicorn/prefer-negative-index": "error",
102
- "unicorn/prefer-node-protocol": "error",
103
- "unicorn/prefer-number-coercion": "error",
104
- "unicorn/prefer-number-properties": ["error", { checkInfinity: true }],
105
- "unicorn/prefer-object-from-entries": "error",
106
- "unicorn/prefer-optional-catch-binding": "off",
107
- "unicorn/prefer-prototype-methods": "error",
108
- "unicorn/prefer-query-selector": "error",
109
- "unicorn/prefer-reflect-apply": "off",
110
- "unicorn/prefer-regexp-test": "error",
111
- "unicorn/prefer-response-static-json": "error",
112
- "unicorn/prefer-set-has": "error",
113
- "unicorn/prefer-set-size": "error",
114
- "unicorn/prefer-single-call": "error",
115
- "unicorn/prefer-spread": "error",
116
- "unicorn/prefer-string-raw": "error",
117
- "unicorn/prefer-string-replace-all": "error",
118
- "unicorn/prefer-string-slice": "error",
119
- "unicorn/prefer-string-starts-ends-with": "off",
120
- "unicorn/prefer-string-trim-start-end": "error",
121
- "unicorn/prefer-structured-clone": "error",
122
- "unicorn/prefer-ternary": "error",
123
- "unicorn/prefer-top-level-await": "error",
124
- "unicorn/prefer-type-error": "error",
125
- "unicorn/relative-url-style": "error",
126
- "unicorn/require-array-join-separator": "error",
127
- "unicorn/require-module-attributes": "error",
128
- "unicorn/require-module-specifiers": "off",
129
- "unicorn/require-number-to-fixed-digits-argument": "error",
130
- "unicorn/require-post-message-target-origin": "error",
131
- "unicorn/switch-case-braces": ["error", "avoid"],
132
- "unicorn/switch-case-break-position": "error",
133
- "unicorn/text-encoding-identifier-case": "error",
134
- "unicorn/throw-new-error": "error"
135
- }
136
- } };
137
- // src/unicorn.ts
138
- const RULES = {};
139
- writeCategoryRules(RULES, CORE.config.categories, UNICORN$1.config.plugins);
140
- writeEslintRules(RULES, UNICORN$1.config.rules);
141
- /** `eslint-plugin-unicorn` rules, generated from the Oxlint `unicorn` entry point. */
142
- const UNICORN = { configs: [{
143
- name: "@bastidood/eslint-config/unicorn",
144
- plugins: { unicorn: unicornPlugin },
145
- rules: RULES
146
- }] };
147
- export { UNICORN };