@memberjunction/react-test-harness 2.121.0 → 2.122.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Control Flow Analyzer
3
+ *
4
+ * Tracks how types and values narrow through JavaScript code based on runtime checks.
5
+ * Similar to TypeScript's control flow analysis for type narrowing.
6
+ *
7
+ * This eliminates false positives in linting rules by understanding patterns like:
8
+ * - if (x != null) { x.method() } // x is non-null here
9
+ * - if (typeof x === 'number') { x + 1 } // x is number here
10
+ * - if (arr.length > 0) { arr[0] } // arr has elements here
11
+ *
12
+ * @example
13
+ * const cfa = new ControlFlowAnalyzer(ast, componentSpec);
14
+ * if (cfa.isDefinitelyNonNull(node, path)) {
15
+ * // Safe to access property - no violation
16
+ * }
17
+ */
18
+ import * as t from '@babel/types';
19
+ import type { NodePath } from '@babel/traverse';
20
+ import type { ComponentSpec } from '@memberjunction/interactive-component-types';
21
+ export declare class ControlFlowAnalyzer {
22
+ private ast;
23
+ private componentSpec?;
24
+ private typeEngine;
25
+ constructor(ast: t.File, componentSpec?: ComponentSpec);
26
+ /**
27
+ * Check if a node is protected by a ternary/conditional guard
28
+ * Useful for checking expressions inside template literals within ternaries
29
+ *
30
+ * @param node - The node to check (e.g., member expression)
31
+ * @param path - Current path in the AST (should be close to the node's location)
32
+ * @returns true if protected by a ternary guard, false otherwise
33
+ */
34
+ isProtectedByTernary(node: t.Node, path: NodePath): boolean;
35
+ /**
36
+ * Check if a variable/property is definitely non-null at this location
37
+ *
38
+ * Detects patterns like:
39
+ * - if (x != null) { x.method() } // x is non-null here
40
+ * - if (x !== undefined) { x.prop }
41
+ * - if (x) { x.prop } // truthiness check
42
+ * - x && x.prop // short-circuit &&
43
+ * - x ? x.prop : default // ternary check
44
+ *
45
+ * @param node - The node being accessed (identifier or member expression)
46
+ * @param path - Current path in the AST
47
+ * @returns true if guaranteed non-null, false otherwise
48
+ */
49
+ isDefinitelyNonNull(node: t.Node, path: NodePath): boolean;
50
+ /**
51
+ * Check if a variable is narrowed to a specific type at this location
52
+ *
53
+ * Detects patterns like:
54
+ * - if (typeof x === 'number') { x + 1 } // x is number
55
+ * - if (x instanceof Date) { x.getTime() } // x is Date
56
+ * - if (Array.isArray(x)) { x.push() } // x is array
57
+ *
58
+ * @param node - The node being checked
59
+ * @param path - Current path in the AST
60
+ * @param expectedType - The type to check for ('number', 'string', 'Date', etc.)
61
+ * @returns true if narrowed to that type, false otherwise
62
+ */
63
+ isNarrowedToType(node: t.Node, path: NodePath, expectedType: string): boolean;
64
+ /**
65
+ * Recursively check for typeof guards in nested && expressions
66
+ */
67
+ private detectTypeofGuardRecursive;
68
+ /**
69
+ * Detect typeof guard pattern: typeof x === 'type'
70
+ */
71
+ private detectTypeofGuard;
72
+ /**
73
+ * Detect null/undefined guard pattern: x != null, x !== null, x !== undefined
74
+ * Also detects short-circuit OR patterns: !x || x.prop (x.prop is safe due to short-circuit)
75
+ */
76
+ private detectNullGuard;
77
+ /**
78
+ * Detect truthiness guard pattern: if (x), x && expr, x ? ... : ...
79
+ *
80
+ * Handles:
81
+ * - Simple identifier: if (x)
82
+ * - Member expression: if (obj.prop)
83
+ * - Full path matching: if (item.TotalCost) protects item.TotalCost.toFixed()
84
+ */
85
+ private detectTruthinessGuard;
86
+ /**
87
+ * Check if expression contains a negated check (!x) for the variable
88
+ * Used for detecting guards within OR chains
89
+ *
90
+ * @param expr - Expression to check
91
+ * @param varName - Variable name to look for
92
+ * @returns true if !varName exists in the expression
93
+ */
94
+ private detectNegatedCheck;
95
+ /**
96
+ * Detect negated null guard pattern for alternate branches
97
+ *
98
+ * In the alternate (else) branch of these patterns, the variable is proven truthy:
99
+ * - !x || ... ? ... : <here> (if !x is false, x is truthy)
100
+ * - !x.prop || ... ? ... : <here> (if !x.prop is false, x is truthy)
101
+ *
102
+ * @param test - The conditional test expression
103
+ * @param varName - Variable name or full member path to check
104
+ * @returns true if the pattern proves varName is truthy in the alternate branch
105
+ */
106
+ private detectNegatedNullGuard;
107
+ /**
108
+ * Extract variable name or full member expression path from node
109
+ *
110
+ * Examples:
111
+ * - `arr` → "arr"
112
+ * - `obj.prop` → "obj.prop"
113
+ * - `result.Results` → "result.Results"
114
+ * - `accountsResult.Results` → "accountsResult.Results"
115
+ *
116
+ * This allows CFA to match guards on nested properties correctly.
117
+ * For example, guard `accountsResult.Results?.length > 0` protects `accountsResult.Results[0]`
118
+ */
119
+ private extractVariableName;
120
+ /**
121
+ * Serialize a member expression to its full path string
122
+ * Handles both regular and optional member expressions
123
+ *
124
+ * Examples:
125
+ * - obj.prop → "obj.prop"
126
+ * - obj?.prop → "obj.prop" (normalized, ignores optional chaining syntax)
127
+ * - obj.prop.nested → "obj.prop.nested"
128
+ */
129
+ private serializeMemberExpression;
130
+ /**
131
+ * Check if path is inside the consequent (then block) of an if/ternary
132
+ */
133
+ private isInConsequent;
134
+ /**
135
+ * Check if path is in the alternate (else) branch of an if or ternary
136
+ */
137
+ private isInAlternate;
138
+ /**
139
+ * Check if path is on the right side of a logical && expression
140
+ */
141
+ private isInRightSide;
142
+ /**
143
+ * Check if an array access is safe due to bounds checking guards
144
+ *
145
+ * Detects patterns like:
146
+ * - if (arr.length > 0) { arr[0] } // index 0 is safe
147
+ * - if (arr.length > 2) { arr[2] } // index 2 is safe
148
+ * - if (arr.length === 0) return; arr[0] // early return pattern
149
+ * - arr.length > 0 && arr[0] // inline guard
150
+ * - arr ? arr[0] : default // ternary guard
151
+ *
152
+ * @param arrayNode - The array being accessed (identifier or member expression)
153
+ * @param accessIndex - The index being accessed (e.g., 0 for arr[0])
154
+ * @param path - Current path in the AST
155
+ * @returns true if access is guaranteed safe, false otherwise
156
+ */
157
+ isArrayAccessSafe(arrayNode: t.Node, accessIndex: number, path: NodePath): boolean;
158
+ /**
159
+ * Extract the maximum safe array index from a length check expression
160
+ *
161
+ * Examples:
162
+ * - arr.length > 0 → returns 0 (index 0 is safe)
163
+ * - arr?.length > 0 → returns 0 (optional chaining proves non-null)
164
+ * - arr.length > 2 → returns 2 (indices 0-2 are safe)
165
+ * - arr.length >= 3 → returns 2 (indices 0-2 are safe)
166
+ * - arr.length !== 0 → returns 0 (index 0 is safe)
167
+ *
168
+ * @param test - The test expression to analyze
169
+ * @param arrayName - The array variable name to look for
170
+ * @returns Maximum safe index, or -1 if no length check found
171
+ */
172
+ private getMaxSafeIndexFromLengthCheck;
173
+ /**
174
+ * Check if an expression is accessing the length property of an array
175
+ * Handles both regular and optional chaining: arr.length and arr?.length
176
+ * Also handles nested paths: obj.arr.length and obj.arr?.length
177
+ */
178
+ private isLengthAccess;
179
+ /**
180
+ * Check if a statement or block contains an early return
181
+ */
182
+ private hasEarlyReturn;
183
+ }
184
+ //# sourceMappingURL=control-flow-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-flow-analyzer.d.ts","sourceRoot":"","sources":["../../src/lib/control-flow-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAClC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AAGjF,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,UAAU,CAAsB;gBAE5B,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,aAAa;IAMtD;;;;;;;OAOG;IACH,oBAAoB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO;IA0E3D;;;;;;;;;;;;;OAaG;IACH,mBAAmB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO;IA4F1D;;;;;;;;;;;;OAYG;IACH,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO;IAwD7E;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAelC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA0BzB;;;OAGG;IACH,OAAO,CAAC,eAAe;IA6DvB;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB;IAgC7B;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAuB1B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,sBAAsB;IA2B9B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,mBAAmB;IAc3B;;;;;;;;OAQG;IACH,OAAO,CAAC,yBAAyB;IA2BjC;;OAEG;IACH,OAAO,CAAC,cAAc;IA4BtB;;OAEG;IACH,OAAO,CAAC,aAAa;IA4BrB;;OAEG;IACH,OAAO,CAAC,aAAa;IAmBrB;;;;;;;;;;;;;;OAcG;IACH,iBAAiB,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO;IAkHlF;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,8BAA8B;IA8DtC;;;;OAIG;IACH,OAAO,CAAC,cAAc;IA2BtB;;OAEG;IACH,OAAO,CAAC,cAAc;CAevB"}