@yasainet/eslint 0.0.3 → 0.0.5

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
@@ -8,34 +8,42 @@ Shared ESLint configuration for feature-based architecture.
8
8
  npm install -D @yasainet/eslint eslint
9
9
  ```
10
10
 
11
- ## Usage
11
+ ## Entry Points
12
+
13
+ | Entry | Feature Root | Description |
14
+ | ----------------------- | ------------------------------ | ----------------------------------------------------------------------------------- |
15
+ | `@yasainet/eslint/next` | `src/features/` | Common rules + Next.js-specific rules (hooks, components, directives, lib-boundary) |
16
+ | `@yasainet/eslint/node` | `scripts/features/` | Common rules only |
17
+ | `@yasainet/eslint/deno` | `supabase/functions/features/` | Common rules only |
12
18
 
13
- ### Next.js
19
+ ## Usage
14
20
 
15
21
  ```js
16
22
  // eslint.config.mjs
23
+ import { eslintConfig as nextEslintConfig } from "@yasainet/eslint/next";
24
+ import { eslintConfig as nodeEslintConfig } from "@yasainet/eslint/node";
25
+ import { eslintConfig as denoEslintConfig } from "@yasainet/eslint/deno";
17
26
  import { defineConfig, globalIgnores } from "eslint/config";
18
27
  import nextVitals from "eslint-config-next/core-web-vitals";
19
28
  import nextTs from "eslint-config-next/typescript";
20
- import { eslintConfig } from "@yasainet/eslint/next";
21
29
 
22
30
  export default defineConfig([
23
31
  ...nextVitals,
24
32
  ...nextTs,
25
- globalIgnores([".next/**", "out/**", "build/**", "next-env.d.ts"]),
26
- ...eslintConfig,
33
+ // Override default ignores of eslint-config-next.
34
+ globalIgnores([
35
+ // Default ignores of eslint-config-next:
36
+ ".next/**",
37
+ "out/**",
38
+ "build/**",
39
+ "next-env.d.ts",
40
+ ]),
41
+ ...nextEslintConfig,
42
+ ...nodeEslintConfig,
43
+ ...denoEslintConfig,
27
44
  ]);
28
45
  ```
29
46
 
30
- ### Node.js
31
-
32
- ```js
33
- // eslint.config.mjs
34
- import { eslintConfig } from "@yasainet/eslint/node";
35
-
36
- export default eslintConfig;
37
- ```
38
-
39
47
  ## Release
40
48
 
41
49
  1. Update `version` in `package.json`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yasainet/eslint",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "ESLint",
5
5
  "type": "module",
6
6
  "exports": {
@@ -11,6 +11,10 @@
11
11
  "./node": {
12
12
  "types": "./src/node/index.d.mts",
13
13
  "default": "./src/node/index.mjs"
14
+ },
15
+ "./deno": {
16
+ "types": "./src/deno/index.d.mts",
17
+ "default": "./src/deno/index.mjs"
14
18
  }
15
19
  },
16
20
  "files": [
@@ -20,12 +20,6 @@ function findProjectRoot() {
20
20
 
21
21
  const PROJECT_ROOT = findProjectRoot();
22
22
 
23
- export const FEATURE_ROOTS = [
24
- "src/features",
25
- "scripts/features",
26
- "supabase/functions/features",
27
- ];
28
-
29
23
  const EXCLUDE_LIST = ["proxy.ts", "types"];
30
24
 
31
25
  function generatePrefixLibMapping() {
@@ -68,5 +62,6 @@ function generatePrefixLibMapping() {
68
62
 
69
63
  export const PREFIX_LIB_MAPPING = generatePrefixLibMapping();
70
64
 
71
- export const featuresGlob = (subpath) =>
72
- FEATURE_ROOTS.map((root) => `${root}/${subpath}`);
65
+ export const featuresGlob = (featureRoot, subpath) => [
66
+ `${featureRoot}/${subpath}`,
67
+ ];
@@ -112,22 +112,31 @@ function makeConfig(name, files, ...patternArrays) {
112
112
  };
113
113
  }
114
114
 
115
- function generateImportConfigs() {
116
- const configs = [];
117
-
118
- configs.push({
115
+ /** @description Next.js-only: restrict @/lib imports to repositories */
116
+ export const libBoundaryConfigs = [
117
+ {
119
118
  name: "imports/lib-boundary",
120
119
  files: ["src/**/*.{ts,tsx}"],
121
- ignores: ["src/lib/**", "src/proxy.ts", "src/app/sitemap.ts"],
120
+ ignores: [
121
+ "src/lib/**",
122
+ "src/proxy.ts",
123
+ "src/app/sitemap.ts",
124
+ "src/features/**/repositories/**",
125
+ ],
122
126
  rules: {
123
127
  "no-restricted-imports": ["error", { patterns: LIB_BOUNDARY_PATTERNS }],
124
128
  },
125
- });
129
+ },
130
+ ];
131
+
132
+ /** @description Scope import restriction rules to the given feature root */
133
+ export function createImportsConfigs(featureRoot) {
134
+ const configs = [];
126
135
 
127
136
  configs.push(
128
137
  makeConfig(
129
138
  "repositories",
130
- ["**/repositories/*.ts"],
139
+ [`${featureRoot}/**/repositories/*.ts`],
131
140
  LAYER_PATTERNS.repositories,
132
141
  LATERAL_PATTERNS.repositories,
133
142
  ),
@@ -139,7 +148,7 @@ function generateImportConfigs() {
139
148
  configs.push(
140
149
  makeConfig(
141
150
  `repositories/${prefix}`,
142
- [`**/repositories/${prefix}.repo.ts`],
151
+ [`${featureRoot}/**/repositories/${prefix}.repo.ts`],
143
152
  LAYER_PATTERNS.repositories,
144
153
  LATERAL_PATTERNS.repositories,
145
154
  patterns,
@@ -150,7 +159,7 @@ function generateImportConfigs() {
150
159
  configs.push(
151
160
  makeConfig(
152
161
  "services",
153
- ["**/services/*.ts"],
162
+ [`${featureRoot}/**/services/*.ts`],
154
163
  LAYER_PATTERNS.services,
155
164
  LATERAL_PATTERNS.services,
156
165
  LIB_BOUNDARY_PATTERNS,
@@ -160,7 +169,7 @@ function generateImportConfigs() {
160
169
  configs.push(
161
170
  makeConfig(
162
171
  "actions",
163
- ["**/actions/*.ts"],
172
+ [`${featureRoot}/**/actions/*.ts`],
164
173
  LAYER_PATTERNS.actions,
165
174
  LATERAL_PATTERNS.actions,
166
175
  LIB_BOUNDARY_PATTERNS,
@@ -171,7 +180,7 @@ function generateImportConfigs() {
171
180
  configs.push(
172
181
  makeConfig(
173
182
  `actions/${prefix}`,
174
- [`**/actions/${prefix}.action.ts`],
183
+ [`${featureRoot}/**/actions/${prefix}.action.ts`],
175
184
  LAYER_PATTERNS.actions,
176
185
  LATERAL_PATTERNS.actions,
177
186
  CARDINALITY_PATTERNS[prefix],
@@ -182,5 +191,3 @@ function generateImportConfigs() {
182
191
 
183
192
  return configs.filter(Boolean);
184
193
  }
185
-
186
- export const importsConfigs = generateImportConfigs();
@@ -1,13 +1,16 @@
1
- import { importsConfigs } from "./imports.mjs";
2
- import { jsdocConfigs } from "./jsdoc.mjs";
3
- import { layersConfigs } from "./layers.mjs";
4
- import { namingConfigs } from "./naming.mjs";
1
+ import { createImportsConfigs } from "./imports.mjs";
2
+ import { createJsdocConfigs } from "./jsdoc.mjs";
3
+ import { createLayersConfigs } from "./layers.mjs";
4
+ import { createNamingConfigs } from "./naming.mjs";
5
5
  import { rulesConfigs } from "./rules.mjs";
6
6
 
7
- export const commonConfigs = [
8
- ...rulesConfigs,
9
- ...namingConfigs,
10
- ...layersConfigs,
11
- ...importsConfigs,
12
- ...jsdocConfigs,
13
- ];
7
+ /** @description Build common configs scoped to the given feature root */
8
+ export function createCommonConfigs(featureRoot) {
9
+ return [
10
+ ...rulesConfigs,
11
+ ...createNamingConfigs(featureRoot),
12
+ ...createLayersConfigs(featureRoot),
13
+ ...createImportsConfigs(featureRoot),
14
+ ...createJsdocConfigs(featureRoot),
15
+ ];
16
+ }
@@ -2,38 +2,41 @@ import jsdocPlugin from "eslint-plugin-jsdoc";
2
2
 
3
3
  import { featuresGlob } from "./constants.mjs";
4
4
 
5
- export const jsdocConfigs = [
6
- {
7
- name: "jsdoc",
8
- files: [
9
- ...featuresGlob("**/repositories/*.ts"),
10
- ...featuresGlob("**/services*/*.ts"),
11
- ...featuresGlob("**/utils*/*.ts"),
12
- ],
13
- plugins: {
14
- jsdoc: jsdocPlugin,
15
- },
16
- rules: {
17
- "jsdoc/require-jsdoc": [
18
- "warn",
19
- {
20
- publicOnly: true,
21
- require: {
22
- FunctionDeclaration: true,
23
- ArrowFunctionExpression: true,
24
- FunctionExpression: true,
25
- },
26
- checkGetters: false,
27
- checkSetters: false,
28
- checkConstructors: false,
29
- },
30
- ],
31
- "jsdoc/require-description": [
32
- "warn",
33
- {
34
- contexts: ["any"],
35
- },
5
+ /** @description Scope JSDoc rules to the given feature root */
6
+ export function createJsdocConfigs(featureRoot) {
7
+ return [
8
+ {
9
+ name: "jsdoc",
10
+ files: [
11
+ ...featuresGlob(featureRoot, "**/repositories/*.ts"),
12
+ ...featuresGlob(featureRoot, "**/services*/*.ts"),
13
+ ...featuresGlob(featureRoot, "**/utils*/*.ts"),
36
14
  ],
15
+ plugins: {
16
+ jsdoc: jsdocPlugin,
17
+ },
18
+ rules: {
19
+ "jsdoc/require-jsdoc": [
20
+ "warn",
21
+ {
22
+ publicOnly: true,
23
+ require: {
24
+ FunctionDeclaration: true,
25
+ ArrowFunctionExpression: true,
26
+ FunctionExpression: true,
27
+ },
28
+ checkGetters: false,
29
+ checkSetters: false,
30
+ checkConstructors: false,
31
+ },
32
+ ],
33
+ "jsdoc/require-description": [
34
+ "warn",
35
+ {
36
+ contexts: ["any"],
37
+ },
38
+ ],
39
+ },
37
40
  },
38
- },
39
- ];
41
+ ];
42
+ }
@@ -1,35 +1,38 @@
1
- export const layersConfigs = [
2
- {
3
- name: "layers/repositories",
4
- files: ["**/repositories/*.ts"],
5
- rules: {
6
- "no-restricted-syntax": [
7
- "error",
8
- {
9
- selector: "TryStatement",
10
- message:
11
- "try-catch is not allowed in repositories. Error handling belongs in actions.",
12
- },
13
- {
14
- selector: "IfStatement",
15
- message:
16
- "if statements are not allowed in repositories. Conditional logic belongs in services.",
17
- },
18
- ],
1
+ /** @description Scope layer rules to the given feature root */
2
+ export function createLayersConfigs(featureRoot) {
3
+ return [
4
+ {
5
+ name: "layers/repositories",
6
+ files: [`${featureRoot}/**/repositories/*.ts`],
7
+ rules: {
8
+ "no-restricted-syntax": [
9
+ "error",
10
+ {
11
+ selector: "TryStatement",
12
+ message:
13
+ "try-catch is not allowed in repositories. Error handling belongs in actions.",
14
+ },
15
+ {
16
+ selector: "IfStatement",
17
+ message:
18
+ "if statements are not allowed in repositories. Conditional logic belongs in services.",
19
+ },
20
+ ],
21
+ },
19
22
  },
20
- },
21
- {
22
- name: "layers/services",
23
- files: ["**/services/*.ts"],
24
- rules: {
25
- "no-restricted-syntax": [
26
- "error",
27
- {
28
- selector: "TryStatement",
29
- message:
30
- "try-catch is not allowed in services. Error handling belongs in actions.",
31
- },
32
- ],
23
+ {
24
+ name: "layers/services",
25
+ files: [`${featureRoot}/**/services/*.ts`],
26
+ rules: {
27
+ "no-restricted-syntax": [
28
+ "error",
29
+ {
30
+ selector: "TryStatement",
31
+ message:
32
+ "try-catch is not allowed in services. Error handling belongs in actions.",
33
+ },
34
+ ],
35
+ },
33
36
  },
34
- },
35
- ];
37
+ ];
38
+ }
@@ -4,147 +4,152 @@ import { actionHandleServiceRule } from "./local-plugins/action-handle-service.m
4
4
 
5
5
  const prefixPattern = `@(${Object.keys(PREFIX_LIB_MAPPING).join("|")})`;
6
6
 
7
- export const namingConfigs = [
8
- {
9
- name: "naming/services",
10
- files: featuresGlob("**/services/*.ts"),
11
- plugins: { "check-file": checkFile },
12
- rules: {
13
- "check-file/filename-naming-convention": [
14
- "error",
15
- { "**/*.ts": `${prefixPattern}.service` },
16
- ],
7
+ /** @description Scope naming rules to the given feature root */
8
+ export function createNamingConfigs(featureRoot) {
9
+ return [
10
+ {
11
+ name: "naming/services",
12
+ files: featuresGlob(featureRoot, "**/services/*.ts"),
13
+ plugins: { "check-file": checkFile },
14
+ rules: {
15
+ "check-file/filename-naming-convention": [
16
+ "error",
17
+ { "**/*.ts": `${prefixPattern}.service` },
18
+ ],
19
+ },
17
20
  },
18
- },
19
- {
20
- name: "naming/repositories",
21
- files: featuresGlob("**/repositories/*.ts"),
22
- plugins: { "check-file": checkFile },
23
- rules: {
24
- "check-file/filename-naming-convention": [
25
- "error",
26
- { "**/*.ts": `${prefixPattern}.repo` },
27
- ],
21
+ {
22
+ name: "naming/repositories",
23
+ files: featuresGlob(featureRoot, "**/repositories/*.ts"),
24
+ plugins: { "check-file": checkFile },
25
+ rules: {
26
+ "check-file/filename-naming-convention": [
27
+ "error",
28
+ { "**/*.ts": `${prefixPattern}.repo` },
29
+ ],
30
+ },
28
31
  },
29
- },
30
- {
31
- name: "naming/types",
32
- files: featuresGlob("*/types/*.type.ts"),
33
- ignores: featuresGlob("shared/types/*.ts"),
34
- plugins: { "check-file": checkFile },
35
- rules: {
36
- "check-file/filename-naming-convention": [
37
- "error",
38
- { "**/*/types/*.ts": "<1>" },
39
- { ignoreMiddleExtensions: true },
40
- ],
32
+ {
33
+ name: "naming/types",
34
+ files: featuresGlob(featureRoot, "*/types/*.type.ts"),
35
+ ignores: featuresGlob(featureRoot, "shared/types/*.ts"),
36
+ plugins: { "check-file": checkFile },
37
+ rules: {
38
+ "check-file/filename-naming-convention": [
39
+ "error",
40
+ { "**/*/types/*.ts": "<1>" },
41
+ { ignoreMiddleExtensions: true },
42
+ ],
43
+ },
41
44
  },
42
- },
43
- {
44
- name: "naming/types-shared",
45
- files: featuresGlob("shared/types/*.ts"),
46
- plugins: { "check-file": checkFile },
47
- rules: {
48
- "check-file/filename-naming-convention": [
49
- "error",
50
- { "**/*.ts": "+([a-z0-9_-]).type" },
51
- ],
45
+ {
46
+ name: "naming/types-shared",
47
+ files: featuresGlob(featureRoot, "shared/types/*.ts"),
48
+ plugins: { "check-file": checkFile },
49
+ rules: {
50
+ "check-file/filename-naming-convention": [
51
+ "error",
52
+ { "**/*.ts": "+([a-z0-9_-]).type" },
53
+ ],
54
+ },
52
55
  },
53
- },
54
- {
55
- name: "naming/schemas",
56
- files: featuresGlob("**/schemas/*.ts"),
57
- plugins: { "check-file": checkFile },
58
- rules: {
59
- "check-file/filename-naming-convention": [
60
- "error",
61
- { "**/*.ts": "+([a-z0-9-]).schema" },
62
- ],
56
+ {
57
+ name: "naming/schemas",
58
+ files: featuresGlob(featureRoot, "**/schemas/*.ts"),
59
+ plugins: { "check-file": checkFile },
60
+ rules: {
61
+ "check-file/filename-naming-convention": [
62
+ "error",
63
+ { "**/*.ts": "+([a-z0-9-]).schema" },
64
+ ],
65
+ },
63
66
  },
64
- },
65
- {
66
- name: "naming/utils",
67
- files: featuresGlob("*/utils/*.util.ts"),
68
- ignores: featuresGlob("shared/utils/*.ts"),
69
- plugins: { "check-file": checkFile },
70
- rules: {
71
- "check-file/filename-naming-convention": [
72
- "error",
73
- { "**/*/utils/*.ts": "<1>" },
74
- { ignoreMiddleExtensions: true },
75
- ],
67
+ {
68
+ name: "naming/utils",
69
+ files: featuresGlob(featureRoot, "*/utils/*.util.ts"),
70
+ ignores: featuresGlob(featureRoot, "shared/utils/*.ts"),
71
+ plugins: { "check-file": checkFile },
72
+ rules: {
73
+ "check-file/filename-naming-convention": [
74
+ "error",
75
+ { "**/*/utils/*.ts": "<1>" },
76
+ { ignoreMiddleExtensions: true },
77
+ ],
78
+ },
76
79
  },
77
- },
78
- {
79
- name: "naming/utils-shared",
80
- files: featuresGlob("shared/utils/*.ts"),
81
- plugins: { "check-file": checkFile },
82
- rules: {
83
- "check-file/filename-naming-convention": [
84
- "error",
85
- { "**/*.ts": "+([a-z0-9_-]).util" },
86
- ],
80
+ {
81
+ name: "naming/utils-shared",
82
+ files: featuresGlob(featureRoot, "shared/utils/*.ts"),
83
+ plugins: { "check-file": checkFile },
84
+ rules: {
85
+ "check-file/filename-naming-convention": [
86
+ "error",
87
+ { "**/*.ts": "+([a-z0-9_-]).util" },
88
+ ],
89
+ },
87
90
  },
88
- },
89
- {
90
- name: "naming/constants",
91
- files: featuresGlob("**/constants/*.ts"),
92
- plugins: { "check-file": checkFile },
93
- rules: {
94
- "check-file/filename-naming-convention": [
95
- "error",
96
- { "**/*.ts": "+([a-z0-9-]).constant" },
97
- ],
91
+ {
92
+ name: "naming/constants",
93
+ files: featuresGlob(featureRoot, "**/constants/*.ts"),
94
+ plugins: { "check-file": checkFile },
95
+ rules: {
96
+ "check-file/filename-naming-convention": [
97
+ "error",
98
+ { "**/*.ts": "+([a-z0-9-]).constant" },
99
+ ],
100
+ },
98
101
  },
99
- },
100
- {
101
- name: "naming/actions",
102
- files: featuresGlob("**/actions/*.ts"),
103
- plugins: { "check-file": checkFile },
104
- rules: {
105
- "check-file/filename-naming-convention": [
106
- "error",
107
- { "**/*.ts": `${prefixPattern}.action` },
108
- ],
102
+ {
103
+ name: "naming/actions",
104
+ files: featuresGlob(featureRoot, "**/actions/*.ts"),
105
+ plugins: { "check-file": checkFile },
106
+ rules: {
107
+ "check-file/filename-naming-convention": [
108
+ "error",
109
+ { "**/*.ts": `${prefixPattern}.action` },
110
+ ],
111
+ },
109
112
  },
110
- },
111
- {
112
- name: "naming/actions-export",
113
- files: featuresGlob("**/actions/*.ts"),
114
- rules: {
115
- "no-restricted-syntax": [
116
- "error",
117
- {
118
- selector:
119
- "ExportNamedDeclaration > FunctionDeclaration[id.name!=/^handle[A-Z]/]",
120
- message:
121
- "Exported functions in actions must start with 'handle' (e.g., handleGetComics).",
122
- },
123
- ],
124
- },
125
- },
126
- {
127
- name: "naming/actions-handle-service",
128
- files: featuresGlob("**/actions/*.ts"),
129
- plugins: {
130
- local: { rules: { "action-handle-service": actionHandleServiceRule } },
113
+ {
114
+ name: "naming/actions-export",
115
+ files: featuresGlob(featureRoot, "**/actions/*.ts"),
116
+ rules: {
117
+ "no-restricted-syntax": [
118
+ "error",
119
+ {
120
+ selector:
121
+ "ExportNamedDeclaration > FunctionDeclaration[id.name!=/^handle[A-Z]/]",
122
+ message:
123
+ "Exported functions in actions must start with 'handle' (e.g., handleGetComics).",
124
+ },
125
+ ],
126
+ },
131
127
  },
132
- rules: {
133
- "local/action-handle-service": "error",
134
- },
135
- },
136
- {
137
- name: "naming/features-ts-only",
138
- files: featuresGlob("**/*.tsx"),
139
- rules: {
140
- "no-restricted-syntax": [
141
- "error",
142
- {
143
- selector: "Program",
144
- message:
145
- "features/ must only contain .ts files. Components belong in src/components/.",
128
+ {
129
+ name: "naming/actions-handle-service",
130
+ files: featuresGlob(featureRoot, "**/actions/*.ts"),
131
+ plugins: {
132
+ local: {
133
+ rules: { "action-handle-service": actionHandleServiceRule },
146
134
  },
147
- ],
135
+ },
136
+ rules: {
137
+ "local/action-handle-service": "error",
138
+ },
139
+ },
140
+ {
141
+ name: "naming/features-ts-only",
142
+ files: featuresGlob(featureRoot, "**/*.tsx"),
143
+ rules: {
144
+ "no-restricted-syntax": [
145
+ "error",
146
+ {
147
+ selector: "Program",
148
+ message:
149
+ "features/ must only contain .ts files. Components belong in src/components/.",
150
+ },
151
+ ],
152
+ },
148
153
  },
149
- },
150
- ];
154
+ ];
155
+ }
@@ -0,0 +1,3 @@
1
+ import type { Linter } from "eslint";
2
+
3
+ export declare const eslintConfig: Linter.Config[];
@@ -0,0 +1,5 @@
1
+ import { createCommonConfigs } from "../common/index.mjs";
2
+
3
+ export const eslintConfig = [
4
+ ...createCommonConfigs("supabase/functions/features"),
5
+ ];
@@ -1,10 +1,12 @@
1
- import { commonConfigs } from "../common/index.mjs";
1
+ import { createCommonConfigs } from "../common/index.mjs";
2
+ import { libBoundaryConfigs } from "../common/imports.mjs";
2
3
 
3
4
  import { directivesConfigs } from "./directives.mjs";
4
5
  import { namingConfigs } from "./naming.mjs";
5
6
 
6
7
  export const eslintConfig = [
7
- ...commonConfigs,
8
+ ...createCommonConfigs("src/features"),
9
+ ...libBoundaryConfigs,
8
10
  ...namingConfigs,
9
11
  ...directivesConfigs,
10
12
  ];
@@ -1,10 +1,9 @@
1
- import { featuresGlob } from "../common/constants.mjs";
2
1
  import { checkFile } from "../common/plugins.mjs";
3
2
 
4
3
  export const namingConfigs = [
5
4
  {
6
5
  name: "naming/hooks",
7
- files: featuresGlob("**/hooks/*.ts"),
6
+ files: ["src/features/**/hooks/*.ts"],
8
7
  plugins: { "check-file": checkFile },
9
8
  rules: {
10
9
  "check-file/filename-naming-convention": [
@@ -16,7 +15,7 @@ export const namingConfigs = [
16
15
  },
17
16
  {
18
17
  name: "naming/hooks-export",
19
- files: featuresGlob("**/hooks/*.ts"),
18
+ files: ["src/features/**/hooks/*.ts"],
20
19
  rules: {
21
20
  "no-restricted-syntax": [
22
21
  "error",
@@ -1,3 +1,3 @@
1
- import { commonConfigs } from "../common/index.mjs";
1
+ import { createCommonConfigs } from "../common/index.mjs";
2
2
 
3
- export const eslintConfig = [...commonConfigs];
3
+ export const eslintConfig = [...createCommonConfigs("scripts/features")];