eslint-plugin-use-agnostic 0.10.7 → 0.11.1
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 +2 -4
- package/library/_commons/constants/bases.js +12 -0
- package/library/_commons/utilities/helpers.js +43 -15
- package/library/agnostic20/_commons/constants/bases.js +10 -10
- package/library/agnostic20/_commons/utilities/flows.js +1 -1
- package/library/agnostic20/_commons/utilities/helpers.js +45 -40
- package/library/agnostic20/config.js +2 -5
- package/library/directive21/_commons/utilities/helpers.js +1 -1
- package/library/directive21/config.js +2 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,9 +74,7 @@ With this list established, it thus becomes possible to recognize static import
|
|
|
74
74
|
|
|
75
75
|
## Caveats
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
Aliased import paths are resolved only if your ESLint config file and your `tsconfig.json` file are in the same directory. At least to my knowledge, since the resolution depends on the `cwd` property from ESLint rules' `context` objects.
|
|
77
|
+
Base url and aliased import paths are currently resolved under the assumption that `process.cwd()` and `context.cwd` have the same value.
|
|
80
78
|
|
|
81
79
|
It is up to you to confirm that your Agnostic Modules are indeed agnostic, meaning that they have neither server- nor client-side code. `eslint-plugin-use-agnostic`, at least at this time, does not do this verification for you.
|
|
82
80
|
|
|
@@ -102,4 +100,4 @@ But not having a directive to distinguish between 1. non-special Server Modules
|
|
|
102
100
|
|
|
103
101
|
This is what the `'use agnostic'` directive solves. It clearly marks a module to be an Agnostic Module. And if a module that used to lack a directive can now be marked as an Agnostic Module, this allows modules without a directive to finally, truly be Server Modules by default. And `eslint-plugin-use-agnostic` can work from there.
|
|
104
102
|
|
|
105
|
-
A lot more needs to be done, and a lot of it unfortunately can only be optimized
|
|
103
|
+
A lot more needs to be done, and I suspect a lot of it unfortunately can only be optimized deeperly into React's innerworkings. But if the introduction of `'use agnostic'` can already create such powerful static analysis, imagine what it could produce if only it were incorporated into React as an official directive of the Fullstack React Architecture.
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { Linter } from "eslint";
|
|
2
|
+
import tseslint from "typescript-eslint";
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* @typedef {import('../../../types/_commons/typedefs').Extensions} Extensions
|
|
3
6
|
*/
|
|
@@ -117,3 +120,12 @@ export const ARE_NOT_ALLOWED_TO_IMPORT = "are not allowed to import";
|
|
|
117
120
|
export const skip = Object.freeze({
|
|
118
121
|
skip: true,
|
|
119
122
|
});
|
|
123
|
+
|
|
124
|
+
// common linter for AST retrieval
|
|
125
|
+
export const linter = new Linter();
|
|
126
|
+
|
|
127
|
+
// ESLint configs language options
|
|
128
|
+
export const typeScriptCompatible = Object.freeze({
|
|
129
|
+
// for compatibility with .ts and .tsx
|
|
130
|
+
parser: tseslint.parser,
|
|
131
|
+
});
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
|
|
4
|
+
import { Linter } from "eslint";
|
|
4
5
|
import { loadConfig, createMatchPath } from "tsconfig-paths";
|
|
5
6
|
|
|
6
7
|
import {
|
|
7
8
|
EXTENSIONS,
|
|
8
9
|
ARE_NOT_ALLOWED_TO_IMPORT,
|
|
9
10
|
resolvedDirectives_resolvedModules,
|
|
11
|
+
// linter,
|
|
12
|
+
typeScriptCompatible,
|
|
10
13
|
} from "../constants/bases.js";
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
|
-
* @typedef {import('../../../types/_commons/typedefs').ResolvedDirectiveWithoutUseAgnosticStrategies} ResolvedDirectiveWithoutUseAgnosticStrategies
|
|
14
16
|
* @typedef {import('../../../types/_commons/typedefs').Context<string, readonly unknown[]>} Context
|
|
17
|
+
* @typedef {import('../../../types/_commons/typedefs').ResolvedDirectiveWithoutUseAgnosticStrategies} ResolvedDirectiveWithoutUseAgnosticStrategies
|
|
15
18
|
*/
|
|
16
19
|
|
|
17
20
|
/**
|
|
@@ -36,16 +39,16 @@ const findExistingPath = (basePath) => {
|
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
41
|
* Resolves an import path to a filesystem path, handling:
|
|
39
|
-
* -
|
|
40
|
-
* - Missing extensions (appends
|
|
42
|
+
* - Base url and aliases (via tsconfig.json `baseUrl` and `paths` compiler options)
|
|
43
|
+
* - Missing extensions (appends `.ts`, `.tsx`, etc.)
|
|
41
44
|
* - Directory imports (e.g., `./components` → `./components/index.ts`)
|
|
42
45
|
* @param {string} currentDir The directory of the file containing the import (from `path.dirname(context.filename)`).
|
|
43
46
|
* @param {string} importPath The import specifier (e.g., `@/components/Button` or `./utils`), from the current node.
|
|
44
|
-
* @param {string} cwd The project root (from `context.cwd`).
|
|
47
|
+
* @param {string} cwd The project root (from `context.cwd`).
|
|
45
48
|
* @returns The absolute resolved path or `null` if no path is found.
|
|
46
49
|
*/
|
|
47
50
|
export const resolveImportPath = (currentDir, importPath, cwd) => {
|
|
48
|
-
// Step 1:
|
|
51
|
+
// Step 1: Resolves baseUrl and aliases
|
|
49
52
|
const config = loadConfig(cwd);
|
|
50
53
|
|
|
51
54
|
const resolveTSConfig =
|
|
@@ -53,12 +56,12 @@ export const resolveImportPath = (currentDir, importPath, cwd) => {
|
|
|
53
56
|
? createMatchPath(config.absoluteBaseUrl, config.paths)
|
|
54
57
|
: null;
|
|
55
58
|
|
|
56
|
-
const
|
|
59
|
+
const baseUrlOrAliasedPath = resolveTSConfig
|
|
57
60
|
? resolveTSConfig(importPath, undefined, undefined, EXTENSIONS)
|
|
58
61
|
: null;
|
|
59
62
|
|
|
60
|
-
// Step 2:
|
|
61
|
-
const basePath =
|
|
63
|
+
// Step 2: Resolves relative/absolute paths
|
|
64
|
+
const basePath = baseUrlOrAliasedPath || path.resolve(currentDir, importPath);
|
|
62
65
|
|
|
63
66
|
// does not resolve on node_modules
|
|
64
67
|
if (basePath.includes("node_modules")) return null;
|
|
@@ -66,7 +69,7 @@ export const resolveImportPath = (currentDir, importPath, cwd) => {
|
|
|
66
69
|
// Case 1: File with extension exists
|
|
67
70
|
if (path.extname(importPath) && fs.existsSync(basePath)) return basePath;
|
|
68
71
|
|
|
69
|
-
// Case 2:
|
|
72
|
+
// Case 2: Tries appending extensions
|
|
70
73
|
const extensionlessImportPath = findExistingPath(basePath);
|
|
71
74
|
if (extensionlessImportPath) return extensionlessImportPath;
|
|
72
75
|
|
|
@@ -78,7 +81,30 @@ export const resolveImportPath = (currentDir, importPath, cwd) => {
|
|
|
78
81
|
return null; // not found
|
|
79
82
|
};
|
|
80
83
|
|
|
81
|
-
/*
|
|
84
|
+
/* getASTFromResolvedPath */ // for agnostic20
|
|
85
|
+
// Note: For agnostic20, I need the AST so that the directive can be picked up on any line as long as it is the first statement of the file.
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Gets the ESLint-generated Abstract Syntax Tree of a file from its resolved path.
|
|
89
|
+
* @param {string} resolvedPath The resolved path of the file.
|
|
90
|
+
* @returns The ESLint-generated AST (Abstract Syntax Tree) of the file.
|
|
91
|
+
*/
|
|
92
|
+
export const getASTFromFilePath = (resolvedPath) => {
|
|
93
|
+
const linter = new Linter();
|
|
94
|
+
// the raw code of the file at the end of the resolved path
|
|
95
|
+
const text = fs.readFileSync(resolvedPath, "utf8");
|
|
96
|
+
// utilizes linter.verify ...
|
|
97
|
+
linter.verify(text, { languageOptions: typeScriptCompatible });
|
|
98
|
+
// ... to retrieve the raw code as a SourceCode object ...
|
|
99
|
+
const code = linter.getSourceCode();
|
|
100
|
+
// ... from which to extra the ESLint-generated AST
|
|
101
|
+
const ast = code.ast;
|
|
102
|
+
|
|
103
|
+
return ast;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/* getImportedFileFirstLine */ // for directive21
|
|
107
|
+
// Note: For directive21, I prioritize reading from the file system for performance, forgoing the retrieval of the source code comments for imported modules, since the Directive-First Architecture imposes that the first line of the file is reserved for its commented directive.
|
|
82
108
|
|
|
83
109
|
/**
|
|
84
110
|
* Gets the first line of code of the imported module.
|
|
@@ -114,9 +140,10 @@ export const highlightFirstLineOfCode = (context) => ({
|
|
|
114
140
|
/**
|
|
115
141
|
* Returns a boolean deciding if an imported file's "resolved" directive is incompatible with the current file's "resolved" directive.
|
|
116
142
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} T
|
|
143
|
+
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} U
|
|
117
144
|
* @param {ResolvedDirectives_BlockedImports<T>} resolvedDirectives_blockedImports The blocked imports object, either for agnostic20 or for directive21.
|
|
118
145
|
* @param {T} currentFileResolvedDirective The current file's "resolved" directive.
|
|
119
|
-
* @param {
|
|
146
|
+
* @param {U} importedFileResolvedDirective The imported file's "resolved" directive.
|
|
120
147
|
* @returns `true` if the import is blocked, as established in respective `resolvedDirectives_blockedImports`.
|
|
121
148
|
*/
|
|
122
149
|
export const isImportBlocked = (
|
|
@@ -135,8 +162,8 @@ export const isImportBlocked = (
|
|
|
135
162
|
* Makes the intro for each specific import rule violation messages.
|
|
136
163
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} T
|
|
137
164
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} U
|
|
138
|
-
* @param {T} currentFileResolvedDirective The current file's "resolved" directive
|
|
139
|
-
* @param {U} importedFileResolvedDirective The imported file's "resolved" directive
|
|
165
|
+
* @param {T} currentFileResolvedDirective The current file's "resolved" directive.
|
|
166
|
+
* @param {U} importedFileResolvedDirective The imported file's "resolved" directive.
|
|
140
167
|
* @returns "[Current file 'resolved' modules] are not allowed to import [imported file 'resolved' modules]."
|
|
141
168
|
*/
|
|
142
169
|
export const makeIntroForSpecificViolationMessage = (
|
|
@@ -194,9 +221,10 @@ export const makeMessageFromCurrentFileResolvedDirective = (
|
|
|
194
221
|
/**
|
|
195
222
|
* Finds the `message` for the specific violation of "resolved" directives import rules based on `resolvedDirectives_blockedImports`.
|
|
196
223
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} T
|
|
224
|
+
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} U
|
|
197
225
|
* @param {ResolvedDirectives_BlockedImports<T>} resolvedDirectives_blockedImports The blocked imports object, either for agnostic20 or for directive21.
|
|
198
|
-
* @param {T} currentFileResolvedDirective The current file's "resolved" directive
|
|
199
|
-
* @param {
|
|
226
|
+
* @param {T} currentFileResolvedDirective The current file's "resolved" directive.
|
|
227
|
+
* @param {U} importedFileResolvedDirective The imported file's "resolved" directive.
|
|
200
228
|
* @returns The corresponding `message`.
|
|
201
229
|
*/
|
|
202
230
|
export const findSpecificViolationMessage = (
|
|
@@ -54,28 +54,28 @@ export const FUNCTIONS = "functions";
|
|
|
54
54
|
|
|
55
55
|
// mapping directives with effective directives
|
|
56
56
|
/** @type {Directives_EffectiveDirectives} */
|
|
57
|
-
export const directives_effectiveDirectives = {
|
|
58
|
-
[NO_DIRECTIVE]: {
|
|
57
|
+
export const directives_effectiveDirectives = Object.freeze({
|
|
58
|
+
[NO_DIRECTIVE]: Object.freeze({
|
|
59
59
|
[LOGICS]: USE_SERVER_LOGICS,
|
|
60
60
|
[COMPONENTS]: USE_SERVER_COMPONENTS,
|
|
61
61
|
[FUNCTIONS]: null,
|
|
62
|
-
},
|
|
63
|
-
[USE_SERVER]: {
|
|
62
|
+
}),
|
|
63
|
+
[USE_SERVER]: Object.freeze({
|
|
64
64
|
[LOGICS]: null,
|
|
65
65
|
[COMPONENTS]: null,
|
|
66
66
|
[FUNCTIONS]: USE_SERVER_FUNCTIONS,
|
|
67
|
-
},
|
|
68
|
-
[USE_CLIENT]: {
|
|
67
|
+
}),
|
|
68
|
+
[USE_CLIENT]: Object.freeze({
|
|
69
69
|
[LOGICS]: USE_CLIENT_LOGICS,
|
|
70
70
|
[COMPONENTS]: USE_CLIENT_COMPONENTS,
|
|
71
71
|
[FUNCTIONS]: null,
|
|
72
|
-
},
|
|
73
|
-
[USE_AGNOSTIC]: {
|
|
72
|
+
}),
|
|
73
|
+
[USE_AGNOSTIC]: Object.freeze({
|
|
74
74
|
[LOGICS]: USE_AGNOSTIC_LOGICS,
|
|
75
75
|
[COMPONENTS]: USE_AGNOSTIC_COMPONENTS,
|
|
76
76
|
[FUNCTIONS]: null,
|
|
77
|
-
},
|
|
78
|
-
};
|
|
77
|
+
}),
|
|
78
|
+
});
|
|
79
79
|
|
|
80
80
|
// message placeholders
|
|
81
81
|
export const currentFileEffectiveDirective = "currentFileEffectiveDirective";
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
/* currentFileFlow */
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* The flow that begins the import rules enforcement rule, retrieving the
|
|
43
|
+
* The flow that begins the import rules enforcement rule, retrieving the effective directive of the current file before comparing it to upcoming effective directives of the files it imports.
|
|
44
44
|
* @param {Context} context The ESLint rule's `context` object.
|
|
45
45
|
* @returns Either an object with `skip: true` to disregard or one with the non-null `currentFileEffectiveDirective`.
|
|
46
46
|
*/
|
|
@@ -9,13 +9,14 @@ import {
|
|
|
9
9
|
} from "../constants/bases.js";
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
|
-
getImportedFileFirstLine,
|
|
13
12
|
isImportBlocked as commonsIsImportBlocked,
|
|
14
13
|
makeMessageFromCurrentFileResolvedDirective,
|
|
15
14
|
findSpecificViolationMessage as commonsFindSpecificViolationMessage,
|
|
15
|
+
getASTFromFilePath,
|
|
16
16
|
} from "../../../_commons/utilities/helpers.js";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
+
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').AST} AST
|
|
19
20
|
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').Context} Context
|
|
20
21
|
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').Directive} Directive
|
|
21
22
|
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').NoDirective} NoDirective
|
|
@@ -23,20 +24,20 @@ import {
|
|
|
23
24
|
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').EffectiveDirective} EffectiveDirective
|
|
24
25
|
*/
|
|
25
26
|
|
|
26
|
-
/*
|
|
27
|
+
/* getDirectiveFromModule */
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
|
-
* Gets the directive of
|
|
30
|
+
* Gets the directive of a module from its Abstract Syntax Tree.
|
|
30
31
|
* - `null` denotes a server-by-default module, ideally a Server Module.
|
|
31
32
|
* - `'use client'` denotes a Client Module.
|
|
32
33
|
* - `'use server'` denotes a Server Functions Module.
|
|
33
34
|
* - `'use agnostic'` denotes an Agnostic Module (formerly Shared Module).
|
|
34
|
-
* @param {
|
|
35
|
+
* @param {AST} ast The module's AST (Abstract Syntax Tree).
|
|
35
36
|
* @returns The directive, or lack thereof via `null`. The lack of a directive is considered server-by-default.
|
|
36
37
|
*/
|
|
37
|
-
export const
|
|
38
|
+
export const getDirectiveFromModule = (ast) => {
|
|
38
39
|
// the AST body to check for the top-of-the-file directive
|
|
39
|
-
const { body } =
|
|
40
|
+
const { body } = ast;
|
|
40
41
|
|
|
41
42
|
// the first statement from the source code's Abstract Syntax Tree
|
|
42
43
|
const firstStatement = body[0];
|
|
@@ -52,10 +53,46 @@ export const getDirectiveFromCurrentModule = (context) => {
|
|
|
52
53
|
if (value === null) return value;
|
|
53
54
|
|
|
54
55
|
// the value to be exactly 'use client', 'use server' or 'use agnostic' in order not to be considered null by default, or server-by-default
|
|
55
|
-
const
|
|
56
|
+
const moduleDirective =
|
|
56
57
|
directivesArray.find((directive) => directive === value) ?? null;
|
|
57
58
|
|
|
58
|
-
return
|
|
59
|
+
return moduleDirective;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/* getDirectiveFromCurrentModule */
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Gets the directive of the current module.
|
|
66
|
+
* - `null` denotes a server-by-default module, ideally a Server Module.
|
|
67
|
+
* - `'use client'` denotes a Client Module.
|
|
68
|
+
* - `'use server'` denotes a Server Functions Module.
|
|
69
|
+
* - `'use agnostic'` denotes an Agnostic Module (formerly Shared Module).
|
|
70
|
+
* @param {Context} context The ESLint rule's `context` object.
|
|
71
|
+
* @returns The directive, or lack thereof via `null`. The lack of a directive is considered server-by-default.
|
|
72
|
+
*/
|
|
73
|
+
export const getDirectiveFromCurrentModule = (context) => {
|
|
74
|
+
// the AST of the current module
|
|
75
|
+
const ast = context.sourceCode.ast;
|
|
76
|
+
|
|
77
|
+
return getDirectiveFromModule(ast);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/* getDirectiveFromImportedModule */
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Gets the directive of the imported module.
|
|
84
|
+
* - `'use client'` denotes a Client Module.
|
|
85
|
+
* - `'use server'` denotes a Server Functions Module.
|
|
86
|
+
* - `'use agnostic'` denotes an Agnostic Module (formerly Shared Module).
|
|
87
|
+
* - `null` denotes a server-by-default module, ideally a Server Module.
|
|
88
|
+
* @param {string} resolvedImportPath The resolved path of the import.
|
|
89
|
+
* @returns The directive, or lack thereof via `null`. The lack of a directive is considered server-by-default.
|
|
90
|
+
*/
|
|
91
|
+
export const getDirectiveFromImportedModule = (resolvedImportPath) => {
|
|
92
|
+
// the AST of the imported module
|
|
93
|
+
const ast = getASTFromFilePath(resolvedImportPath);
|
|
94
|
+
|
|
95
|
+
return getDirectiveFromModule(ast);
|
|
59
96
|
};
|
|
60
97
|
|
|
61
98
|
/* getEffectiveDirective */
|
|
@@ -83,38 +120,6 @@ export const getEffectiveDirective = (directive, extension) => {
|
|
|
83
120
|
return directives_effectiveDirectives[directive][moduleKind];
|
|
84
121
|
};
|
|
85
122
|
|
|
86
|
-
/* getDirectiveFromImportedModule */
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Gets the directive of the imported module.
|
|
90
|
-
* - `'use client'` denotes a Client Module.
|
|
91
|
-
* - `'use server'` denotes a Server Functions Module.
|
|
92
|
-
* - `'use agnostic'` denotes an Agnostic Module (formerly Shared Module).
|
|
93
|
-
* - `null` denotes a server-by-default module, ideally a Server Module.
|
|
94
|
-
* @param {string} resolvedImportPath The resolved path of the import.
|
|
95
|
-
* @returns The directive, or lack thereof via `null`. The lack of a directive is considered server-by-default.
|
|
96
|
-
*/
|
|
97
|
-
export const getDirectiveFromImportedModule = (resolvedImportPath) => {
|
|
98
|
-
// gets the first line of the code of the import
|
|
99
|
-
const importedFileFirstLine = getImportedFileFirstLine(resolvedImportPath);
|
|
100
|
-
|
|
101
|
-
// verifies that this first line starts with a valid directive, thus excluding comments
|
|
102
|
-
const hasAcceptedDirective = directivesArray.some(
|
|
103
|
-
(directive) =>
|
|
104
|
-
importedFileFirstLine.startsWith(`'${directive}'`) ||
|
|
105
|
-
importedFileFirstLine.startsWith(`"${directive}"`)
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
// applies the correct directive or the lack thereof with null
|
|
109
|
-
const importedFileDirective = hasAcceptedDirective
|
|
110
|
-
? directivesArray.find((directive) =>
|
|
111
|
-
importedFileFirstLine.includes(directive)
|
|
112
|
-
) ?? null
|
|
113
|
-
: null;
|
|
114
|
-
|
|
115
|
-
return importedFileDirective;
|
|
116
|
-
};
|
|
117
|
-
|
|
118
123
|
/* isImportBlocked */
|
|
119
124
|
|
|
120
125
|
/**
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { defineConfig } from "eslint/config";
|
|
2
|
-
import tseslint from "typescript-eslint";
|
|
3
2
|
|
|
4
3
|
import {
|
|
5
4
|
agnostic20ConfigName,
|
|
6
5
|
useAgnosticPluginName,
|
|
7
6
|
enforceEffectiveDirectivesRuleName,
|
|
7
|
+
typeScriptCompatible,
|
|
8
8
|
} from "../_commons/constants/bases.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -26,10 +26,7 @@ export const makeAgnostic20Config = (plugin) => ({
|
|
|
26
26
|
[`${useAgnosticPluginName}/${enforceEffectiveDirectivesRuleName}`]:
|
|
27
27
|
"warn",
|
|
28
28
|
},
|
|
29
|
-
languageOptions:
|
|
30
|
-
// for compatibility with .ts and .tsx
|
|
31
|
-
parser: tseslint.parser,
|
|
32
|
-
},
|
|
29
|
+
languageOptions: typeScriptCompatible,
|
|
33
30
|
},
|
|
34
31
|
]),
|
|
35
32
|
});
|
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
} from "../constants/bases.js";
|
|
12
12
|
|
|
13
13
|
import {
|
|
14
|
-
getImportedFileFirstLine,
|
|
15
14
|
isImportBlocked as commonsIsImportBlocked,
|
|
16
15
|
makeMessageFromCurrentFileResolvedDirective,
|
|
17
16
|
findSpecificViolationMessage as commonsFindSpecificViolationMessage,
|
|
17
|
+
getImportedFileFirstLine,
|
|
18
18
|
} from "../../../_commons/utilities/helpers.js";
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { defineConfig } from "eslint/config";
|
|
2
|
-
import tseslint from "typescript-eslint";
|
|
3
2
|
|
|
4
3
|
import {
|
|
5
4
|
directive21ConfigName,
|
|
6
5
|
useAgnosticPluginName,
|
|
7
6
|
enforceCommentedDirectivesRuleName,
|
|
7
|
+
typeScriptCompatible,
|
|
8
8
|
} from "../_commons/constants/bases.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -26,10 +26,7 @@ export const makeDirective21Config = (plugin) => ({
|
|
|
26
26
|
[`${useAgnosticPluginName}/${enforceCommentedDirectivesRuleName}`]:
|
|
27
27
|
"warn",
|
|
28
28
|
},
|
|
29
|
-
languageOptions:
|
|
30
|
-
// for compatibility with .ts and .tsx
|
|
31
|
-
parser: tseslint.parser,
|
|
32
|
-
},
|
|
29
|
+
languageOptions: typeScriptCompatible,
|
|
33
30
|
},
|
|
34
31
|
]),
|
|
35
32
|
});
|