@eventra_dev/eventra-cli 0.1.24 → 0.1.26

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.
@@ -7,9 +7,11 @@ exports.check = check;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
8
  const fast_glob_1 = __importDefault(require("fast-glob"));
9
9
  const promises_1 = __importDefault(require("fs/promises"));
10
+ const path_1 = __importDefault(require("path"));
10
11
  const config_1 = require("../utils/config");
11
12
  const engine_1 = require("../engine/engine");
12
13
  const processFile_1 = require("../utils/processFile");
14
+ const getVirtualFile_1 = require("../utils/getVirtualFile");
13
15
  async function check({ fix = false }) {
14
16
  const config = await (0, config_1.loadConfig)();
15
17
  if (!config) {
@@ -19,37 +21,59 @@ async function check({ fix = false }) {
19
21
  console.log(chalk_1.default.blue("Checking events..."));
20
22
  const files = await (0, fast_glob_1.default)(config.sync.include, {
21
23
  ignore: config.sync.exclude,
24
+ absolute: true,
22
25
  });
23
26
  const engine = new engine_1.EventraEngine(process.cwd());
27
+ const toScan = new Set();
28
+ const cache = new Map();
29
+ // COLLECT + CACHE
24
30
  for (const file of files) {
25
31
  try {
26
32
  const raw = await promises_1.default.readFile(file, "utf-8");
27
- const { content, virtualFile, deps } = (0, processFile_1.processFile)(file, raw);
28
- engine.scanFile(virtualFile, content, config);
29
- for (const dep of deps) {
30
- try {
31
- const depRaw = await promises_1.default.readFile(dep, "utf-8");
32
- const { content: depContent, virtualFile: depVirtual, } = (0, processFile_1.processFile)(dep, depRaw);
33
- engine.scanFile(depVirtual, depContent, config);
34
- }
35
- catch { }
33
+ if (raw.length > 2_000_000)
34
+ continue;
35
+ const parsed = (0, processFile_1.processFile)(file, raw);
36
+ cache.set(file, parsed);
37
+ toScan.add(file);
38
+ for (const dep of parsed.deps) {
39
+ toScan.add(path_1.default.resolve(dep));
36
40
  }
37
41
  }
38
- catch (err) {
39
- console.log(chalk_1.default.yellow(`Skipped: ${file}`));
42
+ catch { }
43
+ }
44
+ // PRELOAD
45
+ for (const file of toScan) {
46
+ try {
47
+ let parsed = cache.get(file);
48
+ if (!parsed) {
49
+ const raw = await promises_1.default.readFile(file, "utf-8");
50
+ parsed = (0, processFile_1.processFile)(file, raw);
51
+ cache.set(file, parsed);
52
+ }
53
+ const virtual = (0, getVirtualFile_1.getVirtualFile)(file);
54
+ engine.preloadFile(virtual, parsed.content);
55
+ }
56
+ catch { }
57
+ }
58
+ // SCAN
59
+ for (const file of toScan) {
60
+ try {
61
+ const parsed = cache.get(file);
62
+ if (!parsed)
63
+ continue;
64
+ const virtual = (0, getVirtualFile_1.getVirtualFile)(file);
65
+ engine.scanFile(virtual, parsed.content, config);
40
66
  }
67
+ catch { }
41
68
  }
69
+ // DIFF
42
70
  const found = new Set(engine.getAllEvents());
43
71
  const known = new Set(config.events ?? []);
44
72
  const newEvents = [...found].filter(e => !known.has(e));
45
73
  const removed = [...known].filter(e => !found.has(e));
46
74
  // FIX MODE
47
75
  if (fix) {
48
- const next = new Set();
49
- found.forEach(e => next.add(e));
50
- newEvents.forEach(e => console.log(chalk_1.default.green(`+ ${e}`)));
51
- removed.forEach(e => console.log(chalk_1.default.red(`- ${e}`)));
52
- config.events = [...next].sort();
76
+ config.events = [...found].sort();
53
77
  await (0, config_1.saveConfig)(config);
54
78
  console.log(chalk_1.default.green(`\nSynced (${config.events.length} events)`));
55
79
  return;
@@ -7,9 +7,11 @@ exports.sync = sync;
7
7
  const fast_glob_1 = __importDefault(require("fast-glob"));
8
8
  const promises_1 = __importDefault(require("fs/promises"));
9
9
  const chalk_1 = __importDefault(require("chalk"));
10
+ const path_1 = __importDefault(require("path"));
10
11
  const config_1 = require("../utils/config");
11
12
  const engine_1 = require("../engine/engine");
12
13
  const processFile_1 = require("../utils/processFile");
14
+ const getVirtualFile_1 = require("../utils/getVirtualFile");
13
15
  async function sync() {
14
16
  const config = await (0, config_1.loadConfig)();
15
17
  if (!config)
@@ -17,73 +19,73 @@ async function sync() {
17
19
  console.log(chalk_1.default.blue("Scanning..."));
18
20
  const files = await (0, fast_glob_1.default)(config.sync.include, {
19
21
  ignore: config.sync.exclude,
22
+ absolute: true,
20
23
  });
21
24
  if (!files.length) {
22
25
  console.log(chalk_1.default.yellow("No files found"));
23
26
  return;
24
27
  }
25
28
  const engine = new engine_1.EventraEngine(process.cwd());
26
- const detectedFn = new Set();
27
- const detectedCmp = new Map();
28
- const fileCache = [];
29
+ const toScan = new Set();
30
+ const cache = new Map();
31
+ // COLLECT + CACHE
29
32
  for (const file of files) {
30
33
  try {
31
34
  const raw = await promises_1.default.readFile(file, "utf-8");
32
- const { content, virtualFile, deps } = (0, processFile_1.processFile)(file, raw);
33
- engine["ts"].updateFile(virtualFile, content);
34
- fileCache.push({ file: virtualFile, content });
35
- // deps
36
- for (const dep of deps) {
37
- try {
38
- const depRaw = await promises_1.default.readFile(dep, "utf-8");
39
- const { content: depContent, virtualFile: depVirtual, } = (0, processFile_1.processFile)(dep, depRaw);
40
- engine["ts"].updateFile(depVirtual, depContent);
41
- fileCache.push({ file: depVirtual, content: depContent });
42
- }
43
- catch { }
35
+ if (raw.length > 2_000_000)
36
+ continue;
37
+ const parsed = (0, processFile_1.processFile)(file, raw);
38
+ cache.set(file, parsed);
39
+ toScan.add(file);
40
+ for (const dep of parsed.deps) {
41
+ toScan.add(path_1.default.resolve(dep));
44
42
  }
45
43
  }
46
44
  catch { }
47
45
  }
48
- for (const { file, content } of fileCache) {
46
+ // PRELOAD
47
+ for (const file of toScan) {
49
48
  try {
50
- const res = engine.scanFile(file, content, config);
51
- for (const w of res.detectedFunctionWrappers) {
52
- detectedFn.add(w);
49
+ let parsed = cache.get(file);
50
+ if (!parsed) {
51
+ const raw = await promises_1.default.readFile(file, "utf-8");
52
+ parsed = (0, processFile_1.processFile)(file, raw);
53
+ cache.set(file, parsed);
53
54
  }
55
+ const virtual = (0, getVirtualFile_1.getVirtualFile)(file);
56
+ engine.preloadFile(virtual, parsed.content);
57
+ }
58
+ catch { }
59
+ }
60
+ // SCAN
61
+ const detectedFn = new Set();
62
+ const detectedCmp = new Map();
63
+ for (const file of toScan) {
64
+ try {
65
+ const parsed = cache.get(file);
66
+ if (!parsed)
67
+ continue;
68
+ const virtual = (0, getVirtualFile_1.getVirtualFile)(file);
69
+ const res = engine.scanFile(virtual, parsed.content, config);
70
+ res.detectedFunctionWrappers.forEach(w => detectedFn.add(w));
54
71
  for (const [k, v] of res.detectedComponentWrappers) {
55
72
  detectedCmp.set(k, v);
56
73
  }
57
74
  }
58
- catch (err) {
59
- console.log(chalk_1.default.yellow(`Skipped: ${file}`));
60
- if (err instanceof Error) {
61
- console.log(chalk_1.default.gray(err.message));
62
- }
75
+ catch {
76
+ console.log(chalk_1.default.gray(`skip: ${file}`));
63
77
  }
64
78
  }
65
- // EVENTS
79
+ // RESULT
66
80
  const events = engine.getAllEvents().sort();
67
- const mergedEvents = new Set(config.events ?? []);
68
- events.forEach(e => mergedEvents.add(e));
69
- config.events = [...mergedEvents].sort();
70
- // FUNCTION WRAPPERS
81
+ config.events = events;
71
82
  config.functionWrappers = mergeUnique(config.functionWrappers ?? [], [...detectedFn].map(name => ({ name })), w => w.name);
72
- // COMPONENT WRAPPERS
73
83
  config.wrappers = mergeUnique(config.wrappers ?? [], [...detectedCmp.entries()].map(([name, prop]) => ({
74
84
  name,
75
85
  prop,
76
86
  })), w => `${w.name}:${w.prop}`);
77
87
  await (0, config_1.saveConfig)(config);
78
88
  console.log(chalk_1.default.green(`Found ${events.length} events`));
79
- if (detectedFn.size) {
80
- console.log(chalk_1.default.blue("\nDetected function wrappers:"));
81
- detectedFn.forEach(w => console.log(chalk_1.default.gray(`• ${w}`)));
82
- }
83
- if (detectedCmp.size) {
84
- console.log(chalk_1.default.blue("\nDetected component wrappers:"));
85
- detectedCmp.forEach((prop, name) => console.log(chalk_1.default.gray(`• ${name} (${prop})`)));
86
- }
87
89
  }
88
90
  // HELPERS
89
91
  function mergeUnique(a, b, key) {
@@ -12,11 +12,9 @@ const path_1 = __importDefault(require("path"));
12
12
  const config_1 = require("../utils/config");
13
13
  const engine_1 = require("../engine/engine");
14
14
  const processFile_1 = require("../utils/processFile");
15
- // stabile virtual mapping
16
- function getVirtualFile(file) {
17
- return /\.(vue|svelte|astro|html)$/i.test(file)
18
- ? file + ".tsx"
19
- : file;
15
+ const getVirtualFile_1 = require("../utils/getVirtualFile");
16
+ function normalize(file) {
17
+ return path_1.default.resolve(file).replace(/\\/g, "/");
20
18
  }
21
19
  async function watch() {
22
20
  const config = await (0, config_1.loadConfig)();
@@ -25,58 +23,108 @@ async function watch() {
25
23
  console.log(chalk_1.default.blue("Watching...\n"));
26
24
  const files = await (0, fast_glob_1.default)(config.sync.include, {
27
25
  ignore: config.sync.exclude,
26
+ absolute: true,
28
27
  });
29
28
  const engine = new engine_1.EventraEngine(process.cwd());
30
29
  const watchedDeps = new Set();
31
- // INITIAL LOAD
30
+ const cache = new Map();
31
+ const toScan = new Set();
32
+ // COLLECT + CACHE
32
33
  for (const file of files) {
33
34
  try {
34
- const abs = path_1.default.resolve(file);
35
+ const abs = normalize(file);
35
36
  const raw = await promises_1.default.readFile(abs, "utf-8");
36
- const { content, deps } = (0, processFile_1.processFile)(abs, raw);
37
- const virtual = getVirtualFile(abs);
38
- engine.scanFile(virtual, content, config);
39
- // deps
40
- for (const dep of deps) {
41
- watchedDeps.add(path_1.default.resolve(dep));
37
+ if (raw.length > 2_000_000)
38
+ continue;
39
+ const parsed = (0, processFile_1.processFile)(abs, raw);
40
+ cache.set(abs, parsed);
41
+ toScan.add(abs);
42
+ for (const dep of parsed.deps) {
43
+ toScan.add(normalize(dep));
42
44
  }
43
45
  }
44
46
  catch {
45
47
  console.log(chalk_1.default.gray(`skip: ${file}`));
46
48
  }
47
49
  }
50
+ // PRELOAD
51
+ for (const file of toScan) {
52
+ try {
53
+ let parsed = cache.get(file);
54
+ if (!parsed) {
55
+ const raw = await promises_1.default.readFile(file, "utf-8");
56
+ parsed = (0, processFile_1.processFile)(file, raw);
57
+ cache.set(file, parsed);
58
+ }
59
+ const virtual = (0, getVirtualFile_1.getVirtualFile)(file);
60
+ engine.preloadFile?.(virtual, parsed.content);
61
+ }
62
+ catch { }
63
+ }
64
+ // INITIAL SCAN
65
+ for (const file of toScan) {
66
+ try {
67
+ let parsed = cache.get(file);
68
+ if (!parsed) {
69
+ const raw = await promises_1.default.readFile(file, "utf-8");
70
+ parsed = (0, processFile_1.processFile)(file, raw);
71
+ }
72
+ const virtual = (0, getVirtualFile_1.getVirtualFile)(file);
73
+ engine.scanFile(virtual, parsed.content, config);
74
+ for (const dep of parsed.deps) {
75
+ watchedDeps.add(normalize(dep));
76
+ }
77
+ }
78
+ catch { }
79
+ }
48
80
  config.events = engine.getAllEvents().sort();
49
81
  await (0, config_1.saveConfig)(config);
50
82
  console.log(chalk_1.default.gray(`Initial: ${config.events.length} events\n`));
51
83
  // QUEUE
52
84
  let locked = false;
53
- let queued = new Map();
85
+ const queued = new Map();
54
86
  let timer = null;
55
87
  const run = async () => {
56
- if (locked) {
57
- timer = setTimeout(run, 100);
88
+ if (locked)
58
89
  return;
59
- }
60
90
  locked = true;
61
91
  const batch = [...queued.values()];
62
92
  queued.clear();
63
93
  for (const item of batch) {
64
94
  try {
65
95
  const raw = await promises_1.default.readFile(item.real, "utf-8");
66
- const { content, deps } = (0, processFile_1.processFile)(item.real, raw);
67
- engine.updateFile(item.virtual, content, config);
68
- // DEPS
69
- for (const dep of deps) {
70
- const absDep = path_1.default.resolve(dep);
71
- if (!watchedDeps.has(absDep)) {
72
- watcher.add(absDep);
73
- watchedDeps.add(absDep);
96
+ if (raw.length > 2_000_000)
97
+ continue;
98
+ const parsed = (0, processFile_1.processFile)(item.real, raw);
99
+ cache.set(item.real, parsed);
100
+ engine.updateFile(item.virtual, parsed.content, config);
101
+ // DEPENDENCY DIFF
102
+ const nextDeps = new Set();
103
+ for (const dep of parsed.deps) {
104
+ nextDeps.add(normalize(dep));
105
+ }
106
+ // add new deps
107
+ for (const dep of nextDeps) {
108
+ if (!watchedDeps.has(dep)) {
109
+ watcher.add(dep);
110
+ watchedDeps.add(dep);
74
111
  }
112
+ }
113
+ // remove old deps
114
+ for (const dep of [...watchedDeps]) {
115
+ if (!nextDeps.has(dep)) {
116
+ watcher.unwatch(dep);
117
+ watchedDeps.delete(dep);
118
+ }
119
+ }
120
+ // preload deps
121
+ for (const dep of nextDeps) {
75
122
  try {
76
- const depRaw = await promises_1.default.readFile(absDep, "utf-8");
77
- const { content: depContent } = (0, processFile_1.processFile)(absDep, depRaw);
78
- const depVirtual = getVirtualFile(absDep);
79
- engine.updateFile(depVirtual, depContent, config);
123
+ const raw = await promises_1.default.readFile(dep, "utf-8");
124
+ const parsedDep = (0, processFile_1.processFile)(dep, raw);
125
+ cache.set(dep, parsedDep);
126
+ const virtual = (0, getVirtualFile_1.getVirtualFile)(dep);
127
+ engine.updateFile(virtual, parsedDep.content, config);
80
128
  }
81
129
  catch { }
82
130
  }
@@ -85,7 +133,7 @@ async function watch() {
85
133
  console.log(chalk_1.default.gray(`skip: ${item.real}`));
86
134
  }
87
135
  }
88
- // EVENTS DIFF
136
+ // DIFF EVENTS
89
137
  const next = engine.getAllEvents();
90
138
  const added = next.filter(e => !config.events.includes(e));
91
139
  const removed = config.events.filter(e => !next.includes(e));
@@ -100,33 +148,39 @@ async function watch() {
100
148
  };
101
149
  // SCHEDULER
102
150
  const schedule = (file) => {
103
- const abs = path_1.default.resolve(file);
104
- const virtual = getVirtualFile(abs);
151
+ const abs = normalize(file);
152
+ const virtual = (0, getVirtualFile_1.getVirtualFile)(abs);
153
+ console.log(chalk_1.default.gray(`change: ${file}`));
105
154
  queued.set(abs, { real: abs, virtual });
106
155
  if (timer)
107
156
  clearTimeout(timer);
108
- timer = setTimeout(run, 300);
157
+ timer = setTimeout(run, 200);
109
158
  };
110
159
  // WATCHER
111
160
  const watcher = chokidar_1.default.watch(config.sync.include, {
112
161
  ignored: config.sync.exclude,
113
162
  ignoreInitial: true,
163
+ persistent: true,
114
164
  });
115
165
  watcher
116
166
  .on("add", schedule)
117
167
  .on("change", schedule)
118
168
  .on("unlink", async (file) => {
119
- const abs = path_1.default.resolve(file);
169
+ const abs = normalize(file);
120
170
  console.log(chalk_1.default.gray(`remove: ${file}`));
121
- const virtual = getVirtualFile(abs);
171
+ const virtual = (0, getVirtualFile_1.getVirtualFile)(abs);
122
172
  engine.removeFile(virtual, config);
173
+ watcher.unwatch(abs);
123
174
  watchedDeps.delete(abs);
124
175
  const next = engine.getAllEvents();
125
176
  config.events = next.sort();
126
177
  await (0, config_1.saveConfig)(config);
127
178
  console.log(chalk_1.default.gray(`Total: ${config.events.length} events\n`));
179
+ })
180
+ .on("error", (err) => {
181
+ console.error(chalk_1.default.red("Watcher error:"), err);
128
182
  });
129
- // WATCH DEPS
183
+ // WATCH DEPS INIT
130
184
  for (const dep of watchedDeps) {
131
185
  watcher.add(dep);
132
186
  }
@@ -23,15 +23,37 @@ function resolveFromSymbol(symbol, checker, visited = new Set(), depth = 0) {
23
23
  const aliased = checker.getAliasedSymbol(symbol);
24
24
  return resolveFromSymbol(aliased, checker, visited, depth + 1);
25
25
  }
26
+ // re-export support
27
+ if (symbol.exports) {
28
+ for (const exp of symbol.exports.values()) {
29
+ const resolved = resolveFromSymbol(exp, checker, visited, depth + 1);
30
+ if (resolved)
31
+ return resolved;
32
+ }
33
+ }
26
34
  const decls = symbol.getDeclarations() ?? [];
27
35
  for (const decl of decls) {
36
+ // direct function
28
37
  if (isFunctionLike(decl)) {
29
38
  return decl;
30
39
  }
31
- // MethodSignature
40
+ // VARIABLE → FUNCTION
41
+ if (typescript_1.default.isVariableDeclaration(decl) && decl.initializer) {
42
+ if (isFunctionLike(decl.initializer)) {
43
+ return decl.initializer;
44
+ }
45
+ const innerSymbol = checker.getSymbolAtLocation(decl.initializer);
46
+ if (innerSymbol && innerSymbol !== symbol) {
47
+ const resolved = resolveFromSymbol(innerSymbol, checker, visited, depth + 1);
48
+ if (resolved)
49
+ return resolved;
50
+ }
51
+ }
52
+ // MethodSignature (interface / type)
32
53
  if (typescript_1.default.isMethodSignature(decl)) {
33
54
  const parent = decl.parent;
34
- if (typescript_1.default.isInterfaceDeclaration(parent) || typescript_1.default.isTypeLiteralNode(parent)) {
55
+ if (typescript_1.default.isInterfaceDeclaration(parent) ||
56
+ typescript_1.default.isTypeLiteralNode(parent)) {
35
57
  const name = decl.name.getText();
36
58
  const type = checker.getTypeAtLocation(parent);
37
59
  const props = type.getProperties();
@@ -44,7 +66,7 @@ function resolveFromSymbol(symbol, checker, visited = new Set(), depth = 0) {
44
66
  }
45
67
  }
46
68
  }
47
- // SAFE fallback
69
+ // fallback recursion
48
70
  const s = checker.getSymbolAtLocation(decl);
49
71
  if (s && s !== symbol) {
50
72
  const resolved = resolveFromSymbol(s, checker, visited, depth + 1);
@@ -55,6 +77,28 @@ function resolveFromSymbol(symbol, checker, visited = new Set(), depth = 0) {
55
77
  return null;
56
78
  }
57
79
  function resolveFunctionFromCall(expr, checker) {
80
+ // tracker.track
81
+ if (typescript_1.default.isPropertyAccessExpression(expr)) {
82
+ let symbol = checker.getSymbolAtLocation(expr.name);
83
+ if (symbol && (symbol.flags & typescript_1.default.SymbolFlags.Alias)) {
84
+ symbol = checker.getAliasedSymbol(symbol);
85
+ }
86
+ if (symbol) {
87
+ const resolved = resolveFromSymbol(symbol, checker);
88
+ if (resolved)
89
+ return resolved;
90
+ }
91
+ }
92
+ // tracker["track"]
93
+ if (typescript_1.default.isElementAccessExpression(expr)) {
94
+ const symbol = checker.getSymbolAtLocation(expr.argumentExpression);
95
+ if (symbol) {
96
+ const resolved = resolveFromSymbol(symbol, checker);
97
+ if (resolved)
98
+ return resolved;
99
+ }
100
+ }
101
+ // normal call signatures
58
102
  const type = checker.getTypeAtLocation(expr);
59
103
  const signatures = type.getCallSignatures();
60
104
  for (const sig of signatures) {
@@ -64,7 +108,6 @@ function resolveFunctionFromCall(expr, checker) {
64
108
  if (isFunctionLike(decl)) {
65
109
  return decl;
66
110
  }
67
- // interface method
68
111
  if (typescript_1.default.isMethodSignature(decl)) {
69
112
  const symbol = checker.getSymbolAtLocation(decl.name);
70
113
  if (symbol) {
@@ -74,5 +117,10 @@ function resolveFunctionFromCall(expr, checker) {
74
117
  }
75
118
  }
76
119
  }
120
+ // fallback
121
+ const symbol = checker.getSymbolAtLocation(expr);
122
+ if (symbol) {
123
+ return resolveFromSymbol(symbol, checker);
124
+ }
77
125
  return null;
78
126
  }
@@ -1,6 +1,11 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.EventraEngine = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = __importDefault(require("fs"));
4
9
  const languageService_1 = require("./languageService");
5
10
  const scanner_1 = require("./scanner");
6
11
  const graph_1 = require("./graph");
@@ -16,28 +21,40 @@ class EventraEngine {
16
21
  const { baseUrl, paths } = this.ts.getModuleResolutionConfig();
17
22
  this.graph = new graph_1.DependencyGraph(baseUrl, paths);
18
23
  }
24
+ normalize(file) {
25
+ return path_1.default.resolve(file).replace(/\\/g, "/");
26
+ }
27
+ empty() {
28
+ return {
29
+ events: new Set(),
30
+ detectedFunctionWrappers: new Set(),
31
+ detectedComponentWrappers: new Map(),
32
+ };
33
+ }
34
+ // PRELOAD
35
+ preloadFile(file, content) {
36
+ file = this.normalize(file);
37
+ this.ts.updateFile(file, content);
38
+ const source = this.ts.getSourceFile(file);
39
+ if (source) {
40
+ this.graph.update(file, source);
41
+ }
42
+ }
19
43
  // SCAN FILE
20
44
  scanFile(file, content, config) {
45
+ file = this.normalize(file);
21
46
  const h = (0, hash_1.hash)(content);
22
- // skip unchanged
23
47
  if (this.fileHash.get(file) === h) {
24
- return (this.fileResults.get(file) ?? {
25
- events: new Set(),
26
- detectedFunctionWrappers: new Set(),
27
- detectedComponentWrappers: new Map(),
28
- });
48
+ return this.fileResults.get(file) ?? this.empty();
29
49
  }
30
50
  this.fileHash.set(file, h);
31
51
  this.ts.updateFile(file, content);
32
52
  const source = this.ts.getSourceFile(file);
33
53
  const checker = this.ts.getChecker();
34
54
  if (!source || !checker) {
35
- return {
36
- events: new Set(),
37
- detectedFunctionWrappers: new Set(),
38
- detectedComponentWrappers: new Map(),
39
- };
55
+ return this.empty();
40
56
  }
57
+ // обновляем graph
41
58
  this.graph.update(file, source);
42
59
  const res = (0, scanner_1.scanSource)(source, checker, config);
43
60
  this.fileResults.set(file, res);
@@ -45,27 +62,35 @@ class EventraEngine {
45
62
  }
46
63
  // UPDATE FILE (incremental)
47
64
  updateFile(file, content, config) {
48
- // сначала обновляем текущий файл
65
+ file = this.normalize(file);
49
66
  const res = this.scanFile(file, content, config);
50
67
  const dependents = this.graph.getAllDependentsDeep(file);
51
68
  for (const dep of dependents) {
52
- if ((0, boundary_1.isExternalFile)(dep))
53
- continue;
54
- const depContent = this.ts.getFileContent(dep);
55
- if (!depContent)
69
+ const abs = this.normalize(dep);
70
+ if ((0, boundary_1.isExternalFile)(abs))
56
71
  continue;
72
+ let depContent = this.ts.getFileContent(abs);
73
+ if (!depContent) {
74
+ try {
75
+ depContent = fs_1.default.readFileSync(abs, "utf-8");
76
+ }
77
+ catch {
78
+ continue;
79
+ }
80
+ }
57
81
  const h = (0, hash_1.hash)(depContent);
58
- if (this.fileHash.get(dep) === h)
82
+ if (this.fileHash.get(abs) === h) {
59
83
  continue;
60
- this.fileHash.set(dep, h);
61
- this.ts.updateFile(dep, depContent);
62
- const source = this.ts.getSourceFile(dep);
84
+ }
85
+ this.fileHash.set(abs, h);
86
+ this.ts.updateFile(abs, depContent);
87
+ const source = this.ts.getSourceFile(abs);
63
88
  const checker = this.ts.getChecker();
64
89
  if (!source || !checker)
65
90
  continue;
66
- this.graph.update(dep, source);
91
+ this.graph.update(abs, source);
67
92
  const r = (0, scanner_1.scanSource)(source, checker, config);
68
- this.fileResults.set(dep, r);
93
+ this.fileResults.set(abs, r);
69
94
  }
70
95
  return res;
71
96
  }
@@ -79,33 +104,42 @@ class EventraEngine {
79
104
  }
80
105
  // REMOVE FILE
81
106
  removeFile(file, config) {
107
+ file = this.normalize(file);
108
+ const dependents = this.graph.getAllDependentsDeep(file);
82
109
  this.ts.removeFile(file);
83
110
  this.fileResults.delete(file);
84
111
  this.fileHash.delete(file);
85
112
  this.graph.remove(file);
86
- const dependents = this.graph.getAllDependentsDeep(file);
87
113
  for (const dep of dependents) {
88
- if ((0, boundary_1.isExternalFile)(dep))
89
- continue;
90
- const content = this.ts.getFileContent(dep);
91
- if (!content)
114
+ const abs = this.normalize(dep);
115
+ if ((0, boundary_1.isExternalFile)(abs))
92
116
  continue;
117
+ let content = this.ts.getFileContent(abs);
118
+ if (!content) {
119
+ try {
120
+ content = fs_1.default.readFileSync(abs, "utf-8");
121
+ }
122
+ catch {
123
+ continue;
124
+ }
125
+ }
93
126
  const h = (0, hash_1.hash)(content);
94
- if (this.fileHash.get(dep) === h)
127
+ if (this.fileHash.get(abs) === h)
95
128
  continue;
96
- this.fileHash.set(dep, h);
97
- this.ts.updateFile(dep, content);
98
- const source = this.ts.getSourceFile(dep);
129
+ this.fileHash.set(abs, h);
130
+ this.ts.updateFile(abs, content);
131
+ const source = this.ts.getSourceFile(abs);
99
132
  const checker = this.ts.getChecker();
100
133
  if (!source || !checker)
101
134
  continue;
135
+ this.graph.update(abs, source);
102
136
  const r = (0, scanner_1.scanSource)(source, checker, config ?? {
103
137
  events: [],
104
138
  wrappers: [],
105
139
  functionWrappers: [],
106
140
  sync: { include: [], exclude: [] },
107
141
  });
108
- this.fileResults.set(dep, r);
142
+ this.fileResults.set(abs, r);
109
143
  }
110
144
  }
111
145
  }