@scayle/eslint-config-storefront
v5.1.1
Published
SCAYLE Commerce Engine specific eslint configuration
Downloads
21,876
Keywords
Readme
@scayle/eslint-config-storefront
A shared eslint config for SCAYLE Storefront projects and packages.
Provides SCAYLE-specific eslint configuration for Frontend and Node.js projects using TypeScript.
Flat config only (ESLint 10.4+). 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.
Should you require support for eslint@8, please use @scayle/eslint-config-storefront@3.
Install
Add the @scayle/eslint-config-storefront manually to your project:
pnpm i -D eslint @scayle/eslint-config-storefront
yarn add -D eslint @scayle/eslint-config-storefront
And create a eslint.config.mjs in your project root:
// eslint.config.mjs
import storefront from '@scayle/eslint-config-storefront'
export default storefront()Nuxt projects
Nuxt projects already get JavaScript, TypeScript, JSDoc, and import rules from
@nuxt/eslint. Use the /nuxt entry point instead, which
only adds the framework-agnostic rules (comments hygiene, Node.js, JSON/JSONC, test-file
conventions, SonarJS, Promise usage, modernization, and regex safety):
// eslint.config.mjs
import storefrontNuxt from '@scayle/eslint-config-storefront/nuxt'
import withNuxt from './.nuxt/eslint.config.mjs'
export default withNuxt(storefrontNuxt())Storefront Application V3 projects
The Storefront Application V3 stack (Hono + Inertia.js + Vue 3, not Nuxt) should use the
/v3 entry point. 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 a TypeScript-aware import resolver:
// eslint.config.mjs
import storefrontV3 from '@scayle/eslint-config-storefront/v3'
export default storefrontV3({
tailwind: {
entryPoint: './src/client/index.css',
},
i18n: {
localeDir: './src/i18n/locales/*.json',
},
})tailwind.entryPoint and i18n.localeDir are required, the underlying plugins can't
validate Tailwind classes or i18n keys without a real path. Optional options:
typescript.tsconfigPath: absolute path to atsconfig.json. Enables type-aware TypeScript rules and points the import resolver at that file instead of<root>/tsconfig.jsonresolver.tsconfigPath: absolute path to atsconfig.jsonfor the import resolver only, independent oftypescript.tsconfigPath. Use this instead when you want the resolver fix below without also switching on type-aware TypeScript rulesi18n.messageSyntaxVersion:vue-i18nmessage syntax version, defaults to^11.2.8i18n.unusedKeyIgnores: regex-string patterns for translation keys used dynamically in codevue.undefComponentIgnores: custom element (web component) tag names to exempt fromvue/no-undef-componentsvueComposable.fallthroughAttrsIgnores: path fragments to exempt fromrequire-explicit-fallthrough-attrs(e.g. router-mounted page/layout roots that never receive fallthrough attributes)
Import resolution
/v3 wires eslint-import-resolver-typescript, so import-x rules resolve tsconfig.json
path aliases (@client/*, @server/*, or any other paths entry) to their real files
instead of only matching literal relative imports. Three rules depend on that resolution
to work correctly against an aliased import:
import-x/no-restricted-paths: zone violations across an alias fail lint, not just across a relative pathimport-x/no-cycle: circular dependencies through an aliased import are caught..vuefiles are the one exception, a cycle through a.vuefile only surfaces when ESLint lints that file directlyimport-x/order: aliased imports rank alongside package imports (external), ahead of relative ones, instead of dropping to last place once the resolver can see they resolve to a project file
Without resolver.tsconfigPath or typescript.tsconfigPath set, both the resolver and
import-x/no-restricted-paths's zones resolve relative to ESLint's own working directory.
That's correct for pnpm lint and CI, since a monorepo's task runner always runs a
package's lint script with that package as the working directory, but not guaranteed for
an editor's ESLint extension, which can run with the workspace root as its working
directory instead. Set resolver.tsconfigPath to an absolute path (for example,
new URL('./tsconfig.json', import.meta.url).pathname in your eslint.config.mjs) if your
editor's linting needs to match the command-line result.
Add script for package.json
For example:
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix"
}
}VS Code support (auto fix on save)
Install VS Code ESLint extension
Add the following settings to your .vscode/settings.json:
{
// Enable the ESlint flat config support
"eslint.experimental.useFlatConfig": true,
// Auto fix
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never",
},
// Enable eslint for all supported languages
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"jsonc",
"yaml",
],
}Customization
Default config / @scayle/eslint-config-storefront
// eslint.config.mjs
import storefront from '@scayle/eslint-config-storefront'
export default storefront({
typescript: {
// Enables type-aware rules for the given tsconfig
tsconfigPath: 'path/to/tsconfig.json',
},
})Nuxt config / @scayle/eslint-config-storefront/nuxt
// eslint.config.mjs
import storefrontNuxt from '@scayle/eslint-config-storefront/nuxt'
export default storefrontNuxt()Storefront Application V3 config / @scayle/eslint-config-storefront/v3
See Storefront Application V3 projects above for the full option list.
All three entry points return a FlatConfigComposer,
so you can chain .append(...), .prepend(...), .override(...), or .renamePlugins(...) to layer
project-specific rules on top.
Plugin names
Rules use each plugin's own published name (@typescript-eslint/*, import-x/*, jsonc/*,
jsdoc/*, node/*, promise/*, sonarjs/*, unicorn/*, regexp/*, e18e/*, vitest/*,
eslint-comments/*). There's no alias renaming. When you override or disable a rule inline,
use that plugin's real prefix:
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
type Foo = { bar: 2 }e18e/* rules ship as warnings
The e18e community's rule set (modernization, module-replacement, and
performance rules) is enabled by default, but every e18e/* rule ships at warn, not error.
The plugin is still pre-1.0, and its rule set hasn't been reviewed against every consuming
project. A warning won't fail your build.
One rule worth knowing about specifically: e18e/ban-dependencies flags a dependency in your
project that has a lighter recommended alternative (for example ora in favor of
nanospinner). Treat that finding as something to evaluate, not something to fix immediately.
Swapping a dependency is a real decision with its own testing cost, not a lint fix. If you've
decided to keep a flagged dependency, allowlist it explicitly rather than turning the rule off:
export default storefront().append({
rules: {
'e18e/ban-dependencies': ['warn', { allowed: ['ora'] }],
},
})View what rules are enabled
@eslint/config-inspector is a visual tool maintained by the ESLint core team to help you view what rules are enabled in your project and which files they apply to.
Go into your project root that contains eslint.config.js and run:
npx @eslint/config-inspector
License
Licensed under the MIT License
