eslint-plugin-use-agnostic 1.3.3 → 1.3.4
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/comments.config.json +2700 -540
- package/jscomments/_commons/constants/bases.js +5 -1
- package/jscomments/jsdoc/composed-variables.js +6 -3
- package/library/_commons/utilities/helpers.js +21 -21
- package/library/agnostic20/_commons/constants/bases.js +58 -62
- package/library/agnostic20/_commons/utilities/flows.js +17 -17
- package/library/agnostic20/_commons/utilities/helpers.js +43 -43
- package/library/agnostic20/config.js +3 -3
- package/library/directive21/_commons/constants/bases.js +86 -90
- package/library/directive21/_commons/utilities/flows.js +18 -18
- package/library/directive21/_commons/utilities/helpers.js +86 -86
- package/library/directive21/config.js +3 -3
- package/package.json +1 -1
|
@@ -4,15 +4,19 @@ import path from "path";
|
|
|
4
4
|
import { createRequire } from "module";
|
|
5
5
|
const require = createRequire(import.meta.url);
|
|
6
6
|
|
|
7
|
+
// // (Only useful during development.)
|
|
8
|
+
// const resolvedConfigDataForType = await import("../../../comments.config.json");
|
|
9
|
+
|
|
7
10
|
const filename = url.fileURLToPath(import.meta.url);
|
|
8
11
|
const dirname = path.dirname(filename);
|
|
9
12
|
|
|
10
13
|
const rawPath = path.join(dirname, "../../../comments.config.json");
|
|
11
14
|
|
|
15
|
+
// /** @type {typeof resolvedConfigDataForType.default} (The `default` property on `resolvedConfigDataForType` – and I assume on `raw` itself – is a copy of the whole thing, naturally not including the `default` property recursively. Though `.default` here is unnecessary and technically untrue, it allows the inferred type to look better.) */
|
|
12
16
|
const raw = require(rawPath);
|
|
13
17
|
export const resolvedConfigData = raw;
|
|
14
18
|
|
|
15
19
|
/* Notes
|
|
16
20
|
We're actually not supposed to install comment-variables-resolve-config. What's supposed to happen is that the resolved config data should be made and consumed as a JSON either via a command in the CLI or automatically on save by the VS Code extension.
|
|
17
|
-
For the CLI, the decision has been taken to automatically create the JSON every time the CLI is successfully run with any command.
|
|
21
|
+
For the CLI, the decision has been taken to automatically create the JSON every time the CLI is successfully run with any command. For the plugin, that's on every save connected to the config file.
|
|
18
22
|
*/
|
|
@@ -79,9 +79,12 @@ export const forComposedVariables = Object.freeze({
|
|
|
79
79
|
"for agnostic20." /* $COMMENT#JSDOC#FORCOMPOSEDVARIABLES#FORAGNOSTIC20 */,
|
|
80
80
|
forDirective21:
|
|
81
81
|
"for directive21." /* $COMMENT#JSDOC#FORCOMPOSEDVARIABLES#FORDIRECTIVE21 */,
|
|
82
|
-
ruleTesterArray:
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
ruleTesterArray:
|
|
83
|
+
"The RuleTester's array of" /* $COMMENT#JSDOC#FORCOMPOSEDVARIABLES#RULETESTERARRAY */,
|
|
84
|
+
withNeededProperties:
|
|
85
|
+
"with needed properties" /* $COMMENT#JSDOC#FORCOMPOSEDVARIABLES#WITHNEEDEDPROPERTIES */,
|
|
86
|
+
withNeededPropertiesPeriod:
|
|
87
|
+
"with needed properties." /* $COMMENT#JSDOC#FORCOMPOSEDVARIABLES#WITHNEEDEDPROPERTIESPERIOD */,
|
|
85
88
|
theCurrentFile:
|
|
86
89
|
"The current file's" /* $COMMENT#JSDOC#FORCOMPOSEDVARIABLES#THECURRENTFILE */,
|
|
87
90
|
theImportedFile:
|
|
@@ -17,9 +17,9 @@ import {
|
|
|
17
17
|
/* highlightFirstLineOfCode */
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
* @param {Context} context
|
|
22
|
-
* @returns
|
|
20
|
+
* Gets the coordinates for the first line of code of a file.
|
|
21
|
+
* @param {Context} context An ESLint rule's `context` object.
|
|
22
|
+
* @returns The `context.report` `loc`-compatible coordinates for the first line of code of a file.
|
|
23
23
|
*/
|
|
24
24
|
export const highlightFirstLineOfCode = (context) => ({
|
|
25
25
|
start: { line: 1, column: 0 },
|
|
@@ -29,13 +29,13 @@ export const highlightFirstLineOfCode = (context) => ({
|
|
|
29
29
|
/* isImportBlocked */
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
32
|
+
* Returns a boolean deciding if an imported file's "resolved" directive is incompatible with the current file's "resolved" directive.
|
|
33
33
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} T
|
|
34
34
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} U
|
|
35
|
-
* @param {ResolvedDirectives_BlockedImports<T, U>} resolvedDirectives_blockedImports
|
|
36
|
-
* @param {T} currentFileResolvedDirective
|
|
37
|
-
* @param {U} importedFileResolvedDirective
|
|
38
|
-
* @returns
|
|
35
|
+
* @param {ResolvedDirectives_BlockedImports<T, U>} resolvedDirectives_blockedImports The blocked imports object, either for agnostic20 or for directive21.
|
|
36
|
+
* @param {T} currentFileResolvedDirective The current file's "resolved" directive.
|
|
37
|
+
* @param {U} importedFileResolvedDirective The imported file's "resolved" directive.
|
|
38
|
+
* @returns `true` if the import is blocked, as established in respective `resolvedDirectives_blockedImports`.
|
|
39
39
|
*/
|
|
40
40
|
export const isImportBlocked = (
|
|
41
41
|
// 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.
|
|
@@ -50,12 +50,12 @@ export const isImportBlocked = (
|
|
|
50
50
|
/* makeIntroForSpecificViolationMessage */
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
|
-
*
|
|
53
|
+
* Makes the intro for each specific import rule violation messages.
|
|
54
54
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} T
|
|
55
55
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} U
|
|
56
|
-
* @param {T} currentFileResolvedDirective
|
|
57
|
-
* @param {U} importedFileResolvedDirective
|
|
58
|
-
* @returns
|
|
56
|
+
* @param {T} currentFileResolvedDirective The current file's "resolved" directive.
|
|
57
|
+
* @param {U} importedFileResolvedDirective The imported file's "resolved" directive.
|
|
58
|
+
* @returns "[Current file 'resolved' modules] are not allowed to import [imported file 'resolved' modules]."
|
|
59
59
|
*/
|
|
60
60
|
export const makeIntroForSpecificViolationMessage = (
|
|
61
61
|
currentFileResolvedDirective,
|
|
@@ -70,12 +70,12 @@ export const makeIntroForSpecificViolationMessage = (
|
|
|
70
70
|
/* makeMessageFromCurrentFileResolvedDirective */
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
|
-
*
|
|
73
|
+
* Lists in an message the "resolved" modules incompatible with a "resolved" module based on its "resolved" directive.
|
|
74
74
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} T
|
|
75
75
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} U
|
|
76
|
-
* @param {ResolvedDirectives_BlockedImports<T, U>} resolvedDirectives_blockedImports
|
|
77
|
-
* @param {T} currentFileResolvedDirective
|
|
78
|
-
* @returns
|
|
76
|
+
* @param {ResolvedDirectives_BlockedImports<T, U>} resolvedDirectives_blockedImports The blocked imports object, either for agnostic20 or for directive21.
|
|
77
|
+
* @param {T} currentFileResolvedDirective The "resolved" directive of the "resolved" module.
|
|
78
|
+
* @returns The message listing the incompatible "resolved" modules.
|
|
79
79
|
*/
|
|
80
80
|
export const makeMessageFromCurrentFileResolvedDirective = (
|
|
81
81
|
resolvedDirectives_blockedImports,
|
|
@@ -111,13 +111,13 @@ export const makeMessageFromCurrentFileResolvedDirective = (
|
|
|
111
111
|
/* findSpecificViolationMessage */
|
|
112
112
|
|
|
113
113
|
/**
|
|
114
|
-
*
|
|
114
|
+
* Finds the `message` for the specific violation of "resolved" directives import rules based on `resolvedDirectives_blockedImports`.
|
|
115
115
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} T
|
|
116
116
|
* @template {ResolvedDirectiveWithoutUseAgnosticStrategies} U
|
|
117
|
-
* @param {ResolvedDirectives_BlockedImports<T, U>} resolvedDirectives_blockedImports
|
|
118
|
-
* @param {T} currentFileResolvedDirective
|
|
119
|
-
* @param {U} importedFileResolvedDirective
|
|
120
|
-
* @returns
|
|
117
|
+
* @param {ResolvedDirectives_BlockedImports<T, U>} resolvedDirectives_blockedImports The blocked imports object, either for agnostic20 or for directive21.
|
|
118
|
+
* @param {T} currentFileResolvedDirective The current file's "resolved" directive.
|
|
119
|
+
* @param {U} importedFileResolvedDirective The imported file's "resolved" directive.
|
|
120
|
+
* @returns The corresponding `message`.
|
|
121
121
|
*/
|
|
122
122
|
export const findSpecificViolationMessage = (
|
|
123
123
|
resolvedDirectives_blockedImports,
|
|
@@ -13,10 +13,6 @@ import { makeIntroForSpecificViolationMessage } from "../../../_commons/utilitie
|
|
|
13
13
|
|
|
14
14
|
import { resolvedConfigData } from "../../../../jscomments/_commons/constants/bases.js";
|
|
15
15
|
|
|
16
|
-
// const resolvedConfigData = await import("../../../../comments.config.json", {
|
|
17
|
-
// assert: { type: "json" },
|
|
18
|
-
// });
|
|
19
|
-
|
|
20
16
|
/**
|
|
21
17
|
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').Directive} Directive
|
|
22
18
|
* @typedef {import('../../../../types/agnostic20/_commons/typedefs.js').Directives} Directives
|
|
@@ -93,12 +89,12 @@ const SUGGEST_USE_AGNOSTIC =
|
|
|
93
89
|
"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.";
|
|
94
90
|
|
|
95
91
|
/**
|
|
96
|
-
*
|
|
92
|
+
* Makes a blockedImport object for the identified blocked import at hand.
|
|
97
93
|
* @template {EffectiveDirective} T
|
|
98
94
|
* @template {EffectiveDirective} U
|
|
99
|
-
* @param {T} currentFileEffectiveDirective
|
|
100
|
-
* @param {U} importedFileEffectiveDirective
|
|
101
|
-
* @returns
|
|
95
|
+
* @param {T} currentFileEffectiveDirective The current file's effective directive.
|
|
96
|
+
* @param {U} importedFileEffectiveDirective The imported file's effective directive.
|
|
97
|
+
* @returns The blockedImport object for the identified blocked import at hand.
|
|
102
98
|
*/
|
|
103
99
|
export const makeBlockedImport = (
|
|
104
100
|
currentFileEffectiveDirective,
|
|
@@ -112,18 +108,18 @@ export const makeBlockedImport = (
|
|
|
112
108
|
)} ${
|
|
113
109
|
resolvedConfigData[agnostic20ConfigName][currentFileEffectiveDirective][
|
|
114
110
|
importedFileEffectiveDirective
|
|
115
|
-
]
|
|
111
|
+
].value
|
|
116
112
|
}`,
|
|
117
113
|
});
|
|
118
114
|
};
|
|
119
115
|
|
|
120
116
|
/**
|
|
121
|
-
*
|
|
117
|
+
* Makes a blockedImport object for the identified blocked import at hand enhanced with the suggestion to use the `'use agnostic'` directive.
|
|
122
118
|
* @template {EffectiveDirective} T
|
|
123
119
|
* @template {EffectiveDirective} U
|
|
124
|
-
* @param {T} currentFileEffectiveDirective
|
|
125
|
-
* @param {U} importedFileEffectiveDirective
|
|
126
|
-
* @returns
|
|
120
|
+
* @param {T} currentFileEffectiveDirective The current file's effective directive.
|
|
121
|
+
* @param {U} importedFileEffectiveDirective The imported file's effective directive.
|
|
122
|
+
* @returns The enhanced blockedImport object with the suggestion to use the `'use agnostic'` directive.
|
|
127
123
|
*/
|
|
128
124
|
const makeBlockedImportSuggestingUseAgnostic = (
|
|
129
125
|
currentFileEffectiveDirective,
|
|
@@ -149,123 +145,123 @@ const makeBlockedImportSuggestingUseAgnostic = (
|
|
|
149
145
|
// const jscommentsConfigData = makeResolvedConfig(configPath)
|
|
150
146
|
export const effectiveDirectives_blockedImports = Object.freeze({
|
|
151
147
|
[USE_SERVER_LOGICS]: Object.freeze([
|
|
152
|
-
// USE_SERVER_LOGICS
|
|
153
|
-
// USE_SERVER_COMPONENTS
|
|
154
|
-
// USE_SERVER_FUNCTIONS
|
|
148
|
+
// USE_SERVER_LOGICS allowed, because Server Logics can compose with one another.
|
|
149
|
+
// 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.
|
|
150
|
+
// USE_SERVER_FUNCTIONS allowed, because Server Functions, being able to import one another, can compose and do so via Server Logics, despite this method seeming superfluous at first glance. (Perhaps a preferrable use case for this has been found or could be found either today or in the future.)
|
|
155
151
|
makeBlockedImport(
|
|
156
152
|
USE_SERVER_LOGICS,
|
|
157
153
|
USE_CLIENT_LOGICS
|
|
158
|
-
) /*
|
|
154
|
+
) /* Client Logics should never leak to the server. */,
|
|
159
155
|
makeBlockedImport(
|
|
160
156
|
USE_SERVER_LOGICS,
|
|
161
157
|
USE_CLIENT_COMPONENTS
|
|
162
|
-
) /*
|
|
163
|
-
// USE_AGNOSTIC_LOGICS
|
|
164
|
-
// USE_AGNOSTIC_COMPONENTS
|
|
158
|
+
) /* Client Components cannot be tinkered with on the server. */,
|
|
159
|
+
// USE_AGNOSTIC_LOGICS allowed, because Agnostic Logics can run safely on the server just like they can on the client.
|
|
160
|
+
// USE_AGNOSTIC_COMPONENTS allowed, because Agnostic Components can be composed with Logics on the server just like they can on the client, as long at the Server Logics Module, by convention, does not export React components.
|
|
165
161
|
]),
|
|
166
162
|
[USE_SERVER_COMPONENTS]: Object.freeze([
|
|
167
|
-
// USE_SERVER_LOGICS
|
|
168
|
-
// USE_SERVER_COMPONENTS
|
|
169
|
-
// USE_SERVER_FUNCTIONS
|
|
163
|
+
// USE_SERVER_LOGICS allowed, because Server Logics, being logic from the server, can safely support Server Components.
|
|
164
|
+
// USE_SERVER_COMPONENTS allowed, because Server Components can compose with one another, assuming thanks to the inclusion of the 'use agnostic' directive that they are actual Server Components.
|
|
165
|
+
// USE_SERVER_FUNCTIONS allowed, because Server Functions can be passed to imported Client Components within Server Components Modules, even though indeed Server Components Modules and Server Components can make their own Server Functions through inline `'use server'` directives.
|
|
170
166
|
makeBlockedImport(
|
|
171
167
|
USE_SERVER_COMPONENTS,
|
|
172
168
|
USE_CLIENT_LOGICS
|
|
173
|
-
) /*
|
|
174
|
-
// USE_CLIENT_COMPONENTS
|
|
175
|
-
// USE_AGNOSTIC_LOGICS
|
|
176
|
-
// USE_AGNOSTIC_COMPONENTS
|
|
169
|
+
) /* Client Logics should never leak to the server. */,
|
|
170
|
+
// USE_CLIENT_COMPONENTS allowed, because Client Components can be nested inside Server Components either to wrap some of the tree with client state accessible through child Client Components and pass through Server Components or to create client boundaries when the root of the application is planted on the server.
|
|
171
|
+
// USE_AGNOSTIC_LOGICS allowed, because Agnostic Logics can run safely on the server just like they can on the client.
|
|
172
|
+
// USE_AGNOSTIC_COMPONENTS allowed, because Agnostic Components can render safely on the server just like they can on the client.
|
|
177
173
|
]),
|
|
178
174
|
[USE_SERVER_FUNCTIONS]: Object.freeze([
|
|
179
|
-
// USE_SERVER_LOGICS
|
|
175
|
+
// USE_SERVER_LOGICS allowed, because Server Logics, being logic from the server, can safely support Server Functions.
|
|
180
176
|
makeBlockedImport(
|
|
181
177
|
USE_SERVER_FUNCTIONS,
|
|
182
178
|
USE_SERVER_COMPONENTS
|
|
183
|
-
) /*
|
|
184
|
-
// USE_SERVER_FUNCTIONS
|
|
179
|
+
) /* Server Components aren't allowed because Server Functions have no business working with React Components. */,
|
|
180
|
+
// USE_SERVER_FUNCTIONS allowed, because Server Functions, even though they don't need to import one another and the same results can be generated via Server Logics for the outcome of a single Server Function, can still compose with one another. (Perhaps a preferrable use case for this has been found or could be found either today or in the future.)
|
|
185
181
|
makeBlockedImport(
|
|
186
182
|
USE_SERVER_FUNCTIONS,
|
|
187
183
|
USE_CLIENT_LOGICS
|
|
188
|
-
) /*
|
|
184
|
+
) /* Client Logics should never leak to the server. */,
|
|
189
185
|
makeBlockedImport(
|
|
190
186
|
USE_SERVER_FUNCTIONS,
|
|
191
187
|
USE_CLIENT_COMPONENTS
|
|
192
|
-
) /*
|
|
193
|
-
// USE_AGNOSTIC_LOGICS
|
|
188
|
+
) /* Client Components aren't allowed because Server Functions have no business working with React Components. */,
|
|
189
|
+
// USE_AGNOSTIC_LOGICS allowed, because Agnostic Logics can run safely on the server just like they can on the client.
|
|
194
190
|
makeBlockedImport(
|
|
195
191
|
USE_SERVER_FUNCTIONS,
|
|
196
192
|
USE_AGNOSTIC_COMPONENTS
|
|
197
|
-
) /*
|
|
193
|
+
) /* Agnostic Components aren't allowed because Server Functions have no business working with React Components. */,
|
|
198
194
|
]),
|
|
199
195
|
[USE_CLIENT_LOGICS]: Object.freeze([
|
|
200
196
|
makeBlockedImportSuggestingUseAgnostic(
|
|
201
197
|
USE_CLIENT_LOGICS,
|
|
202
198
|
USE_SERVER_LOGICS
|
|
203
|
-
) /*
|
|
199
|
+
) /* Server Logics should never leak to the client. */,
|
|
204
200
|
makeBlockedImportSuggestingUseAgnostic(
|
|
205
201
|
USE_CLIENT_LOGICS,
|
|
206
202
|
USE_SERVER_COMPONENTS
|
|
207
|
-
) /*
|
|
208
|
-
// USE_SERVER_FUNCTIONS
|
|
209
|
-
// USE_CLIENT_LOGICS
|
|
210
|
-
// USE_CLIENT_COMPONENTS
|
|
211
|
-
// USE_AGNOSTIC_LOGICS
|
|
212
|
-
// USE_AGNOSTIC_COMPONENTS
|
|
203
|
+
) /* Server Components cannot be tinkered with on the client. */,
|
|
204
|
+
// USE_SERVER_FUNCTIONS allowed, because Server Functions can technically be attached to Client Components that are being tinkered with within Client Logics Modules.
|
|
205
|
+
// USE_CLIENT_LOGICS allowed, because Client Logics can compose with one another.
|
|
206
|
+
// USE_CLIENT_COMPONENTS allowed, because Client Components are OK to be composed with Client Logics as long as the Client Logics Module, by convention, does not export React components.
|
|
207
|
+
// USE_AGNOSTIC_LOGICS allowed, because Agnostic Logics can run safely on the client just like they can on the server.
|
|
208
|
+
// USE_AGNOSTIC_COMPONENTS allowed, because Agnostic Components can be composed with Logics on the client just like they can on the server, as long as the Client Logics Module, by convention, does not export React components.
|
|
213
209
|
]),
|
|
214
210
|
[USE_CLIENT_COMPONENTS]: Object.freeze([
|
|
215
211
|
makeBlockedImportSuggestingUseAgnostic(
|
|
216
212
|
USE_CLIENT_LOGICS,
|
|
217
213
|
USE_SERVER_LOGICS
|
|
218
|
-
) /*
|
|
214
|
+
) /* Server Logics should never leak to the client. */,
|
|
219
215
|
makeBlockedImportSuggestingUseAgnostic(
|
|
220
216
|
USE_CLIENT_LOGICS,
|
|
221
217
|
USE_SERVER_COMPONENTS
|
|
222
|
-
) /*
|
|
223
|
-
// USE_SERVER_FUNCTIONS
|
|
224
|
-
// USE_CLIENT_LOGICS
|
|
225
|
-
// USE_CLIENT_COMPONENTS
|
|
226
|
-
// USE_AGNOSTIC_LOGICS
|
|
227
|
-
// USE_AGNOSTIC_COMPONENTS
|
|
218
|
+
) /* Server Components cannot be tinkered with on the client. */,
|
|
219
|
+
// USE_SERVER_FUNCTIONS allowed, because Server Functions can specifically be triggered by Client Components.
|
|
220
|
+
// USE_CLIENT_LOGICS allowed, because Client Logics, being logic from the client, can safely support Client Components.
|
|
221
|
+
// USE_CLIENT_COMPONENTS allowed, because Client Components can compose with one another.
|
|
222
|
+
// USE_AGNOSTIC_LOGICS allowed, because Agnostic Logics can run safely on the client just like they can on the server.
|
|
223
|
+
// USE_AGNOSTIC_COMPONENTS allowed, because Agnostic Components can render safely on the client just like they can on the server.
|
|
228
224
|
]),
|
|
229
225
|
[USE_AGNOSTIC_LOGICS]: Object.freeze([
|
|
230
226
|
makeBlockedImportSuggestingUseAgnostic(
|
|
231
227
|
USE_AGNOSTIC_LOGICS,
|
|
232
228
|
USE_SERVER_LOGICS
|
|
233
|
-
) /*
|
|
229
|
+
) /* Server Logics cannot run on both the server and the client. */,
|
|
234
230
|
makeBlockedImportSuggestingUseAgnostic(
|
|
235
231
|
USE_AGNOSTIC_LOGICS,
|
|
236
232
|
USE_SERVER_COMPONENTS
|
|
237
|
-
) /*
|
|
233
|
+
) /* Server Components cannot be tinkered with on both the server and the client. */,
|
|
238
234
|
makeBlockedImport(
|
|
239
235
|
USE_AGNOSTIC_LOGICS,
|
|
240
236
|
USE_SERVER_FUNCTIONS
|
|
241
|
-
) /*
|
|
237
|
+
) /* Server Functions can be modified on the server and on the client, but their use cases on both environments are not one-to-one compatible, since they're being addressed as they are on the server and addressed as references on the client. */,
|
|
242
238
|
makeBlockedImport(
|
|
243
239
|
USE_AGNOSTIC_LOGICS,
|
|
244
240
|
USE_CLIENT_LOGICS
|
|
245
|
-
) /*
|
|
241
|
+
) /* Client Logics cannot run on both the server and the client. */,
|
|
246
242
|
makeBlockedImport(
|
|
247
243
|
USE_AGNOSTIC_LOGICS,
|
|
248
244
|
USE_CLIENT_COMPONENTS
|
|
249
|
-
) /*
|
|
250
|
-
// USE_AGNOSTIC_LOGICS
|
|
251
|
-
// USE_AGNOSTIC_COMPONENTS
|
|
245
|
+
) /* Client Components cannot be tinkered with on both the server and the client. */,
|
|
246
|
+
// USE_AGNOSTIC_LOGICS allowed, because Agnostic Logics can compose with one another.
|
|
247
|
+
// USE_AGNOSTIC_COMPONENTS allowed, because Agnostic Components can be composed with Logics agnostically as long as the Agnostic Logics Module, by convention, does not export React components.
|
|
252
248
|
]),
|
|
253
249
|
[USE_AGNOSTIC_COMPONENTS]: Object.freeze([
|
|
254
250
|
makeBlockedImportSuggestingUseAgnostic(
|
|
255
251
|
USE_AGNOSTIC_COMPONENTS,
|
|
256
252
|
USE_SERVER_LOGICS
|
|
257
|
-
) /*
|
|
253
|
+
) /* Server Logics cannot run on both the server and the client. */,
|
|
258
254
|
makeBlockedImportSuggestingUseAgnostic(
|
|
259
255
|
USE_AGNOSTIC_COMPONENTS,
|
|
260
256
|
USE_SERVER_COMPONENTS
|
|
261
|
-
) /*
|
|
262
|
-
// USE_SERVER_FUNCTIONS
|
|
257
|
+
) /* Server Components, unlike Client Components, cannot make silos of their own once on the opposing environment (the client in this case), and therefore cannot be executed from the client, making them unable to execute agnostically from both the server and the client. */,
|
|
258
|
+
// USE_SERVER_FUNCTIONS allowed, because Server Functions can be passed to Client Components as props when Client Components are also legally imported into Agnostic Components Modules.
|
|
263
259
|
makeBlockedImport(
|
|
264
260
|
USE_AGNOSTIC_COMPONENTS,
|
|
265
261
|
USE_CLIENT_LOGICS
|
|
266
|
-
) /*
|
|
267
|
-
// USE_CLIENT_COMPONENTS
|
|
268
|
-
// USE_AGNOSTIC_LOGICS
|
|
269
|
-
// USE_AGNOSTIC_COMPONENTS
|
|
262
|
+
) /* Client Logics cannot run on both the server and the client. */,
|
|
263
|
+
// USE_CLIENT_COMPONENTS allowed, because Client Components can be nested inside Agnostic Components either to wrap some of the tree with client state accessible through child Client Components and pass through Server Components — if still on the Server Tree — or to create client boundaries when the root of the application is planted on the server.
|
|
264
|
+
// USE_AGNOSTIC_LOGICS allowed, because Agnostic Logics, being environment-agnostic logic, can safely support Agnostic Components.
|
|
265
|
+
// USE_AGNOSTIC_COMPONENTS allowed, because Agnostic Components can compose with one another.
|
|
270
266
|
]),
|
|
271
267
|
});
|
|
@@ -39,9 +39,9 @@ import {
|
|
|
39
39
|
/* currentFileFlow */
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
* @param {Context} context
|
|
44
|
-
* @returns
|
|
42
|
+
* 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.
|
|
43
|
+
* @param {Context} context The ESLint rule's `context` object.
|
|
44
|
+
* @returns Either an object with `skip: true` to disregard or one with the non-null `currentFileEffectiveDirective`.
|
|
45
45
|
*/
|
|
46
46
|
export const currentFileFlow = (context) => {
|
|
47
47
|
const skipTrue = { ...skip, currentFileEffectiveDirective: undefined };
|
|
@@ -94,10 +94,10 @@ export const currentFileFlow = (context) => {
|
|
|
94
94
|
/* importedFileFlow */
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
|
-
*
|
|
98
|
-
* @param {Context} context
|
|
99
|
-
* @param {ImportDeclaration} node
|
|
100
|
-
* @returns
|
|
97
|
+
* The flow that is shared between import and re-export traversals to obtain the import file's effective directive.
|
|
98
|
+
* @param {Context} context The ESLint rule's `context` object.
|
|
99
|
+
* @param {ImportDeclaration} node The ESLint `node` of the rule's current traversal.
|
|
100
|
+
* @returns Either an object with `skip: true` to disregard or one with the non-null `importedFileEffectiveDirective`.
|
|
101
101
|
*/
|
|
102
102
|
const importedFileFlow = (context, node) => {
|
|
103
103
|
const skipTrue = { ...skip, importedFileEffectiveDirective: undefined };
|
|
@@ -143,11 +143,11 @@ const importedFileFlow = (context, node) => {
|
|
|
143
143
|
|
|
144
144
|
/* importsFlow */
|
|
145
145
|
|
|
146
|
-
/**
|
|
147
|
-
* @param {Context} context
|
|
148
|
-
* @param {ImportDeclaration} node
|
|
149
|
-
* @param {EffectiveDirective} currentFileEffectiveDirective
|
|
150
|
-
* @returns
|
|
146
|
+
/** The full flow for import traversals to enforce effective directives import rules.
|
|
147
|
+
* @param {Context} context The ESLint rule's `context` object.
|
|
148
|
+
* @param {ImportDeclaration} node The ESLint `node` of the rule's current traversal.
|
|
149
|
+
* @param {EffectiveDirective} currentFileEffectiveDirective The current file's effective directive.
|
|
150
|
+
* @returns Early if the flow needs to be interrupted.
|
|
151
151
|
*/
|
|
152
152
|
export const importsFlow = (context, node, currentFileEffectiveDirective) => {
|
|
153
153
|
// does not operate on `import type`
|
|
@@ -183,11 +183,11 @@ export const importsFlow = (context, node, currentFileEffectiveDirective) => {
|
|
|
183
183
|
|
|
184
184
|
/* reExportsFlow */
|
|
185
185
|
|
|
186
|
-
/**
|
|
187
|
-
* @param {Context} context
|
|
188
|
-
* @param {ExportNamedDeclaration | ExportAllDeclaration} node
|
|
189
|
-
* @param {EffectiveDirective} currentFileEffectiveDirective
|
|
190
|
-
* @returns
|
|
186
|
+
/** The full flow for export traversals, shared between `ExportNamedDeclaration` and `ExportAllDeclaration`, to ensure same effective directive re-exports.
|
|
187
|
+
* @param {Context} context The ESLint rule's `context` object.
|
|
188
|
+
* @param {ExportNamedDeclaration | ExportAllDeclaration} node The ESLint `node` of the rule's current traversal.
|
|
189
|
+
* @param {EffectiveDirective} currentFileEffectiveDirective The current file's effective directive.
|
|
190
|
+
* @returns Early if the flow needs to be interrupted.
|
|
191
191
|
*/
|
|
192
192
|
export const reExportsFlow = (context, node, currentFileEffectiveDirective) => {
|
|
193
193
|
// does not operate on `export type`
|
|
@@ -28,13 +28,13 @@ import {
|
|
|
28
28
|
/* getDirectiveFromModule */
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
* -
|
|
33
|
-
* -
|
|
34
|
-
* -
|
|
35
|
-
* -
|
|
36
|
-
* @param {AST} ast
|
|
37
|
-
* @returns
|
|
31
|
+
* Gets the directive of a module from its Abstract Syntax Tree.
|
|
32
|
+
* - `null` denotes a server-by-default module, ideally a Server Module.
|
|
33
|
+
* - `'use server'` denotes a Server Functions Module.
|
|
34
|
+
* - `'use client'` denotes a Client Module.
|
|
35
|
+
* - `'use agnostic'` denotes an Agnostic Module (formerly Shared Module).
|
|
36
|
+
* @param {AST} ast The module's AST (Abstract Syntax Tree).
|
|
37
|
+
* @returns The directive, or lack thereof via `null`. The lack of a directive is considered server-by-default.
|
|
38
38
|
*/
|
|
39
39
|
export const getDirectiveFromModule = (ast) => {
|
|
40
40
|
// the AST body to check for the top-of-the-file directive
|
|
@@ -63,13 +63,13 @@ export const getDirectiveFromModule = (ast) => {
|
|
|
63
63
|
/* getDirectiveFromCurrentModule */
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
67
|
-
* -
|
|
68
|
-
* -
|
|
69
|
-
* -
|
|
70
|
-
* -
|
|
71
|
-
* @param {Context} context
|
|
72
|
-
* @returns
|
|
66
|
+
* Gets the directive of the current module.
|
|
67
|
+
* - `null` denotes a server-by-default module, ideally a Server Module.
|
|
68
|
+
* - `'use server'` denotes a Server Functions Module.
|
|
69
|
+
* - `'use client'` denotes a Client Module.
|
|
70
|
+
* - `'use agnostic'` denotes an Agnostic Module (formerly Shared Module).
|
|
71
|
+
* @param {Context} context The ESLint rule's `context` object.
|
|
72
|
+
* @returns The directive, or lack thereof via `null`. The lack of a directive is considered server-by-default.
|
|
73
73
|
*/
|
|
74
74
|
export const getDirectiveFromCurrentModule = (context) => {
|
|
75
75
|
// the AST of the current module
|
|
@@ -81,13 +81,13 @@ export const getDirectiveFromCurrentModule = (context) => {
|
|
|
81
81
|
/* getDirectiveFromImportedModule */
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
*
|
|
85
|
-
* -
|
|
86
|
-
* -
|
|
87
|
-
* -
|
|
88
|
-
* -
|
|
89
|
-
* @param {string} resolvedPath
|
|
90
|
-
* @returns
|
|
84
|
+
* Gets the directive of the imported module.
|
|
85
|
+
* - `null` denotes a server-by-default module, ideally a Server Module.
|
|
86
|
+
* - `'use server'` denotes a Server Functions Module.
|
|
87
|
+
* - `'use client'` denotes a Client Module.
|
|
88
|
+
* - `'use agnostic'` denotes an Agnostic Module (formerly Shared Module).
|
|
89
|
+
* @param {string} resolvedPath The resolved path of the imported module.
|
|
90
|
+
* @returns The directive, or lack thereof via `null`. The lack of a directive is considered server-by-default.
|
|
91
91
|
*/
|
|
92
92
|
export const getDirectiveFromImportedModule = (resolvedPath) => {
|
|
93
93
|
// the AST of the imported module
|
|
@@ -99,17 +99,17 @@ export const getDirectiveFromImportedModule = (resolvedPath) => {
|
|
|
99
99
|
/* getEffectiveDirective */
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
|
-
*
|
|
103
|
-
* -
|
|
104
|
-
* -
|
|
105
|
-
* -
|
|
106
|
-
* -
|
|
107
|
-
* -
|
|
108
|
-
* -
|
|
109
|
-
* -
|
|
110
|
-
* @param {Directive | NoDirective} directive
|
|
111
|
-
* @param {Extension} extension
|
|
112
|
-
* @returns
|
|
102
|
+
* Gets the effective directive of a module, based on the combination of its directive (or lack thereof) and its extension (depending on whether it ends with 'x' for JSX).
|
|
103
|
+
* - `'use server logics'` denotes a Server Logics Module.
|
|
104
|
+
* - `'use server components'` denotes a Server Components Module.
|
|
105
|
+
* - `'use server functions'` denotes a Server Functions Module.
|
|
106
|
+
* - `'use client logics'` denotes a Client Logics Module.
|
|
107
|
+
* - `'use client components'` denotes a Client Components Module.
|
|
108
|
+
* - `'use agnostic logics'` denotes an Agnostic Logics Module.
|
|
109
|
+
* - `'use agnostic components'` denotes an Agnostic Components Module.
|
|
110
|
+
* @param {Directive | NoDirective} directive The directive as written on top of the file (`"no directive"` if no valid directive).
|
|
111
|
+
* @param {Extension} extension The JavaScript (TypeScript) extension of the file.
|
|
112
|
+
* @returns The effective directive, from which imports rules are applied.
|
|
113
113
|
*/
|
|
114
114
|
export const getEffectiveDirective = (directive, extension) => {
|
|
115
115
|
const moduleKind = extension.endsWith("x")
|
|
@@ -124,10 +124,10 @@ export const getEffectiveDirective = (directive, extension) => {
|
|
|
124
124
|
/* isImportBlocked */
|
|
125
125
|
|
|
126
126
|
/**
|
|
127
|
-
*
|
|
128
|
-
* @param {EffectiveDirective} currentFileEffectiveDirective
|
|
129
|
-
* @param {EffectiveDirective} importedFileEffectiveDirective
|
|
130
|
-
* @returns
|
|
127
|
+
* Returns a boolean deciding if an imported file's effective directive is incompatible with the current file's effective directive.
|
|
128
|
+
* @param {EffectiveDirective} currentFileEffectiveDirective The current file's effective directive.
|
|
129
|
+
* @param {EffectiveDirective} importedFileEffectiveDirective The imported file's effective directive.
|
|
130
|
+
* @returns `true` if the import is blocked, as established in `effectiveDirectives_BlockedImports`.
|
|
131
131
|
*/
|
|
132
132
|
export const isImportBlocked = (
|
|
133
133
|
currentFileEffectiveDirective,
|
|
@@ -142,9 +142,9 @@ export const isImportBlocked = (
|
|
|
142
142
|
/* makeMessageFromCurrentFileEffectiveDirective */
|
|
143
143
|
|
|
144
144
|
/**
|
|
145
|
-
*
|
|
146
|
-
* @param {EffectiveDirective} effectiveDirective
|
|
147
|
-
* @returns
|
|
145
|
+
* Lists in an message the effective modules incompatible with a effective module based on its effective directive.
|
|
146
|
+
* @param {EffectiveDirective} effectiveDirective The effective directive of the effective module.
|
|
147
|
+
* @returns The message listing the incompatible effective modules.
|
|
148
148
|
*/
|
|
149
149
|
export const makeMessageFromCurrentFileEffectiveDirective = (
|
|
150
150
|
effectiveDirective
|
|
@@ -157,10 +157,10 @@ export const makeMessageFromCurrentFileEffectiveDirective = (
|
|
|
157
157
|
/* findSpecificViolationMessage */
|
|
158
158
|
|
|
159
159
|
/**
|
|
160
|
-
*
|
|
161
|
-
* @param {EffectiveDirective} currentFileEffectiveDirective
|
|
162
|
-
* @param {EffectiveDirective} importedFileEffectiveDirective
|
|
163
|
-
* @returns
|
|
160
|
+
* Finds the `message` for the specific violation of effective directives import rules based on `effectiveDirectives_BlockedImports`.
|
|
161
|
+
* @param {EffectiveDirective} currentFileEffectiveDirective The current file's effective directive.
|
|
162
|
+
* @param {EffectiveDirective} importedFileEffectiveDirective The imported file's effective directive.
|
|
163
|
+
* @returns The corresponding `message`.
|
|
164
164
|
*/
|
|
165
165
|
export const findSpecificViolationMessage = (
|
|
166
166
|
currentFileEffectiveDirective,
|
|
@@ -12,9 +12,9 @@ import {
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
* @param {Plugin} plugin
|
|
17
|
-
* @returns
|
|
15
|
+
* Makes the agnostic20 config for the use-agnostic ESLint plugin.
|
|
16
|
+
* @param {Plugin} plugin The use-agnostic ESLint plugin itself.
|
|
17
|
+
* @returns The agnostic20 config's name as a key and its config as its value.
|
|
18
18
|
*/
|
|
19
19
|
export const makeAgnostic20Config = (plugin) => ({
|
|
20
20
|
[agnostic20ConfigName]: defineConfig([
|