@eslint-react/ast 3.0.0-next.8 → 3.0.0-next.80

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/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { unit } from "@eslint-react/eff";
2
1
  import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
3
2
  import { TSESTree as TSESTree$1 } from "@typescript-eslint/utils";
4
3
 
@@ -34,7 +33,7 @@ type TSESTreeProperty = TSESTree$1.PropertyDefinition | TSESTree$1.TSIndexSignat
34
33
  /**
35
34
  * Represents all JSX-related nodes in TSESTree
36
35
  */
37
- type TSESTreeJSX = TSESTree$1.JSXAttribute | TSESTree$1.JSXChild | TSESTree$1.JSXClosingElement | TSESTree$1.JSXClosingFragment | TSESTree$1.JSXElement | TSESTree$1.JSXEmptyExpression | TSESTree$1.JSXExpression | TSESTree$1.JSXExpressionContainer | TSESTree$1.JSXFragment | TSESTree$1.JSXIdentifier | TSESTree$1.JSXIdentifierToken | TSESTree$1.JSXMemberExpression | TSESTree$1.JSXNamespacedName | TSESTree$1.JSXOpeningElement | TSESTree$1.JSXOpeningFragment | TSESTree$1.JSXSpreadAttribute | TSESTree$1.JSXSpreadChild | TSESTree$1.JSXTagNameExpression | TSESTree$1.JSXText | TSESTree$1.JSXTextToken;
36
+ type TSESTreeJSX = TSESTree$1.JSXAttribute | TSESTree$1.JSXChild | TSESTree$1.JSXClosingElement | TSESTree$1.JSXClosingFragment | TSESTree$1.JSXEmptyExpression | TSESTree$1.JSXIdentifierToken | TSESTree$1.JSXOpeningElement | TSESTree$1.JSXOpeningFragment | TSESTree$1.JSXSpreadAttribute | TSESTree$1.JSXTagNameExpression | TSESTree$1.JSXTextToken;
38
37
  /**
39
38
  * Represents JSX attribute-like nodes (attributes and spread attributes)
40
39
  */
@@ -56,7 +55,7 @@ type TSESTreeTypeExpression = TSESTree$1.TSAsExpression | TSESTree$1.TSNonNullEx
56
55
  */
57
56
  type TSESTreeTypeAssertionExpression = TSESTree$1.TSAsExpression | TSESTree$1.TSNonNullExpression | TSESTree$1.TSSatisfiesExpression | TSESTree$1.TSTypeAssertion;
58
57
  /**
59
- * Represents a directive expression statement in TSESTree (e.g., "use strict";)
58
+ * Represents a directive expression statement in TSESTree (ex: "use strict";)
60
59
  */
61
60
  type TSESTreeDirective = TSESTree$1.ExpressionStatement & {
62
61
  directive: string;
@@ -73,37 +72,9 @@ type TSESTreeDirectiveLike = TSESTree$1.ExpressionStatement & {
73
72
  /**
74
73
  * Get the class identifier of a class node
75
74
  * @param node The class node to get the identifier from
76
- * @returns The class identifier or unit if not found
75
+ * @returns The class identifier or null if not found
77
76
  */
78
- declare function getClassId(node: TSESTreeClass): TSESTree.BindingName | unit;
79
- //#endregion
80
- //#region src/directive-helper.d.ts
81
- /**
82
- * Get all directive expression statements from the top of a program AST node
83
- * @param node The program AST node
84
- * @returns The array of directive string literals (e.g., "use strict")
85
- */
86
- declare function getFileDirectives(node: TSESTree.Program): TSESTreeDirective[];
87
- /**
88
- * Get all directive expression statements from the top of a function AST node
89
- * @param node The function AST node
90
- * @returns The array of directive string literals (e.g., "use memo", "use no memo")
91
- */
92
- declare function getFunctionDirectives(node: TSESTreeFunction): TSESTreeDirective[];
93
- /**
94
- * Check if a directive with the given name exists in the file or function directives
95
- * @param node The program or function AST node
96
- * @param name The directive name to check (e.g., "use strict", "use memo", "use no memo")
97
- * @returns True if the directive exists, false otherwise
98
- */
99
- declare function isDirectiveInFile(node: TSESTree.Program, name: string): boolean;
100
- /**
101
- * Check if a directive with the given name exists in the function directives
102
- * @param node The function AST node
103
- * @param name The directive name to check (e.g., "use memo", "use no memo")
104
- * @returns True if the directive exists, false otherwise
105
- */
106
- declare function isDirectiveInFunction(node: TSESTreeFunction, name: string): boolean;
77
+ declare function getClassId(node: TSESTreeClass): TSESTree.BindingName | null;
107
78
  //#endregion
108
79
  //#region src/directive-is.d.ts
109
80
  /**
@@ -136,15 +107,6 @@ declare function isDirectiveKind(kind: string): kind is DirectiveKind;
136
107
  */
137
108
  declare function isDirectiveName(name: string): boolean;
138
109
  //#endregion
139
- //#region src/expression-base.d.ts
140
- /**
141
- * Unwraps any type expressions to get the underlying JavaScript expression node.
142
- * Recursively processes nodes until a non-type expression is found.
143
- * @param node The AST node to unwrap
144
- * @returns The underlying JavaScript expression node
145
- */
146
- declare function getUnderlyingExpression(node: TSESTree.Node): Exclude<TSESTree.Node, TSESTreeTypeExpression>;
147
- //#endregion
148
110
  //#region src/expression-is.d.ts
149
111
  /**
150
112
  * Check if the given expression is a 'this' expression
@@ -190,6 +152,36 @@ declare const getNestedNewExpressions: (node: TSESTree.Node) => TSESTree.NewExpr
190
152
  */
191
153
  declare const getNestedCallExpressions: (node: TSESTree.Node) => TSESTree.CallExpression[];
192
154
  //#endregion
155
+ //#region src/file-directive.d.ts
156
+ /**
157
+ * Get all directive expression statements from the top of a program AST node
158
+ * @param node The program AST node
159
+ * @returns The array of directive string literals (ex: "use strict")
160
+ */
161
+ declare function getFileDirectives(node: TSESTree.Program): TSESTreeDirective[];
162
+ /**
163
+ * Check if a directive with the given name exists in the file or function directives
164
+ * @param node The program or function AST node
165
+ * @param name The directive name to check (ex: "use strict", "use memo", "use no memo")
166
+ * @returns True if the directive exists, false otherwise
167
+ */
168
+ declare function isDirectiveInFile(node: TSESTree.Program, name: string): boolean;
169
+ //#endregion
170
+ //#region src/function-directive.d.ts
171
+ /**
172
+ * Get all directive expression statements from the top of a function AST node
173
+ * @param node The function AST node
174
+ * @returns The array of directive string literals (ex: "use memo", "use no memo")
175
+ */
176
+ declare function getFunctionDirectives(node: TSESTreeFunction): TSESTreeDirective[];
177
+ /**
178
+ * Check if a directive with the given name exists in the function directives
179
+ * @param node The function AST node
180
+ * @param name The directive name to check (ex: "use memo", "use no memo")
181
+ * @returns True if the directive exists, false otherwise
182
+ */
183
+ declare function isDirectiveInFunction(node: TSESTreeFunction, name: string): boolean;
184
+ //#endregion
193
185
  //#region src/function-id.d.ts
194
186
  /**
195
187
  * Gets the static name of a function AST node. For function declarations it is
@@ -198,7 +190,7 @@ declare const getNestedCallExpressions: (node: TSESTree.Node) => TSESTree.CallEx
198
190
  * where JS gives anonymous function expressions names. We roughly detect the
199
191
  * same AST nodes with some exceptions to better fit our use case.
200
192
  */
201
- declare function getFunctionId(node: TSESTree.Expression | TSESTreeFunction): TSESTree.ArrayExpression | TSESTree.ArrayPattern | TSESTree.ArrowFunctionExpression | TSESTree.AssignmentExpression | TSESTree.AwaitExpression | TSESTree.PrivateInExpression | TSESTree.SymmetricBinaryExpression | TSESTree.CallExpression | TSESTree.ChainExpression | TSESTree.ClassExpression | TSESTree.ConditionalExpression | TSESTree.FunctionExpression | TSESTree.Identifier | TSESTree.ImportExpression | TSESTree.JSXElement | TSESTree.JSXFragment | TSESTree.BigIntLiteral | TSESTree.BooleanLiteral | TSESTree.NullLiteral | TSESTree.NumberLiteral | TSESTree.RegExpLiteral | TSESTree.StringLiteral | TSESTree.LogicalExpression | TSESTree.MemberExpressionComputedName | TSESTree.MemberExpressionNonComputedName | TSESTree.MetaProperty | TSESTree.NewExpression | TSESTree.ObjectExpression | TSESTree.ObjectPattern | TSESTree.PrivateIdentifier | TSESTree.SequenceExpression | TSESTree.Super | TSESTree.TaggedTemplateExpression | TSESTree.TemplateLiteral | TSESTree.ThisExpression | TSESTree.TSAsExpression | TSESTree.TSInstantiationExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion | TSESTree.UnaryExpressionBitwiseNot | TSESTree.UnaryExpressionDelete | TSESTree.UnaryExpressionMinus | TSESTree.UnaryExpressionNot | TSESTree.UnaryExpressionPlus | TSESTree.UnaryExpressionTypeof | TSESTree.UnaryExpressionVoid | TSESTree.UpdateExpression | TSESTree.YieldExpression | undefined;
193
+ declare function getFunctionId(node: TSESTree.Expression | TSESTreeFunction): TSESTree.ArrayExpression | TSESTree.ArrayPattern | TSESTree.ArrowFunctionExpression | TSESTree.AssignmentExpression | TSESTree.AwaitExpression | TSESTree.PrivateInExpression | TSESTree.SymmetricBinaryExpression | TSESTree.CallExpression | TSESTree.ChainExpression | TSESTree.ClassExpression | TSESTree.ConditionalExpression | TSESTree.FunctionExpression | TSESTree.Identifier | TSESTree.ImportExpression | TSESTree.JSXElement | TSESTree.JSXFragment | TSESTree.BigIntLiteral | TSESTree.BooleanLiteral | TSESTree.NullLiteral | TSESTree.NumberLiteral | TSESTree.RegExpLiteral | TSESTree.StringLiteral | TSESTree.LogicalExpression | TSESTree.MemberExpressionComputedName | TSESTree.MemberExpressionNonComputedName | TSESTree.MetaProperty | TSESTree.NewExpression | TSESTree.ObjectExpression | TSESTree.ObjectPattern | TSESTree.PrivateIdentifier | TSESTree.SequenceExpression | TSESTree.Super | TSESTree.TaggedTemplateExpression | TSESTree.TemplateLiteral | TSESTree.ThisExpression | TSESTree.TSAsExpression | TSESTree.TSInstantiationExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion | TSESTree.UnaryExpressionBitwiseNot | TSESTree.UnaryExpressionDelete | TSESTree.UnaryExpressionMinus | TSESTree.UnaryExpressionNot | TSESTree.UnaryExpressionPlus | TSESTree.UnaryExpressionTypeof | TSESTree.UnaryExpressionVoid | TSESTree.UpdateExpression | TSESTree.YieldExpression | null;
202
194
  /**
203
195
  * Type representing the return type of getFunctionId
204
196
  */
@@ -215,14 +207,14 @@ type FunctionInitPath = readonly [TSESTree.FunctionDeclaration] | readonly [TSES
215
207
  * Determine what kind of component declaration pattern the function belongs to.
216
208
  *
217
209
  * @param node The function node to analyze
218
- * @returns The function initialization path or unit if not identifiable
210
+ * @returns The function initialization path or null if not identifiable
219
211
  */
220
- declare function getFunctionInitPath(node: TSESTreeFunction): unit | FunctionInitPath;
212
+ declare function getFunctionInitPath(node: TSESTreeFunction): null | FunctionInitPath;
221
213
  /**
222
214
  * Check if a specific function call exists in the function initialization path.
223
215
  * Useful for detecting HOCs like React.memo, React.forwardRef, etc.
224
216
  *
225
- * @param callName The name of the call to check for (e.g., "memo", "forwardRef")
217
+ * @param callName The name of the call to check for (ex: "memo", "forwardRef")
226
218
  * @param initPath The function initialization path to search in
227
219
  * @returns True if the call exists in the path, false otherwise
228
220
  */
@@ -249,7 +241,7 @@ declare function isFunctionImmediatelyInvoked(node: TSESTreeFunction): boolean;
249
241
  * @param name The name to check
250
242
  * @returns True if the node is an identifier, false otherwise
251
243
  */
252
- declare function isIdentifier(node: TSESTree.Node | null | unit, name?: string): node is TSESTree.Identifier;
244
+ declare function isIdentifier(node: TSESTree.Node | null, name?: string): node is TSESTree.Identifier;
253
245
  //#endregion
254
246
  //#region src/identifier-name.d.ts
255
247
  /**
@@ -259,6 +251,15 @@ declare function isIdentifier(node: TSESTree.Node | null | unit, name?: string):
259
251
  */
260
252
  declare function isIdentifierName(name: string): boolean;
261
253
  //#endregion
254
+ //#region src/identifier-traverse.d.ts
255
+ /**
256
+ * Get the root identifier of a (possibly nested) member expression.
257
+ * For `a.b.c`, returns the `a` Identifier node.
258
+ * @param node The expression to analyze
259
+ * @returns The root Identifier node, or null if it cannot be determined (ex: non-identifier root)
260
+ */
261
+ declare function getRootIdentifier(node: TSESTree.Expression | TSESTree.PrivateIdentifier): TSESTree.Identifier | null;
262
+ //#endregion
262
263
  //#region src/literal-is.d.ts
263
264
  /**
264
265
  * Check if a node is a literal value
@@ -272,7 +273,7 @@ declare function isLiteral(node: TSESTree.Node, type: "number"): node is TSESTre
272
273
  declare function isLiteral(node: TSESTree.Node, type: "regexp"): node is TSESTree.RegExpLiteral;
273
274
  declare function isLiteral(node: TSESTree.Node, type: "string"): node is TSESTree.StringLiteral;
274
275
  //#endregion
275
- //#region src/node-equal.d.ts
276
+ //#region src/node-equality.d.ts
276
277
  /**
277
278
  * Check if two nodes are equal
278
279
  * @param a node to compare
@@ -442,24 +443,33 @@ declare const SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION: string;
442
443
  * Find the parent node that satisfies the test function
443
444
  * @param node The AST node
444
445
  * @param test The test function
445
- * @returns The parent node that satisfies the test function or `_` if not found
446
+ * @returns The parent node that satisfies the test function or `null` if not found
446
447
  */
447
- declare function findParentNode<A extends TSESTree.Node>(node: TSESTree.Node | unit, test: (n: TSESTree.Node) => n is A): A | unit;
448
+ declare function findParentNode<A extends TSESTree.Node>(node: TSESTree.Node | null, test: (n: TSESTree.Node) => n is A): A | null;
448
449
  /**
449
- * Find the parent node that satisfies the test function or `_` if not found
450
+ * Find the parent node that satisfies the test function or `null` if not found
450
451
  * @param node The AST node
451
452
  * @param test The test function
452
453
  * @returns The parent node that satisfies the test function
453
454
  */
454
- declare function findParentNode(node: TSESTree.Node | unit, test: (node: TSESTree.Node) => boolean): TSESTree.Node | unit;
455
+ declare function findParentNode(node: TSESTree.Node | null, test: (node: TSESTree.Node) => boolean): TSESTree.Node | null;
455
456
  //#endregion
456
- //#region src/process-env-node-env.d.ts
457
+ //#region src/node-unwrap.d.ts
458
+ /**
459
+ * Unwraps any type expressions to get the underlying JavaScript expression node.
460
+ * Recursively processes nodes until a non-type expression is found.
461
+ * @param node The AST node to unwrap
462
+ * @returns The underlying JavaScript expression node
463
+ */
464
+ declare function getUnderlyingExpression(node: TSESTree.Node): Exclude<TSESTree.Node, TSESTreeTypeExpression>;
465
+ //#endregion
466
+ //#region src/pattern-process-env-node-env.d.ts
457
467
  /**
458
468
  * Check if the given node is a member expression that accesses `process.env.NODE_ENV`
459
469
  * @param node The AST node
460
470
  * @returns True if the node is a member expression that accesses `process.env.NODE_ENV`, false otherwise
461
471
  */
462
- declare function isProcessEnvNodeEnv(node: TSESTree.Node | null | unit): node is TSESTree.MemberExpression;
472
+ declare function isProcessEnvNodeEnv(node: TSESTree.Node | null): node is TSESTree.MemberExpression;
463
473
  /**
464
474
  * Check if the given node is a binary expression that compares `process.env.NODE_ENV` with a string literal.
465
475
  * @param node The AST node
@@ -467,31 +477,40 @@ declare function isProcessEnvNodeEnv(node: TSESTree.Node | null | unit): node is
467
477
  * @param value The string literal value to compare against
468
478
  * @returns True if the node is a binary expression that compares `process.env.NODE_ENV` with the specified value, false otherwise
469
479
  */
470
- declare function isProcessEnvNodeEnvCompare(node: TSESTree.Node | null | unit, operator: "===" | "!==", value: "development" | "production"): node is TSESTree.BinaryExpression;
471
- //#endregion
472
- //#region src/property-name.d.ts
473
- /**
474
- * Get the name of a property from a node
475
- * Handles identifiers, private identifiers, literals, and template literals
476
- * @param node The node to get the property name from
477
- * @returns The property name or unit if not determinable
478
- */
479
- declare function getPropertyName(node: TSESTree.Node): string | unit;
480
+ declare function isProcessEnvNodeEnvCompare(node: TSESTree.Node | null, operator: "===" | "!==", value: "development" | "production"): node is TSESTree.BinaryExpression;
480
481
  //#endregion
481
- //#region src/vitest-mock.d.ts
482
+ //#region src/pattern-vitest-mock.d.ts
482
483
  /**
483
484
  * Check if the given node is a `vi.mock`.
484
485
  * @param node The node to check
485
486
  * @returns `true` if the node is a `vi.mock`, otherwise `false`.
486
487
  * @internal
487
488
  */
488
- declare function isViMock(node: TSESTree.Node | null | unit): node is TSESTree.MemberExpression;
489
+ declare function isViMock(node: TSESTree.Node | null): node is TSESTree.MemberExpression;
489
490
  /**
490
491
  * Check if the given node is a `vi.mock` callback.
491
492
  * @param node The node to check
492
493
  * @returns `true` if the node is a `vi.mock` callback, otherwise `false`.
493
494
  * @internal
494
495
  */
495
- declare function isViMockCallback(node: TSESTree.Node | null | unit): boolean;
496
+ declare function isViMockCallback(node: TSESTree.Node | null): boolean;
497
+ //#endregion
498
+ //#region src/property-name.d.ts
499
+ /**
500
+ * Get the name of a property from a node
501
+ * Handles identifiers, private identifiers, literals, and template literals
502
+ * @param node The node to get the property name from
503
+ * @returns The property name or null if not determinable
504
+ */
505
+ declare function getPropertyName(node: TSESTree.Node): string | null;
506
+ //#endregion
507
+ //#region src/property-traverse.d.ts
508
+ /**
509
+ * Recursively traverses an object expression's properties to find a property with the specified name
510
+ * @param properties The properties of the object expression to traverse
511
+ * @param name The name of the property to find
512
+ * @returns The matching property node, or null if not found
513
+ */
514
+ declare function findProperty(properties: TSESTree.ObjectLiteralElement[], name: string): TSESTree.Property | null;
496
515
  //#endregion
497
- export { DirectiveKind, DisplayNameAssignmentExpression, FunctionID, FunctionInitPath, ImplicitReturnArrowFunctionExpression, ObjectDestructuringVariableDeclarator, SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION, SEL_IMPLICIT_RETURN_ARROW_FUNCTION_EXPRESSION, SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR, TSESTreeArrayTupleType, TSESTreeClass, TSESTreeDestructuringPattern, TSESTreeDirective, TSESTreeDirectiveLike, TSESTreeFunction, TSESTreeFunctionType, TSESTreeJSX, TSESTreeJSXAttributeLike, TSESTreeLoop, TSESTreeMethodOrProperty, TSESTreeProperty, TSESTreeTypeAssertionExpression, TSESTreeTypeDeclaration, TSESTreeTypeExpression, findParentNode, getClassId, getFileDirectives, getFullyQualifiedName, getFunctionDirectives, getFunctionId, getFunctionInitPath, getHumanReadableKind, getNestedCallExpressions, getNestedExpressionsOfType, getNestedIdentifiers, getNestedNewExpressions, getNestedReturnStatements, getPropertyName, getUnderlyingExpression, hasCallInFunctionInitPath, is, isClass, isConditional, isControlFlow, isDirective, isDirectiveInFile, isDirectiveInFunction, isDirectiveKind, isDirectiveLike, isDirectiveName, isFunction, isFunctionEmpty, isFunctionImmediatelyInvoked, isFunctionType, isIdentifier, isIdentifierName, isJSX, isJSXElement, isJSXFragment, isJSXTagNameExpression, isLineBreak, isLiteral, isLoop, isMethodOrProperty, isMultiLine, isNodeEqual, isOneOf, isProcessEnvNodeEnv, isProcessEnvNodeEnvCompare, isProperty, isThisExpressionLoose, isTypeAssertionExpression, isTypeExpression, isViMock, isViMockCallback };
516
+ export { DirectiveKind, DisplayNameAssignmentExpression, FunctionID, FunctionInitPath, ImplicitReturnArrowFunctionExpression, ObjectDestructuringVariableDeclarator, SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION, SEL_IMPLICIT_RETURN_ARROW_FUNCTION_EXPRESSION, SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR, TSESTreeArrayTupleType, TSESTreeClass, TSESTreeDestructuringPattern, TSESTreeDirective, TSESTreeDirectiveLike, TSESTreeFunction, TSESTreeFunctionType, TSESTreeJSX, TSESTreeJSXAttributeLike, TSESTreeLoop, TSESTreeMethodOrProperty, TSESTreeProperty, TSESTreeTypeAssertionExpression, TSESTreeTypeDeclaration, TSESTreeTypeExpression, findParentNode, findProperty, getClassId, getFileDirectives, getFullyQualifiedName, getFunctionDirectives, getFunctionId, getFunctionInitPath, getHumanReadableKind, getNestedCallExpressions, getNestedExpressionsOfType, getNestedIdentifiers, getNestedNewExpressions, getNestedReturnStatements, getPropertyName, getRootIdentifier, getUnderlyingExpression, hasCallInFunctionInitPath, is, isClass, isConditional, isControlFlow, isDirective, isDirectiveInFile, isDirectiveInFunction, isDirectiveKind, isDirectiveLike, isDirectiveName, isFunction, isFunctionEmpty, isFunctionImmediatelyInvoked, isFunctionType, isIdentifier, isIdentifierName, isJSX, isJSXElement, isJSXFragment, isJSXTagNameExpression, isLineBreak, isLiteral, isLoop, isMethodOrProperty, isMultiLine, isNodeEqual, isOneOf, isProcessEnvNodeEnv, isProcessEnvNodeEnvCompare, isProperty, isThisExpressionLoose, isTypeAssertionExpression, isTypeExpression, isViMock, isViMockCallback };
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
- import { dual, or, unit } from "@eslint-react/eff";
2
- import { AST_NODE_TYPES } from "@typescript-eslint/types";
1
+ import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
3
2
  import { ASTUtils } from "@typescript-eslint/utils";
4
3
  import { simpleTraverse } from "@typescript-eslint/typescript-estree";
5
4
  import { delimiterCase, replace, toLowerCase } from "string-ts";
@@ -8,12 +7,12 @@ import { delimiterCase, replace, toLowerCase } from "string-ts";
8
7
  /**
9
8
  * Get the class identifier of a class node
10
9
  * @param node The class node to get the identifier from
11
- * @returns The class identifier or unit if not found
10
+ * @returns The class identifier or null if not found
12
11
  */
13
12
  function getClassId(node) {
14
13
  if (node.id != null) return node.id;
15
14
  if (node.parent.type === AST_NODE_TYPES.VariableDeclarator) return node.parent.id;
16
- return unit;
15
+ return null;
17
16
  }
18
17
 
19
18
  //#endregion
@@ -60,54 +59,6 @@ function isDirectiveLike(node) {
60
59
  return node.type === AST_NODE_TYPES.ExpressionStatement && isLiteral(node.expression, "string") && isDirectiveName(node.expression.value);
61
60
  }
62
61
 
63
- //#endregion
64
- //#region src/directive-helper.ts
65
- /**
66
- * Get all directive expression statements from the top of a program AST node
67
- * @param node The program AST node
68
- * @returns The array of directive string literals (e.g., "use strict")
69
- */
70
- function getFileDirectives(node) {
71
- const directives = [];
72
- for (const stmt of node.body) {
73
- if (!isDirective(stmt)) continue;
74
- directives.push(stmt);
75
- }
76
- return directives;
77
- }
78
- /**
79
- * Get all directive expression statements from the top of a function AST node
80
- * @param node The function AST node
81
- * @returns The array of directive string literals (e.g., "use memo", "use no memo")
82
- */
83
- function getFunctionDirectives(node) {
84
- const directives = [];
85
- if (node.body.type !== AST_NODE_TYPES.BlockStatement) return directives;
86
- for (const stmt of node.body.body) {
87
- if (!isDirective(stmt)) continue;
88
- directives.push(stmt);
89
- }
90
- return directives;
91
- }
92
- /**
93
- * Check if a directive with the given name exists in the file or function directives
94
- * @param node The program or function AST node
95
- * @param name The directive name to check (e.g., "use strict", "use memo", "use no memo")
96
- * @returns True if the directive exists, false otherwise
97
- */
98
- function isDirectiveInFile(node, name) {
99
- return getFileDirectives(node).some((d) => d.directive === name);
100
- }
101
- /**
102
- * Check if a directive with the given name exists in the function directives
103
- * @param node The function AST node
104
- * @param name The directive name to check (e.g., "use memo", "use no memo")
105
- * @returns True if the directive exists, false otherwise
106
- */
107
- function isDirectiveInFunction(node, name) {
108
- return getFunctionDirectives(node).some((d) => d.directive === name);
109
- }
110
-
111
62
  //#endregion
112
63
  //#region src/directive-kind.ts
113
64
  /**
@@ -119,6 +70,127 @@ function isDirectiveKind(kind) {
119
70
  return kind === "use client" || kind === "use server" || kind === "use memo" || kind === "use no memo";
120
71
  }
121
72
 
73
+ //#endregion
74
+ //#region ../../../.pkgs/eff/dist/index.js
75
+ function or(a, b) {
76
+ return (data) => a(data) || b(data);
77
+ }
78
+ /**
79
+ * Creates a function that can be used in a data-last (aka `pipe`able) or
80
+ * data-first style.
81
+ *
82
+ * The first parameter to `dual` is either the arity of the uncurried function
83
+ * or a predicate that determines if the function is being used in a data-first
84
+ * or data-last style.
85
+ *
86
+ * Using the arity is the most common use case, but there are some cases where
87
+ * you may want to use a predicate. For example, if you have a function that
88
+ * takes an optional argument, you can use a predicate to determine if the
89
+ * function is being used in a data-first or data-last style.
90
+ *
91
+ * You can pass either the arity of the uncurried function or a predicate
92
+ * which determines if the function is being used in a data-first or
93
+ * data-last style.
94
+ *
95
+ * **Example** (Using arity to determine data-first or data-last style)
96
+ *
97
+ * ```ts
98
+ * import { dual, pipe } from "effect/Function"
99
+ *
100
+ * const sum = dual<
101
+ * (that: number) => (self: number) => number,
102
+ * (self: number, that: number) => number
103
+ * >(2, (self, that) => self + that)
104
+ *
105
+ * console.log(sum(2, 3)) // 5
106
+ * console.log(pipe(2, sum(3))) // 5
107
+ * ```
108
+ *
109
+ * **Example** (Using call signatures to define the overloads)
110
+ *
111
+ * ```ts
112
+ * import { dual, pipe } from "effect/Function"
113
+ *
114
+ * const sum: {
115
+ * (that: number): (self: number) => number
116
+ * (self: number, that: number): number
117
+ * } = dual(2, (self: number, that: number): number => self + that)
118
+ *
119
+ * console.log(sum(2, 3)) // 5
120
+ * console.log(pipe(2, sum(3))) // 5
121
+ * ```
122
+ *
123
+ * **Example** (Using a predicate to determine data-first or data-last style)
124
+ *
125
+ * ```ts
126
+ * import { dual, pipe } from "effect/Function"
127
+ *
128
+ * const sum = dual<
129
+ * (that: number) => (self: number) => number,
130
+ * (self: number, that: number) => number
131
+ * >(
132
+ * (args) => args.length === 2,
133
+ * (self, that) => self + that
134
+ * )
135
+ *
136
+ * console.log(sum(2, 3)) // 5
137
+ * console.log(pipe(2, sum(3))) // 5
138
+ * ```
139
+ *
140
+ * @param arity - The arity of the uncurried function or a predicate that determines if the function is being used in a data-first or data-last style.
141
+ * @param body - The function to be curried.
142
+ * @since 1.0.0
143
+ */
144
+ const dual = function(arity, body) {
145
+ if (typeof arity === "function") return function() {
146
+ return arity(arguments) ? body.apply(this, arguments) : ((self) => body(self, ...arguments));
147
+ };
148
+ switch (arity) {
149
+ case 0:
150
+ case 1: throw new RangeError(`Invalid arity ${arity}`);
151
+ case 2: return function(a, b) {
152
+ if (arguments.length >= 2) return body(a, b);
153
+ return function(self) {
154
+ return body(self, a);
155
+ };
156
+ };
157
+ case 3: return function(a, b, c) {
158
+ if (arguments.length >= 3) return body(a, b, c);
159
+ return function(self) {
160
+ return body(self, a, b);
161
+ };
162
+ };
163
+ default: return function() {
164
+ if (arguments.length >= arity) return body.apply(this, arguments);
165
+ const args = arguments;
166
+ return function(self) {
167
+ return body(self, ...args);
168
+ };
169
+ };
170
+ }
171
+ };
172
+ /**
173
+ * Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`.
174
+ * The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`.
175
+ *
176
+ * @param self - The first function to apply (or the composed function in data-last style).
177
+ * @param bc - The second function to apply.
178
+ * @returns A composed function that applies both functions in sequence.
179
+ * @example
180
+ * ```ts
181
+ * import * as assert from "node:assert"
182
+ * import { compose } from "effect/Function"
183
+ *
184
+ * const increment = (n: number) => n + 1;
185
+ * const square = (n: number) => n * n;
186
+ *
187
+ * assert.strictEqual(compose(increment, square)(2), 9);
188
+ * ```
189
+ *
190
+ * @since 1.0.0
191
+ */
192
+ const compose = dual(2, (ab, bc) => (a) => bc(ab(a)));
193
+
122
194
  //#endregion
123
195
  //#region src/node-is.ts
124
196
  /**
@@ -275,7 +347,7 @@ const isTypeAssertionExpression = isOneOf([
275
347
  ]);
276
348
 
277
349
  //#endregion
278
- //#region src/expression-base.ts
350
+ //#region src/node-unwrap.ts
279
351
  /**
280
352
  * Unwraps any type expressions to get the underlying JavaScript expression node.
281
353
  * Recursively processes nodes until a non-type expression is found.
@@ -303,13 +375,13 @@ function isThisExpressionLoose(node) {
303
375
  //#endregion
304
376
  //#region src/node-traverse.ts
305
377
  function findParentNode(node, test) {
306
- if (node == null) return unit;
378
+ if (node == null) return null;
307
379
  let parent = node.parent;
308
380
  while (parent != null && parent.type !== AST_NODE_TYPES.Program) {
309
381
  if (test(parent)) return parent;
310
382
  parent = parent.parent;
311
383
  }
312
- return unit;
384
+ return null;
313
385
  }
314
386
 
315
387
  //#endregion
@@ -495,6 +567,57 @@ const getNestedNewExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.NewExp
495
567
  */
496
568
  const getNestedCallExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.CallExpression);
497
569
 
570
+ //#endregion
571
+ //#region src/file-directive.ts
572
+ /**
573
+ * Get all directive expression statements from the top of a program AST node
574
+ * @param node The program AST node
575
+ * @returns The array of directive string literals (ex: "use strict")
576
+ */
577
+ function getFileDirectives(node) {
578
+ const directives = [];
579
+ for (const stmt of node.body) {
580
+ if (!isDirective(stmt)) continue;
581
+ directives.push(stmt);
582
+ }
583
+ return directives;
584
+ }
585
+ /**
586
+ * Check if a directive with the given name exists in the file or function directives
587
+ * @param node The program or function AST node
588
+ * @param name The directive name to check (ex: "use strict", "use memo", "use no memo")
589
+ * @returns True if the directive exists, false otherwise
590
+ */
591
+ function isDirectiveInFile(node, name) {
592
+ return getFileDirectives(node).some((d) => d.directive === name);
593
+ }
594
+
595
+ //#endregion
596
+ //#region src/function-directive.ts
597
+ /**
598
+ * Get all directive expression statements from the top of a function AST node
599
+ * @param node The function AST node
600
+ * @returns The array of directive string literals (ex: "use memo", "use no memo")
601
+ */
602
+ function getFunctionDirectives(node) {
603
+ const directives = [];
604
+ if (node.body.type !== AST_NODE_TYPES.BlockStatement) return directives;
605
+ for (const stmt of node.body.body) {
606
+ if (!isDirective(stmt)) continue;
607
+ directives.push(stmt);
608
+ }
609
+ return directives;
610
+ }
611
+ /**
612
+ * Check if a directive with the given name exists in the function directives
613
+ * @param node The function AST node
614
+ * @param name The directive name to check (ex: "use memo", "use no memo")
615
+ * @returns True if the directive exists, false otherwise
616
+ */
617
+ function isDirectiveInFunction(node, name) {
618
+ return getFunctionDirectives(node).some((d) => d.directive === name);
619
+ }
620
+
498
621
  //#endregion
499
622
  //#region src/function-id.ts
500
623
  /**
@@ -515,7 +638,7 @@ function getFunctionId(node) {
515
638
  case node.parent.type === AST_NODE_TYPES.ConditionalExpression: return getFunctionId(node.parent);
516
639
  case isTypeAssertionExpression(node.parent): return getFunctionId(node.parent);
517
640
  }
518
- return unit;
641
+ return null;
519
642
  }
520
643
 
521
644
  //#endregion
@@ -525,7 +648,7 @@ function getFunctionId(node) {
525
648
  * Determine what kind of component declaration pattern the function belongs to.
526
649
  *
527
650
  * @param node The function node to analyze
528
- * @returns The function initialization path or unit if not identifiable
651
+ * @returns The function initialization path or null if not identifiable
529
652
  */
530
653
  function getFunctionInitPath(node) {
531
654
  if (node.type === AST_NODE_TYPES.FunctionDeclaration) return [node];
@@ -569,13 +692,13 @@ function getFunctionInitPath(node) {
569
692
  node
570
693
  ];
571
694
  }
572
- return unit;
695
+ return null;
573
696
  }
574
697
  /**
575
698
  * Check if a specific function call exists in the function initialization path.
576
699
  * Useful for detecting HOCs like React.memo, React.forwardRef, etc.
577
700
  *
578
- * @param callName The name of the call to check for (e.g., "memo", "forwardRef")
701
+ * @param callName The name of the call to check for (ex: "memo", "forwardRef")
579
702
  * @param initPath The function initialization path to search in
580
703
  * @returns True if the call exists in the path, false otherwise
581
704
  */
@@ -632,7 +755,24 @@ function isIdentifierName(name) {
632
755
  }
633
756
 
634
757
  //#endregion
635
- //#region src/node-equal.ts
758
+ //#region src/identifier-traverse.ts
759
+ /**
760
+ * Get the root identifier of a (possibly nested) member expression.
761
+ * For `a.b.c`, returns the `a` Identifier node.
762
+ * @param node The expression to analyze
763
+ * @returns The root Identifier node, or null if it cannot be determined (ex: non-identifier root)
764
+ */
765
+ function getRootIdentifier(node) {
766
+ const expr = getUnderlyingExpression(node);
767
+ switch (expr.type) {
768
+ case AST_NODE_TYPES.Identifier: return expr;
769
+ case AST_NODE_TYPES.MemberExpression: return getRootIdentifier(expr.object);
770
+ default: return null;
771
+ }
772
+ }
773
+
774
+ //#endregion
775
+ //#region src/node-equality.ts
636
776
  /**
637
777
  * Check if two nodes are equal
638
778
  * @param a node to compare
@@ -734,7 +874,7 @@ const SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION = [
734
874
  ].join("");
735
875
 
736
876
  //#endregion
737
- //#region src/process-env-node-env.ts
877
+ //#region src/pattern-process-env-node-env.ts
738
878
  /**
739
879
  * Check if the given node is a member expression that accesses `process.env.NODE_ENV`
740
880
  * @param node The AST node
@@ -760,23 +900,7 @@ function isProcessEnvNodeEnvCompare(node, operator, value) {
760
900
  }
761
901
 
762
902
  //#endregion
763
- //#region src/property-name.ts
764
- /**
765
- * Get the name of a property from a node
766
- * Handles identifiers, private identifiers, literals, and template literals
767
- * @param node The node to get the property name from
768
- * @returns The property name or unit if not determinable
769
- */
770
- function getPropertyName(node) {
771
- if (isTypeExpression(node)) return getPropertyName(getUnderlyingExpression(node));
772
- if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) return node.name;
773
- if (node.type === AST_NODE_TYPES.Literal) return String(node.value);
774
- if (node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0) return node.quasis[0]?.value.raw;
775
- return unit;
776
- }
777
-
778
- //#endregion
779
- //#region src/vitest-mock.ts
903
+ //#region src/pattern-vitest-mock.ts
780
904
  /**
781
905
  * Check if the given node is a `vi.mock`.
782
906
  * @param node The node to check
@@ -797,4 +921,39 @@ function isViMockCallback(node) {
797
921
  }
798
922
 
799
923
  //#endregion
800
- export { SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION, SEL_IMPLICIT_RETURN_ARROW_FUNCTION_EXPRESSION, SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR, findParentNode, getClassId, getFileDirectives, getFullyQualifiedName, getFunctionDirectives, getFunctionId, getFunctionInitPath, getHumanReadableKind, getNestedCallExpressions, getNestedExpressionsOfType, getNestedIdentifiers, getNestedNewExpressions, getNestedReturnStatements, getPropertyName, getUnderlyingExpression, hasCallInFunctionInitPath, is, isClass, isConditional, isControlFlow, isDirective, isDirectiveInFile, isDirectiveInFunction, isDirectiveKind, isDirectiveLike, isDirectiveName, isFunction, isFunctionEmpty, isFunctionImmediatelyInvoked, isFunctionType, isIdentifier, isIdentifierName, isJSX, isJSXElement, isJSXFragment, isJSXTagNameExpression, isLineBreak, isLiteral, isLoop, isMethodOrProperty, isMultiLine, isNodeEqual, isOneOf, isProcessEnvNodeEnv, isProcessEnvNodeEnvCompare, isProperty, isThisExpressionLoose, isTypeAssertionExpression, isTypeExpression, isViMock, isViMockCallback };
924
+ //#region src/property-name.ts
925
+ /**
926
+ * Get the name of a property from a node
927
+ * Handles identifiers, private identifiers, literals, and template literals
928
+ * @param node The node to get the property name from
929
+ * @returns The property name or null if not determinable
930
+ */
931
+ function getPropertyName(node) {
932
+ if (isTypeExpression(node)) return getPropertyName(getUnderlyingExpression(node));
933
+ if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) return node.name;
934
+ if (node.type === AST_NODE_TYPES.Literal) return String(node.value);
935
+ if (node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0) return node.quasis[0]?.value.cooked ?? node.quasis[0]?.value.raw ?? null;
936
+ return null;
937
+ }
938
+
939
+ //#endregion
940
+ //#region src/property-traverse.ts
941
+ /**
942
+ * Recursively traverses an object expression's properties to find a property with the specified name
943
+ * @param properties The properties of the object expression to traverse
944
+ * @param name The name of the property to find
945
+ * @returns The matching property node, or null if not found
946
+ */
947
+ function findProperty(properties, name) {
948
+ for (const prop of properties) {
949
+ if (prop.type === AST_NODE_TYPES.Property && getPropertyName(prop.key) === name) return prop;
950
+ if (prop.type === AST_NODE_TYPES.SpreadElement && prop.argument.type === AST_NODE_TYPES.ObjectExpression) {
951
+ const found = findProperty(prop.argument.properties, name);
952
+ if (found != null) return found;
953
+ }
954
+ }
955
+ return null;
956
+ }
957
+
958
+ //#endregion
959
+ export { SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION, SEL_IMPLICIT_RETURN_ARROW_FUNCTION_EXPRESSION, SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR, findParentNode, findProperty, getClassId, getFileDirectives, getFullyQualifiedName, getFunctionDirectives, getFunctionId, getFunctionInitPath, getHumanReadableKind, getNestedCallExpressions, getNestedExpressionsOfType, getNestedIdentifiers, getNestedNewExpressions, getNestedReturnStatements, getPropertyName, getRootIdentifier, getUnderlyingExpression, hasCallInFunctionInitPath, is, isClass, isConditional, isControlFlow, isDirective, isDirectiveInFile, isDirectiveInFunction, isDirectiveKind, isDirectiveLike, isDirectiveName, isFunction, isFunctionEmpty, isFunctionImmediatelyInvoked, isFunctionType, isIdentifier, isIdentifierName, isJSX, isJSXElement, isJSXFragment, isJSXTagNameExpression, isLineBreak, isLiteral, isLoop, isMethodOrProperty, isMultiLine, isNodeEqual, isOneOf, isProcessEnvNodeEnv, isProcessEnvNodeEnvCompare, isProperty, isThisExpressionLoose, isTypeAssertionExpression, isTypeExpression, isViMock, isViMockCallback };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint-react/ast",
3
- "version": "3.0.0-next.8",
3
+ "version": "3.0.0-next.80",
4
4
  "description": "ESLint React's TSESTree AST utility module.",
5
5
  "homepage": "https://github.com/Rel1cx/eslint-react",
6
6
  "bugs": {
@@ -33,16 +33,16 @@
33
33
  "@typescript-eslint/types": "canary",
34
34
  "@typescript-eslint/typescript-estree": "canary",
35
35
  "@typescript-eslint/utils": "canary",
36
- "string-ts": "^2.3.1",
37
- "@eslint-react/eff": "3.0.0-next.8"
36
+ "string-ts": "^2.3.1"
38
37
  },
39
38
  "devDependencies": {
40
- "tsdown": "^0.20.3",
41
- "@local/configs": "0.0.0"
39
+ "tsdown": "^0.21.0",
40
+ "@local/configs": "0.0.0",
41
+ "@local/eff": "3.0.0-beta.72"
42
42
  },
43
43
  "peerDependencies": {
44
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
45
- "typescript": ">=4.8.4 <6.0.0"
44
+ "eslint": "^10.0.0",
45
+ "typescript": "*"
46
46
  },
47
47
  "engines": {
48
48
  "node": ">=22.0.0"
@@ -50,6 +50,6 @@
50
50
  "scripts": {
51
51
  "build": "tsdown --dts-resolve",
52
52
  "lint:publish": "publint",
53
- "lint:ts": "tsc --noEmit"
53
+ "lint:ts": "tsl"
54
54
  }
55
55
  }