@scayle/eslint-config-storefront 4.8.3-alpha.1 → 5.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,122 @@
1
1
  # @aboutyou/eslint-config-sfc
2
2
 
3
+ ## 5.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - `@scayle/eslint-config-storefront/v3` now wires an `eslint-import-resolver-typescript` resolver by default, pointed at the project's `tsconfig.json`. Path aliases like `@client/*` or `@server/*` resolve to real files, so `import-x/no-restricted-paths` and `import-x/no-cycle` see through them instead of only matching literal relative imports.
8
+
9
+ Two rules also newly cover ground they didn't before, both enabled for the first time rather than tightened:
10
+
11
+ - `import-x/order` wasn't configured anywhere in `/v3` until now. It ships at `error`, with an explicit `groups` option ranking aliased imports alongside package imports, ahead of relative ones. A project already using `/v3` may see new ordering errors on upgrade.
12
+ - `import-x/no-cycle` previously only saw `.js`/`.mjs`/`.cjs` files. `.ts` and `.tsx` are now included, so a circular dependency that only existed between TypeScript files, alias or not, is caught for the first time.
13
+
14
+ `resolver.tsconfigPath` points the resolver at a specific tsconfig, independent of `typescript.tsconfigPath` (which also switches on type-aware TypeScript rules). Without either set, the resolver and the `no-restricted-paths` zones fall back to resolving relative to ESLint's working directory, correct when linting runs via `pnpm lint`/CI but not guaranteed for an editor's ESLint extension. Set `resolver.tsconfigPath` to an absolute path if that matters for your setup.
15
+
16
+ ### Patch Changes
17
+
18
+ - Added dependency `eslint-import-resolver-typescript@^4.4.5`
19
+
20
+ ## 5.0.0
21
+
22
+ ### Major Changes
23
+
24
+ - Rebuilds the shared ESLint config directly on first-class plugins (`@eslint/js`, `typescript-eslint`, `eslint-plugin-n`, `eslint-plugin-jsonc`, `eslint-plugin-jsdoc`, `eslint-plugin-unicorn`, `eslint-plugin-regexp`, `@e18e/eslint-plugin`, `@eslint-community/eslint-plugin-eslint-comments`, `@vitest/eslint-plugin`) instead of wrapping `@antfu/eslint-config`. This drops the transitive dependency on framework-specific plugins (Vue, React, Astro, and others) this package never used, and makes every enabled rule visible directly in `config/`.
25
+
26
+ ## Breaking changes
27
+ - `eslintConfigStorefront({ isNuxt: true })` is replaced by a dedicated entry point: `import eslintConfigStorefrontNuxt from '@scayle/eslint-config-storefront/nuxt'`. `eslintConfigStorefront()` no longer accepts an `isNuxt` option. It always applies the framework-agnostic and JavaScript/TypeScript/JSDoc rule set.
28
+ - Rules keep each plugin's own published name instead of antfu's renamed aliases: `@typescript-eslint/*` (not `ts/*`), `vitest/*` (not `test/*` for Vitest-specific rules; `no-only-tests/*` is unchanged). Update any inline `eslint-disable` comment that references the old alias.
29
+ - `config/flat/` moved to `config/`. Flat config is the only supported mode, so the `flat/` segment was redundant. If your project imported anything from `@scayle/eslint-config-storefront/config/flat/*` directly, update the import path.
30
+ - `@typescript-eslint/consistent-type-imports` now allows `import('mod').Type` inline type annotations (`disallowTypeAnnotations: false`), matching common TypeScript usage the previous rule severity silently never reached under the old rule composition.
31
+ - The `eslint` peer dependency floor moves from `>=9.0.0` to `>=10.4.0`, matching what `eslint-plugin-unicorn@73` actually requires. An ESLint 9 project installed this package cleanly before but hit unmet peer warnings from the plugins themselves. Upgrade ESLint to 10.4 or later before upgrading this package.
32
+
33
+ ## New rule sets
34
+
35
+ Three additions widen the default coverage. Each is on by default in both `eslintConfigStorefront()` and `eslintConfigStorefrontNuxt()`, and each can surface new findings in an existing project on upgrade:
36
+
37
+ - **`eslint-plugin-unicorn`**: a curated subset of modernization rules (not the plugin's full `recommended` preset, which is hundreds of rules and largely stylistic). Covers things like preferring `node:`-prefixed core imports, `Array.isArray` over `instanceof Array`, and `Number.isNaN` over the global `isNaN`.
38
+ - **`eslint-plugin-regexp`**: the plugin's own `flat/recommended` preset. Flags unsafe or redundant regex patterns, including some that can cause catastrophic backtracking.
39
+ - **`@e18e/eslint-plugin`**: the [e18e](https://e18e.dev) community's `recommended` preset (modernization, module-replacement, and performance rules), with every rule downgraded to `warn`. The plugin is pre-1.0, and its rule set hasn't been reviewed against every consuming project yet, so findings surface without failing CI. Includes `ban-dependencies`, which flags known heavier packages with a lighter recommended alternative (for example `ora` in favor of `nanospinner`). Treat a `ban-dependencies` finding as a suggestion to evaluate, not a required change: swapping a dependency is a real decision with its own testing burden, not a lint fix.
40
+
41
+ ## Upgrading
42
+ 1. Run `eslint .` after upgrading. Fix or explicitly suppress any new finding before merging.
43
+ 2. If your project used `eslintConfigStorefront({ isNuxt: true })`, switch to the `/nuxt` entry point:
44
+
45
+ ```js
46
+ // Before
47
+ import eslintConfigStorefront from '@scayle/eslint-config-storefront'
48
+ export default eslintConfigStorefront({ isNuxt: true })
49
+
50
+ // After
51
+ import eslintConfigStorefrontNuxt from '@scayle/eslint-config-storefront/nuxt'
52
+ export default eslintConfigStorefrontNuxt()
53
+ ```
54
+
55
+ 3. Search your project for any inline rule reference using an antfu alias (`ts/`, `test/` for Vitest rules) and update it to the plugin's real prefix (`@typescript-eslint/`, `vitest/`).
56
+
57
+ - Adds `@scayle/eslint-config-storefront/v3`, a third entry point for the Storefront Application V3 stack (Hono, Inertia.js, Vue 3, not Nuxt). It builds on the default config and adds Vue language wiring, Vue rules, accessibility rules, `vue-i18n` linting, `@scayle/vue-composable` rules, Storybook file conventions, Tailwind CSS class validation, and `vue/block-order` enforcement.
58
+
59
+ ## Breaking changes
60
+ - The named exports `eslintConfigStorefront` and `eslintConfigStorefrontNuxt` are now `storefront` and `storefrontNuxt`. Neither name, nor the `./nuxt` entry point itself, shipped in a published release before this change, so this only affects code already on this pre-release. Default exports are unaffected:
61
+
62
+ ```js
63
+ // Before
64
+ import { eslintConfigStorefront } from '@scayle/eslint-config-storefront'
65
+
66
+ // After
67
+ import { storefront } from '@scayle/eslint-config-storefront'
68
+ ```
69
+
70
+ - `vue/block-order` is now enforced at error severity on `./v3`, with `template` before `script` before `style`. `eslint-plugin-vue`'s own `recommended` default only warns and defaults to script-first. Any `.vue` file with a script or style block ahead of its template now fails lint. Run `eslint --fix` to reorder them; the fix is purely mechanical and doesn't change behavior.
71
+
72
+ ## New entry point
73
+
74
+ `@scayle/eslint-config-storefront/v3` takes required `tailwind.entryPoint` and `i18n.localeDir` options, since the underlying plugins can't validate Tailwind classes or i18n keys without a real path. Optional options cover a shop's own custom elements, dynamically-used i18n keys, and fallthrough-attribute exceptions:
75
+
76
+ ```js
77
+ // eslint.config.mjs
78
+ import storefrontV3 from '@scayle/eslint-config-storefront/v3'
79
+
80
+ export default storefrontV3({
81
+ tailwind: {
82
+ entryPoint: './src/client/index.css',
83
+ },
84
+ i18n: {
85
+ localeDir: './src/i18n/locales/*.json',
86
+ },
87
+ })
88
+ ```
89
+
90
+ Named `v3`, not `vue`, since a future non-Vue Storefront Application V3 stack would extend this same entry point rather than needing a separate one.
91
+
92
+ ### Patch Changes
93
+
94
+ - Added dependency `@e18e/eslint-plugin@^0.8.0`
95
+ - Added dependency `@eslint-community/eslint-plugin-eslint-comments@^4.7.2`
96
+ - Added dependency `@eslint/js@^10.0.0`
97
+ - Added dependency `@intlify/eslint-plugin-vue-i18n@^4.5.1`
98
+ - Added dependency `@scayle/eslint-plugin-vue-composable@workspace:*`
99
+ - Added dependency `@vitest/eslint-plugin@^1.6.20`
100
+ - Added dependency `eslint-plugin-better-tailwindcss@^4.7.0`
101
+ - Added dependency `eslint-plugin-jsdoc@^64.2.1`
102
+ - Added dependency `eslint-plugin-jsonc@^3.4.1`
103
+ - Added dependency `eslint-plugin-n@^18.3.0`
104
+ - Added dependency `eslint-plugin-no-only-tests@^3.4.0`
105
+ - Added dependency `eslint-plugin-regexp@^3.2.0`
106
+ - Added dependency `eslint-plugin-storybook@^10.5.8`
107
+ - Added dependency `eslint-plugin-unicorn@^73.0.0`
108
+ - Added dependency `eslint-plugin-vue@^10.10.0`
109
+ - Added dependency `eslint-plugin-vuejs-accessibility@^2.6.0`
110
+ - Added dependency `globals@^17.7.0`
111
+ - Added dependency `vue-eslint-parser@^10.4.1`
112
+ - Removed dependency `@antfu/eslint-config@^9.0.0`
113
+ - Removed dependency `@eslint/eslintrc@^3.3.5`
114
+ - Removed dependency `local-pkg@^1.2.1`
115
+ - Updated dependency `eslint-config-flat-gitignore@^2.2.0` to `eslint-config-flat-gitignore@^2.3.0`
116
+ - Updated dependency `eslint-plugin-import-x@^4.16.2` to `eslint-plugin-import-x@^4.17.1`
117
+ - Updated dependency `eslint-plugin-sonarjs@^4.0.3` to `eslint-plugin-sonarjs@^4.2.0`
118
+ - Updated dependency `typescript-eslint@8.67.0` to `typescript-eslint@^8.67.0`
119
+
3
120
  ## 4.8.3-alpha.1
4
121
 
5
122
  ### Patch Changes
package/README.md CHANGED
@@ -3,11 +3,10 @@
3
3
  A [shared `eslint` config](https://eslint.org/docs/latest/extend/shareable-configs#creating-a-shareable-config) for SCAYLE Storefront projects and packages.
4
4
  Provides SCAYLE-specific `eslint` configuration for Frontend and Node.js projects using TypeScript.
5
5
 
6
- We migrated to `eslint@9` and [ESLint Flat config](https://eslint.org/docs/latest/use/configure/configuration-files), to provide improved organization and composition.
6
+ Flat config only ([ESLint 10.4+](https://eslint.org/docs/latest/use/configure/configuration-files)). Built directly on first-class plugins (`@eslint/js`, `typescript-eslint`, `eslint-plugin-n`, `eslint-plugin-jsonc`, `eslint-plugin-jsdoc`, `eslint-plugin-unicorn`, `eslint-plugin-regexp`, `@e18e/eslint-plugin`, and others) with no shared-config aggregator dependency.
7
7
 
8
8
  Should you require support for `eslint@8`, please use `@scayle/eslint-config-storefront@3`.
9
9
 
10
- - Partially based on [@antfu/eslint-config](https://github.com/antfu/eslint-config)
11
10
  - [Official ESLint Documentation](https://eslint.org/docs/latest/)
12
11
 
13
12
  ---
@@ -24,11 +23,86 @@ And create a `eslint.config.mjs` in your project root:
24
23
 
25
24
  ```js
26
25
  // eslint.config.mjs
27
- import eslintConfigStorefront from '@scayle/eslint-config-storefront'
26
+ import storefront from '@scayle/eslint-config-storefront'
28
27
 
29
- export default eslintConfigStorefront()
28
+ export default storefront()
30
29
  ```
31
30
 
31
+ ### Nuxt projects
32
+
33
+ Nuxt projects already get JavaScript, TypeScript, JSDoc, and import rules from
34
+ [`@nuxt/eslint`](https://eslint.nuxt.com/). Use the `/nuxt` entry point instead, which
35
+ only adds the framework-agnostic rules (comments hygiene, Node.js, JSON/JSONC, test-file
36
+ conventions, SonarJS, Promise usage, modernization, and regex safety):
37
+
38
+ ```js
39
+ // eslint.config.mjs
40
+ import storefrontNuxt from '@scayle/eslint-config-storefront/nuxt'
41
+ import withNuxt from './.nuxt/eslint.config.mjs'
42
+
43
+ export default withNuxt(storefrontNuxt())
44
+ ```
45
+
46
+ ### Storefront Application V3 projects
47
+
48
+ The Storefront Application V3 stack (Hono + Inertia.js + Vue 3, not Nuxt) should use the
49
+ `/v3` entry point. It builds on the default config and adds Vue language wiring, Vue rules,
50
+ accessibility rules, `vue-i18n` linting, `@scayle/vue-composable` rules, Storybook file
51
+ conventions, Tailwind CSS class validation, and a TypeScript-aware import resolver:
52
+
53
+ ```js
54
+ // eslint.config.mjs
55
+ import storefrontV3 from '@scayle/eslint-config-storefront/v3'
56
+
57
+ export default storefrontV3({
58
+ tailwind: {
59
+ entryPoint: './src/client/index.css',
60
+ },
61
+ i18n: {
62
+ localeDir: './src/i18n/locales/*.json',
63
+ },
64
+ })
65
+ ```
66
+
67
+ `tailwind.entryPoint` and `i18n.localeDir` are required, the underlying plugins can't
68
+ validate Tailwind classes or i18n keys without a real path. Optional options:
69
+
70
+ - `typescript.tsconfigPath`: absolute path to a `tsconfig.json`. Enables type-aware
71
+ TypeScript rules and points the import resolver at that file instead of
72
+ `<root>/tsconfig.json`
73
+ - `resolver.tsconfigPath`: absolute path to a `tsconfig.json` for the import resolver only,
74
+ independent of `typescript.tsconfigPath`. Use this instead when you want the resolver
75
+ fix below without also switching on type-aware TypeScript rules
76
+ - `i18n.messageSyntaxVersion`: `vue-i18n` message syntax version, defaults to `^11.2.8`
77
+ - `i18n.unusedKeyIgnores`: regex-string patterns for translation keys used dynamically in code
78
+ - `vue.undefComponentIgnores`: custom element (web component) tag names to exempt from `vue/no-undef-components`
79
+ - `vueComposable.fallthroughAttrsIgnores`: path fragments to exempt from `require-explicit-fallthrough-attrs` (e.g. router-mounted page/layout roots that never receive fallthrough attributes)
80
+
81
+ #### Import resolution
82
+
83
+ `/v3` wires `eslint-import-resolver-typescript`, so `import-x` rules resolve `tsconfig.json`
84
+ path aliases (`@client/*`, `@server/*`, or any other `paths` entry) to their real files
85
+ instead of only matching literal relative imports. Three rules depend on that resolution
86
+ to work correctly against an aliased import:
87
+
88
+ - `import-x/no-restricted-paths`: zone violations across an alias fail lint, not just
89
+ across a relative path
90
+ - `import-x/no-cycle`: circular dependencies through an aliased import are caught. `.vue`
91
+ files are the one exception, a cycle through a `.vue` file only surfaces when ESLint
92
+ lints that file directly
93
+ - `import-x/order`: aliased imports rank alongside package imports (`external`), ahead of
94
+ relative ones, instead of dropping to last place once the resolver can see they resolve
95
+ to a project file
96
+
97
+ Without `resolver.tsconfigPath` or `typescript.tsconfigPath` set, both the resolver and
98
+ `import-x/no-restricted-paths`'s zones resolve relative to ESLint's own working directory.
99
+ That's correct for `pnpm lint` and CI, since a monorepo's task runner always runs a
100
+ package's lint script with that package as the working directory, but not guaranteed for
101
+ an editor's ESLint extension, which can run with the workspace root as its working
102
+ directory instead. Set `resolver.tsconfigPath` to an absolute path (for example,
103
+ `new URL('./tsconfig.json', import.meta.url).pathname` in your `eslint.config.mjs`) if your
104
+ editor's linting needs to match the command-line result.
105
+
32
106
  ### Add script for package.json
33
107
 
34
108
  For example:
@@ -77,66 +151,75 @@ Add the following settings to your `.vscode/settings.json`:
77
151
 
78
152
  ## Customization
79
153
 
80
- ### Provides shared configurations
81
-
82
- #### Default config / `@scayle/eslint-config-storefront`
83
-
84
- Normally you only need to import the antfu preset:
154
+ ### Default config / `@scayle/eslint-config-storefront`
85
155
 
86
156
  ```js
87
157
  // eslint.config.mjs
88
- import eslintConfigStorefront from '@scayle/eslint-config-storefront'
158
+ import storefront from '@scayle/eslint-config-storefront'
89
159
 
90
- export default eslintConfigStorefront()
160
+ export default storefront({
161
+ typescript: {
162
+ // Enables type-aware rules for the given tsconfig
163
+ tsconfigPath: 'path/to/tsconfig.json',
164
+ },
165
+ })
91
166
  ```
92
167
 
93
- ### Extended Configuration
168
+ ### Nuxt config / `@scayle/eslint-config-storefront/nuxt`
94
169
 
95
170
  ```js
96
171
  // eslint.config.mjs
97
- import eslintConfigStorefront from '@scayle/eslint-config-storefront'
172
+ import storefrontNuxt from '@scayle/eslint-config-storefront/nuxt'
98
173
 
99
- export default eslintConfigStorefront({
100
- // If set to `true` removes all rule configurations
101
- // that are provided by the `@nuxt/eslint` package
102
- isNuxt: true, // Default via auto-detection of package `@nuxt/eslint`
174
+ export default storefrontNuxt()
175
+ ```
103
176
 
104
- // If set to `true` adds `eslint-plugin-tailwind`
105
- isTailwind: true, // Default via auto-detection of package `eslint-plugin-tailwind`
177
+ ### Storefront Application V3 config / `@scayle/eslint-config-storefront/v3`
106
178
 
107
- typescript: {
108
- // Enables type-aware rules
109
- // Only works if `isNuxt` is `false`!
110
- // <https://github.com/antfu/eslint-config?tab=readme-ov-file#type-aware-rules>
111
- tsconfigPath: 'path/to/tsconfig.ts',
112
- },
113
- })
114
- ```
179
+ See [Storefront Application V3 projects](#storefront-application-v3-projects) above for the full option list.
180
+
181
+ All three entry points return a [`FlatConfigComposer`](https://github.com/antfu/eslint-flat-config-utils),
182
+ so you can chain `.append(...)`, `.prepend(...)`, `.override(...)`, or `.renamePlugins(...)` to layer
183
+ project-specific rules on top.
184
+
185
+ ### Plugin names
115
186
 
116
- ### Plugins Renaming
187
+ Rules use each plugin's own published name (`@typescript-eslint/*`, `import-x/*`, `jsonc/*`,
188
+ `jsdoc/*`, `node/*`, `promise/*`, `sonarjs/*`, `unicorn/*`, `regexp/*`, `e18e/*`, `vitest/*`,
189
+ `eslint-comments/*`). There's no alias renaming. When you override or disable a rule inline,
190
+ use that plugin's real prefix:
117
191
 
118
- Since flat config requires us to explicitly provide the plugin names (instead of the mandatory convention from npm package name), we renamed some plugins to make the overall scope more consistent and easier to write.
192
+ ```js
193
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
194
+ type Foo = { bar: 2 }
195
+ ```
119
196
 
120
- | New Prefix | Original Prefix | Source Plugin |
121
- | ---------- | ---------------------- | ------------------------------------------------------------------------------------------ |
122
- | `import/*` | `import-x/*` | [eslint-plugin-import-x](https://github.com/un-es/eslint-plugin-import-x) |
123
- | `node/*` | `n/*` | [eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n) |
124
- | `yaml/*` | `yml/*` | [eslint-plugin-yml](https://github.com/ota-meshi/eslint-plugin-yml) |
125
- | `ts/*` | `@typescript-eslint/*` | [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint) |
126
- | `test/*` | `vitest/*` | [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest) |
127
- | `test/*` | `no-only-tests/*` | [eslint-plugin-no-only-tests](https://github.com/levibuzolic/eslint-plugin-no-only-tests) |
197
+ ### `e18e/*` rules ship as warnings
128
198
 
129
- When you want to override rules, or disable them inline, you need to update to the new prefix:
199
+ The [e18e](https://e18e.dev) community's rule set (modernization, module-replacement, and
200
+ performance rules) is enabled by default, but every `e18e/*` rule ships at `warn`, not `error`.
201
+ The plugin is still pre-1.0, and its rule set hasn't been reviewed against every consuming
202
+ project. A warning won't fail your build.
130
203
 
131
- ```diff
132
- -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
133
- +// eslint-disable-next-line ts/consistent-type-definitions
134
- type foo = { bar: 2 }
204
+ One rule worth knowing about specifically: `e18e/ban-dependencies` flags a dependency in your
205
+ project that has a lighter recommended alternative (for example `ora` in favor of
206
+ `nanospinner`). Treat that finding as something to evaluate, not something to fix immediately.
207
+ Swapping a dependency is a real decision with its own testing cost, not a lint fix. If you've
208
+ decided to keep a flagged dependency, allowlist it explicitly rather than turning the rule off:
209
+
210
+ ```js
211
+ export default storefront().append({
212
+ rules: {
213
+ 'e18e/ban-dependencies': ['warn', { allowed: ['ora'] }],
214
+ },
215
+ })
135
216
  ```
136
217
 
137
218
  ## View what rules are enabled
138
219
 
139
- [Anthony Fu](https://github.com/antfu) built a visual tool to help you view what rules are enabled in your project and apply them to what files, [@eslint/config-inspector](https://github.com/eslint/config-inspector).
220
+ [@eslint/config-inspector](https://github.com/eslint/config-inspector) is a visual tool maintained
221
+ by the ESLint core team to help you view what rules are enabled in your project and which files
222
+ they apply to.
140
223
 
141
224
  Go into your project root that contains eslint.config.js and run:
142
225
 
@@ -0,0 +1,46 @@
1
+ // Build artifacts, lockfiles, and tooling caches that no project should lint.
2
+ export const GLOB_EXCLUDE = [
3
+ '**/node_modules',
4
+ '**/dist',
5
+ '**/package-lock.json',
6
+ '**/yarn.lock',
7
+ '**/pnpm-lock.yaml',
8
+ '**/bun.lockb',
9
+ '**/output',
10
+ '**/coverage',
11
+ '**/playwright-report',
12
+ '**/test-results',
13
+ '**/temp',
14
+ '**/.temp',
15
+ '**/tmp',
16
+ '**/.tmp',
17
+ '**/.history',
18
+ '**/.vitepress/cache',
19
+ '**/.nuxt',
20
+ '**/.next',
21
+ '**/.svelte-kit',
22
+ '**/.vercel',
23
+ '**/.changeset',
24
+ '**/.idea',
25
+ '**/.cache',
26
+ '**/.output',
27
+ '**/.vite-inspect',
28
+ '**/.yarn',
29
+ '**/CHANGELOG*.md',
30
+ '**/LICENSE*',
31
+ '**/*.min.*',
32
+ '**/__snapshots__',
33
+ '**/vite.config.*.timestamp-*',
34
+ '**/auto-import?(s).d.ts',
35
+ '**/components.d.ts',
36
+ ]
37
+
38
+ /** @returns {import('eslint').Linter.Config[]} Flat config entries excluding build artifacts and tooling caches from linting. */
39
+ export function ignoresConfig() {
40
+ return [
41
+ {
42
+ name: 'storefront/ignores',
43
+ ignores: GLOB_EXCLUDE,
44
+ },
45
+ ]
46
+ }
@@ -0,0 +1,129 @@
1
+ import { FlatConfigComposer } from 'eslint-flat-config-utils'
2
+ import gitignore from 'eslint-config-flat-gitignore'
3
+ import {
4
+ commentsConfig,
5
+ nodeConfig,
6
+ jsoncConfig,
7
+ sonarjsConfig,
8
+ promiseConfig,
9
+ importXConfig,
10
+ jsdocConfig,
11
+ regexpConfig,
12
+ e18eConfig,
13
+ } from './rules.mjs'
14
+ import { testConfig, GLOB_TESTS } from './test.mjs'
15
+ import { ignoresConfig } from './ignores.mjs'
16
+ import { javascriptConfig } from './javascript.mjs'
17
+ import { typescriptConfig } from './typescript.mjs'
18
+ import { unicornConfig } from './unicorn.mjs'
19
+
20
+ /** @type {import('eslint').Linter.RuleEntry} */
21
+ const CURLY_RULE = ['error', 'all']
22
+
23
+ /** @type {import('eslint').Linter.RulesRecord} */
24
+ const GLOBAL_RULES = {
25
+ curly: CURLY_RULE,
26
+ 'node/prefer-global/process': 'off',
27
+ }
28
+
29
+ /** @type {import('eslint').Linter.RulesRecord} */
30
+ const TEST_RULES = {
31
+ 'no-console': 'off',
32
+ '@typescript-eslint/no-explicit-any': 'off',
33
+ 'promise/avoid-new': 'off',
34
+ }
35
+
36
+ const IGNORE_PATTERNS = ['**/fixtures/**/*', '**/*.jsonc']
37
+
38
+ /**
39
+ * @typedef {object} EslintConfigStorefrontOptions
40
+ * @property {object} [typescript] Options forwarded to `typescriptConfig`.
41
+ * @property {string} [typescript.tsconfigPath] Enables type-aware TypeScript rules when set.
42
+ */
43
+
44
+ // Rules shared by every project regardless of framework: comments hygiene, Node.js,
45
+ // JSON/JSONC, test-file conventions, SonarJS, Promise usage, modernization (unicorn,
46
+ // e18e), and regex safety.
47
+ function baseConfigs() {
48
+ return [
49
+ ...commentsConfig(),
50
+ ...nodeConfig(),
51
+ ...jsoncConfig(),
52
+ ...testConfig(),
53
+ ...sonarjsConfig(),
54
+ ...promiseConfig(),
55
+ ...unicornConfig(),
56
+ ...e18eConfig(),
57
+ ...regexpConfig(),
58
+ ]
59
+ }
60
+
61
+ // Global and test-file overrides. Flat config is last-match-wins, so these must be
62
+ // appended after typescriptConfig() (and, on the base entry point, javascriptConfig()
63
+ // and jsdocConfig()) on both entry points, not folded into baseConfigs(): otherwise a
64
+ // rule these set (e.g. @typescript-eslint/no-explicit-any: 'off' for test files) gets
65
+ // re-enabled by a later config with the same rule key for the same files.
66
+ function overrideConfigs() {
67
+ return [
68
+ {
69
+ rules: GLOBAL_RULES,
70
+ ignores: [IGNORE_PATTERNS[0]],
71
+ },
72
+ {
73
+ files: GLOB_TESTS,
74
+ rules: TEST_RULES,
75
+ },
76
+ { ignores: [IGNORE_PATTERNS[1]] },
77
+ ]
78
+ }
79
+
80
+ /**
81
+ * Builds the SCAYLE Storefront ESLint flat config for a framework-agnostic or
82
+ * plain TypeScript project. Nuxt projects should use
83
+ * `@scayle/eslint-config-storefront/nuxt` instead, since `@nuxt/eslint` already
84
+ * covers JavaScript, TypeScript, JSDoc, and import rules.
85
+ *
86
+ * @param {EslintConfigStorefrontOptions} [config]
87
+ * @returns {FlatConfigComposer<import('eslint').Linter.Config, never>} Returns a FlatConfigComposer object to be consumed in projects eslint.config.mjs files
88
+ */
89
+ export const storefront = function (config = {}) {
90
+ /** @type {FlatConfigComposer<import('eslint').Linter.Config, never>} */
91
+ const flatConfigComposer = new FlatConfigComposer()
92
+
93
+ const configs = [
94
+ ...baseConfigs(),
95
+ gitignore({ strict: false }),
96
+ ...ignoresConfig(),
97
+ ...importXConfig(),
98
+ ...javascriptConfig(),
99
+ ...typescriptConfig(config.typescript),
100
+ ...jsdocConfig(),
101
+ // Set tsconfigRootDir for all TypeScript files to support monorepo structure
102
+ // This ensures ESLint uses the correct tsconfig.json when multiple exist
103
+ {
104
+ files: ['**/*.mjs', '**/*.cjs', '**/*.ts', '**/*.tsx'],
105
+ languageOptions: {
106
+ parserOptions: {
107
+ tsconfigRootDir: process.cwd(),
108
+ },
109
+ },
110
+ },
111
+ ...overrideConfigs(),
112
+ ]
113
+
114
+ return flatConfigComposer.append(...configs)
115
+ }
116
+
117
+ /**
118
+ * Builds the SCAYLE Storefront ESLint flat config for a Nuxt project. Omits
119
+ * JavaScript, TypeScript, JSDoc, ignores, and import rules, since `@nuxt/eslint`
120
+ * already provides those for a Nuxt project.
121
+ *
122
+ * @returns {FlatConfigComposer<import('eslint').Linter.Config, never>} Returns a FlatConfigComposer object to be consumed in projects eslint.config.mjs files
123
+ */
124
+ export const storefrontNuxt = function () {
125
+ /** @type {FlatConfigComposer<import('eslint').Linter.Config, never>} */
126
+ const flatConfigComposer = new FlatConfigComposer()
127
+
128
+ return flatConfigComposer.append(...baseConfigs(), ...overrideConfigs())
129
+ }