@scayle/eslint-config-storefront 4.8.3-alpha.1 → 5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,105 @@
1
1
  # @aboutyou/eslint-config-sfc
2
2
 
3
+ ## 5.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 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/`.
8
+
9
+ ## Breaking changes
10
+ - `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.
11
+ - 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.
12
+ - `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.
13
+ - `@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.
14
+ - 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.
15
+
16
+ ## New rule sets
17
+
18
+ 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:
19
+
20
+ - **`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`.
21
+ - **`eslint-plugin-regexp`**: the plugin's own `flat/recommended` preset. Flags unsafe or redundant regex patterns, including some that can cause catastrophic backtracking.
22
+ - **`@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.
23
+
24
+ ## Upgrading
25
+ 1. Run `eslint .` after upgrading. Fix or explicitly suppress any new finding before merging.
26
+ 2. If your project used `eslintConfigStorefront({ isNuxt: true })`, switch to the `/nuxt` entry point:
27
+
28
+ ```js
29
+ // Before
30
+ import eslintConfigStorefront from '@scayle/eslint-config-storefront'
31
+ export default eslintConfigStorefront({ isNuxt: true })
32
+
33
+ // After
34
+ import eslintConfigStorefrontNuxt from '@scayle/eslint-config-storefront/nuxt'
35
+ export default eslintConfigStorefrontNuxt()
36
+ ```
37
+
38
+ 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/`).
39
+
40
+ - 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.
41
+
42
+ ## Breaking changes
43
+ - 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:
44
+
45
+ ```js
46
+ // Before
47
+ import { eslintConfigStorefront } from '@scayle/eslint-config-storefront'
48
+
49
+ // After
50
+ import { storefront } from '@scayle/eslint-config-storefront'
51
+ ```
52
+
53
+ - `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.
54
+
55
+ ## New entry point
56
+
57
+ `@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:
58
+
59
+ ```js
60
+ // eslint.config.mjs
61
+ import storefrontV3 from '@scayle/eslint-config-storefront/v3'
62
+
63
+ export default storefrontV3({
64
+ tailwind: {
65
+ entryPoint: './src/client/index.css',
66
+ },
67
+ i18n: {
68
+ localeDir: './src/i18n/locales/*.json',
69
+ },
70
+ })
71
+ ```
72
+
73
+ 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.
74
+
75
+ ### Patch Changes
76
+
77
+ - Added dependency `@e18e/eslint-plugin@^0.8.0`
78
+ - Added dependency `@eslint-community/eslint-plugin-eslint-comments@^4.7.2`
79
+ - Added dependency `@eslint/js@^10.0.0`
80
+ - Added dependency `@intlify/eslint-plugin-vue-i18n@^4.5.1`
81
+ - Added dependency `@scayle/eslint-plugin-vue-composable@workspace:*`
82
+ - Added dependency `@vitest/eslint-plugin@^1.6.20`
83
+ - Added dependency `eslint-plugin-better-tailwindcss@^4.7.0`
84
+ - Added dependency `eslint-plugin-jsdoc@^64.2.1`
85
+ - Added dependency `eslint-plugin-jsonc@^3.4.1`
86
+ - Added dependency `eslint-plugin-n@^18.3.0`
87
+ - Added dependency `eslint-plugin-no-only-tests@^3.4.0`
88
+ - Added dependency `eslint-plugin-regexp@^3.2.0`
89
+ - Added dependency `eslint-plugin-storybook@^10.5.8`
90
+ - Added dependency `eslint-plugin-unicorn@^73.0.0`
91
+ - Added dependency `eslint-plugin-vue@^10.10.0`
92
+ - Added dependency `eslint-plugin-vuejs-accessibility@^2.6.0`
93
+ - Added dependency `globals@^17.7.0`
94
+ - Added dependency `vue-eslint-parser@^10.4.1`
95
+ - Removed dependency `@antfu/eslint-config@^9.0.0`
96
+ - Removed dependency `@eslint/eslintrc@^3.3.5`
97
+ - Removed dependency `local-pkg@^1.2.1`
98
+ - Updated dependency `eslint-config-flat-gitignore@^2.2.0` to `eslint-config-flat-gitignore@^2.3.0`
99
+ - Updated dependency `eslint-plugin-import-x@^4.16.2` to `eslint-plugin-import-x@^4.17.1`
100
+ - Updated dependency `eslint-plugin-sonarjs@^4.0.3` to `eslint-plugin-sonarjs@^4.2.0`
101
+ - Updated dependency `typescript-eslint@8.67.0` to `typescript-eslint@^8.67.0`
102
+
3
103
  ## 4.8.3-alpha.1
4
104
 
5
105
  ### 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,54 @@ 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, and Tailwind CSS class validation:
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
+ - `i18n.unusedKeyIgnores`: regex-string patterns for translation keys used dynamically in code
71
+ - `vue.undefComponentIgnores`: custom element (web component) tag names to exempt from `vue/no-undef-components`
72
+ - `vueComposable.fallthroughAttrsIgnores`: path fragments to exempt from `require-explicit-fallthrough-attrs` (e.g. router-mounted page/layout roots that never receive fallthrough attributes)
73
+
32
74
  ### Add script for package.json
33
75
 
34
76
  For example:
@@ -77,66 +119,75 @@ Add the following settings to your `.vscode/settings.json`:
77
119
 
78
120
  ## Customization
79
121
 
80
- ### Provides shared configurations
81
-
82
- #### Default config / `@scayle/eslint-config-storefront`
83
-
84
- Normally you only need to import the antfu preset:
122
+ ### Default config / `@scayle/eslint-config-storefront`
85
123
 
86
124
  ```js
87
125
  // eslint.config.mjs
88
- import eslintConfigStorefront from '@scayle/eslint-config-storefront'
126
+ import storefront from '@scayle/eslint-config-storefront'
89
127
 
90
- export default eslintConfigStorefront()
128
+ export default storefront({
129
+ typescript: {
130
+ // Enables type-aware rules for the given tsconfig
131
+ tsconfigPath: 'path/to/tsconfig.json',
132
+ },
133
+ })
91
134
  ```
92
135
 
93
- ### Extended Configuration
136
+ ### Nuxt config / `@scayle/eslint-config-storefront/nuxt`
94
137
 
95
138
  ```js
96
139
  // eslint.config.mjs
97
- import eslintConfigStorefront from '@scayle/eslint-config-storefront'
140
+ import storefrontNuxt from '@scayle/eslint-config-storefront/nuxt'
98
141
 
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`
142
+ export default storefrontNuxt()
143
+ ```
103
144
 
104
- // If set to `true` adds `eslint-plugin-tailwind`
105
- isTailwind: true, // Default via auto-detection of package `eslint-plugin-tailwind`
145
+ ### Storefront Application V3 config / `@scayle/eslint-config-storefront/v3`
106
146
 
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
- ```
147
+ See [Storefront Application V3 projects](#storefront-application-v3-projects) above for the full option list.
148
+
149
+ All three entry points return a [`FlatConfigComposer`](https://github.com/antfu/eslint-flat-config-utils),
150
+ so you can chain `.append(...)`, `.prepend(...)`, `.override(...)`, or `.renamePlugins(...)` to layer
151
+ project-specific rules on top.
152
+
153
+ ### Plugin names
115
154
 
116
- ### Plugins Renaming
155
+ Rules use each plugin's own published name (`@typescript-eslint/*`, `import-x/*`, `jsonc/*`,
156
+ `jsdoc/*`, `node/*`, `promise/*`, `sonarjs/*`, `unicorn/*`, `regexp/*`, `e18e/*`, `vitest/*`,
157
+ `eslint-comments/*`). There's no alias renaming. When you override or disable a rule inline,
158
+ use that plugin's real prefix:
117
159
 
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.
160
+ ```js
161
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
162
+ type Foo = { bar: 2 }
163
+ ```
119
164
 
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) |
165
+ ### `e18e/*` rules ship as warnings
128
166
 
129
- When you want to override rules, or disable them inline, you need to update to the new prefix:
167
+ The [e18e](https://e18e.dev) community's rule set (modernization, module-replacement, and
168
+ performance rules) is enabled by default, but every `e18e/*` rule ships at `warn`, not `error`.
169
+ The plugin is still pre-1.0, and its rule set hasn't been reviewed against every consuming
170
+ project. A warning won't fail your build.
130
171
 
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 }
172
+ One rule worth knowing about specifically: `e18e/ban-dependencies` flags a dependency in your
173
+ project that has a lighter recommended alternative (for example `ora` in favor of
174
+ `nanospinner`). Treat that finding as something to evaluate, not something to fix immediately.
175
+ Swapping a dependency is a real decision with its own testing cost, not a lint fix. If you've
176
+ decided to keep a flagged dependency, allowlist it explicitly rather than turning the rule off:
177
+
178
+ ```js
179
+ export default storefront().append({
180
+ rules: {
181
+ 'e18e/ban-dependencies': ['warn', { allowed: ['ora'] }],
182
+ },
183
+ })
135
184
  ```
136
185
 
137
186
  ## View what rules are enabled
138
187
 
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).
188
+ [@eslint/config-inspector](https://github.com/eslint/config-inspector) is a visual tool maintained
189
+ by the ESLint core team to help you view what rules are enabled in your project and which files
190
+ they apply to.
140
191
 
141
192
  Go into your project root that contains eslint.config.js and run:
142
193
 
@@ -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
+ }
@@ -0,0 +1,159 @@
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+
4
+ // Core JavaScript correctness rules, plus a handful of Storefront-specific overrides
5
+ // on top of `@eslint/js`'s `recommended` preset.
6
+ /** @returns {import('eslint').Linter.Config[]} Flat config entries for core JavaScript correctness rules. */
7
+ export function javascriptConfig() {
8
+ return [
9
+ {
10
+ name: 'storefront/javascript/setup',
11
+ languageOptions: {
12
+ ecmaVersion: 'latest',
13
+ sourceType: 'module',
14
+ globals: {
15
+ ...globals.browser,
16
+ ...globals.es2021,
17
+ ...globals.node,
18
+ },
19
+ parserOptions: {
20
+ ecmaFeatures: { jsx: true },
21
+ },
22
+ },
23
+ },
24
+ {
25
+ name: 'storefront/javascript/rules',
26
+ rules: {
27
+ ...js.configs.recommended.rules,
28
+ 'accessor-pairs': [
29
+ 'error',
30
+ { enforceForClassMembers: true, setWithoutGet: true },
31
+ ],
32
+ 'array-callback-return': 'error',
33
+ 'block-scoped-var': 'error',
34
+ 'default-case-last': 'error',
35
+ 'dot-notation': ['error', { allowKeywords: true }],
36
+ eqeqeq: ['error', 'smart'],
37
+ 'new-cap': [
38
+ 'error',
39
+ { capIsNew: false, newIsCap: true, properties: true },
40
+ ],
41
+ 'no-alert': 'error',
42
+ 'no-caller': 'error',
43
+ 'no-eval': 'error',
44
+ 'no-extend-native': 'error',
45
+ 'no-extra-bind': 'error',
46
+ 'no-implied-eval': 'error',
47
+ 'no-iterator': 'error',
48
+ 'no-labels': ['error', { allowLoop: false, allowSwitch: false }],
49
+ 'no-lone-blocks': 'error',
50
+ 'no-multi-str': 'error',
51
+ 'no-new': 'error',
52
+ 'no-new-func': 'error',
53
+ 'no-new-wrappers': 'error',
54
+ 'no-octal-escape': 'error',
55
+ 'no-proto': 'error',
56
+ 'no-restricted-globals': [
57
+ 'error',
58
+ { name: 'global', message: 'Use `globalThis` instead.' },
59
+ { name: 'self', message: 'Use `globalThis` instead.' },
60
+ ],
61
+ 'no-restricted-properties': [
62
+ 'error',
63
+ {
64
+ property: '__proto__',
65
+ message:
66
+ 'Use `Object.getPrototypeOf` or `Object.setPrototypeOf` instead.',
67
+ },
68
+ {
69
+ property: '__defineGetter__',
70
+ message: 'Use `Object.defineProperty` instead.',
71
+ },
72
+ {
73
+ property: '__defineSetter__',
74
+ message: 'Use `Object.defineProperty` instead.',
75
+ },
76
+ {
77
+ property: '__lookupGetter__',
78
+ message: 'Use `Object.getOwnPropertyDescriptor` instead.',
79
+ },
80
+ {
81
+ property: '__lookupSetter__',
82
+ message: 'Use `Object.getOwnPropertyDescriptor` instead.',
83
+ },
84
+ ],
85
+ 'no-self-compare': 'error',
86
+ 'no-sequences': 'error',
87
+ 'no-template-curly-in-string': 'error',
88
+ 'no-throw-literal': 'error',
89
+ 'no-undef-init': 'error',
90
+ 'no-unmodified-loop-condition': 'error',
91
+ 'no-unneeded-ternary': ['error', { defaultAssignment: false }],
92
+ 'no-unreachable-loop': 'error',
93
+ 'no-unused-expressions': [
94
+ 'error',
95
+ {
96
+ allowShortCircuit: true,
97
+ allowTernary: true,
98
+ allowTaggedTemplates: true,
99
+ },
100
+ ],
101
+ 'no-unused-vars': [
102
+ 'error',
103
+ {
104
+ args: 'all',
105
+ argsIgnorePattern: '^_',
106
+ caughtErrors: 'all',
107
+ caughtErrorsIgnorePattern: '^_',
108
+ destructuredArrayIgnorePattern: '^_',
109
+ varsIgnorePattern: '^_',
110
+ ignoreRestSiblings: true,
111
+ },
112
+ ],
113
+ 'no-use-before-define': [
114
+ 'error',
115
+ { functions: false, classes: false, variables: true },
116
+ ],
117
+ 'no-useless-call': 'error',
118
+ 'no-useless-computed-key': 'error',
119
+ // Off: a subclass constructor that only forwards to `super(...)` is
120
+ // still meaningful documentation of the accepted argument types at
121
+ // an extension point (e.g. a mapper/service subclass), even when it
122
+ // matches the base class's signature exactly.
123
+ 'no-useless-constructor': 'off',
124
+ 'no-useless-rename': 'error',
125
+ 'no-useless-return': 'error',
126
+ 'no-var': 'error',
127
+ 'object-shorthand': [
128
+ 'error',
129
+ 'always',
130
+ { avoidQuotes: true, ignoreConstructors: false },
131
+ ],
132
+ 'one-var': ['error', { initialized: 'never' }],
133
+ 'prefer-arrow-callback': [
134
+ 'error',
135
+ { allowNamedFunctions: false, allowUnboundThis: true },
136
+ ],
137
+ 'prefer-const': [
138
+ 'error',
139
+ { destructuring: 'all', ignoreReadBeforeAssign: true },
140
+ ],
141
+ 'prefer-exponentiation-operator': 'error',
142
+ 'prefer-promise-reject-errors': 'error',
143
+ 'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }],
144
+ 'prefer-rest-params': 'error',
145
+ 'prefer-spread': 'error',
146
+ 'prefer-template': 'error',
147
+ 'symbol-description': 'error',
148
+ 'unicode-bom': ['error', 'never'],
149
+ 'use-isnan': [
150
+ 'error',
151
+ { enforceForIndexOf: true, enforceForSwitchCase: true },
152
+ ],
153
+ 'valid-typeof': ['error', { requireStringLiterals: true }],
154
+ 'vars-on-top': 'error',
155
+ yoda: ['error', 'never'],
156
+ },
157
+ },
158
+ ]
159
+ }