@eventra_dev/eventra-cli 0.2.4 → 0.3.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.
Files changed (89) hide show
  1. package/README.md +154 -32
  2. package/dist/analysis/cache/evaluationCache.js +21 -0
  3. package/dist/analysis/cache/resolvedCallCache.js +21 -0
  4. package/dist/analysis/cache/resolvedExportCache.js +21 -0
  5. package/dist/analysis/cache/semanticDependencyGraph.js +25 -0
  6. package/dist/analysis/cache/symbolInvalidation.js +20 -0
  7. package/dist/analysis/extractor/extractor.js +47 -0
  8. package/dist/analysis/extractor/propagationExtractor.js +52 -0
  9. package/dist/analysis/pipeline/semanticPass.js +2 -0
  10. package/dist/analysis/resolver/callResolver.js +125 -0
  11. package/dist/analysis/resolver/exportResolver.js +75 -0
  12. package/dist/analysis/resolver/resolver.js +133 -0
  13. package/dist/analysis/scanner/analyzer/propagationAnalyzer.js +193 -0
  14. package/dist/analysis/scanner/analyzer/returnPropagationAnalyzer.js +105 -0
  15. package/dist/analysis/scanner/scanner.js +117 -0
  16. package/dist/analysis/scanner/sinkDetector.js +91 -0
  17. package/dist/analysis/shared/evaluationContext.js +9 -0
  18. package/dist/analysis/shared/propagation.js +3 -0
  19. package/dist/analysis/shared/returnPropagation.js +2 -0
  20. package/dist/analysis/shared/types.js +2 -0
  21. package/dist/analysis/shared/utils.js +62 -0
  22. package/dist/analysis/symbols/symbolUtils.js +68 -0
  23. package/dist/analysis/symbols/wrapperRegistry.js +55 -0
  24. package/dist/cli/check.js +73 -0
  25. package/dist/{commands → cli}/init.js +1 -1
  26. package/dist/{commands → cli}/send.js +1 -1
  27. package/dist/cli/sync.js +56 -0
  28. package/dist/{commands → cli}/watch.js +41 -25
  29. package/dist/compiler/compilerContext.js +204 -0
  30. package/dist/compiler/documentRegistry.js +78 -0
  31. package/dist/compiler/importGraph.js +83 -0
  32. package/dist/compiler/scheduler.js +29 -0
  33. package/dist/core/EventraEngine.js +234 -0
  34. package/dist/core/projectScanner.js +73 -0
  35. package/dist/{utils → filesystem}/getVirtualFile.js +1 -3
  36. package/dist/filesystem/processFile.js +38 -0
  37. package/dist/index.js +5 -5
  38. package/dist/shared/buildSyntheticTsx.js +20 -0
  39. package/dist/shared/templateExpressionExtractor.js +22 -0
  40. package/package.json +32 -9
  41. package/.github/workflows/release.yml +0 -43
  42. package/ARCHITECTURE.md +0 -88
  43. package/assets/eventra-icon-animated.svg +0 -19
  44. package/dist/commands/check.js +0 -78
  45. package/dist/commands/sync.js +0 -79
  46. package/dist/engine/boundary.js +0 -14
  47. package/dist/engine/callResolver.js +0 -58
  48. package/dist/engine/engine.js +0 -154
  49. package/dist/engine/exportResolver.js +0 -46
  50. package/dist/engine/functionAnalyzer.js +0 -71
  51. package/dist/engine/graph.js +0 -168
  52. package/dist/engine/languageService.js +0 -152
  53. package/dist/engine/resolver.js +0 -149
  54. package/dist/engine/scanner.js +0 -230
  55. package/dist/utils/processFile.js +0 -28
  56. package/dist/utils/universal.js +0 -190
  57. package/src/commands/check.ts +0 -91
  58. package/src/commands/init.ts +0 -174
  59. package/src/commands/send.ts +0 -213
  60. package/src/commands/sync.ts +0 -106
  61. package/src/commands/watch.ts +0 -144
  62. package/src/engine/boundary.ts +0 -12
  63. package/src/engine/callResolver.ts +0 -65
  64. package/src/engine/engine.ts +0 -227
  65. package/src/engine/exportResolver.ts +0 -56
  66. package/src/engine/functionAnalyzer.ts +0 -81
  67. package/src/engine/graph.ts +0 -193
  68. package/src/engine/hash.ts +0 -5
  69. package/src/engine/languageService.ts +0 -197
  70. package/src/engine/resolver.ts +0 -177
  71. package/src/engine/scanner.ts +0 -298
  72. package/src/index.ts +0 -49
  73. package/src/types.ts +0 -35
  74. package/src/utils/config.ts +0 -53
  75. package/src/utils/getVirtualFile.ts +0 -5
  76. package/src/utils/processFile.ts +0 -29
  77. package/src/utils/universal.ts +0 -249
  78. package/tests/fixtures/backend/express/app.ts +0 -233
  79. package/tests/fixtures/backend/nest/service.ts +0 -70
  80. package/tests/fixtures/backend/node/index.ts +0 -63
  81. package/tests/fixtures/frontend/next/page.tsx +0 -101
  82. package/tests/fixtures/frontend/react/App.tsx +0 -104
  83. package/tests/fixtures/frontend/vue/App.vue +0 -83
  84. package/tests/fixtures/wrappers/component/test.tsx +0 -62
  85. package/tests/fixtures/wrappers/function/test.ts +0 -60
  86. package/tests/run.ts +0 -106
  87. package/tsconfig.json +0 -14
  88. /package/dist/{utils → config}/config.js +0 -0
  89. /package/dist/{engine → shared}/hash.js +0 -0
@@ -1,197 +0,0 @@
1
- import ts from "typescript";
2
- import fs from "fs";
3
- import path from "path";
4
-
5
- export class TSService {
6
- private files = new Map<string, { version: number; content: string }>();
7
- private fileNames = new Set<string>();
8
- private service: ts.LanguageService;
9
-
10
- private compilerOptions: ts.CompilerOptions;
11
- private baseUrl: string;
12
- private paths: Record<string, string[]>;
13
-
14
- constructor(private root: string) {
15
- const configPath = ts.findConfigFile(
16
- root,
17
- ts.sys.fileExists,
18
- "tsconfig.json"
19
- );
20
-
21
- let compilerOptions: ts.CompilerOptions = {
22
- allowJs: true,
23
- allowNonTsExtensions: true,
24
- jsx: ts.JsxEmit.Preserve,
25
- jsxImportSource: "react",
26
- moduleResolution: ts.ModuleResolutionKind.Node16,
27
- target: ts.ScriptTarget.ESNext,
28
- esModuleInterop: true,
29
- allowSyntheticDefaultImports: true,
30
- skipLibCheck: true,
31
- };
32
-
33
- let baseUrl = root;
34
- let paths: Record<string, string[]> = {};
35
-
36
- if (configPath) {
37
- const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
38
-
39
- const parsed = ts.parseJsonConfigFileContent(
40
- configFile.config,
41
- ts.sys,
42
- root
43
- );
44
-
45
- compilerOptions = {
46
- ...compilerOptions,
47
- ...parsed.options,
48
- };
49
-
50
- paths = parsed.options.paths || {};
51
- baseUrl = parsed.options.baseUrl
52
- ? path.resolve(root, parsed.options.baseUrl)
53
- : root;
54
- }
55
-
56
- this.compilerOptions = compilerOptions;
57
- this.baseUrl = baseUrl;
58
- this.paths = paths;
59
-
60
- const allFiles = ts.sys.readDirectory(
61
- root,
62
- [".ts", ".tsx", ".js", ".jsx"],
63
- undefined,
64
- undefined
65
- );
66
-
67
- for (const f of allFiles) {
68
- this.fileNames.add(this.normalize(f));
69
- }
70
-
71
- const host: ts.LanguageServiceHost = {
72
- getScriptFileNames: () => {
73
- return Array.from(this.fileNames);
74
- },
75
-
76
- getScriptVersion: (file) => {
77
- file = this.normalize(file);
78
- return this.files.get(file)?.version.toString() ?? "0";
79
- },
80
- getScriptKind: (fileName) => {
81
- fileName = this.normalize(fileName);
82
-
83
- if (fileName.endsWith(".tsx")) {
84
- return ts.ScriptKind.TSX;
85
- }
86
-
87
- if (fileName.endsWith(".ts")) {
88
- return ts.ScriptKind.TS;
89
- }
90
-
91
- if (fileName.endsWith(".jsx")) {
92
- return ts.ScriptKind.JSX;
93
- }
94
-
95
- if (fileName.endsWith(".js")) {
96
- return ts.ScriptKind.JS;
97
- }
98
-
99
- return ts.ScriptKind.Unknown;
100
- },
101
- getScriptSnapshot: (file) => {
102
- file = this.normalize(file);
103
- const f = this.files.get(file);
104
- if (f) {
105
- return ts.ScriptSnapshot.fromString(f.content);
106
- }
107
-
108
- try {
109
- if (fs.existsSync(file)) {
110
- const content = fs.readFileSync(file, "utf-8");
111
-
112
- this.files.set(file, {
113
- content,
114
- version: 1,
115
- });
116
-
117
- this.fileNames.add(file);
118
-
119
- return ts.ScriptSnapshot.fromString(content);
120
- }
121
- } catch {
122
- }
123
-
124
- return ts.ScriptSnapshot.fromString("");
125
- },
126
-
127
- getCurrentDirectory: () => this.root,
128
- getCompilationSettings: () => this.compilerOptions,
129
- getDefaultLibFileName: (opts) =>
130
- ts.getDefaultLibFilePath(opts),
131
-
132
- fileExists: (file) => {
133
- file = this.normalize(file);
134
- return this.files.has(file) || ts.sys.fileExists(file);
135
- },
136
-
137
- readFile: (file) => {
138
- file = this.normalize(file);
139
- return this.files.get(file)?.content ?? ts.sys.readFile(file);
140
- },
141
-
142
- readDirectory: ts.sys.readDirectory,
143
- };
144
-
145
- this.service = ts.createLanguageService(host);
146
- }
147
-
148
- private normalize(file: string) {
149
- return path.resolve(file).replace(/\\/g, "/");
150
- }
151
-
152
- // PUBLIC API
153
- updateFile(file: string, content: string) {
154
- file = this.normalize(file);
155
-
156
- const prev = this.files.get(file);
157
-
158
- this.files.set(file, {
159
- content,
160
- version: prev ? prev.version + 1 : 1,
161
- });
162
-
163
- this.fileNames.add(file);
164
- }
165
-
166
- removeFile(file: string) {
167
- file = this.normalize(file);
168
-
169
- this.files.delete(file);
170
- this.fileNames.delete(file);
171
- }
172
-
173
- getProgram() {
174
- return this.service.getProgram();
175
- }
176
-
177
- getChecker() {
178
- return this.getProgram()?.getTypeChecker();
179
- }
180
-
181
- getSourceFile(file: string) {
182
- file = this.normalize(file);
183
- return this.getProgram()?.getSourceFile(file);
184
- }
185
-
186
- getFileContent(file: string) {
187
- file = this.normalize(file);
188
- return this.files.get(file)?.content;
189
- }
190
-
191
- getModuleResolutionConfig() {
192
- return {
193
- baseUrl: this.baseUrl,
194
- paths: this.paths,
195
- };
196
- }
197
- }
@@ -1,177 +0,0 @@
1
- import ts from "typescript";
2
- import { resolveExportedSymbol } from "./exportResolver";
3
- import { resolveFunctionFromCall } from "./callResolver";
4
-
5
- export type ResolveResult = {
6
- values: string[];
7
- dynamic: boolean;
8
- };
9
-
10
- export function resolveNodeValue(
11
- node: ts.Node,
12
- checker: ts.TypeChecker,
13
- paramMap?: Map<string, ts.Expression>,
14
- seen = new Set<ts.Node>()
15
- ): ResolveResult {
16
- if (seen.has(node)) return { values: [], dynamic: true };
17
- seen.add(node);
18
-
19
- // param passthrough
20
- if (ts.isIdentifier(node) && paramMap?.has(node.text)) {
21
- return resolveNodeValue(paramMap.get(node.text)!, checker, paramMap, seen);
22
- }
23
-
24
- // string
25
- if (ts.isStringLiteral(node)) {
26
- return { values: [node.text], dynamic: false };
27
- }
28
-
29
- // template
30
- if (ts.isTemplateExpression(node)) {
31
- let results = node.head.text ? [node.head.text] : [""];
32
- for (const span of node.templateSpans) {
33
- const r = resolveNodeValue(span.expression, checker, paramMap, seen);
34
- results = results.flatMap(s =>
35
- r.values.length ? r.values.map(v => s + v) : [s + "*"]
36
- );
37
- results = results.map(s => s + span.literal.text);
38
- }
39
- return { values: results, dynamic: true };
40
- }
41
-
42
- // ternary
43
- if (ts.isConditionalExpression(node)) {
44
- const a = resolveNodeValue(node.whenTrue, checker, paramMap, seen);
45
- const b = resolveNodeValue(node.whenFalse, checker, paramMap, seen);
46
- return {
47
- values: [...new Set([...a.values, ...b.values])],
48
- dynamic: true,
49
- };
50
- }
51
-
52
- // object (event/name priority)
53
- if (ts.isObjectLiteralExpression(node)) {
54
- for (const p of node.properties) {
55
- if (ts.isPropertyAssignment(p)) {
56
- const key = p.name.getText();
57
- if (key === "event" || key === "name") {
58
- return resolveNodeValue(p.initializer, checker, paramMap, seen);
59
- }
60
- }
61
- }
62
- const vals: string[] = [];
63
- for (const p of node.properties) {
64
- if (!ts.isPropertyAssignment(p)) continue;
65
- const r = resolveNodeValue(p.initializer, checker, paramMap, seen);
66
- vals.push(...r.values);
67
- }
68
- return { values: [...new Set(vals)], dynamic: true };
69
- }
70
-
71
- // array
72
- if (ts.isArrayLiteralExpression(node)) {
73
- const vals: string[] = [];
74
- for (const el of node.elements) {
75
- const r = resolveNodeValue(el, checker, paramMap, seen);
76
- vals.push(...r.values);
77
- }
78
- return { values: [...new Set(vals)], dynamic: true };
79
- }
80
-
81
- // concat
82
- if (ts.isBinaryExpression(node) &&
83
- node.operatorToken.kind === ts.SyntaxKind.PlusToken) {
84
- const l = resolveNodeValue(node.left, checker, paramMap, seen);
85
- const r = resolveNodeValue(node.right, checker, paramMap, seen);
86
- return {
87
- values: l.values.flatMap(a =>
88
- r.values.length ? r.values.map(b => a + b) : [a + "*"]
89
- ),
90
- dynamic: true,
91
- };
92
- }
93
-
94
- // identifier (const / enum)
95
- if (ts.isIdentifier(node)) {
96
- let s = checker.getSymbolAtLocation(node);
97
- if (!s) return { values: [], dynamic: true };
98
-
99
- s = resolveExportedSymbol(s, checker) ?? s;
100
-
101
- for (const d of s.getDeclarations() ?? []) {
102
- if (ts.isVariableDeclaration(d) && d.initializer) {
103
- return resolveNodeValue(d.initializer, checker, paramMap, seen);
104
- }
105
- if (ts.isEnumMember(d) && d.initializer && ts.isStringLiteral(d.initializer)) {
106
- return { values: [d.initializer.text], dynamic: false };
107
- }
108
- }
109
- return { values: [], dynamic: true };
110
- }
111
-
112
- // PROPERTY ACCESS (OBJECT + ENUM)
113
- if (ts.isPropertyAccessExpression(node)) {
114
- const obj = node.expression;
115
- const prop = node.name.text;
116
-
117
- // object literal lookup
118
- if (ts.isIdentifier(obj)) {
119
- const sym = checker.getSymbolAtLocation(obj);
120
- if (sym) {
121
- const s = resolveExportedSymbol(sym, checker) ?? sym;
122
- for (const d of s.getDeclarations() ?? []) {
123
- if (
124
- ts.isVariableDeclaration(d) &&
125
- d.initializer &&
126
- ts.isObjectLiteralExpression(d.initializer)
127
- ) {
128
- for (const p of d.initializer.properties) {
129
- if (
130
- ts.isPropertyAssignment(p) &&
131
- p.name.getText() === prop
132
- ) {
133
- return resolveNodeValue(p.initializer, checker, paramMap, seen);
134
- }
135
- }
136
- }
137
- }
138
- }
139
- }
140
-
141
- // enum fallback
142
- const sym = checker.getSymbolAtLocation(node);
143
- if (sym) {
144
- let s = resolveExportedSymbol(sym, checker) ?? sym;
145
- if (s.flags & ts.SymbolFlags.Alias) s = checker.getAliasedSymbol(s);
146
- for (const d of s.getDeclarations() ?? []) {
147
- if (ts.isEnumMember(d) && d.initializer && ts.isStringLiteral(d.initializer)) {
148
- return { values: [d.initializer.text], dynamic: false };
149
- }
150
- }
151
- }
152
-
153
- return { values: [], dynamic: true };
154
- }
155
-
156
- // CALL (unwrap + dive into wrapper body)
157
- if (ts.isCallExpression(node)) {
158
- const vals: string[] = [];
159
-
160
- // args
161
- for (const a of node.arguments) {
162
- const r = resolveNodeValue(a, checker, paramMap, seen);
163
- vals.push(...r.values);
164
- }
165
-
166
- // dive into called function (wrapper support)
167
- const fn = resolveFunctionFromCall(node.expression, checker);
168
- if (fn?.body) {
169
- const r = resolveNodeValue(fn.body, checker, paramMap, seen);
170
- vals.push(...r.values);
171
- }
172
-
173
- return { values: [...new Set(vals)], dynamic: true };
174
- }
175
-
176
- return { values: [], dynamic: true };
177
- }
@@ -1,298 +0,0 @@
1
- import ts from "typescript";
2
- import { resolveNodeValue } from "./resolver";
3
- import { resolveFunctionFromCall } from "./callResolver";
4
- import { resolveExportedSymbol } from "./exportResolver";
5
- import { EventraConfig, ScanResult } from "../types";
6
-
7
- // HELPERS
8
- function isValidEvent(v: string) {
9
- return (
10
- v &&
11
- v.length > 1 &&
12
- v.length < 120 &&
13
- !v.includes(" ") &&
14
- /^[a-zA-Z0-9._:-]+$/.test(v)
15
- );
16
- }
17
-
18
- function getCallName(expr: ts.Expression): string {
19
- if (ts.isIdentifier(expr)) return expr.text;
20
- if (ts.isPropertyAccessExpression(expr)) return expr.name.text;
21
- return "";
22
- }
23
-
24
- function getJsxTagName(tag: ts.JsxTagNameExpression): string {
25
- if (ts.isIdentifier(tag)) return tag.text;
26
- if (ts.isPropertyAccessExpression(tag)) return tag.name.text;
27
- return tag.getText();
28
- }
29
-
30
- function getJsxAttrName(name: ts.JsxAttributeName): string {
31
- if (ts.isIdentifier(name)) return name.text;
32
- if (ts.isJsxNamespacedName(name)) return name.name.text;
33
- return "";
34
- }
35
-
36
- // MAIN
37
- export function scanSource(
38
- source: ts.SourceFile,
39
- checker: ts.TypeChecker,
40
- config: EventraConfig,
41
- visited = new Set<string>(),
42
- inheritedParamMap?: Map<string, ts.Expression>,
43
- wrapperCache = new Map<string, string | null>()
44
- ): ScanResult {
45
- const events = new Set<string>();
46
- const detectedFunctionWrappers = new Set<string>();
47
- const detectedComponentWrappers = new Map<string, string>();
48
-
49
- if (visited.has(source.fileName)) {
50
- return { events, detectedFunctionWrappers, detectedComponentWrappers };
51
- }
52
-
53
- visited.add(source.fileName);
54
-
55
- // TRACK DETECTION
56
- function isTrackCall(expr: ts.Expression) {
57
- const name = getCallName(expr);
58
-
59
- // direct track()
60
- if (name === "track") {
61
- return true;
62
- }
63
-
64
- // configured wrappers
65
- if (
66
- config.functionWrappers?.some(
67
- w => w.name === name
68
- )
69
- ) {
70
- return true;
71
- }
72
-
73
- // *.track()
74
- return ts.isPropertyAccessExpression(expr) &&
75
- expr.name.text === "track";
76
-
77
-
78
- }
79
-
80
- function extractTrackCall(
81
- node: ts.CallExpression,
82
- paramMap: Map<string, ts.Expression>
83
- ) {
84
- if (!isTrackCall(node.expression)) return;
85
-
86
- const arg = node.arguments[0];
87
- if (!arg) return;
88
-
89
- const res = resolveNodeValue(arg, checker, paramMap);
90
-
91
- for (const v of res.values) {
92
- if (isValidEvent(v)) {
93
- events.add(v);
94
- }
95
- }
96
- }
97
-
98
- // WRAPPER DETECTION
99
- function isWrapperFunction(fn: ts.FunctionLikeDeclaration) {
100
- let found = false;
101
-
102
- function walk(n: ts.Node) {
103
- if (found) return;
104
-
105
- if (ts.isCallExpression(n) && isTrackCall(n.expression)) {
106
- found = true;
107
- return;
108
- }
109
-
110
- ts.forEachChild(n, walk);
111
- }
112
-
113
- if (fn.body) walk(fn.body);
114
- return found;
115
- }
116
-
117
- // COMPONENT WRAPPER
118
- function detectComponentWrapper(tag: ts.JsxTagNameExpression): string | null {
119
- const tagName = getJsxTagName(tag);
120
-
121
- if (wrapperCache.has(tagName)) {
122
- return wrapperCache.get(tagName)!;
123
- }
124
-
125
- let symbol = checker.getSymbolAtLocation(tag);
126
-
127
- if (symbol && (symbol.flags & ts.SymbolFlags.Alias)) {
128
- symbol = checker.getAliasedSymbol(symbol);
129
- }
130
-
131
- if (!symbol) {
132
- wrapperCache.set(tagName, null);
133
- return null;
134
- }
135
-
136
- symbol = resolveExportedSymbol(symbol, checker) ?? symbol;
137
-
138
- for (const decl of symbol.getDeclarations() ?? []) {
139
- let fn: ts.FunctionLikeDeclaration | null = null;
140
-
141
- if (ts.isFunctionDeclaration(decl)) fn = decl;
142
-
143
- if (
144
- ts.isVariableDeclaration(decl) &&
145
- decl.initializer &&
146
- (ts.isArrowFunction(decl.initializer) ||
147
- ts.isFunctionExpression(decl.initializer))
148
- ) {
149
- fn = decl.initializer;
150
- }
151
-
152
- if (!fn || !fn.body) continue;
153
-
154
- let prop: string | null = null;
155
-
156
- function walk(n: ts.Node) {
157
- if (prop) return;
158
-
159
- if (ts.isCallExpression(n) && isTrackCall(n.expression)) {
160
- const arg = n.arguments[0];
161
-
162
- if (ts.isPropertyAccessExpression(arg)) {
163
- prop = arg.name.text;
164
- return;
165
- }
166
- }
167
-
168
- ts.forEachChild(n, walk);
169
- }
170
-
171
- walk(fn.body);
172
-
173
- wrapperCache.set(tagName, prop);
174
-
175
- if (prop) {
176
- detectedComponentWrappers.set(tagName, prop);
177
- return prop;
178
- }
179
- }
180
-
181
- wrapperCache.set(tagName, null);
182
- return null;
183
- }
184
-
185
- // VISITOR
186
- function visit(node: ts.Node) {
187
- // JSX
188
- if (ts.isJsxSelfClosingElement(node) || ts.isJsxOpeningElement(node)) {
189
- const tagName = getJsxTagName(node.tagName);
190
-
191
- if (tagName[0] === tagName[0].toLowerCase()) {
192
- ts.forEachChild(node, visit);
193
- return;
194
- }
195
-
196
- let wrapper = config.wrappers.find(w => w.name === tagName);
197
-
198
- if (!wrapper) {
199
- const prop = detectComponentWrapper(node.tagName);
200
- if (prop) wrapper = { name: tagName, prop };
201
- }
202
-
203
- if (wrapper) {
204
- for (const attr of node.attributes.properties) {
205
- if (!ts.isJsxAttribute(attr)) continue;
206
-
207
- const name = getJsxAttrName(attr.name);
208
- if (name !== wrapper.prop) continue;
209
-
210
- if (!attr.initializer) continue;
211
-
212
- if (ts.isStringLiteral(attr.initializer)) {
213
- if (isValidEvent(attr.initializer.text)) {
214
- events.add(attr.initializer.text);
215
- }
216
- }
217
-
218
- if (ts.isJsxExpression(attr.initializer)) {
219
- const expr = attr.initializer.expression;
220
- if (!expr) continue;
221
-
222
- const res = resolveNodeValue(expr, checker);
223
- res.values.forEach(v => {
224
- if (isValidEvent(v)) events.add(v);
225
- });
226
- }
227
- }
228
- }
229
-
230
- ts.forEachChild(node, visit);
231
- return;
232
- }
233
-
234
- // CALL
235
- if (ts.isCallExpression(node)) {
236
- const resolvedFn = resolveFunctionFromCall(node.expression, checker);
237
-
238
- const paramMap = new Map(inheritedParamMap ?? []);
239
-
240
- if (resolvedFn) {
241
- resolvedFn.parameters.forEach((p, i) => {
242
- const arg = node.arguments[i];
243
- if (!arg) return;
244
-
245
- if (ts.isIdentifier(p.name)) {
246
- paramMap.set(p.name.text, arg);
247
- }
248
- });
249
- }
250
-
251
- extractTrackCall(node, paramMap);
252
-
253
- if (resolvedFn && isWrapperFunction(resolvedFn)) {
254
- const name = getCallName(node.expression);
255
-
256
- if (name && name !== "track") {
257
- detectedFunctionWrappers.add(name);
258
- }
259
-
260
- if (resolvedFn.body) {
261
- visit(resolvedFn.body);
262
- }
263
- }
264
-
265
- if (resolvedFn && resolvedFn.body) {
266
- const sf = resolvedFn.getSourceFile();
267
-
268
- if (!visited.has(sf.fileName)) {
269
- const res = scanSource(
270
- sf,
271
- checker,
272
- config,
273
- visited,
274
- paramMap,
275
- wrapperCache
276
- );
277
-
278
- res.events.forEach(e => events.add(e));
279
- }
280
- }
281
-
282
- node.arguments.forEach(visit);
283
- visit(node.expression);
284
-
285
- return;
286
- }
287
-
288
- ts.forEachChild(node, visit);
289
- }
290
-
291
- visit(source);
292
-
293
- return {
294
- events,
295
- detectedFunctionWrappers,
296
- detectedComponentWrappers,
297
- };
298
- }
package/src/index.ts DELETED
@@ -1,49 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { Command } from "commander";
4
-
5
- const program = new Command();
6
-
7
- program
8
- .name("eventra")
9
- .description("Eventra CLI")
10
- .version("0.0.1");
11
-
12
- program
13
- .command("init")
14
- .action(async () => {
15
- const { init } = await import("./commands/init");
16
- await init();
17
- });
18
-
19
- program
20
- .command("sync")
21
- .action(async () => {
22
- const { sync } = await import("./commands/sync");
23
- await sync();
24
- });
25
-
26
- program
27
- .command("check")
28
- .option("--fix", "auto fix issues")
29
- .action(async (opts) => {
30
- const { check } = await import("./commands/check");
31
- await check({ fix: opts.fix });
32
- });
33
-
34
- program
35
- .command("watch")
36
- .description("Watch files and detect events in real-time")
37
- .action(async () => {
38
- const { watch } = await import("./commands/watch");
39
- await watch();
40
- });
41
-
42
- program
43
- .command("send")
44
- .action(async () => {
45
- const { send } = await import("./commands/send");
46
- await send();
47
- });
48
-
49
- program.parse();