@eventra_dev/eventra-cli 0.1.28 → 0.1.30

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.
@@ -10,25 +10,11 @@ function findTrackParamIndex(fn) {
10
10
  fn.parameters.forEach((p, i) => {
11
11
  if (typescript_1.default.isIdentifier(p.name)) {
12
12
  paramIndex.set(p.name.text, i);
13
- // default param: (name = "x")
14
- if (p.initializer && typescript_1.default.isStringLiteral(p.initializer)) {
15
- if (i === 0)
16
- return 0;
17
- }
18
13
  }
19
14
  });
20
15
  let result = null;
21
- function unwrap(node) {
22
- // as / parentheses
23
- while (typescript_1.default.isAsExpression(node) ||
24
- typescript_1.default.isParenthesizedExpression(node)) {
25
- node = node.expression;
26
- }
27
- return node;
28
- }
29
- function checkArg(arg) {
30
- arg = unwrap(arg);
31
- // identifier → param
16
+ function check(arg) {
17
+ // identifier
32
18
  if (typescript_1.default.isIdentifier(arg)) {
33
19
  const idx = paramIndex.get(arg.text);
34
20
  if (idx !== undefined) {
@@ -36,12 +22,7 @@ function findTrackParamIndex(fn) {
36
22
  return true;
37
23
  }
38
24
  }
39
- // string literal
40
- if (typescript_1.default.isStringLiteral(arg)) {
41
- result = 0;
42
- return true;
43
- }
44
- // template `${name}`
25
+ // template
45
26
  if (typescript_1.default.isTemplateExpression(arg)) {
46
27
  for (const span of arg.templateSpans) {
47
28
  if (typescript_1.default.isIdentifier(span.expression)) {
@@ -52,49 +33,33 @@ function findTrackParamIndex(fn) {
52
33
  }
53
34
  }
54
35
  }
55
- result = 0;
56
- return true;
57
36
  }
58
37
  // object { event: name }
59
38
  if (typescript_1.default.isObjectLiteralExpression(arg)) {
60
39
  for (const prop of arg.properties) {
61
40
  if (!typescript_1.default.isPropertyAssignment(prop))
62
41
  continue;
63
- const name = prop.name.getText();
64
- if (["event", "name", "type"].includes(name)) {
65
- return checkArg(prop.initializer);
42
+ const key = prop.name.getText();
43
+ if (["event", "name", "type"].includes(key)) {
44
+ return check(prop.initializer);
66
45
  }
67
46
  }
68
47
  }
69
- // call: String(name)
70
- if (typescript_1.default.isCallExpression(arg)) {
71
- for (const inner of arg.arguments) {
72
- if (checkArg(inner))
73
- return true;
74
- }
75
- }
76
48
  return false;
77
49
  }
78
50
  function visit(node) {
79
51
  if (result !== null)
80
52
  return;
81
53
  if (typescript_1.default.isCallExpression(node)) {
82
- let isTrackCall = false;
83
- if (typescript_1.default.isPropertyAccessExpression(node.expression)) {
84
- if (node.expression.name.text === "track") {
85
- isTrackCall = true;
86
- }
87
- }
88
- if (typescript_1.default.isIdentifier(node.expression)) {
89
- if (node.expression.text === "track") {
90
- isTrackCall = true;
91
- }
92
- }
93
- if (isTrackCall) {
94
- for (const arg of node.arguments) {
95
- if (checkArg(arg))
96
- return;
97
- }
54
+ const expr = node.expression;
55
+ const isTrack = (typescript_1.default.isIdentifier(expr) && expr.text === "track") ||
56
+ (typescript_1.default.isPropertyAccessExpression(expr) &&
57
+ expr.name.text === "track");
58
+ if (!isTrack)
59
+ return;
60
+ for (const arg of node.arguments) {
61
+ if (check(arg))
62
+ return;
98
63
  }
99
64
  }
100
65
  typescript_1.default.forEachChild(node, visit);
@@ -11,7 +11,7 @@ function resolveNodeValue(node, checker, paramMap, seen = new Set()) {
11
11
  return { values: [], dynamic: true };
12
12
  }
13
13
  seen.add(node);
14
- // PARAM MAPPING
14
+ // PARAM MAP (wrapper args)
15
15
  if (typescript_1.default.isIdentifier(node) && paramMap?.has(node.text)) {
16
16
  return resolveNodeValue(paramMap.get(node.text), checker, paramMap, seen);
17
17
  }
@@ -19,36 +19,19 @@ function resolveNodeValue(node, checker, paramMap, seen = new Set()) {
19
19
  if (typescript_1.default.isStringLiteral(node)) {
20
20
  return { values: [node.text], dynamic: false };
21
21
  }
22
- // ARRAY
23
- if (typescript_1.default.isArrayLiteralExpression(node)) {
24
- const values = [];
25
- for (const el of node.elements) {
26
- const res = resolveNodeValue(el, checker, paramMap, seen);
27
- if (res.values.length) {
28
- values.push(...res.values);
29
- }
30
- }
31
- return {
32
- values: [...new Set(values)],
33
- dynamic: true
34
- };
35
- }
36
22
  // TEMPLATE
37
23
  if (typescript_1.default.isTemplateExpression(node)) {
38
24
  let results = node.head.text ? [node.head.text] : [""];
39
25
  for (const span of node.templateSpans) {
40
26
  const res = resolveNodeValue(span.expression, checker, paramMap, seen);
41
- if (res.values.length) {
42
- results = results.flatMap(r => res.values.map(v => r + v));
43
- }
44
- else {
45
- results = results.map(r => r + "*");
46
- }
27
+ results = results.flatMap(r => res.values.length
28
+ ? res.values.map(v => r + v)
29
+ : [r + "*"]);
47
30
  results = results.map(r => r + span.literal.text);
48
31
  }
49
32
  return { values: results, dynamic: true };
50
33
  }
51
- // CONDITIONAL
34
+ // CONDITIONAL (a ? b : c)
52
35
  if (typescript_1.default.isConditionalExpression(node)) {
53
36
  const a = resolveNodeValue(node.whenTrue, checker, paramMap, seen);
54
37
  const b = resolveNodeValue(node.whenFalse, checker, paramMap, seen);
@@ -57,23 +40,57 @@ function resolveNodeValue(node, checker, paramMap, seen = new Set()) {
57
40
  dynamic: true,
58
41
  };
59
42
  }
43
+ // OBJECT → берём ВСЕ значения (без привязки к ключам)
44
+ if (typescript_1.default.isObjectLiteralExpression(node)) {
45
+ const values = [];
46
+ for (const prop of node.properties) {
47
+ if (!typescript_1.default.isPropertyAssignment(prop))
48
+ continue;
49
+ const res = resolveNodeValue(prop.initializer, checker, paramMap, seen);
50
+ values.push(...res.values);
51
+ }
52
+ return {
53
+ values: [...new Set(values)],
54
+ dynamic: true,
55
+ };
56
+ }
57
+ // ARRAY
58
+ if (typescript_1.default.isArrayLiteralExpression(node)) {
59
+ const values = [];
60
+ for (const el of node.elements) {
61
+ const res = resolveNodeValue(el, checker, paramMap, seen);
62
+ values.push(...res.values);
63
+ }
64
+ return {
65
+ values: [...new Set(values)],
66
+ dynamic: true,
67
+ };
68
+ }
69
+ // BINARY CONCAT
70
+ if (typescript_1.default.isBinaryExpression(node)) {
71
+ if (node.operatorToken.kind === typescript_1.default.SyntaxKind.PlusToken) {
72
+ const left = resolveNodeValue(node.left, checker, paramMap, seen);
73
+ const right = resolveNodeValue(node.right, checker, paramMap, seen);
74
+ return {
75
+ values: left.values.flatMap(l => right.values.length
76
+ ? right.values.map(r => l + r)
77
+ : [l + "*"]),
78
+ dynamic: true,
79
+ };
80
+ }
81
+ }
60
82
  // IDENTIFIER
61
83
  if (typescript_1.default.isIdentifier(node)) {
62
84
  let symbol = checker.getSymbolAtLocation(node);
63
85
  if (!symbol)
64
86
  return { values: [], dynamic: true };
65
- // INLINE FIRST
87
+ symbol = (0, exportResolver_1.resolveExportedSymbol)(symbol, checker) ?? symbol;
88
+ // const VAR = "click"
66
89
  for (const decl of symbol.getDeclarations() ?? []) {
67
90
  if (typescript_1.default.isVariableDeclaration(decl) && decl.initializer) {
68
91
  return resolveNodeValue(decl.initializer, checker, paramMap, seen);
69
92
  }
70
- }
71
- // unwrap export
72
- symbol = (0, exportResolver_1.resolveExportedSymbol)(symbol, checker) ?? symbol;
73
- if (symbol.flags & typescript_1.default.SymbolFlags.Alias) {
74
- symbol = checker.getAliasedSymbol(symbol);
75
- }
76
- for (const decl of symbol.getDeclarations() ?? []) {
93
+ // enum
77
94
  if (typescript_1.default.isEnumMember(decl) && decl.initializer) {
78
95
  if (typescript_1.default.isStringLiteral(decl.initializer)) {
79
96
  return {
@@ -83,29 +100,9 @@ function resolveNodeValue(node, checker, paramMap, seen = new Set()) {
83
100
  }
84
101
  }
85
102
  }
86
- const type = checker.getTypeAtLocation(node);
87
- // UNION
88
- if (type.isUnion()) {
89
- const values = [];
90
- for (const t of type.types) {
91
- if (t.flags & typescript_1.default.TypeFlags.StringLiteral) {
92
- values.push(t.value);
93
- }
94
- }
95
- if (values.length) {
96
- return { values, dynamic: false };
97
- }
98
- }
99
- // STRING LITERAL TYPE
100
- if (type.flags & typescript_1.default.TypeFlags.StringLiteral) {
101
- return {
102
- values: [type.value],
103
- dynamic: false
104
- };
105
- }
106
103
  return { values: [], dynamic: true };
107
104
  }
108
- // PROPERTY ACCESS
105
+ // PROPERTY ACCESS (ENUM / CONST)
109
106
  if (typescript_1.default.isPropertyAccessExpression(node)) {
110
107
  const symbol = checker.getSymbolAtLocation(node);
111
108
  if (symbol) {
@@ -124,96 +121,18 @@ function resolveNodeValue(node, checker, paramMap, seen = new Set()) {
124
121
  }
125
122
  }
126
123
  }
127
- const constantValue = checker.getConstantValue(node);
128
- if (typeof constantValue === "string") {
129
- return { values: [constantValue], dynamic: false };
130
- }
131
- const type = checker.getTypeAtLocation(node);
132
- if (type.flags & typescript_1.default.TypeFlags.StringLiteral) {
133
- return {
134
- values: [type.value],
135
- dynamic: false,
136
- };
137
- }
138
- // object literal resolve
139
- if (typescript_1.default.isIdentifier(node.expression)) {
140
- const objSymbol = checker.getSymbolAtLocation(node.expression);
141
- if (objSymbol) {
142
- for (const decl of objSymbol.getDeclarations() ?? []) {
143
- if (typescript_1.default.isVariableDeclaration(decl) &&
144
- decl.initializer &&
145
- typescript_1.default.isObjectLiteralExpression(decl.initializer)) {
146
- for (const prop of decl.initializer.properties) {
147
- if (!typescript_1.default.isPropertyAssignment(prop))
148
- continue;
149
- const name = prop.name.getText();
150
- if (name === node.name.text) {
151
- return resolveNodeValue(prop.initializer, checker, paramMap, seen);
152
- }
153
- }
154
- }
155
- }
156
- }
157
- }
158
- // fallback
159
- return resolveNodeValue(node.name, checker, paramMap, seen);
160
- }
161
- // ARRAY ACCESS
162
- if (typescript_1.default.isElementAccessExpression(node)) {
163
- const obj = resolveNodeValue(node.expression, checker, paramMap, seen);
164
- if (!node.argumentExpression) {
165
- return { values: obj.values, dynamic: true };
166
- }
167
- const index = resolveNodeValue(node.argumentExpression, checker, paramMap, seen);
168
- if (index.values.length === 1) {
169
- const i = Number(index.values[0]);
170
- if (!Number.isNaN(i) && obj.values[i] !== undefined) {
171
- return {
172
- values: [obj.values[i]],
173
- dynamic: false,
174
- };
175
- }
176
- }
177
- return obj.values.length
178
- ? { values: obj.values, dynamic: true }
179
- : { values: [], dynamic: true };
124
+ return { values: [], dynamic: true };
180
125
  }
181
- // OBJECT
182
- if (typescript_1.default.isObjectLiteralExpression(node)) {
126
+ // CALL → unwrap args
127
+ if (typescript_1.default.isCallExpression(node)) {
183
128
  const values = [];
184
- for (const prop of node.properties) {
185
- if (!typescript_1.default.isPropertyAssignment(prop))
186
- continue;
187
- const name = prop.name.getText();
188
- if (["event", "name", "type"].includes(name)) {
189
- const res = resolveNodeValue(prop.initializer, checker, paramMap, seen);
190
- values.push(...res.values);
191
- }
192
- }
193
- return {
194
- values: [...new Set(values)],
195
- dynamic: true
196
- };
197
- }
198
- // BINARY ("btn_" + name)
199
- if (typescript_1.default.isBinaryExpression(node)) {
200
- if (node.operatorToken.kind === typescript_1.default.SyntaxKind.PlusToken) {
201
- const left = resolveNodeValue(node.left, checker, paramMap, seen);
202
- const right = resolveNodeValue(node.right, checker, paramMap, seen);
203
- if (!left.values.length) {
204
- return { values: [], dynamic: true };
205
- }
206
- return {
207
- values: left.values.flatMap(l => right.values.length
208
- ? right.values.map(r => l + r)
209
- : [l + "*"]),
210
- dynamic: true,
211
- };
129
+ for (const arg of node.arguments) {
130
+ const res = resolveNodeValue(arg, checker, paramMap, seen);
131
+ values.push(...res.values);
212
132
  }
213
- }
214
- // CALL → dynamic
215
- if (typescript_1.default.isCallExpression(node)) {
216
- return { values: [], dynamic: true };
133
+ return values.length
134
+ ? { values, dynamic: true }
135
+ : { values: [], dynamic: true };
217
136
  }
218
137
  return { values: [], dynamic: true };
219
138
  }
@@ -7,9 +7,8 @@ exports.scanSource = scanSource;
7
7
  const typescript_1 = __importDefault(require("typescript"));
8
8
  const resolver_1 = require("./resolver");
9
9
  const callResolver_1 = require("./callResolver");
10
- const exportResolver_1 = require("./exportResolver");
11
10
  const functionAnalyzer_1 = require("./functionAnalyzer");
12
- const trackingDetector_1 = require("./trackingDetector");
11
+ const boundary_1 = require("./boundary");
13
12
  function getCallName(expr) {
14
13
  if (typescript_1.default.isIdentifier(expr))
15
14
  return expr.text;
@@ -17,23 +16,6 @@ function getCallName(expr) {
17
16
  return expr.name.text;
18
17
  return "";
19
18
  }
20
- function getJsxAttrName(name) {
21
- if (typescript_1.default.isIdentifier(name))
22
- return name.text;
23
- if (typescript_1.default.isJsxNamespacedName(name))
24
- return name.name.text;
25
- return null;
26
- }
27
- // unwrap
28
- function unwrap(expr) {
29
- while (typescript_1.default.isAsExpression(expr) ||
30
- typescript_1.default.isParenthesizedExpression(expr) ||
31
- typescript_1.default.isTypeAssertionExpression(expr) ||
32
- typescript_1.default.isNonNullExpression(expr)) {
33
- expr = expr.expression;
34
- }
35
- return expr;
36
- }
37
19
  function isValidEvent(v) {
38
20
  return (v &&
39
21
  v.length > 1 &&
@@ -41,31 +23,7 @@ function isValidEvent(v) {
41
23
  !v.includes(" ") &&
42
24
  /^[a-zA-Z0-9._:-]+$/.test(v));
43
25
  }
44
- function isPropUsedInTracking(fn, checker, prop) {
45
- let found = false;
46
- function visit(node) {
47
- if (typescript_1.default.isCallExpression(node)) {
48
- if (!(0, trackingDetector_1.isTrackingCall)(node, checker)) {
49
- typescript_1.default.forEachChild(node, visit);
50
- return;
51
- }
52
- for (const arg of node.arguments) {
53
- const a = unwrap(arg);
54
- if ((typescript_1.default.isIdentifier(a) && a.text === prop) ||
55
- (typescript_1.default.isPropertyAccessExpression(a) &&
56
- a.name.text === prop)) {
57
- found = true;
58
- }
59
- }
60
- }
61
- typescript_1.default.forEachChild(node, visit);
62
- }
63
- if (fn.body) {
64
- visit(fn.body);
65
- }
66
- return found;
67
- }
68
- function scanSource(source, checker, config, visited = new Set(), depth = 0, inheritedParamMap) {
26
+ function scanSource(source, checker, config, visited = new Set(), inheritedParamMap) {
69
27
  const events = new Set();
70
28
  const detectedFunctionWrappers = new Set();
71
29
  const detectedComponentWrappers = new Map();
@@ -74,40 +32,24 @@ function scanSource(source, checker, config, visited = new Set(), depth = 0, inh
74
32
  }
75
33
  visited.add(source.fileName);
76
34
  function visit(node) {
77
- // CALL EXPRESSIONS
78
35
  if (typescript_1.default.isCallExpression(node)) {
79
36
  const name = getCallName(node.expression);
80
37
  const isKnownWrapper = config.functionWrappers.some(w => w.name === name);
81
- const isTrackingByType = (0, trackingDetector_1.isTrackingCall)(node, checker);
82
- let resolvedFn = (0, callResolver_1.resolveFunctionFromCall)(node.expression, checker);
83
- const isAutoWrapper = resolvedFn && (0, functionAnalyzer_1.findTrackParamIndex)(resolvedFn) !== null;
84
- let isTracking = isKnownWrapper ||
85
- isTrackingByType ||
86
- isAutoWrapper ||
87
- name.startsWith("$");
88
- // fallback track(...)
89
- if (!isTracking) {
90
- if (typescript_1.default.isPropertyAccessExpression(node.expression) &&
91
- node.expression.name.text === "track") {
92
- isTracking = true;
93
- }
94
- else if (typescript_1.default.isIdentifier(node.expression) &&
95
- node.expression.text === "track") {
96
- isTracking = true;
97
- }
98
- }
38
+ const resolvedFn = (0, callResolver_1.resolveFunctionFromCall)(node.expression, checker);
39
+ const isAutoWrapper = !!resolvedFn && (0, functionAnalyzer_1.findTrackParamIndex)(resolvedFn) !== null;
40
+ const isTracking = name === "track" ||
41
+ isKnownWrapper ||
42
+ (isAutoWrapper &&
43
+ resolvedFn &&
44
+ !(0, boundary_1.isExternalFile)(resolvedFn.getSourceFile().fileName));
99
45
  if (!isTracking) {
100
46
  typescript_1.default.forEachChild(node, visit);
101
47
  return;
102
48
  }
103
- // DETECT WRAPPERS
104
- if (!isKnownWrapper &&
105
- isAutoWrapper &&
106
- !isTrackingByType &&
107
- !name.startsWith("track")) {
49
+ // авто-детект wrapper
50
+ if (!isKnownWrapper && isAutoWrapper && name !== "track") {
108
51
  detectedFunctionWrappers.add(name);
109
52
  }
110
- // PARAM MAP
111
53
  const paramMap = new Map(inheritedParamMap ?? []);
112
54
  if (resolvedFn && typescript_1.default.isFunctionLike(resolvedFn)) {
113
55
  resolvedFn.parameters.forEach((param, i) => {
@@ -119,97 +61,24 @@ function scanSource(source, checker, config, visited = new Set(), depth = 0, inh
119
61
  }
120
62
  });
121
63
  }
122
- let handled = false;
123
- // MAIN RESOLVE
64
+ // ✅ ТОЛЬКО правильный аргумент
124
65
  if (resolvedFn) {
125
66
  const idx = (0, functionAnalyzer_1.findTrackParamIndex)(resolvedFn);
126
67
  if (idx !== null && node.arguments[idx]) {
127
68
  const res = (0, resolver_1.resolveNodeValue)(node.arguments[idx], checker, paramMap);
128
- res.values.forEach(v => {
129
- if (isValidEvent(v))
130
- events.add(v);
131
- });
132
- handled = true;
133
- }
134
- }
135
- // fallback
136
- if (!handled) {
137
- for (const arg of node.arguments) {
138
- const res = (0, resolver_1.resolveNodeValue)(arg, checker, paramMap);
139
- res.values.forEach(v => {
140
- if (isValidEvent(v))
69
+ for (const v of res.values) {
70
+ if (isValidEvent(v)) {
141
71
  events.add(v);
142
- });
72
+ }
73
+ }
143
74
  }
144
75
  }
145
76
  // CROSS FILE
146
77
  if (resolvedFn) {
147
78
  const sf = resolvedFn.getSourceFile();
148
79
  if (!visited.has(sf.fileName)) {
149
- const res = scanSource(sf, checker, config, visited, depth + 1, paramMap);
150
- res.events.forEach(e => events.add(e));
151
- }
152
- }
153
- }
154
- // JSX
155
- if (typescript_1.default.isJsxSelfClosingElement(node) ||
156
- typescript_1.default.isJsxOpeningElement(node)) {
157
- const tagNode = typescript_1.default.isPropertyAccessExpression(node.tagName)
158
- ? node.tagName.name
159
- : node.tagName;
160
- let symbol = checker.getSymbolAtLocation(tagNode);
161
- if (symbol) {
162
- symbol = (0, exportResolver_1.resolveExportedSymbol)(symbol, checker) ?? symbol;
163
- }
164
- if (symbol && (symbol.flags & typescript_1.default.SymbolFlags.Alias)) {
165
- symbol = checker.getAliasedSymbol(symbol);
166
- }
167
- if (!symbol) {
168
- typescript_1.default.forEachChild(node, visit);
169
- return;
170
- }
171
- const tagName = typescript_1.default.isPropertyAccessExpression(node.tagName)
172
- ? node.tagName.name.getText()
173
- : node.tagName.getText();
174
- for (const decl of symbol.getDeclarations() ?? []) {
175
- let fn = null;
176
- if (typescript_1.default.isFunctionDeclaration(decl))
177
- fn = decl;
178
- if (typescript_1.default.isVariableDeclaration(decl) && decl.initializer) {
179
- const init = decl.initializer;
180
- if (typescript_1.default.isArrowFunction(init) ||
181
- typescript_1.default.isFunctionExpression(init)) {
182
- fn = init;
183
- }
184
- }
185
- if (!fn)
186
- continue;
187
- const param = fn.parameters[0];
188
- if (!param || !typescript_1.default.isObjectBindingPattern(param.name))
189
- continue;
190
- for (const el of param.name.elements) {
191
- const prop = el.name.getText();
192
- const isEvent = isPropUsedInTracking(fn, checker, prop) ||
193
- config.wrappers.some(w => w.name === tagName && w.prop === prop);
194
- if (!isEvent)
195
- continue;
196
- const attr = node.attributes.properties.find(p => {
197
- if (!typescript_1.default.isJsxAttribute(p))
198
- return false;
199
- return getJsxAttrName(p.name) === prop;
200
- });
201
- if (!attr || !attr.initializer)
202
- continue;
203
- const expr = typescript_1.default.isJsxExpression(attr.initializer)
204
- ? attr.initializer.expression
205
- : attr.initializer;
206
- if (!expr)
207
- continue;
208
- const paramMap = new Map();
209
- paramMap.set(prop, expr);
210
- const res = scanSource(fn.getSourceFile(), checker, config, visited, depth + 1, paramMap);
80
+ const res = scanSource(sf, checker, config, visited, paramMap);
211
81
  res.events.forEach(e => events.add(e));
212
- detectedComponentWrappers.set(tagName, prop);
213
82
  }
214
83
  }
215
84
  }
@@ -5,64 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.isTrackingCall = isTrackingCall;
7
7
  const typescript_1 = __importDefault(require("typescript"));
8
- function isStringLike(type) {
9
- return ((type.flags & typescript_1.default.TypeFlags.StringLike) !== 0 ||
10
- (type.flags & typescript_1.default.TypeFlags.StringLiteral) !== 0);
11
- }
12
- function hasTrackLikeSignature(type, checker) {
13
- const sigs = type.getCallSignatures();
14
- for (const sig of sigs) {
15
- const params = sig.getParameters();
16
- if (!params.length)
17
- continue;
18
- const t = checker.getTypeOfSymbolAtLocation(params[0], params[0].valueDeclaration);
19
- if (isStringLike(t)) {
20
- return true;
21
- }
22
- }
23
- return false;
24
- }
25
- function isEventraLikeType(type, checker) {
26
- const props = type.getProperties();
27
- for (const prop of props) {
28
- const decl = prop.valueDeclaration ?? prop.declarations?.[0];
29
- if (!decl)
30
- continue;
31
- const t = checker.getTypeOfSymbolAtLocation(prop, decl);
32
- if (hasTrackLikeSignature(t, checker)) {
33
- return true;
34
- }
35
- }
36
- return false;
37
- }
38
- function isTrackingCall(node, checker) {
8
+ function isTrackingCall(node) {
39
9
  const expr = node.expression;
40
- // fn(...)
41
10
  if (typescript_1.default.isIdentifier(expr)) {
42
- const type = checker.getTypeAtLocation(expr);
43
- if (hasTrackLikeSignature(type, checker)) {
44
- return true;
45
- }
11
+ return expr.text === "track";
46
12
  }
47
- // obj.method(...)
48
13
  if (typescript_1.default.isPropertyAccessExpression(expr)) {
49
- const objType = checker.getTypeAtLocation(expr.expression);
50
- // объект похож на tracker
51
- if (isEventraLikeType(objType, checker)) {
52
- return true;
53
- }
54
- // fallback
55
- const methodType = checker.getTypeAtLocation(expr.name);
56
- if (hasTrackLikeSignature(methodType, checker)) {
57
- return true;
58
- }
59
- }
60
- // obj["track"](...)
61
- if (typescript_1.default.isElementAccessExpression(expr)) {
62
- const objType = checker.getTypeAtLocation(expr.expression);
63
- if (isEventraLikeType(objType, checker)) {
64
- return true;
65
- }
14
+ return expr.name.text === "track";
66
15
  }
67
16
  return false;
68
17
  }