eslint-plugin-use-agnostic 0.9.6 → 0.9.7
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 +1 -1
- package/library/_commons/constants/bases.js +34 -1
- package/library/_commons/utilities/helpers.js +41 -44
- package/library/agnostic20/_commons/constants/bases.js +36 -31
- package/library/agnostic20/_commons/rules/import-rules.js +5 -1
- package/library/agnostic20/_commons/utilities/flows.js +34 -26
- package/library/agnostic20/_commons/utilities/helpers.js +41 -29
- package/library/agnostic20/config.js +5 -1
- package/library/directive21/_commons/constants/bases.js +31 -58
- package/library/directive21/_commons/rules/import-rules.js +5 -1
- package/library/directive21/_commons/utilities/flows.js +36 -32
- package/library/directive21/_commons/utilities/helpers.js +50 -64
- package/library/directive21/config.js +5 -1
- package/library/index.js +9 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ import { defineConfig, globalIgnores } from "eslint/config";
|
|
|
20
20
|
import useAgnostic, {
|
|
21
21
|
useAgnosticPluginName,
|
|
22
22
|
agnostic20ConfigName,
|
|
23
|
-
} from "eslint-plugin-use-agnostic";
|
|
23
|
+
} from "eslint-plugin-use-agnostic";
|
|
24
24
|
|
|
25
25
|
export default defineConfig([
|
|
26
26
|
globalIgnores([".next", ".react-router", "node_modules"]),
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('../../../types/_commons/typedefs').Extensions} Extensions
|
|
3
|
+
*/
|
|
4
|
+
|
|
1
5
|
/* plugin names */
|
|
2
6
|
// use-agnostic
|
|
3
7
|
export const useAgnosticPluginName = "use-agnostic";
|
|
@@ -45,6 +49,7 @@ export const exportNotStrategized =
|
|
|
45
49
|
// all "resolved" directives (from AIA/agnostic20 & DFA/directive21)
|
|
46
50
|
// - AIA: Agnostic-Included Architecture (agnostic20)
|
|
47
51
|
// - DFA: Directive-First Architecture (directive21)
|
|
52
|
+
// agnostic20
|
|
48
53
|
export const USE_SERVER_LOGICS = "use server logics";
|
|
49
54
|
export const USE_CLIENT_LOGICS = "use client logics";
|
|
50
55
|
export const USE_AGNOSTIC_LOGICS = "use agnostic logics";
|
|
@@ -52,11 +57,13 @@ export const USE_SERVER_COMPONENTS = "use server components";
|
|
|
52
57
|
export const USE_CLIENT_COMPONENTS = "use client components";
|
|
53
58
|
export const USE_AGNOSTIC_COMPONENTS = "use agnostic components";
|
|
54
59
|
export const USE_SERVER_FUNCTIONS = "use server functions";
|
|
60
|
+
// and directive21
|
|
55
61
|
export const USE_CLIENT_CONTEXTS = "use client contexts";
|
|
56
62
|
export const USE_AGNOSTIC_CONDITIONS = "use agnostic conditions";
|
|
57
63
|
export const USE_AGNOSTIC_STRATEGIES = "use agnostic strategies";
|
|
58
64
|
|
|
59
65
|
// all "resolved" modules (from AIA/agnostic20 & DFA/directive21)
|
|
66
|
+
// agnostic20
|
|
60
67
|
export const SERVER_LOGICS_MODULE = "Server Logics Module";
|
|
61
68
|
export const CLIENT_LOGICS_MODULE = "Client Logics Module";
|
|
62
69
|
export const AGNOSTIC_LOGICS_MODULE = "Agnostic Logics Module";
|
|
@@ -64,10 +71,30 @@ export const SERVER_COMPONENTS_MODULE = "Server Components Module";
|
|
|
64
71
|
export const CLIENT_COMPONENTS_MODULE = "Client Components Module";
|
|
65
72
|
export const AGNOSTIC_COMPONENTS_MODULE = "Agnostic Components Module";
|
|
66
73
|
export const SERVER_FUNCTIONS_MODULE = "Server Functions Module";
|
|
74
|
+
// and directive21
|
|
67
75
|
export const CLIENT_CONTEXTS_MODULE = "Client Contexts Module";
|
|
68
76
|
export const AGNOSTIC_CONDITIONS_MODULE = "Agnostic Conditions Module";
|
|
69
77
|
export const AGNOSTIC_STRATEGIES_MODULE = "Agnostic Strategies Module";
|
|
70
78
|
|
|
79
|
+
// all mappings of "resolved" directives with "resolved" modules
|
|
80
|
+
// agnostic20
|
|
81
|
+
export const effectiveDirectives_effectiveModules = Object.freeze({
|
|
82
|
+
[USE_SERVER_LOGICS]: SERVER_LOGICS_MODULE,
|
|
83
|
+
[USE_SERVER_COMPONENTS]: SERVER_COMPONENTS_MODULE,
|
|
84
|
+
[USE_SERVER_FUNCTIONS]: SERVER_FUNCTIONS_MODULE,
|
|
85
|
+
[USE_CLIENT_LOGICS]: CLIENT_LOGICS_MODULE,
|
|
86
|
+
[USE_CLIENT_COMPONENTS]: CLIENT_COMPONENTS_MODULE,
|
|
87
|
+
[USE_AGNOSTIC_LOGICS]: AGNOSTIC_LOGICS_MODULE,
|
|
88
|
+
[USE_AGNOSTIC_COMPONENTS]: AGNOSTIC_COMPONENTS_MODULE,
|
|
89
|
+
});
|
|
90
|
+
// and directive21
|
|
91
|
+
export const commentedDirectives_commentedModules = Object.freeze({
|
|
92
|
+
[USE_CLIENT_CONTEXTS]: CLIENT_CONTEXTS_MODULE,
|
|
93
|
+
[USE_AGNOSTIC_CONDITIONS]: AGNOSTIC_CONDITIONS_MODULE,
|
|
94
|
+
[USE_AGNOSTIC_STRATEGIES]: AGNOSTIC_STRATEGIES_MODULE,
|
|
95
|
+
...effectiveDirectives_effectiveModules,
|
|
96
|
+
});
|
|
97
|
+
|
|
71
98
|
// JavaScript/TypeScript extensions
|
|
72
99
|
export const TSX = ".tsx";
|
|
73
100
|
export const TS = ".ts";
|
|
@@ -77,8 +104,14 @@ export const MJS = ".mjs";
|
|
|
77
104
|
export const CJS = ".cjs";
|
|
78
105
|
|
|
79
106
|
// JavaScript/TypeScript extensions array
|
|
80
|
-
/** @type {readonly [TSX, TS, JSX, JS, MJS, CJS]} */
|
|
107
|
+
// /** @type {readonly [TSX, TS, JSX, JS, MJS, CJS]} */
|
|
108
|
+
/** @type {Extensions} */
|
|
81
109
|
export const EXTENSIONS = [TSX, TS, JSX, JS, MJS, CJS]; // In priority order
|
|
82
110
|
|
|
83
111
|
// message strings
|
|
84
112
|
export const ARE_NOT_ALLOWED_TO_IMPORT = "are not allowed to import";
|
|
113
|
+
|
|
114
|
+
// skipping object for flows
|
|
115
|
+
export const skip = Object.freeze({
|
|
116
|
+
skip: true,
|
|
117
|
+
});
|
|
@@ -3,30 +3,23 @@ import path from "path";
|
|
|
3
3
|
|
|
4
4
|
import { loadConfig, createMatchPath } from "tsconfig-paths";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
SERVER_FUNCTIONS_MODULE,
|
|
24
|
-
CLIENT_CONTEXTS_MODULE,
|
|
25
|
-
AGNOSTIC_CONDITIONS_MODULE,
|
|
26
|
-
AGNOSTIC_STRATEGIES_MODULE,
|
|
27
|
-
EXTENSIONS,
|
|
28
|
-
ARE_NOT_ALLOWED_TO_IMPORT,
|
|
29
|
-
} from "../constants/bases.js";
|
|
6
|
+
import { EXTENSIONS, ARE_NOT_ALLOWED_TO_IMPORT } from "../constants/bases.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {import('../../../types/_commons/typedefs').ResolvedDirective} ResolvedDirective
|
|
10
|
+
* @typedef {import('../../../types/_commons/typedefs').ResolvedDirectives_ResolvedModules} ResolvedDirectives_ResolvedModules
|
|
11
|
+
* @typedef {import('../../../types/_commons/typedefs').CurrentFileResolvedDirective} CurrentFileResolvedDirective
|
|
12
|
+
* @typedef {import('../../../types/_commons/typedefs').Context<string, readonly unknown[]>} Context
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @template {CurrentFileResolvedDirective} T
|
|
17
|
+
* @typedef {import('../../../types/_commons/typedefs').ImportedFileResolvedDirective<T>} ImportedFileResolvedDirective
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* @template {CurrentFileResolvedDirective} T
|
|
21
|
+
* @typedef {import('../../../types/_commons/typedefs').ResolvedDirectives_BlockedImports<T>} ResolvedDirectives_BlockedImports
|
|
22
|
+
*/
|
|
30
23
|
|
|
31
24
|
/* resolveImportPath */
|
|
32
25
|
|
|
@@ -110,7 +103,7 @@ export const getImportedFileFirstLine = (resolvedImportPath) => {
|
|
|
110
103
|
|
|
111
104
|
/**
|
|
112
105
|
* Gets the coordinates for the first line of code of a file.
|
|
113
|
-
* @param {
|
|
106
|
+
* @param {Context} context An ESLint rule's `context` object.
|
|
114
107
|
* @returns The `context.report` `loc`-compatible coordinates for the first line of code of a file.
|
|
115
108
|
*/
|
|
116
109
|
export const highlightFirstLineOfCode = (context) => ({
|
|
@@ -122,10 +115,11 @@ export const highlightFirstLineOfCode = (context) => ({
|
|
|
122
115
|
|
|
123
116
|
/**
|
|
124
117
|
* Returns a boolean deciding if an imported file's "resolved" directive is incompatible with the current file's "resolved" directive.
|
|
125
|
-
* @
|
|
126
|
-
* @param {
|
|
127
|
-
* @param {
|
|
128
|
-
* @
|
|
118
|
+
* @template {CurrentFileResolvedDirective} T
|
|
119
|
+
* @param {ResolvedDirectives_BlockedImports<T>} resolvedDirectives_blockedImports The blocked imports object, either for agnostic20 or for directive21.
|
|
120
|
+
* @param {T} currentFileResolvedDirective The current file's "resolved" directive.
|
|
121
|
+
* @param {ImportedFileResolvedDirective<T>} importedFileResolvedDirective The imported file's "resolved" directive.
|
|
122
|
+
* @returns `true` if the import is blocked, as established in respective `resolvedDirectives_blockedImports`.
|
|
129
123
|
*/
|
|
130
124
|
export const isImportBlocked = (
|
|
131
125
|
// Note: "Blocked" here is preferred over "not allowed" because a specific message will be shared for each of the blocked situations, explaining their reasons and the solutions needed.
|
|
@@ -141,33 +135,35 @@ export const isImportBlocked = (
|
|
|
141
135
|
|
|
142
136
|
/**
|
|
143
137
|
* Makes the intro for each specific import rule violation messages.
|
|
144
|
-
* @
|
|
145
|
-
* @param {
|
|
146
|
-
* @param {
|
|
147
|
-
* @
|
|
138
|
+
* @template {CurrentFileResolvedDirective} T
|
|
139
|
+
* @param {ResolvedDirectives_ResolvedModules} resolvedDirectives_resolvedModules The resolved modules object, either for agnostic20 or for directive21.
|
|
140
|
+
* @param {CurrentFileResolvedDirective} currentFileResolvedDirective The current file's "resolved" directive.
|
|
141
|
+
* @param {ImportedFileResolvedDirective<T>} importedFileResolvedDirective The imported file's "resolved" directive.
|
|
142
|
+
* @returns "[Current file 'resolved' modules] are not allowed to import [imported file 'resolved' modules]."
|
|
148
143
|
*/
|
|
149
144
|
export const makeIntroForSpecificViolationMessage = (
|
|
150
|
-
|
|
145
|
+
resolvedDirectives_resolvedModules,
|
|
151
146
|
currentFileResolvedDirective,
|
|
152
147
|
importedFileResolvedDirective
|
|
153
148
|
) =>
|
|
154
|
-
`${
|
|
149
|
+
`${resolvedDirectives_resolvedModules[currentFileResolvedDirective]}s ${ARE_NOT_ALLOWED_TO_IMPORT} ${resolvedDirectives_resolvedModules[importedFileResolvedDirective]}s.`;
|
|
155
150
|
|
|
156
151
|
/* makeMessageFromResolvedDirective */
|
|
157
152
|
|
|
158
153
|
/**
|
|
159
154
|
* Lists in an message the "resolved" modules incompatible with a "resolved" module based on its "resolved" directive.
|
|
160
|
-
* @
|
|
161
|
-
* @param {
|
|
162
|
-
* @param {
|
|
155
|
+
* @template {CurrentFileResolvedDirective} T
|
|
156
|
+
* @param {ResolvedDirectives_ResolvedModules} resolvedDirectives_resolvedModules The resolved modules object, either for agnostic20 or for directive21.
|
|
157
|
+
* @param {ResolvedDirectives_BlockedImports<T>} resolvedDirectives_blockedImports The blocked imports object, either for agnostic20 or for directive21.
|
|
158
|
+
* @param {T} resolvedDirective The "resolved" directive of the "resolved" module.
|
|
163
159
|
* @returns The message listing the incompatible "resolved" modules.
|
|
164
160
|
*/
|
|
165
161
|
export const makeMessageFromResolvedDirective = (
|
|
166
|
-
|
|
162
|
+
resolvedDirectives_resolvedModules,
|
|
167
163
|
resolvedDirectives_blockedImports,
|
|
168
164
|
resolvedDirective
|
|
169
165
|
) => {
|
|
170
|
-
const effectiveModule =
|
|
166
|
+
const effectiveModule = resolvedDirectives_resolvedModules[resolvedDirective];
|
|
171
167
|
const effectiveModulesString = effectiveModule + "s"; // plural
|
|
172
168
|
|
|
173
169
|
const blockedImports =
|
|
@@ -180,7 +176,7 @@ export const makeMessageFromResolvedDirective = (
|
|
|
180
176
|
}
|
|
181
177
|
|
|
182
178
|
const blockedEffectiveModules = blockedImports.map(
|
|
183
|
-
(e) =>
|
|
179
|
+
(e) => resolvedDirectives_resolvedModules[e] + "s" // plural
|
|
184
180
|
);
|
|
185
181
|
|
|
186
182
|
const blockedEffectiveModulesString =
|
|
@@ -197,9 +193,10 @@ export const makeMessageFromResolvedDirective = (
|
|
|
197
193
|
|
|
198
194
|
/**
|
|
199
195
|
* Finds the `message` for the specific violation of "resolved" directives import rules based on `resolvedDirectives_blockedImports`.
|
|
200
|
-
* @
|
|
201
|
-
* @param {
|
|
202
|
-
* @param {
|
|
196
|
+
* @template {CurrentFileResolvedDirective} T
|
|
197
|
+
* @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 {ImportedFileResolvedDirective<T>} importedFileResolvedDirective The imported file's "resolved" directive.
|
|
203
200
|
* @returns The corresponding `message`.
|
|
204
201
|
*/
|
|
205
202
|
export const findSpecificViolationMessage = (
|
|
@@ -6,17 +6,17 @@ import {
|
|
|
6
6
|
USE_CLIENT_COMPONENTS as COMMONS_USE_CLIENT_COMPONENTS,
|
|
7
7
|
USE_AGNOSTIC_LOGICS as COMMONS_USE_AGNOSTIC_LOGICS,
|
|
8
8
|
USE_AGNOSTIC_COMPONENTS as COMMONS_USE_AGNOSTIC_COMPONENTS,
|
|
9
|
-
|
|
10
|
-
SERVER_COMPONENTS_MODULE as COMMONS_SERVER_COMPONENTS_MODULE,
|
|
11
|
-
SERVER_FUNCTIONS_MODULE as COMMONS_SERVER_FUNCTIONS_MODULE,
|
|
12
|
-
CLIENT_LOGICS_MODULE as COMMONS_CLIENT_LOGICS_MODULE,
|
|
13
|
-
CLIENT_COMPONENTS_MODULE as COMMONS_CLIENT_COMPONENTS_MODULE,
|
|
14
|
-
AGNOSTIC_LOGICS_MODULE as COMMONS_AGNOSTIC_LOGICS_MODULE,
|
|
15
|
-
AGNOSTIC_COMPONENTS_MODULE as COMMONS_AGNOSTIC_COMPONENTS_MODULE,
|
|
9
|
+
effectiveDirectives_effectiveModules,
|
|
16
10
|
} from "../../../_commons/constants/bases.js";
|
|
17
11
|
|
|
18
12
|
import { makeIntroForSpecificViolationMessage as commonsMakeIntroForSpecificViolationMessage } from "../../../_commons/utilities/helpers.js";
|
|
19
13
|
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').Directive} Directive
|
|
16
|
+
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').Directives} Directives
|
|
17
|
+
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').EffectiveDirective} EffectiveDirective
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
20
|
// directives
|
|
21
21
|
export const NO_DIRECTIVE = null;
|
|
22
22
|
export const USE_SERVER = "use server";
|
|
@@ -24,11 +24,11 @@ export const USE_CLIENT = "use client";
|
|
|
24
24
|
export const USE_AGNOSTIC = "use agnostic";
|
|
25
25
|
|
|
26
26
|
// directives array
|
|
27
|
-
/** @type {
|
|
27
|
+
/** @type {Directives} */
|
|
28
28
|
export const directivesArray = [USE_SERVER, USE_CLIENT, USE_AGNOSTIC];
|
|
29
29
|
|
|
30
30
|
// directives set
|
|
31
|
-
/** @type {ReadonlySet<
|
|
31
|
+
/** @type {ReadonlySet<Directive>} */
|
|
32
32
|
export const directivesSet = new Set(directivesArray); // no longer used exported to satisfy static type inference
|
|
33
33
|
|
|
34
34
|
// effective directives
|
|
@@ -40,24 +40,29 @@ export const USE_CLIENT_COMPONENTS = COMMONS_USE_CLIENT_COMPONENTS;
|
|
|
40
40
|
export const USE_AGNOSTIC_LOGICS = COMMONS_USE_AGNOSTIC_LOGICS;
|
|
41
41
|
export const USE_AGNOSTIC_COMPONENTS = COMMONS_USE_AGNOSTIC_COMPONENTS;
|
|
42
42
|
|
|
43
|
-
// effective
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
[
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
43
|
+
// mapping directives with effective directives
|
|
44
|
+
/** @type {Readonly<Record<Directive | null, { logics: EffectiveDirective | null, components: EffectiveDirective | null, functions: EffectiveDirective | null }>>} */
|
|
45
|
+
export const directives_effectiveDirectives = Object.freeze({
|
|
46
|
+
[NO_DIRECTIVE]: {
|
|
47
|
+
logics: USE_SERVER_LOGICS,
|
|
48
|
+
components: USE_SERVER_COMPONENTS,
|
|
49
|
+
functions: null,
|
|
50
|
+
},
|
|
51
|
+
[USE_SERVER]: {
|
|
52
|
+
logics: null,
|
|
53
|
+
components: null,
|
|
54
|
+
functions: USE_SERVER_FUNCTIONS,
|
|
55
|
+
},
|
|
56
|
+
[USE_CLIENT]: {
|
|
57
|
+
logics: USE_CLIENT_LOGICS,
|
|
58
|
+
components: USE_CLIENT_COMPONENTS,
|
|
59
|
+
functions: null,
|
|
60
|
+
},
|
|
61
|
+
[USE_AGNOSTIC]: {
|
|
62
|
+
logics: USE_AGNOSTIC_LOGICS,
|
|
63
|
+
components: USE_AGNOSTIC_COMPONENTS,
|
|
64
|
+
functions: null,
|
|
65
|
+
},
|
|
61
66
|
});
|
|
62
67
|
|
|
63
68
|
// message placeholders
|
|
@@ -70,8 +75,8 @@ export const specificViolationMessage = "specificViolationMessage";
|
|
|
70
75
|
|
|
71
76
|
/**
|
|
72
77
|
* Makes the intro for each specific import rule violation messages.
|
|
73
|
-
* @param {
|
|
74
|
-
* @param {
|
|
78
|
+
* @param {EffectiveDirective} currentFileEffectiveDirective The current file's effective directive.
|
|
79
|
+
* @param {EffectiveDirective} importedFileEffectiveDirective The imported file's effective directive.
|
|
75
80
|
* @returns "[Current file effective modules] are not allowed to import [imported file effective modules]."
|
|
76
81
|
*/
|
|
77
82
|
const makeIntroForSpecificViolationMessage = (
|
|
@@ -79,7 +84,7 @@ const makeIntroForSpecificViolationMessage = (
|
|
|
79
84
|
importedFileEffectiveDirective
|
|
80
85
|
) =>
|
|
81
86
|
commonsMakeIntroForSpecificViolationMessage(
|
|
82
|
-
|
|
87
|
+
effectiveDirectives_effectiveModules,
|
|
83
88
|
currentFileEffectiveDirective,
|
|
84
89
|
importedFileEffectiveDirective
|
|
85
90
|
);
|
|
@@ -87,7 +92,7 @@ const makeIntroForSpecificViolationMessage = (
|
|
|
87
92
|
const SUGGEST_USE_AGNOSTIC =
|
|
88
93
|
"If the module you're trying to import does not possess any server-side code however, please mark it with this plugin's own and eponymous 'use agnostic' directive to signal its compatibility across all environments.";
|
|
89
94
|
|
|
90
|
-
export const
|
|
95
|
+
export const effectiveDirectives_blockedImports = Object.freeze({
|
|
91
96
|
[USE_SERVER_LOGICS]: [
|
|
92
97
|
// USE_SERVER_LOGICS allowed, because Server Logics can compose with one another.
|
|
93
98
|
// USE_SERVER_COMPONENTS allowed, because Server Components are OK to be composed with Server Logics as long as the Server Logics Module, by convention, does not export React components.
|
|
@@ -16,7 +16,11 @@ import {
|
|
|
16
16
|
reExportsFlow,
|
|
17
17
|
} from "../utilities/flows.js";
|
|
18
18
|
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').Rule} Rule
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** @type {Rule} */
|
|
20
24
|
const rule = {
|
|
21
25
|
meta: {
|
|
22
26
|
type: "problem",
|
|
@@ -5,16 +5,10 @@ import {
|
|
|
5
5
|
useServerJSXMessageId,
|
|
6
6
|
importBreaksEffectiveImportRulesMessageId,
|
|
7
7
|
reExportNotSameMessageId,
|
|
8
|
+
skip,
|
|
8
9
|
} from "../../../_commons/constants/bases.js";
|
|
9
10
|
import {
|
|
10
11
|
USE_SERVER,
|
|
11
|
-
USE_SERVER_LOGICS,
|
|
12
|
-
USE_SERVER_COMPONENTS,
|
|
13
|
-
USE_SERVER_FUNCTIONS,
|
|
14
|
-
USE_CLIENT_LOGICS,
|
|
15
|
-
USE_CLIENT_COMPONENTS,
|
|
16
|
-
USE_AGNOSTIC_LOGICS,
|
|
17
|
-
USE_AGNOSTIC_COMPONENTS,
|
|
18
12
|
// currentFileEffectiveDirective,
|
|
19
13
|
// importedFileEffectiveDirective,
|
|
20
14
|
effectiveDirectiveMessage,
|
|
@@ -34,14 +28,25 @@ import {
|
|
|
34
28
|
findSpecificViolationMessage,
|
|
35
29
|
} from "./helpers.js";
|
|
36
30
|
|
|
31
|
+
/**
|
|
32
|
+
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').Context} Context
|
|
33
|
+
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').EffectiveDirective} EffectiveDirective
|
|
34
|
+
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').ImportDeclaration} ImportDeclaration
|
|
35
|
+
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').ExportNamedDeclaration} ExportNamedDeclaration
|
|
36
|
+
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').ExportAllDeclaration} ExportAllDeclaration
|
|
37
|
+
*/
|
|
38
|
+
|
|
37
39
|
/* currentFileFlow */
|
|
38
40
|
|
|
41
|
+
// {{skip: true; currentFileEffectiveDirective: undefined;} | {skip: undefined; currentFileEffectiveDirective: EffectiveDirective;}}
|
|
39
42
|
/**
|
|
40
43
|
* The flow that begins the import rules enforcement rule, retrieving the valid directive of the current file before comparing it to upcoming valid directives of the files it imports.
|
|
41
|
-
* @param {
|
|
42
|
-
* @returns
|
|
44
|
+
* @param {Context} context The ESLint rule's `context` object.
|
|
45
|
+
* @returns Either an object with `skip: true` to disregard or one with the non-null `currentFileEffectiveDirective`.
|
|
43
46
|
*/
|
|
44
47
|
export const currentFileFlow = (context) => {
|
|
48
|
+
const skipTrue = { ...skip, currentFileEffectiveDirective: undefined };
|
|
49
|
+
|
|
45
50
|
// GETTING THE EXTENSION OF THE CURRENT FILE
|
|
46
51
|
const currentFileExtension = path.extname(context.filename);
|
|
47
52
|
|
|
@@ -53,7 +58,7 @@ export const currentFileFlow = (context) => {
|
|
|
53
58
|
console.error(
|
|
54
59
|
"ERROR. Linted files for this rule should only be in JavaScript (TypeScript)."
|
|
55
60
|
);
|
|
56
|
-
return
|
|
61
|
+
return skipTrue;
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
/* GETTING THE DIRECTIVE (or lack thereof) OF THE CURRENT FILE */
|
|
@@ -68,7 +73,7 @@ export const currentFileFlow = (context) => {
|
|
|
68
73
|
loc: highlightFirstLineOfCode(context),
|
|
69
74
|
messageId: useServerJSXMessageId,
|
|
70
75
|
});
|
|
71
|
-
return
|
|
76
|
+
return skipTrue;
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
// GETTING THE EFFECTIVE DIRECTIVE OF THE CURRENT FILE
|
|
@@ -80,21 +85,24 @@ export const currentFileFlow = (context) => {
|
|
|
80
85
|
// fails if one of the seven effective directives has not been obtained
|
|
81
86
|
if (currentFileEffectiveDirective === null) {
|
|
82
87
|
console.error("ERROR. Effective directive should never be null.");
|
|
83
|
-
return
|
|
88
|
+
return skipTrue;
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
return { currentFileEffectiveDirective };
|
|
91
|
+
return { skip: undefined, currentFileEffectiveDirective };
|
|
87
92
|
};
|
|
88
93
|
|
|
89
94
|
/* importedFileFlow */
|
|
90
95
|
|
|
96
|
+
// {{skip: true; importedFileEffectiveDirective: undefined;} | {skip: undefined; importedFileEffectiveDirective: EffectiveDirective;}}
|
|
91
97
|
/**
|
|
92
98
|
* The flow that is shared between import and re-export traversals to obtain the import file's effective directive.
|
|
93
|
-
* @param {
|
|
94
|
-
* @param {
|
|
95
|
-
* @returns
|
|
99
|
+
* @param {Context} context The ESLint rule's `context` object.
|
|
100
|
+
* @param {ImportDeclaration} node The ESLint `node` of the rule's current traversal.
|
|
101
|
+
* @returns Either an object with `skip: true` to disregard or one with the non-null `importedFileEffectiveDirective`.
|
|
96
102
|
*/
|
|
97
103
|
const importedFileFlow = (context, node) => {
|
|
104
|
+
const skipTrue = { ...skip, importedFileEffectiveDirective: undefined };
|
|
105
|
+
|
|
98
106
|
// finds the full path of the import
|
|
99
107
|
const resolvedImportPath = resolveImportPath(
|
|
100
108
|
path.dirname(context.filename),
|
|
@@ -103,12 +111,12 @@ const importedFileFlow = (context, node) => {
|
|
|
103
111
|
);
|
|
104
112
|
|
|
105
113
|
// does not operate on paths it did not resolve
|
|
106
|
-
if (resolvedImportPath === null) return
|
|
114
|
+
if (resolvedImportPath === null) return skipTrue;
|
|
107
115
|
// does not operate on non-JS files
|
|
108
116
|
const isImportedFileJS = EXTENSIONS.some((ext) =>
|
|
109
117
|
resolvedImportPath.endsWith(ext)
|
|
110
118
|
);
|
|
111
|
-
if (!isImportedFileJS) return
|
|
119
|
+
if (!isImportedFileJS) return skipTrue;
|
|
112
120
|
|
|
113
121
|
/* GETTING THE DIRECTIVE (or lack thereof) OF THE IMPORTED FILE */
|
|
114
122
|
const importedFileDirective =
|
|
@@ -124,20 +132,20 @@ const importedFileFlow = (context, node) => {
|
|
|
124
132
|
// also fails if one of the seven effective directives has not been obtained
|
|
125
133
|
if (importedFileEffectiveDirective === null) {
|
|
126
134
|
console.error("ERROR. Effective directive should never be null.");
|
|
127
|
-
return
|
|
135
|
+
return skipTrue;
|
|
128
136
|
}
|
|
129
137
|
|
|
130
138
|
// For now skipping on both "does not operate" (which should ignore) and "fails" albeit with console.error (which should crash).
|
|
131
139
|
|
|
132
|
-
return { importedFileEffectiveDirective };
|
|
140
|
+
return { skip: undefined, importedFileEffectiveDirective };
|
|
133
141
|
};
|
|
134
142
|
|
|
135
143
|
/* importsFlow */
|
|
136
144
|
|
|
137
145
|
/** The full flow for import traversals to enforce effective directives import rules.
|
|
138
|
-
* @param {
|
|
139
|
-
* @param {
|
|
140
|
-
* @param {
|
|
146
|
+
* @param {Context} context The ESLint rule's `context` object.
|
|
147
|
+
* @param {ImportDeclaration} node The ESLint `node` of the rule's current traversal.
|
|
148
|
+
* @param {EffectiveDirective} currentFileEffectiveDirective The current file's effective directive.
|
|
141
149
|
* @returns Early if the flow needs to be interrupted.
|
|
142
150
|
*/
|
|
143
151
|
export const importsFlow = (context, node, currentFileEffectiveDirective) => {
|
|
@@ -174,9 +182,9 @@ export const importsFlow = (context, node, currentFileEffectiveDirective) => {
|
|
|
174
182
|
/* reExportsFlow */
|
|
175
183
|
|
|
176
184
|
/** The full flow for export traversals, shared between `ExportNamedDeclaration` and `ExportAllDeclaration`, to ensure same effective directive re-exports.
|
|
177
|
-
* @param {
|
|
178
|
-
* @param {
|
|
179
|
-
* @param {
|
|
185
|
+
* @param {Context} context The ESLint rule's `context` object.
|
|
186
|
+
* @param {ExportNamedDeclaration | ExportAllDeclaration} node The ESLint `node` of the rule's current traversal.
|
|
187
|
+
* @param {EffectiveDirective} currentFileEffectiveDirective The current file's effective directive.
|
|
180
188
|
* @returns Early if the flow needs to be interrupted.
|
|
181
189
|
*/
|
|
182
190
|
export const reExportsFlow = (context, node, currentFileEffectiveDirective) => {
|