@theholocron/eslint-config 8.2.3 → 8.4.2

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
@@ -82,6 +82,10 @@ export default [...nodeApp()];
82
82
  // Publishable library (base + typescript + vitest)
83
83
  import { library } from "@theholocron/eslint-config/bundles/library";
84
84
  export default [...library()];
85
+
86
+ // With browser-targeted packages (turns off a Node-builtins rule that
87
+ // false-positives on navigator/sessionStorage/KeyboardEvent/…):
88
+ export default [...library({ browserPackages: ["packages/browser-utils/src"] })];
85
89
  ```
86
90
 
87
91
  Add project-specific configs after the bundle — they are merged in order:
@@ -1,4 +1,47 @@
1
+ import { Linter } from "eslint";
1
2
  //#region bundles/library.d.ts
2
- declare function library(): import("typescript-eslint").CompatibleConfig[];
3
+ interface LibraryOptions {
4
+ /**
5
+ * Package (or path) globs whose code runs in the browser, not Node —
6
+ * `n/no-unsupported-features/node-builtins` false-positives on browser
7
+ * APIs (`navigator`, `sessionStorage`, `KeyboardEvent`, …) it doesn't
8
+ * recognize. Each entry gets a `<glob>/**` files match with the rule
9
+ * turned off. Rare — most repos need nothing here (`theholocron/utils`
10
+ * is the one org repo that does, for its browser-targeted packages).
11
+ */
12
+ browserPackages?: string[];
13
+ }
14
+ /**
15
+ * Every 5-of-6 org repos' `eslint.config.ts` already reduces to `...library()`
16
+ * with no further composition once `base()`'s gitignore/docs-src absorption
17
+ * (#460) is in place — the sixth (`holocron` itself) only differs by also
18
+ * spreading `vitest()` at its root, which is safe to bake in unconditionally
19
+ * here: {@link vitest}'s config is glob-scoped to test/setup files, so it's a
20
+ * no-op anywhere it doesn't match, same reasoning as `docsSrcConfig`. Once
21
+ * every repo drops its now-redundant local composition (#680, the migration
22
+ * pass), `library()` alone — resolved via `eslint --config`, zero committed
23
+ * file — covers every repo but the `browserPackages` outlier, which keeps a
24
+ * tiny `export default library({ browserPackages: [...] })` (config-resolution
25
+ * workstream, #676 in theholocron/holocron).
26
+ */
27
+ declare function library(options?: LibraryOptions): Linter.Config[];
28
+ /**
29
+ * Ready-to-use config for packages that need no customisation — matches
30
+ * `@theholocron/vitest-config`'s and `@theholocron/tsdown-config`'s existing
31
+ * `export default <preset>()` pattern. `eslint --config <path>` loads a
32
+ * file's *default* export as the flat config directly; a named-export-only
33
+ * file throws `ConfigError: Unexpected key "library" found` (ESLint treats
34
+ * the whole module namespace as the config when there's no default) —
35
+ * required for the resolver (config-resolution workstream, #676 in
36
+ * theholocron/holocron) to point `--config` straight at this file with zero
37
+ * committed local content.
38
+ *
39
+ * The explicit `Linter.Config[]` binding (rather than `export default
40
+ * library();` directly) works around TS2742 — declaration-emit can't
41
+ * portably name library()'s inferred return type without a reference to
42
+ * @eslint/core's internal types; an explicitly-typed intermediate avoids
43
+ * needing to re-infer it.
44
+ */
45
+ declare const resolvedLibrary: Linter.Config[];
3
46
  //#endregion
4
- export { library };
47
+ export { LibraryOptions, resolvedLibrary as default, library };
@@ -2,21 +2,59 @@ import { base } from "../configs/base.js";
2
2
  import { packageJson } from "../configs/package-json.js";
3
3
  import { typescript } from "../configs/typescript.js";
4
4
  import { node } from "../configs/node.js";
5
+ import { vitest as vitestConfig } from "../configs/vitest.js";
5
6
  //#region bundles/library.ts
6
- function library() {
7
+ /**
8
+ * Every 5-of-6 org repos' `eslint.config.ts` already reduces to `...library()`
9
+ * with no further composition once `base()`'s gitignore/docs-src absorption
10
+ * (#460) is in place — the sixth (`holocron` itself) only differs by also
11
+ * spreading `vitest()` at its root, which is safe to bake in unconditionally
12
+ * here: {@link vitest}'s config is glob-scoped to test/setup files, so it's a
13
+ * no-op anywhere it doesn't match, same reasoning as `docsSrcConfig`. Once
14
+ * every repo drops its now-redundant local composition (#680, the migration
15
+ * pass), `library()` alone — resolved via `eslint --config`, zero committed
16
+ * file — covers every repo but the `browserPackages` outlier, which keeps a
17
+ * tiny `export default library({ browserPackages: [...] })` (config-resolution
18
+ * workstream, #676 in theholocron/holocron).
19
+ */
20
+ function library(options = {}) {
7
21
  return [
8
22
  ...base(),
9
23
  ...node(),
10
24
  ...typescript(),
11
25
  ...packageJson(),
26
+ ...vitestConfig(),
12
27
  {
13
28
  name: "@theholocron/library",
14
29
  rules: {
15
30
  "n/hashbang": "off",
16
31
  "n/no-unpublished-import": "off"
17
32
  }
18
- }
33
+ },
34
+ ...options.browserPackages?.length ? [{
35
+ name: "@theholocron/library/browser-packages",
36
+ files: options.browserPackages.map((pkg) => `${pkg}/**`),
37
+ rules: { "n/no-unsupported-features/node-builtins": "off" }
38
+ }] : []
19
39
  ];
20
40
  }
41
+ /**
42
+ * Ready-to-use config for packages that need no customisation — matches
43
+ * `@theholocron/vitest-config`'s and `@theholocron/tsdown-config`'s existing
44
+ * `export default <preset>()` pattern. `eslint --config <path>` loads a
45
+ * file's *default* export as the flat config directly; a named-export-only
46
+ * file throws `ConfigError: Unexpected key "library" found` (ESLint treats
47
+ * the whole module namespace as the config when there's no default) —
48
+ * required for the resolver (config-resolution workstream, #676 in
49
+ * theholocron/holocron) to point `--config` straight at this file with zero
50
+ * committed local content.
51
+ *
52
+ * The explicit `Linter.Config[]` binding (rather than `export default
53
+ * library();` directly) works around TS2742 — declaration-emit can't
54
+ * portably name library()'s inferred return type without a reference to
55
+ * @eslint/core's internal types; an explicitly-typed intermediate avoids
56
+ * needing to re-infer it.
57
+ */
58
+ const resolvedLibrary = library();
21
59
  //#endregion
22
- export { library };
60
+ export { resolvedLibrary as default, library };
@@ -1,11 +1,11 @@
1
1
  import { base } from "../configs/base.js";
2
2
  import { packageJson } from "../configs/package-json.js";
3
3
  import { typescript } from "../configs/typescript.js";
4
+ import { vitest as vitestConfig } from "../configs/vitest.js";
4
5
  import { cypress as cypressConfig } from "../configs/cypress.js";
5
6
  import { next as nextConfig } from "../configs/next.js";
6
7
  import { react as reactConfig } from "../configs/react.js";
7
8
  import { storybook as storybookConfig } from "../configs/storybook.js";
8
- import { vitest as vitestConfig } from "../configs/vitest.js";
9
9
  //#region bundles/next-app.ts
10
10
  function nextApp() {
11
11
  return [
@@ -1,9 +1,9 @@
1
1
  import { base } from "../configs/base.js";
2
2
  import { packageJson } from "../configs/package-json.js";
3
3
  import { typescript } from "../configs/typescript.js";
4
+ import { vitest as vitestConfig } from "../configs/vitest.js";
4
5
  import { react as reactConfig } from "../configs/react.js";
5
6
  import { storybook as storybookConfig } from "../configs/storybook.js";
6
- import { vitest as vitestConfig } from "../configs/vitest.js";
7
7
  //#region bundles/react-app.ts
8
8
  function reactApp() {
9
9
  return [
@@ -1,9 +1,43 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { includeIgnoreFile } from "@eslint/compat";
1
4
  import js from "@eslint/js";
2
5
  import globals from "globals";
3
6
  import simpleImportSort from "eslint-plugin-simple-import-sort";
4
7
  //#region configs/base.ts
8
+ /**
9
+ * Ignore whatever the consuming repo's own .gitignore already ignores
10
+ * (dist/, coverage/, node_modules/, …) instead of every repo hand-maintaining
11
+ * its own `ignores:` array in eslint.config.ts. Resolved against
12
+ * process.cwd() — the repo root ESLint is actually invoked from, whether
13
+ * that's a committed eslint.config.ts re-exporting this bundle or a future
14
+ * `eslint --config <shared path>` invocation with no local file at all
15
+ * (config-resolution workstream, #676 in theholocron/holocron). A repo
16
+ * without a .gitignore (unusual, but not invalid) just gets no extra
17
+ * ignores from this — never throws.
18
+ */
19
+ function gitignoreConfig() {
20
+ const gitignorePath = join(process.cwd(), ".gitignore");
21
+ if (!existsSync(gitignorePath)) return void 0;
22
+ return includeIgnoreFile(gitignorePath, "@theholocron/gitignore");
23
+ }
24
+ /**
25
+ * docs/src imports resolve against the repo ROOT package.json (docs sites
26
+ * in this org are never their own workspace package — see clients/themes/
27
+ * utils/observability), so n/no-extraneous-import flags every import in
28
+ * that directory as a false positive. Scoped to a glob that simply matches
29
+ * nothing in a repo without a docs/src — safe to always include rather
30
+ * than opt into per repo.
31
+ */
32
+ const docsSrcConfig = {
33
+ name: "@theholocron/docs-src",
34
+ files: ["docs/src/**"],
35
+ rules: { "n/no-extraneous-import": "off" }
36
+ };
5
37
  function base() {
38
+ const gitignore = gitignoreConfig();
6
39
  return [
40
+ ...gitignore ? [gitignore] : [],
7
41
  {
8
42
  name: "@theholocron/base",
9
43
  languageOptions: { globals: {
@@ -19,7 +53,8 @@ function base() {
19
53
  "simple-import-sort/imports": "error",
20
54
  "simple-import-sort/exports": "error"
21
55
  }
22
- }
56
+ },
57
+ docsSrcConfig
23
58
  ];
24
59
  }
25
60
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/eslint-config",
3
- "version": "8.2.3",
3
+ "version": "8.4.2",
4
4
  "description": "A ESLint configuration for writing well-formed Javascript within the Galaxy.",
5
5
  "homepage": "https://github.com/theholocron/configs/tree/main/packages/eslint-config#readme",
6
6
  "bugs": "https://github.com/theholocron/configs/issues",
@@ -27,6 +27,7 @@
27
27
  },
28
28
  "devDependencies": {
29
29
  "@eslint/js": "^10.0.0",
30
+ "@theholocron/cli": "5.0.0-alpha.3",
30
31
  "@vitest/coverage-v8": "^4.1.10",
31
32
  "eslint-plugin-simple-import-sort": "^14.0.0",
32
33
  "globals": "^17.11.0",
@@ -34,8 +35,8 @@
34
35
  "typescript": "^5.9.3",
35
36
  "typescript-eslint": "^8.67.0",
36
37
  "vitest": "^4.1.10",
37
- "@theholocron/tsconfig": "8.2.3",
38
- "@theholocron/vitest-config": "8.2.3"
38
+ "@theholocron/tsconfig": "8.4.2",
39
+ "@theholocron/vitest-config": "8.4.2"
39
40
  },
40
41
  "exports": {
41
42
  ".": {
@@ -164,9 +165,10 @@
164
165
  "releases": "https://github.com/theholocron/configs/releases",
165
166
  "wiki": "https://github.com/theholocron/configs/wiki",
166
167
  "scripts": {
167
- "build": "tsdown",
168
- "typecheck": "tsc --noEmit",
169
- "test": "vitest run",
170
- "test:coverage": "vitest run --coverage"
168
+ "delivery.build": "tsdown",
169
+ "sourceQuality.staticAnalysis": "holocron run sourceQuality.staticAnalysis --",
170
+ "test:watch": "vitest",
171
+ "verification.typeSafety": "holocron run verification.typeSafety --",
172
+ "verification.unitTests": "holocron run verification.unitTests --"
171
173
  }
172
174
  }