eslint-plugin-use-agnostic 0.9.2 → 0.9.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.
@@ -17,7 +17,6 @@ export const enforceEffectiveDirectivesRuleName =
17
17
  // directive21
18
18
  export const enforceCommentedDirectivesRuleName =
19
19
  "enforce-commented-directives-import-rules";
20
-
21
20
  // crossingStrategies (canceled)
22
21
  export const verifySpecifierImportRuleName =
23
22
  "verify-specifier-import-export-same-strategy";
@@ -69,8 +68,7 @@ export const CLIENT_CONTEXTS_MODULE = "Client Contexts Module";
69
68
  export const AGNOSTIC_CONDITIONS_MODULE = "Agnostic Conditions Module";
70
69
  export const AGNOSTIC_STRATEGIES_MODULE = "Agnostic Strategies Module";
71
70
 
72
- /* from the resolveImportPath utility */
73
-
71
+ // JavaScript/TypeScript extensions
74
72
  export const TSX = ".tsx";
75
73
  export const TS = ".ts";
76
74
  export const JSX = ".jsx";
@@ -78,8 +76,9 @@ export const JS = ".js";
78
76
  export const MJS = ".mjs";
79
77
  export const CJS = ".cjs";
80
78
 
79
+ // JavaScript/TypeScript extensions array
80
+ /** @type {readonly [TSX, TS, JSX, JS, MJS, CJS]} */
81
81
  export const EXTENSIONS = [TSX, TS, JSX, JS, MJS, CJS]; // In priority order
82
82
 
83
- /* from the isImportBlocked utility */
84
-
83
+ // message strings
85
84
  export const ARE_NOT_ALLOWED_TO_IMPORT = "are not allowed to import";
@@ -30,15 +30,28 @@ import {
30
30
 
31
31
  /* resolveImportPath */
32
32
 
33
+ /**
34
+ * Finds the existing path of an import that does not have an extension specified.
35
+ * @param {string} basePath The absolute import path with extension yet resolved.
36
+ * @returns The absolute path with its extension or `null` if no path is found.
37
+ */
38
+ const findExistingPath = (basePath) => {
39
+ for (const ext of EXTENSIONS) {
40
+ const fullPath = `${basePath}${ext}`;
41
+ if (fs.existsSync(fullPath)) return fullPath;
42
+ }
43
+ return null;
44
+ };
45
+
33
46
  /**
34
47
  * Resolves an import path to a filesystem path, handling:
35
48
  * - Aliases (via tsconfig.json `paths`)
36
49
  * - Missing extensions (appends .ts, .tsx, etc.)
37
50
  * - Directory imports (e.g., `./components` → `./components/index.ts`)
38
- * @param {string} currentDir Directory of the file containing the import (from `path.dirname(context.filename)`).
51
+ * @param {string} currentDir The directory of the file containing the import (from `path.dirname(context.filename)`).
39
52
  * @param {string} importPath The import specifier (e.g., `@/components/Button` or `./utils`), from the current node.
40
- * @param {string} cwd Project root (from `context.cwd`). Caveat: only as an assumption currently.
41
- * @returns {string | null} Absolute resolved path or `null` if not found.
53
+ * @param {string} cwd The project root (from `context.cwd`). Caveat: only as an assumption currently.
54
+ * @returns The absolute resolved path or `null` if no path is found.
42
55
  */
43
56
  export const resolveImportPath = (currentDir, importPath, cwd) => {
44
57
  // --- Step 1: Resolve aliases (if tsconfig.json `paths` exists) ---
@@ -63,19 +76,15 @@ export const resolveImportPath = (currentDir, importPath, cwd) => {
63
76
  if (path.extname(importPath) && fs.existsSync(basePath)) return basePath;
64
77
 
65
78
  // Case 2: Try appending extensions
66
- for (const ext of EXTENSIONS) {
67
- const fullPath = `${basePath}${ext}`;
68
- if (fs.existsSync(fullPath)) return fullPath;
69
- }
79
+ const extensionlessImportPath = findExistingPath(basePath);
80
+ if (extensionlessImportPath) return extensionlessImportPath;
70
81
 
71
82
  // Case 3: Directory import (e.g., `./components` → `./components/index.ts`)
72
83
  const indexPath = path.join(basePath, "index");
73
- for (const ext of EXTENSIONS) {
74
- const fullPath = `${indexPath}${ext}`;
75
- if (fs.existsSync(fullPath)) return fullPath;
76
- }
84
+ const directoryImportPath = findExistingPath(indexPath);
85
+ if (directoryImportPath) return extensionlessImportPath;
77
86
 
78
- return null; // Not found
87
+ return null; // not found
79
88
  };
80
89
 
81
90
  /* getImportedFileFirstLine */
@@ -83,7 +92,7 @@ export const resolveImportPath = (currentDir, importPath, cwd) => {
83
92
  /**
84
93
  * Gets the first line of code of the imported module.
85
94
  * @param {string} resolvedImportPath The resolved path of the imported module.
86
- * @returns {string} Returns the first line of the imported module.
95
+ * @returns The first line of the imported module.
87
96
  */
88
97
  export const getImportedFileFirstLine = (resolvedImportPath) => {
89
98
  // gets the code of the import
@@ -116,7 +125,7 @@ export const highlightFirstLineOfCode = (context) => ({
116
125
  * @param {Readonly<{"use server logics": {blockedImport: string; message: string;}[]; "use client logics": {blockedImport: string; message: string;}[]; "use agnostic logics": {blockedImport: string; message: string;}[]; "use server components": {blockedImport: string; message: string;}[]; "use client components": {blockedImport: string; message: string;}[]; "use agnostic components": {blockedImport: string; message: string;}[]; "use server functions": {blockedImport: string; message: string;}[]; "use client contexts"?: {blockedImport: string; message: string;}[]; "use agnostic conditions"?: {blockedImport: string; message: string;}[]; "use agnostic strategies"?: {blockedImport: string; message: string;}[];}>} resolvedDirectives_blockedImports The blocked imports object, either for agnostic20 or for directive21.
117
126
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES} currentFileResolvedDirective The current file's "resolved" directive.
118
127
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS} importedFileResolvedDirective The imported file's "resolved" directive.
119
- * @returns {boolean} Returns `true` if the import is blocked, as established in respective `resolvedDirectives_blockedImports`.
128
+ * @returns Returns `true` if the import is blocked, as established in respective `resolvedDirectives_blockedImports`.
120
129
  */
121
130
  export const isImportBlocked = (
122
131
  // 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.
@@ -135,7 +144,7 @@ export const isImportBlocked = (
135
144
  * @param {Readonly<{"use server logics": SERVER_LOGICS_MODULE; "use client logics": CLIENT_LOGICS_MODULE; "use agnostic logics": AGNOSTIC_LOGICS_MODULE; "use server components": SERVER_COMPONENTS_MODULE; "use client components": CLIENT_COMPONENTS_MODULE; "use agnostic components": AGNOSTIC_COMPONENTS_MODULE; "use server functions": SERVER_FUNCTIONS_MODULE; "use client contexts": CLIENT_CONTEXTS_MODULE; "use agnostic conditions": AGNOSTIC_CONDITIONS_MODULE; "use agnostic strategies": AGNOSTIC_STRATEGIES_MODULE;}>} resolvedDirectives_ResolvedModules The resolved modules object, either for agnostic20 or for directive21.
136
145
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES} currentFileResolvedDirective The current file's "resolved" directive.
137
146
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS} importedFileResolvedDirective The imported file's "resolved" directive.
138
- * @returns {string} Returns "[Current file 'resolved' modules] are not allowed to import [imported file 'resolved' modules]."
147
+ * @returns Returns "[Current file 'resolved' modules] are not allowed to import [imported file 'resolved' modules]."
139
148
  */
140
149
  export const makeIntroForSpecificViolationMessage = (
141
150
  resolvedDirectives_ResolvedModules,
@@ -151,7 +160,7 @@ export const makeIntroForSpecificViolationMessage = (
151
160
  * @param {Readonly<{"use server logics": SERVER_LOGICS_MODULE; "use client logics": CLIENT_LOGICS_MODULE; "use agnostic logics": AGNOSTIC_LOGICS_MODULE; "use server components": SERVER_COMPONENTS_MODULE; "use client components": CLIENT_COMPONENTS_MODULE; "use agnostic components": AGNOSTIC_COMPONENTS_MODULE; "use server functions": SERVER_FUNCTIONS_MODULE; "use client contexts": CLIENT_CONTEXTS_MODULE; "use agnostic conditions": AGNOSTIC_CONDITIONS_MODULE; "use agnostic strategies": AGNOSTIC_STRATEGIES_MODULE;}>} resolvedDirectives_ResolvedModules The resolved modules object, either for agnostic20 or for directive21.
152
161
  * @param {Readonly<{"use server logics": {blockedImport: string; message: string;}[]; "use client logics": {blockedImport: string; message: string;}[]; "use agnostic logics": {blockedImport: string; message: string;}[]; "use server components": {blockedImport: string; message: string;}[]; "use client components": {blockedImport: string; message: string;}[]; "use agnostic components": {blockedImport: string; message: string;}[]; "use server functions": {blockedImport: string; message: string;}[]; "use client contexts"?: {blockedImport: string; message: string;}[]; "use agnostic conditions"?: {blockedImport: string; message: string;}[]; "use agnostic strategies"?: {blockedImport: string; message: string;}[];}>} resolvedDirectives_blockedImports The blocked imports object, either for agnostic20 or for directive21.
153
162
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES} resolvedDirective The "resolved" directive of the "resolved" module.
154
- * @returns {string} The message listing the incompatible "resolved" modules.
163
+ * @returns The message listing the incompatible "resolved" modules.
155
164
  */
156
165
  export const makeMessageFromResolvedDirective = (
157
166
  resolvedDirectives_ResolvedModules,
@@ -191,7 +200,7 @@ export const makeMessageFromResolvedDirective = (
191
200
  * @param {Readonly<{"use server logics": {blockedImport: string; message: string;}[]; "use client logics": {blockedImport: string; message: string;}[]; "use agnostic logics": {blockedImport: string; message: string;}[]; "use server components": {blockedImport: string; message: string;}[]; "use client components": {blockedImport: string; message: string;}[]; "use agnostic components": {blockedImport: string; message: string;}[]; "use server functions": {blockedImport: string; message: string;}[]; "use client contexts"?: {blockedImport: string; message: string;}[]; "use agnostic conditions"?: {blockedImport: string; message: string;}[]; "use agnostic strategies"?: {blockedImport: string; message: string;}[];}>} resolvedDirectives_blockedImports The blocked imports object, either for agnostic20 or for directive21.
192
201
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES} currentFileResolvedDirective The current file's "resolved" directive.
193
202
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS} importedFileResolvedDirective The imported file's "resolved" directive.
194
- * @returns {string} The corresponding `message`.
203
+ * @returns The corresponding `message`.
195
204
  */
196
205
  export const findSpecificViolationMessage = (
197
206
  resolvedDirectives_blockedImports,
@@ -23,6 +23,14 @@ export const USE_SERVER = "use server";
23
23
  export const USE_CLIENT = "use client";
24
24
  export const USE_AGNOSTIC = "use agnostic";
25
25
 
26
+ // directives array
27
+ /** @type {readonly [USE_SERVER, USE_CLIENT, USE_AGNOSTIC]} */
28
+ export const directivesArray = [USE_SERVER, USE_CLIENT, USE_AGNOSTIC];
29
+
30
+ // directives set
31
+ /** @type {ReadonlySet<USE_SERVER | USE_CLIENT | USE_AGNOSTIC>} */
32
+ export const directivesSet = new Set(directivesArray); // no longer used exported to satisfy static type inference
33
+
26
34
  // effective directives
27
35
  export const USE_SERVER_LOGICS = COMMONS_USE_SERVER_LOGICS;
28
36
  export const USE_SERVER_COMPONENTS = COMMONS_USE_SERVER_COMPONENTS;
@@ -53,30 +61,18 @@ export const effectiveDirectives_EffectiveModules = Object.freeze({
53
61
  });
54
62
 
55
63
  // message placeholders
56
-
57
64
  export const currentFileEffectiveDirective = "currentFileEffectiveDirective";
58
65
  export const importedFileEffectiveDirective = "importedFileEffectiveDirective";
59
66
  export const effectiveDirectiveMessage = "effectiveDirectiveMessage";
60
67
  export const specificViolationMessage = "specificViolationMessage";
61
68
 
62
- /* from the getDirectiveFromCurrentModule utility */
63
-
64
- export const directivesSet = new Set([USE_SERVER, USE_CLIENT, USE_AGNOSTIC]);
65
-
66
- /* from the getDirectiveFromImportedModule utility */
67
-
68
- /** @type {readonly [USE_SERVER, USE_CLIENT, USE_AGNOSTIC]} */
69
- export const directivesArray = Array.from(directivesSet);
70
-
71
- /* from the isImportBlocked utility */
72
-
73
69
  /* effectiveDirectives_BlockedImports */
74
70
 
75
71
  /**
76
72
  * Makes the intro for each specific import rule violation messages.
77
73
  * @param {USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS} currentFileEffectiveDirective The current file's effective directive.
78
74
  * @param {USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS} importedFileEffectiveDirective The imported file's effective directive.
79
- * @returns {string} Returns "[Current file effective modules] are not allowed to import [imported file effective modules]."
75
+ * @returns "[Current file effective modules] are not allowed to import [imported file effective modules]."
80
76
  */
81
77
  const makeIntroForSpecificViolationMessage = (
82
78
  currentFileEffectiveDirective,
@@ -7,6 +7,7 @@ import {
7
7
  reExportNotSameMessageId,
8
8
  } from "../../../_commons/constants/bases.js";
9
9
  import {
10
+ USE_SERVER,
10
11
  USE_SERVER_LOGICS,
11
12
  USE_SERVER_COMPONENTS,
12
13
  USE_SERVER_FUNCTIONS,
@@ -38,7 +39,7 @@ import {
38
39
  /**
39
40
  * 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.
40
41
  * @param {Readonly<import('@typescript-eslint/utils').TSESLint.RuleContext<typeof reExportNotSameMessageId | typeof importBreaksEffectiveImportRulesMessageId | typeof useServerJSXMessageId, []>>} context The ESLint rule's `context` object.
41
- * @returns {{skip: true; currentFileEffectiveDirective: undefined;} | {skip: undefined; currentFileEffectiveDirective: USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS;}} Returns either an object with `skip: true` to disregard or one with the non-null `currentFileEffectiveDirective`.
42
+ * @returns {{skip: true; currentFileEffectiveDirective: undefined;} | {skip: undefined; currentFileEffectiveDirective: USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS;}} Either an object with `skip: true` to disregard or one with the non-null `currentFileEffectiveDirective`.
42
43
  */
43
44
  export const currentFileFlow = (context) => {
44
45
  // GETTING THE EXTENSION OF THE CURRENT FILE
@@ -60,7 +61,7 @@ export const currentFileFlow = (context) => {
60
61
 
61
62
  // reports if a file marked "use server" has a JSX extension
62
63
  if (
63
- currentFileDirective === "use server" &&
64
+ currentFileDirective === USE_SERVER &&
64
65
  currentFileExtension.endsWith("x")
65
66
  ) {
66
67
  context.report({
@@ -82,9 +83,7 @@ export const currentFileFlow = (context) => {
82
83
  return { skip: true };
83
84
  }
84
85
 
85
- return {
86
- currentFileEffectiveDirective,
87
- };
86
+ return { currentFileEffectiveDirective };
88
87
  };
89
88
 
90
89
  /* importedFileFlow */
@@ -93,7 +92,7 @@ export const currentFileFlow = (context) => {
93
92
  * The flow that is shared between import and re-export traversals to obtain the import file's effective directive.
94
93
  * @param {Readonly<import('@typescript-eslint/utils').TSESLint.RuleContext<typeof reExportNotSameMessageId | typeof importBreaksEffectiveImportRulesMessageId | typeof useServerJSXMessageId, []>>} context The ESLint rule's `context` object.
95
94
  * @param {import('@typescript-eslint/types').TSESTree.ImportDeclaration} node The ESLint `node` of the rule's current traversal.
96
- * @returns {{skip: true; importedFileEffectiveDirective: undefined; resolvedImportPath: undefined;} | {skip: undefined; importedFileEffectiveDirective: USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS; resolvedImportPath: string;}} Returns either an object with `skip: true` to disregard or one with the non-null `importedFileEffectiveDirective`.
95
+ * @returns {{skip: true; importedFileEffectiveDirective: undefined;} | {skip: undefined; importedFileEffectiveDirective: USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS;}} Either an object with `skip: true` to disregard or one with the non-null `importedFileEffectiveDirective`.
97
96
  */
98
97
  const importedFileFlow = (context, node) => {
99
98
  // finds the full path of the import
@@ -130,9 +129,7 @@ const importedFileFlow = (context, node) => {
130
129
 
131
130
  // For now skipping on both "does not operate" (which should ignore) and "fails" albeit with console.error (which should crash).
132
131
 
133
- return {
134
- importedFileEffectiveDirective,
135
- };
132
+ return { importedFileEffectiveDirective };
136
133
  };
137
134
 
138
135
  /* importsFlow */
@@ -141,7 +138,7 @@ const importedFileFlow = (context, node) => {
141
138
  * @param {Readonly<import('@typescript-eslint/utils').TSESLint.RuleContext<typeof reExportNotSameMessageId | typeof importBreaksEffectiveImportRulesMessageId | typeof useServerJSXMessageId, []>>} context The ESLint rule's `context` object.
142
139
  * @param {import('@typescript-eslint/types').TSESTree.ImportDeclaration} node The ESLint `node` of the rule's current traversal.
143
140
  * @param {USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS} currentFileEffectiveDirective The current file's effective directive.
144
- * @returns Returns early if the flow needs to be interrupted.
141
+ * @returns Early if the flow needs to be interrupted.
145
142
  */
146
143
  export const importsFlow = (context, node, currentFileEffectiveDirective) => {
147
144
  // does not operate on `import type`
@@ -180,7 +177,7 @@ export const importsFlow = (context, node, currentFileEffectiveDirective) => {
180
177
  * @param {Readonly<import('@typescript-eslint/utils').TSESLint.RuleContext<typeof reExportNotSameMessageId | typeof importBreaksEffectiveImportRulesMessageId | typeof useServerJSXMessageId, []>>} context The ESLint rule's `context` object.
181
178
  * @param {import('@typescript-eslint/types').TSESTree.ExportNamedDeclaration | import('@typescript-eslint/types').TSESTree.ExportAllDeclaration} node The ESLint `node` of the rule's current traversal.
182
179
  * @param {USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS} currentFileEffectiveDirective The current file's effective directive.
183
- * @returns Returns early if the flow needs to be interrupted.
180
+ * @returns Early if the flow needs to be interrupted.
184
181
  */
185
182
  export const reExportsFlow = (context, node, currentFileEffectiveDirective) => {
186
183
  // does not operate on `export type`
@@ -1,13 +1,13 @@
1
1
  import {
2
- useServerJSXMessageId,
3
- importBreaksEffectiveImportRulesMessageId,
4
- reExportNotSameMessageId,
5
2
  TSX,
6
3
  TS,
7
4
  JSX,
8
5
  JS,
9
6
  MJS,
10
7
  CJS,
8
+ useServerJSXMessageId,
9
+ importBreaksEffectiveImportRulesMessageId,
10
+ reExportNotSameMessageId,
11
11
  } from "../../../_commons/constants/bases.js";
12
12
  import {
13
13
  NO_DIRECTIVE,
@@ -22,7 +22,6 @@ import {
22
22
  USE_AGNOSTIC_LOGICS,
23
23
  USE_AGNOSTIC_COMPONENTS,
24
24
  effectiveDirectives_EffectiveModules,
25
- directivesSet,
26
25
  directivesArray,
27
26
  effectiveDirectives_BlockedImports,
28
27
  } from "../constants/bases.js";
@@ -43,7 +42,7 @@ import {
43
42
  * - `'use server'` denotes a Server Functions Module.
44
43
  * - `'use agnostic'` denotes an Agnostic Module (formerly Shared Module).
45
44
  * @param {Readonly<import('@typescript-eslint/utils').TSESLint.RuleContext<typeof reExportNotSameMessageId | typeof importBreaksEffectiveImportRulesMessageId | typeof useServerJSXMessageId, []>>} context The ESLint rule's `context` object.
46
- * @returns {NO_DIRECTIVE | USE_SERVER | USE_CLIENT | USE_AGNOSTIC} The directive, or lack thereof via `null`. The lack of a directive is considered server-by-default.
45
+ * @returns The directive, or lack thereof via `null`. The lack of a directive is considered server-by-default.
47
46
  */
48
47
  export const getDirectiveFromCurrentModule = (context) => {
49
48
  // the AST body to check for the top-of-the-file directive
@@ -63,7 +62,8 @@ export const getDirectiveFromCurrentModule = (context) => {
63
62
  if (value === null) return value;
64
63
 
65
64
  // 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
66
- const currentFileDirective = directivesSet.has(value) ? value : null;
65
+ const currentFileDirective =
66
+ directivesArray.find((directive) => directive === value) ?? null;
67
67
 
68
68
  return currentFileDirective;
69
69
  };
@@ -81,7 +81,7 @@ export const getDirectiveFromCurrentModule = (context) => {
81
81
  * - `'use agnostic components'` denotes an Agnostic Components Module.
82
82
  * @param {NO_DIRECTIVE | USE_SERVER | USE_CLIENT | USE_AGNOSTIC} directive The directive as written on top of the file (`null` if no valid directive).
83
83
  * @param {TSX | TS | JSX | JS | MJS | CJS} extension The JavaScript (TypeScript) extension of the file.
84
- * @returns {USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS | null} The effective directive, from which imports rules are applied.
84
+ * @returns The effective directive, from which imports rules are applied.
85
85
  */
86
86
  export const getEffectiveDirective = (directive, extension) => {
87
87
  // I could use a map, but because this is in JS with JSDoc, a manual solution is peculiarly more typesafe.
@@ -112,7 +112,7 @@ export const getEffectiveDirective = (directive, extension) => {
112
112
  * - `'use agnostic'` denotes an Agnostic Module (formerly Shared Module).
113
113
  * - `null` denotes a server-by-default module, ideally a Server Module.
114
114
  * @param {string} resolvedImportPath The resolved path of the import.
115
- * @returns {USE_SERVER | USE_CLIENT | USE_AGNOSTIC | NO_DIRECTIVE} The directive, or lack thereof via `null`. The lack of a directive is considered server-by-default.
115
+ * @returns The directive, or lack thereof via `null`. The lack of a directive is considered server-by-default.
116
116
  */
117
117
  export const getDirectiveFromImportedModule = (resolvedImportPath) => {
118
118
  // gets the first line of the code of the import
@@ -141,7 +141,7 @@ export const getDirectiveFromImportedModule = (resolvedImportPath) => {
141
141
  * Returns a boolean deciding if an imported file's effective directive is incompatible with the current file's effective directive.
142
142
  * @param {USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS} currentFileEffectiveDirective The current file's effective directive.
143
143
  * @param {USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS} importedFileEffectiveDirective The imported file's effective directive.
144
- * @returns {boolean} Returns `true` if the import is blocked, as established in `effectiveDirectives_BlockedImports`.
144
+ * @returns `true` if the import is blocked, as established in `effectiveDirectives_BlockedImports`.
145
145
  */
146
146
  export const isImportBlocked = (
147
147
  currentFileEffectiveDirective,
@@ -158,7 +158,7 @@ export const isImportBlocked = (
158
158
  /**
159
159
  * Lists in an message the effective modules incompatible with an effective module based on its effective directive.
160
160
  * @param {USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS} effectiveDirective The effective directive of the effective module.
161
- * @returns {string} The message listing the incompatible effective modules.
161
+ * @returns The message listing the incompatible effective modules.
162
162
  */
163
163
  export const makeMessageFromEffectiveDirective = (effectiveDirective) =>
164
164
  makeMessageFromResolvedDirective(
@@ -173,7 +173,7 @@ export const makeMessageFromEffectiveDirective = (effectiveDirective) =>
173
173
  * Finds the `message` for the specific violation of effective directives import rules based on `effectiveDirectives_BlockedImports`.
174
174
  * @param {USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS} currentFileEffectiveDirective The current file's effective directive.
175
175
  * @param {USE_SERVER_LOGICS | USE_SERVER_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_LOGICS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_LOGICS | USE_AGNOSTIC_COMPONENTS} importedFileEffectiveDirective The imported file's effective directive.
176
- * @returns {string} The corresponding `message`.
176
+ * @returns The corresponding `message`.
177
177
  */
178
178
  export const findSpecificViolationMessage = (
179
179
  currentFileEffectiveDirective,
@@ -35,6 +35,25 @@ export const USE_CLIENT_CONTEXTS = COMMONS_USE_CLIENT_CONTEXTS;
35
35
  export const USE_AGNOSTIC_CONDITIONS = COMMONS_USE_AGNOSTIC_CONDITIONS;
36
36
  export const USE_AGNOSTIC_STRATEGIES = COMMONS_USE_AGNOSTIC_STRATEGIES;
37
37
 
38
+ // commented directives array
39
+ /** @type {readonly [USE_SERVER_LOGICS, USE_CLIENT_LOGICS, USE_AGNOSTIC_LOGICS, USE_SERVER_COMPONENTS, USE_CLIENT_COMPONENTS, USE_AGNOSTIC_COMPONENTS, USE_SERVER_FUNCTIONS, USE_CLIENT_CONTEXTS, USE_AGNOSTIC_CONDITIONS, USE_AGNOSTIC_STRATEGIES]} */
40
+ export const directivesArray = [
41
+ USE_SERVER_LOGICS,
42
+ USE_CLIENT_LOGICS,
43
+ USE_AGNOSTIC_LOGICS,
44
+ USE_SERVER_COMPONENTS,
45
+ USE_CLIENT_COMPONENTS,
46
+ USE_AGNOSTIC_COMPONENTS,
47
+ USE_SERVER_FUNCTIONS,
48
+ USE_CLIENT_CONTEXTS,
49
+ USE_AGNOSTIC_CONDITIONS,
50
+ USE_AGNOSTIC_STRATEGIES,
51
+ ];
52
+
53
+ // commented directives set
54
+ /** @type {ReadonlySet<USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES>} */
55
+ export const directivesSet = new Set(directivesArray); // no longer used exported to satisfy static type inference
56
+
38
57
  // commented modules
39
58
  const SERVER_LOGICS_MODULE = COMMONS_SERVER_LOGICS_MODULE;
40
59
  const CLIENT_LOGICS_MODULE = COMMONS_CLIENT_LOGICS_MODULE;
@@ -61,34 +80,55 @@ export const commentedDirectives_CommentedModules = Object.freeze({
61
80
  [USE_AGNOSTIC_STRATEGIES]: AGNOSTIC_STRATEGIES_MODULE,
62
81
  });
63
82
 
64
- // message placeholders
83
+ // commented strategies
84
+ const AT_SERVER_LOGICS = "@serverLogics";
85
+ const AT_CLIENT_LOGICS = "@clientLogics";
86
+ const AT_AGNOSTIC_LOGICS = "@agnosticLogics";
87
+ const AT_SERVER_COMPONENTS = "@serverComponents";
88
+ const AT_CLIENT_COMPONENTS = "@clientComponents";
89
+ const AT_AGNOSTIC_COMPONENTS = "@agnosticComponents";
90
+ const AT_SERVER_FUNCTIONS = "@serverFunctions";
91
+ const AT_CLIENT_CONTEXTS = "@clientContexts";
92
+ const AT_AGNOSTIC_CONDITIONS = "@agnosticConditions";
65
93
 
94
+ // commented strategies array
95
+ /** @type {readonly [AT_SERVER_LOGICS, AT_CLIENT_LOGICS, AT_AGNOSTIC_LOGICS, AT_SERVER_COMPONENTS, AT_CLIENT_COMPONENTS, AT_AGNOSTIC_COMPONENTS, AT_SERVER_FUNCTIONS, AT_CLIENT_CONTEXTS, AT_AGNOSTIC_CONDITIONS]} */
96
+ export const strategiesArray = [
97
+ AT_SERVER_LOGICS,
98
+ AT_CLIENT_LOGICS,
99
+ AT_AGNOSTIC_LOGICS,
100
+ AT_SERVER_COMPONENTS,
101
+ AT_CLIENT_COMPONENTS,
102
+ AT_AGNOSTIC_COMPONENTS,
103
+ AT_SERVER_FUNCTIONS,
104
+ AT_CLIENT_CONTEXTS,
105
+ AT_AGNOSTIC_CONDITIONS,
106
+ ];
107
+
108
+ // commented strategies set
109
+ /** @type {ReadonlySet<AT_SERVER_LOGICS | AT_CLIENT_LOGICS | AT_AGNOSTIC_LOGICS | AT_SERVER_COMPONENTS | AT_CLIENT_COMPONENTS | AT_AGNOSTIC_COMPONENTS | AT_SERVER_FUNCTIONS | AT_CLIENT_CONTEXTS | AT_AGNOSTIC_CONDITIONS>} */
110
+ export const strategiesSet = new Set(strategiesArray); // no longer used exported to satisfy static type inference
111
+
112
+ // mapped commented strategies to their commented directives
113
+ export const commentedStrategies_CommentedDirectives = Object.freeze({
114
+ [AT_SERVER_LOGICS]: USE_SERVER_LOGICS,
115
+ [AT_CLIENT_LOGICS]: USE_CLIENT_LOGICS,
116
+ [AT_AGNOSTIC_LOGICS]: USE_AGNOSTIC_LOGICS,
117
+ [AT_SERVER_COMPONENTS]: USE_SERVER_COMPONENTS,
118
+ [AT_CLIENT_COMPONENTS]: USE_CLIENT_COMPONENTS,
119
+ [AT_AGNOSTIC_COMPONENTS]: USE_AGNOSTIC_COMPONENTS,
120
+ [AT_SERVER_FUNCTIONS]: USE_SERVER_FUNCTIONS,
121
+ [AT_CLIENT_CONTEXTS]: USE_CLIENT_CONTEXTS,
122
+ [AT_AGNOSTIC_CONDITIONS]: USE_AGNOSTIC_CONDITIONS,
123
+ });
124
+
125
+ // message placeholders
66
126
  export const currentFileCommentedDirective = "currentFileCommentedDirective";
67
127
  export const importedFileCommentedDirective = "importedFileCommentedDirective";
68
128
  export const commentedDirectiveMessage = "commentedDirectiveMessage";
69
129
  export const specificViolationMessage = "specificViolationMessage";
70
130
  export const specificFailure = "specificFailure";
71
131
 
72
- /* from the getCommentedDirectiveFromCurrentModule utility */
73
-
74
- export const directivesSet = new Set([
75
- USE_SERVER_LOGICS,
76
- USE_CLIENT_LOGICS,
77
- USE_AGNOSTIC_LOGICS,
78
- USE_SERVER_COMPONENTS,
79
- USE_CLIENT_COMPONENTS,
80
- USE_AGNOSTIC_COMPONENTS,
81
- USE_SERVER_FUNCTIONS,
82
- USE_CLIENT_CONTEXTS,
83
- USE_AGNOSTIC_CONDITIONS,
84
- USE_AGNOSTIC_STRATEGIES,
85
- ]);
86
-
87
- /* from the getCommentedDirectiveFromImportedModule utility */
88
-
89
- /** @type {readonly [USE_SERVER_LOGICS, USE_CLIENT_LOGICS, USE_AGNOSTIC_LOGICS, USE_SERVER_COMPONENTS, USE_CLIENT_COMPONENTS, USE_AGNOSTIC_COMPONENTS, USE_SERVER_FUNCTIONS, USE_CLIENT_CONTEXTS, USE_AGNOSTIC_CONDITIONS, USE_AGNOSTIC_STRATEGIES]} */
90
- export const directivesArray = Array.from(directivesSet);
91
-
92
132
  /* commentedDirectives_4RawImplementations */
93
133
 
94
134
  // all formatting styles as an array of [prefix, quote, suffix]
@@ -97,20 +137,19 @@ const commentStyles = [
97
137
  [`// `, `"`, ``], // V2: `// "directive"`
98
138
  [`/* `, `'`, ` */`], // V3: `/* 'directive' */`
99
139
  [`/* `, `"`, ` */`], // V4: `/* "directive" */`
100
- ];
140
+ ]; // further inference optimation can be made but is overkill...
101
141
 
102
142
  /**
103
143
  * Makes the array of all four accepted commented directive implementations on a directive basis.
104
144
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES} directive The commented directive.
105
- * @returns {string[]} The array of formatted commented directives.
145
+ * @returns The array of formatted commented directives.
106
146
  */
107
147
  const make4RawImplementations = (directive) =>
108
148
  commentStyles.map(
109
149
  ([prefix, quote, suffix]) =>
110
150
  `${prefix}${quote}${directive}${quote}${suffix}`
111
- );
151
+ ); // ...further inference optimation could be an extra challenge but would probably require TypeScript for comfort
112
152
 
113
- // mapped commented directives to their 4 raw implementations
114
153
  export const commentedDirectives_4RawImplementations = Object.freeze({
115
154
  [USE_SERVER_LOGICS]: make4RawImplementations(USE_SERVER_LOGICS),
116
155
  [USE_CLIENT_LOGICS]: make4RawImplementations(USE_CLIENT_LOGICS),
@@ -124,37 +163,35 @@ export const commentedDirectives_4RawImplementations = Object.freeze({
124
163
  [USE_AGNOSTIC_STRATEGIES]: make4RawImplementations(USE_AGNOSTIC_STRATEGIES),
125
164
  });
126
165
 
127
- // commented strategies
128
- export const AT_SERVER_LOGICS = "@serverLogics";
129
- export const AT_CLIENT_LOGICS = "@clientLogics";
130
- export const AT_AGNOSTIC_LOGICS = "@agnosticLogics";
131
- export const AT_SERVER_COMPONENTS = "@serverComponents";
132
- export const AT_CLIENT_COMPONENTS = "@clientComponents";
133
- export const AT_AGNOSTIC_COMPONENTS = "@agnosticComponents";
134
- export const AT_SERVER_FUNCTIONS = "@serverFunctions";
135
- export const AT_CLIENT_CONTEXTS = "@clientContexts";
136
- export const AT_AGNOSTIC_CONDITIONS = "@agnosticConditions";
166
+ /* commentedDirectives_VerificationReports */
137
167
 
138
- // mapped commented strategies to their commented directives
139
- export const commentedStrategies_CommentedDirectives = Object.freeze({
140
- [AT_SERVER_LOGICS]: USE_SERVER_LOGICS,
141
- [AT_CLIENT_LOGICS]: USE_CLIENT_LOGICS,
142
- [AT_AGNOSTIC_LOGICS]: USE_AGNOSTIC_LOGICS,
143
- [AT_SERVER_COMPONENTS]: USE_SERVER_COMPONENTS,
144
- [AT_CLIENT_COMPONENTS]: USE_CLIENT_COMPONENTS,
145
- [AT_AGNOSTIC_COMPONENTS]: USE_AGNOSTIC_COMPONENTS,
146
- [AT_SERVER_FUNCTIONS]: USE_SERVER_FUNCTIONS,
147
- [AT_CLIENT_CONTEXTS]: USE_CLIENT_CONTEXTS,
148
- [AT_AGNOSTIC_CONDITIONS]: USE_AGNOSTIC_CONDITIONS,
168
+ const MODULES_MARKED_WITH_THE_ = "modules marked with the";
169
+ const _DIRECTIVE_MUST_HAVE_A_NON_JSX_FILE_EXTENSION =
170
+ "directive must have a non-JSX file extension";
171
+ const _DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION =
172
+ "directive must have a JSX file extension";
173
+
174
+ export const commentedDirectives_VerificationReports = Object.freeze({
175
+ // somehow doing it by hand is better for type inference in raw JS
176
+ [USE_SERVER_LOGICS]: `${MODULES_MARKED_WITH_THE_} "${USE_SERVER_LOGICS}" ${_DIRECTIVE_MUST_HAVE_A_NON_JSX_FILE_EXTENSION}.`,
177
+ [USE_CLIENT_LOGICS]: `${MODULES_MARKED_WITH_THE_} "${USE_CLIENT_LOGICS}" ${_DIRECTIVE_MUST_HAVE_A_NON_JSX_FILE_EXTENSION}.`,
178
+ [USE_AGNOSTIC_LOGICS]: `${MODULES_MARKED_WITH_THE_} "${USE_AGNOSTIC_LOGICS}" ${_DIRECTIVE_MUST_HAVE_A_NON_JSX_FILE_EXTENSION}.`,
179
+ [USE_SERVER_COMPONENTS]: `${MODULES_MARKED_WITH_THE_} "${USE_SERVER_COMPONENTS}" ${_DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION}.`,
180
+ [USE_CLIENT_COMPONENTS]: `${MODULES_MARKED_WITH_THE_} "${USE_CLIENT_COMPONENTS}" ${_DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION}.`,
181
+ [USE_AGNOSTIC_COMPONENTS]: `${MODULES_MARKED_WITH_THE_} "${USE_AGNOSTIC_COMPONENTS}" ${_DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION}.`,
182
+ [USE_SERVER_FUNCTIONS]: `${MODULES_MARKED_WITH_THE_} "${USE_SERVER_FUNCTIONS}" ${_DIRECTIVE_MUST_HAVE_A_NON_JSX_FILE_EXTENSION}.`,
183
+ [USE_CLIENT_CONTEXTS]: `${MODULES_MARKED_WITH_THE_} "${USE_CLIENT_CONTEXTS}" ${_DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION}.`,
184
+ [USE_AGNOSTIC_CONDITIONS]: `${MODULES_MARKED_WITH_THE_} "${USE_AGNOSTIC_CONDITIONS}" ${_DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION}.`,
185
+ [USE_AGNOSTIC_STRATEGIES]: `${MODULES_MARKED_WITH_THE_} "${USE_AGNOSTIC_STRATEGIES}" directive are free to have the file extension of their choosing. (This is not a problem and should never surface.)`,
149
186
  });
150
187
 
151
- /* from the isImportBlocked utility */
188
+ /* commentedDirectives_BlockedImports */
152
189
 
153
190
  /**
154
191
  * Makes the intro for each specific import rule violation messages.
155
192
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES} currentFileCommentedDirective The current file's commented directive.
156
193
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS} importedFileCommentedDirective The imported file's commented directive.
157
- * @returns {string} Returns "[Current file commented modules] are not allowed to import [imported file commented modules]."
194
+ * @returns "[Current file commented modules] are not allowed to import [imported file commented modules]."
158
195
  */
159
196
  const makeIntroForSpecificViolationMessage = (
160
197
  currentFileCommentedDirective,
@@ -379,7 +416,7 @@ export const commentedDirectives_BlockedImports = Object.freeze({
379
416
  message: `${makeIntroForSpecificViolationMessage(
380
417
  USE_SERVER_FUNCTIONS,
381
418
  USE_AGNOSTIC_CONDITIONS
382
- )} (Special) Agnostic Conditions Components aren't allowed (Special)because Server Functions have no business working with React Components.`,
419
+ )} (Special) Agnostic Conditions Components aren't allowed because (Special) Server Functions have no business working with React Components.`,
383
420
  },
384
421
  ],
385
422
  [USE_CLIENT_CONTEXTS]: [
@@ -397,13 +434,13 @@ export const commentedDirectives_BlockedImports = Object.freeze({
397
434
  message: `${makeIntroForSpecificViolationMessage(
398
435
  USE_CLIENT_CONTEXTS,
399
436
  USE_SERVER_COMPONENTS
400
- )} Lineal Server Components may only pass through Client Contexts Components via the children prop within Server Components Modules.`,
437
+ )} Lineal Server Components may only pass through (Special) Client Contexts Components via the children prop within Server Components Modules.`,
401
438
  },
402
439
  // USE_CLIENT_COMPONENTS allowed, because Lineal Client Components can create client boundaries within (Special) Client Contexts Components.
403
440
  // USE_AGNOSTIC_COMPONENTS allowed, because Lineal Agnostic Components can render safely on the client just like they can on the server.
404
441
  // USE_SERVER_FUNCTIONS allowed, because (Special) Server Functions are specifically triggered by Client Components.
405
442
  // USE_CLIENT_CONTEXTS allowed, because (Special) Client Contexts Components can compose with one another.
406
- // USE_AGNOSTIC_CONDITIONS allowed, because (Special) Agnostic Conditions Components, as if they were Lineal Agnostic Components themselves, can render safely on the client just like they can on the server, in a mechanism that allows Client Contexts Components to safely and indirectly compose with child Server Components within Client Contexts Modules.
443
+ // USE_AGNOSTIC_CONDITIONS allowed, because (Special) Agnostic Conditions Components, as if they were Lineal Agnostic Components themselves, can render safely on the client just like they can on the server, in a mechanism that allows (Special) Client Contexts Components to safely and indirectly compose with child Server Components within Client Contexts Modules.
407
444
  ],
408
445
  [USE_AGNOSTIC_CONDITIONS]: [
409
446
  {
@@ -444,25 +481,3 @@ export const commentedDirectives_BlockedImports = Object.freeze({
444
481
  // (Special) Agnostic Strategies Modules can import all known modules, except themselves since they cannot be imported as they are, only as and via Strategies. (Since Agnostic Strategies Modules cannot be imported as they are, there is no such things as a 'use agnostic strategies' importFileCommentedDirective.)
445
482
  ],
446
483
  });
447
-
448
- /* from the currentFileFlow flow */
449
-
450
- const MODULES_MARKED_WITH_THE_ = "modules marked with the";
451
- const _DIRECTIVE_MUST_HAVE_A_NON_JSX_FILE_EXTENSION =
452
- "directive must have a non-JSX file extension";
453
- const _DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION =
454
- "directive must have a JSX file extension";
455
-
456
- export const commentedDirectives_VerificationReports = Object.freeze({
457
- // somehow doing it by hand is better for type inference in raw JS
458
- [USE_SERVER_LOGICS]: `${MODULES_MARKED_WITH_THE_} "${USE_SERVER_LOGICS}" ${_DIRECTIVE_MUST_HAVE_A_NON_JSX_FILE_EXTENSION}.`,
459
- [USE_CLIENT_LOGICS]: `${MODULES_MARKED_WITH_THE_} "${USE_CLIENT_LOGICS}" ${_DIRECTIVE_MUST_HAVE_A_NON_JSX_FILE_EXTENSION}.`,
460
- [USE_AGNOSTIC_LOGICS]: `${MODULES_MARKED_WITH_THE_} "${USE_AGNOSTIC_LOGICS}" ${_DIRECTIVE_MUST_HAVE_A_NON_JSX_FILE_EXTENSION}.`,
461
- [USE_SERVER_COMPONENTS]: `${MODULES_MARKED_WITH_THE_} "${USE_SERVER_COMPONENTS}" ${_DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION}.`,
462
- [USE_CLIENT_COMPONENTS]: `${MODULES_MARKED_WITH_THE_} "${USE_CLIENT_COMPONENTS}" ${_DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION}.`,
463
- [USE_AGNOSTIC_COMPONENTS]: `${MODULES_MARKED_WITH_THE_} "${USE_AGNOSTIC_COMPONENTS}" ${_DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION}.`,
464
- [USE_SERVER_FUNCTIONS]: `${MODULES_MARKED_WITH_THE_} "${USE_SERVER_FUNCTIONS}" ${_DIRECTIVE_MUST_HAVE_A_NON_JSX_FILE_EXTENSION}.`,
465
- [USE_CLIENT_CONTEXTS]: `${MODULES_MARKED_WITH_THE_} "${USE_CLIENT_CONTEXTS}" ${_DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION}.`,
466
- [USE_AGNOSTIC_CONDITIONS]: `${MODULES_MARKED_WITH_THE_} "${USE_AGNOSTIC_CONDITIONS}" ${_DIRECTIVE_MUST_HAVE_A_JSX_FILE_EXTENSION}.`,
467
- [USE_AGNOSTIC_STRATEGIES]: `${MODULES_MARKED_WITH_THE_} "${USE_AGNOSTIC_STRATEGIES}" directive are free to have the file extension of their choosing. (This is not a problem and should never surface.)`,
468
- });
@@ -48,7 +48,7 @@ import {
48
48
  /**
49
49
  * 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.
50
50
  * @param {Readonly<import('@typescript-eslint/utils').TSESLint.RuleContext<typeof reExportNotSameMessageId | typeof importBreaksCommentedImportRulesMessageId | typeof noCommentedDirective | typeof commentedDirectiveVerificationFailed | typeof importNotStrategized | typeof exportNotStrategized, []>>} context The ESLint rule's `context` object.
51
- * @returns {{skip: true; verifiedCommentedDirective: undefined;} | {skip: undefined; verifiedCommentedDirective: USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES;}} Returns either an object with `skip: true` to disregard or one with the non-null `verifiedCommentedDirective`.
51
+ * @returns {{skip: true; verifiedCommentedDirective: undefined;} | {skip: undefined; verifiedCommentedDirective: USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES;}} Either an object with `skip: true` to disregard or one with the non-null `verifiedCommentedDirective`.
52
52
  */
53
53
  export const currentFileFlow = (context) => {
54
54
  // GETTING THE EXTENSION OF THE CURRENT FILE
@@ -95,9 +95,7 @@ export const currentFileFlow = (context) => {
95
95
  return { skip: true };
96
96
  }
97
97
 
98
- return {
99
- verifiedCommentedDirective,
100
- };
98
+ return { verifiedCommentedDirective };
101
99
  };
102
100
 
103
101
  /* importedFileFlow */
@@ -106,7 +104,7 @@ export const currentFileFlow = (context) => {
106
104
  * The flow that is shared between import and re-export traversals to obtain the import file's commented directive.
107
105
  * @param {Readonly<import('@typescript-eslint/utils').TSESLint.RuleContext<typeof reExportNotSameMessageId | typeof importBreaksCommentedImportRulesMessageId | typeof noCommentedDirective | typeof commentedDirectiveVerificationFailed | typeof importNotStrategized | typeof exportNotStrategized, []>>} context The ESLint rule's `context` object.
108
106
  * @param {import('@typescript-eslint/types').TSESTree.ImportDeclaration} node The ESLint `node` of the rule's current traversal.
109
- * @returns {{skip: true; importedFileCommentedDirective: undefined;} | {skip: undefined; importedFileCommentedDirective: USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS;}} Returns either an object with `skip: true` to disregard or one with the non-null `importedFileCommentedDirective`.
107
+ * @returns {{skip: true; importedFileCommentedDirective: undefined;} | {skip: undefined; importedFileCommentedDirective: USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS;}} Either an object with `skip: true` to disregard or one with the non-null `importedFileCommentedDirective`.
110
108
  */
111
109
  const importedFileFlow = (context, node) => {
112
110
  // finds the full path of the import
@@ -131,18 +129,18 @@ const importedFileFlow = (context, node) => {
131
129
  // returns early if there is no directive or no valid directive (same, but eventually no directive could have defaults)
132
130
  if (!importedFileCommentedDirective) {
133
131
  console.warn(
134
- "The imported file, whose path has been resolved, has no directive. It is thus ignored since the report on that circumstance is available on the imported file itself."
132
+ "WARNING. The imported file, whose path has been resolved, has no directive. It is thus ignored since the report on that circumstance is available on the imported file itself."
135
133
  );
136
134
  return { skip: true };
137
135
  }
138
136
 
139
137
  /* GETTING THE CORRECT DIRECTIVE INTERPRETATION OF STRATEGY FOR AGNOSTIC STRATEGIES MODULES IMPORTS.
140
- (The Directive-First Architecture does not check whether the export and import Strategies are the same at this time, meaning an @clientLogics strategy could be wrongly imported and interpreted as an @serverLogics strategy.
138
+ The Directive-First Architecture does not check whether the export and import Strategies are the same at this time, meaning an @clientLogics strategy could be wrongly imported and interpreted as an @serverLogics strategy.
141
139
 
142
140
  After a short attempt, this feature is currently canceled, mainly since the amount of work it will require will not be able to be transferred in a future where commented strategies will actually be real syntax.
143
141
 
144
- // (Consequently, details below are currently at the stage of wishful thinking.)
145
- However, Strategy exports are planned to be linting in the future within their own Agnostic Strategies Modules to ensure they respect import rules within their own scopes. It may also become possible to check whether the export and import Strategies are the same in the future when identifiers are defined and the same, especially for components modules where a convention could be to for all non-type export to be named and PascalCase.) */
142
+ (Consequently, details below are currently at the stage of wishful thinking.)
143
+ Strategy exports are planned to be linting in the future within their own Agnostic Strategies Modules to ensure they respect import rules within their own scopes. It may also become possible to check whether the export and import Strategies are the same in the future when identifiers are defined and the same, especially for components modules where a convention could be for all non-type exports to be named and PascalCase. */
146
144
  if (importedFileCommentedDirective === USE_AGNOSTIC_STRATEGIES) {
147
145
  const importingFileCommentedDirective = getStrategizedDirective(
148
146
  context,
@@ -171,7 +169,7 @@ const importedFileFlow = (context, node) => {
171
169
  * @param {Readonly<import('@typescript-eslint/utils').TSESLint.RuleContext<typeof reExportNotSameMessageId | typeof importBreaksCommentedImportRulesMessageId | typeof noCommentedDirective | typeof commentedDirectiveVerificationFailed | typeof importNotStrategized | typeof exportNotStrategized, []>>} context The ESLint rule's `context` object.
172
170
  * @param {import('@typescript-eslint/types').TSESTree.ImportDeclaration} node The ESLint `node` of the rule's current traversal.
173
171
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES} currentFileCommentedDirective The current file's commented directive.
174
- * @returns Returns early if the flow needs to be interrupted.
172
+ * @returns Early if the flow needs to be interrupted.
175
173
  */
176
174
  export const importsFlow = (context, node, currentFileCommentedDirective) => {
177
175
  // does not operate on `import type`
@@ -211,7 +209,7 @@ export const importsFlow = (context, node, currentFileCommentedDirective) => {
211
209
  * @param {Readonly<import('@typescript-eslint/utils').TSESLint.RuleContext<typeof reExportNotSameMessageId | typeof importBreaksCommentedImportRulesMessageId | typeof noCommentedDirective | typeof commentedDirectiveVerificationFailed | typeof importNotStrategized | typeof exportNotStrategized, []>>} context The ESLint rule's `context` object.
212
210
  * @param {import('@typescript-eslint/types').TSESTree.ExportNamedDeclaration | import('@typescript-eslint/types').TSESTree.ExportAllDeclaration | import('@typescript-eslint/types').TSESTree.ExportDefaultDeclaration} node The ESLint `node` of the rule's current traversal.
213
211
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES} currentFileCommentedDirective The current file's commented directive.
214
- * @returns Returns early if the flow needs to be interrupted.
212
+ * @returns Early if the flow needs to be interrupted.
215
213
  */
216
214
  export const allExportsFlow = (
217
215
  context,
@@ -250,9 +248,9 @@ export const allExportsFlow = (
250
248
  node,
251
249
  messageId: reExportNotSameMessageId,
252
250
  data: {
253
- // currentFileCommentedDirective
251
+ // currentFileCommentedDirective:
254
252
  currentFileCommentedDirective,
255
- // importedFileCommentedDirective
253
+ // importedFileCommentedDirective:
256
254
  importedFileCommentedDirective,
257
255
  },
258
256
  });
@@ -17,8 +17,8 @@ import {
17
17
  USE_CLIENT_CONTEXTS,
18
18
  USE_AGNOSTIC_CONDITIONS,
19
19
  USE_AGNOSTIC_STRATEGIES,
20
- directivesSet,
21
20
  directivesArray,
21
+ strategiesArray,
22
22
  commentedDirectives_4RawImplementations,
23
23
  commentedStrategies_CommentedDirectives,
24
24
  commentedDirectives_BlockedImports,
@@ -34,6 +34,45 @@ import {
34
34
 
35
35
  /* getCommentedDirectiveFromCurrentModule */
36
36
 
37
+ /**
38
+ * Detects whether a string is single- or double-quoted.
39
+ * @param {string} string
40
+ * @returns
41
+ */
42
+ const detectQuoteType = (string) => {
43
+ if (string.startsWith("'") && string.endsWith("'")) {
44
+ return true; // single quotes
45
+ } else if (string.startsWith('"') && string.endsWith('"')) {
46
+ return false; // double quotes
47
+ } else {
48
+ return null; // neither
49
+ }
50
+ };
51
+
52
+ /**
53
+ * Removes single quotes from a string known to be single-quoted.
54
+ * @param {string} string
55
+ * @returns
56
+ */
57
+ const stripSingleQuotes = (string) => {
58
+ if (string.startsWith("'") && string.endsWith("'")) {
59
+ return string.slice(1, -1);
60
+ }
61
+ return string;
62
+ };
63
+
64
+ /**
65
+ * Removes double quotes from a string known to be double-quoted.
66
+ * @param {string} string
67
+ * @returns
68
+ */
69
+ const stripDoubleQuotes = (string) => {
70
+ if (string.startsWith('"') && string.endsWith('"')) {
71
+ return string.slice(1, -1);
72
+ }
73
+ return string;
74
+ };
75
+
37
76
  /**
38
77
  * Gets the commented directive of the current module.
39
78
  *
@@ -50,7 +89,7 @@ import {
50
89
  * - `'use agnostic conditions'`, `"use agnostic conditions"` denoting an Agnostic Conditions Module.
51
90
  * - `'use agnostic strategies'`, `"use agnostic strategies"` denoting an Agnostic Strategies Module.
52
91
  * @param {Readonly<import('@typescript-eslint/utils').TSESLint.RuleContext<typeof reExportNotSameMessageId | typeof importBreaksCommentedImportRulesMessageId | typeof noCommentedDirective | typeof commentedDirectiveVerificationFailed | typeof importNotStrategized | typeof exportNotStrategized, []>>} context The ESLint rule's `context` object.
53
- * @returns {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES | null} The commented directive, or lack thereof via `null`. Given the strictness of this architecture, the lack of a directive is considered a mistake. (Though rules may provide the opportunity to declare a default, and configs with preset defaults may be provided.)
92
+ * @returns The commented directive, or lack thereof via `null`. Given the strictness of this architecture, the lack of a directive is considered a mistake. (Though rules may provide the opportunity to declare a default, and configs with preset defaults may become provided.)
54
93
  */
55
94
  export const getCommentedDirectiveFromCurrentModule = (context) => {
56
95
  // gets the first comment from the source code
@@ -78,50 +117,12 @@ export const getCommentedDirectiveFromCurrentModule = (context) => {
78
117
  : stripDoubleQuotes(rawValue);
79
118
 
80
119
  // certifies the directive or lack thereof from the obtained value
81
- const commentedDirective = directivesSet.has(value) ? value : null;
120
+ const commentedDirective =
121
+ directivesArray.find((directive) => directive === value) ?? null;
82
122
 
83
123
  return commentedDirective;
84
124
  };
85
125
 
86
- /**
87
- * Detects whether a string is single- or double-quoted.
88
- * @param {string} string
89
- * @returns
90
- */
91
- const detectQuoteType = (string) => {
92
- if (string.startsWith("'") && string.endsWith("'")) {
93
- return true; // single quotes
94
- } else if (string.startsWith('"') && string.endsWith('"')) {
95
- return false; // double quotes
96
- } else {
97
- return null; // neither
98
- }
99
- };
100
-
101
- /**
102
- * Removes single quotes from a string known to be single-quoted.
103
- * @param {string} string
104
- * @returns
105
- */
106
- const stripSingleQuotes = (string) => {
107
- if (string.startsWith("'") && string.endsWith("'")) {
108
- return string.slice(1, -1);
109
- }
110
- return string;
111
- };
112
-
113
- /**
114
- * Removes double quotes from a string known to be double-quoted.
115
- * @param {string} string
116
- * @returns
117
- */
118
- const stripDoubleQuotes = (string) => {
119
- if (string.startsWith('"') && string.endsWith('"')) {
120
- return string.slice(1, -1);
121
- }
122
- return string;
123
- };
124
-
125
126
  /* getVerifiedCommentedDirective */
126
127
 
127
128
  /**
@@ -138,7 +139,7 @@ const stripDoubleQuotes = (string) => {
138
139
  * - `'use agnostic strategies'`: Agnostic Strategies Modules may export JSX.
139
140
  * @param {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES} directive The commented directive as written on top of the file (cannot be `null` at that stage).
140
141
  * @param {TSX | TS | JSX | JS | MJS | CJS} extension The JavaScript (TypeScript) extension of the file.
141
- * @returns {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES | null} The verified commented directive, from which imports rules are applied. Returns `null` if the verification failed, upon which an error will be reported depending on the commented directive, since the error logic here is strictly binary.
142
+ * @returns The verified commented directive, from which imports rules are applied. Returns `null` if the verification failed, upon which an error will be reported depending on the commented directive, since the error logic here is strictly binary.
142
143
  */
143
144
  export const getVerifiedCommentedDirective = (directive, extension) => {
144
145
  // I could use a map, but because this is in JS with JSDoc, a manual solution is peculiarly more typesafe.
@@ -183,7 +184,7 @@ export const getVerifiedCommentedDirective = (directive, extension) => {
183
184
  * - `'use agnostic conditions'`, `"use agnostic conditions"` denoting an Agnostic Conditions Module.
184
185
  * - `'use agnostic strategies'`, `"use agnostic strategies"` denoting an Agnostic Strategies Module.
185
186
  * @param {string} resolvedImportPath The resolved path of the import.
186
- * @returns {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES | null} The commented directive, or lack thereof via `null`. Given the strictness of this architecture, the lack of a directive is considered a mistake. (Though rules may provide the opportunity to declare a default, and configs with preset defaults may be provided.)
187
+ * @returns {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | USE_AGNOSTIC_STRATEGIES | null} The commented directive, or lack thereof via `null`. Given the strictness of this architecture, the lack of a directive is considered a mistake. (Though rules may provide the opportunity to declare a default, and configs with preset defaults may become provided.)
187
188
  */
188
189
  export const getCommentedDirectiveFromImportedModule = (resolvedImportPath) => {
189
190
  // gets the first line of the code of the import
@@ -231,7 +232,7 @@ export const getCommentedDirectiveFromImportedModule = (resolvedImportPath) => {
231
232
  * Gets the interpreted directive from a specified commented Strategy (such as `@serverLogics`) nested inside the import declaration for an import from an Agnostic Strategies Module.
232
233
  * @param {Readonly<import('@typescript-eslint/utils').TSESLint.RuleContext<typeof reExportNotSameMessageId | typeof importBreaksCommentedImportRulesMessageId | typeof noCommentedDirective | typeof commentedDirectiveVerificationFailed | typeof importNotStrategized | typeof exportNotStrategized, []>>} context The ESLint rule's `context` object.
233
234
  * @param {import('@typescript-eslint/types').TSESTree.ImportDeclaration} node The ESLint `node` of the rule's current traversal.
234
- * @returns {USE_SERVER_LOGICS | USE_CLIENT_LOGICS | USE_AGNOSTIC_LOGICS | USE_SERVER_COMPONENTS | USE_CLIENT_COMPONENTS | USE_AGNOSTIC_COMPONENTS | USE_SERVER_FUNCTIONS | USE_CLIENT_CONTEXTS | USE_AGNOSTIC_CONDITIONS | null} Returns the interpreted directive, a.k.a. strategized directive, or lack thereof via `null`.
235
+ * @returns The interpreted directive, a.k.a. strategized directive, or lack thereof via `null`.
235
236
  */
236
237
  export const getStrategizedDirective = (context, node) => {
237
238
  const firstNestedComment = context.sourceCode.getCommentsInside(node)[0];
@@ -239,9 +240,17 @@ export const getStrategizedDirective = (context, node) => {
239
240
  // returns null early if there is no nested comments
240
241
  if (!firstNestedComment) return null;
241
242
 
242
- const strategy = firstNestedComment.value.trim() || null;
243
+ const rawStrategy = firstNestedComment.value.trim() || "";
244
+
245
+ const strategy =
246
+ strategiesArray.find((strategy) => strategy === rawStrategy) ?? null;
247
+
248
+ // returns null early if no strategy was identified
249
+ if (!strategy) return null;
243
250
 
244
- return commentedStrategies_CommentedDirectives[strategy] || null;
251
+ const commentedDirective = commentedStrategies_CommentedDirectives[strategy];
252
+
253
+ return commentedDirective;
245
254
  };
246
255
 
247
256
  /* isImportBlocked */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-use-agnostic",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "description": "Highlights problematic server-client imports in projects made with the Fullstack React Architecture.",
5
5
  "keywords": [
6
6
  "eslint",
@@ -48,5 +48,6 @@
48
48
  "engines": {
49
49
  "node": ">=18.18.0 <18.99 || >=20.9.0 <21.0.0 || >=21.1.0"
50
50
  },
51
- "type": "module"
51
+ "type": "module",
52
+ "types": "types/index.d.ts"
52
53
  }