@eventra_dev/eventra-cli 0.1.34 → 0.2.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.
@@ -4,6 +4,7 @@ import { resolveFunctionFromCall } from "./callResolver";
4
4
  import { resolveExportedSymbol } from "./exportResolver";
5
5
  import { EventraConfig, ScanResult } from "../types";
6
6
 
7
+ // HELPERS
7
8
  function isValidEvent(v: string) {
8
9
  return (
9
10
  v &&
@@ -32,6 +33,7 @@ function getJsxAttrName(name: ts.JsxAttributeName): string {
32
33
  return "";
33
34
  }
34
35
 
36
+ // MAIN
35
37
  export function scanSource(
36
38
  source: ts.SourceFile,
37
39
  checker: ts.TypeChecker,
@@ -47,35 +49,52 @@ export function scanSource(
47
49
  if (visited.has(source.fileName)) {
48
50
  return { events, detectedFunctionWrappers, detectedComponentWrappers };
49
51
  }
52
+
50
53
  visited.add(source.fileName);
51
54
 
52
- function extractTrackCall(node: ts.CallExpression, paramMap: Map<string, ts.Expression>) {
53
- const expr = node.expression;
55
+ // TRACK DETECTION
56
+ function isTrackCall(expr: ts.Expression) {
57
+ if (ts.isIdentifier(expr)) {
58
+ return expr.text === "track";
59
+ }
60
+
61
+ if (ts.isPropertyAccessExpression(expr)) {
62
+ return expr.name.text === "track";
63
+ }
64
+
65
+ return false;
66
+ }
67
+
68
+ function extractTrackCall(
69
+ node: ts.CallExpression,
70
+ paramMap: Map<string, ts.Expression>
71
+ ) {
72
+ if (!isTrackCall(node.expression)) return;
73
+
74
+ const arg = node.arguments[0];
75
+ if (!arg) return;
54
76
 
55
- if (ts.isPropertyAccessExpression(expr) && expr.name.text === "track") {
56
- const arg = node.arguments[0];
57
- if (!arg) return;
77
+ const res = resolveNodeValue(arg, checker, paramMap);
58
78
 
59
- const res = resolveNodeValue(arg, checker, paramMap);
60
- for (const v of res.values) {
61
- if (isValidEvent(v)) events.add(v);
79
+ for (const v of res.values) {
80
+ if (isValidEvent(v)) {
81
+ events.add(v);
62
82
  }
63
83
  }
64
84
  }
65
85
 
86
+ // WRAPPER DETECTION
66
87
  function isWrapperFunction(fn: ts.FunctionLikeDeclaration) {
67
88
  let found = false;
68
89
 
69
90
  function walk(n: ts.Node) {
70
91
  if (found) return;
71
92
 
72
- if (ts.isCallExpression(n)) {
73
- const expr = n.expression;
74
- if (ts.isPropertyAccessExpression(expr) && expr.name.text === "track") {
75
- found = true;
76
- return;
77
- }
93
+ if (ts.isCallExpression(n) && isTrackCall(n.expression)) {
94
+ found = true;
95
+ return;
78
96
  }
97
+
79
98
  ts.forEachChild(n, walk);
80
99
  }
81
100
 
@@ -83,15 +102,20 @@ export function scanSource(
83
102
  return found;
84
103
  }
85
104
 
105
+ // COMPONENT WRAPPER
86
106
  function detectComponentWrapper(tag: ts.JsxTagNameExpression): string | null {
87
107
  const tagName = getJsxTagName(tag);
88
108
 
89
- if (wrapperCache.has(tagName)) return wrapperCache.get(tagName)!;
109
+ if (wrapperCache.has(tagName)) {
110
+ return wrapperCache.get(tagName)!;
111
+ }
90
112
 
91
113
  let symbol = checker.getSymbolAtLocation(tag);
114
+
92
115
  if (symbol && (symbol.flags & ts.SymbolFlags.Alias)) {
93
116
  symbol = checker.getAliasedSymbol(symbol);
94
117
  }
118
+
95
119
  if (!symbol) {
96
120
  wrapperCache.set(tagName, null);
97
121
  return null;
@@ -120,21 +144,20 @@ export function scanSource(
120
144
  function walk(n: ts.Node) {
121
145
  if (prop) return;
122
146
 
123
- if (ts.isCallExpression(n)) {
124
- const expr = n.expression;
147
+ if (ts.isCallExpression(n) && isTrackCall(n.expression)) {
148
+ const arg = n.arguments[0];
125
149
 
126
- if (ts.isPropertyAccessExpression(expr) && expr.name.text === "track") {
127
- const arg = n.arguments[0];
128
- if (ts.isPropertyAccessExpression(arg)) {
129
- prop = arg.name.text;
130
- return;
131
- }
150
+ if (ts.isPropertyAccessExpression(arg)) {
151
+ prop = arg.name.text;
152
+ return;
132
153
  }
133
154
  }
155
+
134
156
  ts.forEachChild(n, walk);
135
157
  }
136
158
 
137
159
  walk(fn.body);
160
+
138
161
  wrapperCache.set(tagName, prop);
139
162
 
140
163
  if (prop) {
@@ -147,6 +170,7 @@ export function scanSource(
147
170
  return null;
148
171
  }
149
172
 
173
+ // VISITOR
150
174
  function visit(node: ts.Node) {
151
175
  // JSX
152
176
  if (ts.isJsxSelfClosingElement(node) || ts.isJsxOpeningElement(node)) {
@@ -205,29 +229,45 @@ export function scanSource(
205
229
  resolvedFn.parameters.forEach((p, i) => {
206
230
  const arg = node.arguments[i];
207
231
  if (!arg) return;
232
+
208
233
  if (ts.isIdentifier(p.name)) {
209
234
  paramMap.set(p.name.text, arg);
210
235
  }
211
236
  });
212
237
  }
213
238
 
214
- // direct track
215
239
  extractTrackCall(node, paramMap);
216
240
 
217
- // wrapper
218
241
  if (resolvedFn && isWrapperFunction(resolvedFn)) {
219
242
  const name = getCallName(node.expression);
243
+
220
244
  if (name && name !== "track") {
221
245
  detectedFunctionWrappers.add(name);
222
246
  }
247
+
223
248
  if (resolvedFn.body) {
224
249
  visit(resolvedFn.body);
225
250
  }
226
251
  }
227
252
 
228
- for (const arg of node.arguments) {
229
- visit(arg);
253
+ if (resolvedFn && resolvedFn.body) {
254
+ const sf = resolvedFn.getSourceFile();
255
+
256
+ if (!visited.has(sf.fileName)) {
257
+ const res = scanSource(
258
+ sf,
259
+ checker,
260
+ config,
261
+ visited,
262
+ paramMap,
263
+ wrapperCache
264
+ );
265
+
266
+ res.events.forEach(e => events.add(e));
267
+ }
230
268
  }
269
+
270
+ node.arguments.forEach(visit);
231
271
  visit(node.expression);
232
272
 
233
273
  return;
@@ -243,7 +243,7 @@ export function parseUniversal(
243
243
  parts.push(...dyn.calls);
244
244
 
245
245
  return {
246
- code: [...new Set(parts)].join("\n"),
246
+ code: content,
247
247
  deps: [...new Set(deps.filter(Boolean))],
248
248
  };
249
249
  }