@eventra_dev/eventra-cli 0.1.25 → 0.1.27

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,7 +10,7 @@ const callResolver_1 = require("./callResolver");
10
10
  const exportResolver_1 = require("./exportResolver");
11
11
  const functionAnalyzer_1 = require("./functionAnalyzer");
12
12
  const boundary_1 = require("./boundary");
13
- const TRACKING_NAMES = new Set(["track", "event", "capture", "send"]);
13
+ const trackingDetector_1 = require("./trackingDetector");
14
14
  function getCallName(expr) {
15
15
  if (typescript_1.default.isIdentifier(expr))
16
16
  return expr.text;
@@ -25,6 +25,16 @@ function getJsxAttrName(name) {
25
25
  return name.name.text;
26
26
  return null;
27
27
  }
28
+ // unwrap
29
+ function unwrap(expr) {
30
+ while (typescript_1.default.isAsExpression(expr) ||
31
+ typescript_1.default.isParenthesizedExpression(expr) ||
32
+ typescript_1.default.isTypeAssertionExpression(expr) ||
33
+ typescript_1.default.isNonNullExpression(expr)) {
34
+ expr = expr.expression;
35
+ }
36
+ return expr;
37
+ }
28
38
  function isValidEvent(v) {
29
39
  return (v &&
30
40
  v.length > 1 &&
@@ -32,70 +42,75 @@ function isValidEvent(v) {
32
42
  !v.includes(" ") &&
33
43
  /^[a-zA-Z0-9._:-]+$/.test(v));
34
44
  }
35
- function isPropUsedInTracking(fn, prop) {
45
+ function isPropUsedInTracking(fn, checker, prop) {
36
46
  let found = false;
37
47
  function visit(node) {
38
48
  if (typescript_1.default.isCallExpression(node)) {
39
- const name = getCallName(node.expression);
40
- if (!TRACKING_NAMES.has(name)) {
49
+ if (!(0, trackingDetector_1.isTrackingCall)(node, checker)) {
41
50
  typescript_1.default.forEachChild(node, visit);
42
51
  return;
43
52
  }
44
53
  for (const arg of node.arguments) {
45
- if ((typescript_1.default.isIdentifier(arg) && arg.text === prop) ||
46
- (typescript_1.default.isPropertyAccessExpression(arg) &&
47
- arg.name.text === prop)) {
54
+ const a = unwrap(arg);
55
+ if ((typescript_1.default.isIdentifier(a) && a.text === prop) ||
56
+ (typescript_1.default.isPropertyAccessExpression(a) &&
57
+ a.name.text === prop)) {
48
58
  found = true;
49
59
  }
50
60
  }
51
61
  }
52
62
  typescript_1.default.forEachChild(node, visit);
53
63
  }
54
- visit(fn);
64
+ if (fn.body) {
65
+ visit(fn.body);
66
+ }
55
67
  return found;
56
68
  }
57
69
  function scanSource(source, checker, config, visited = new Set(), depth = 0, inheritedParamMap) {
58
70
  const events = new Set();
59
71
  const detectedFunctionWrappers = new Set();
60
72
  const detectedComponentWrappers = new Map();
61
- if (depth > 5 || visited.has(source.fileName)) {
73
+ if (visited.has(source.fileName) ||
74
+ depth > 10 ||
75
+ visited.size > 200) {
62
76
  return { events, detectedFunctionWrappers, detectedComponentWrappers };
63
77
  }
64
78
  visited.add(source.fileName);
65
79
  function visit(node) {
66
80
  // CALL EXPRESSIONS
67
81
  if (typescript_1.default.isCallExpression(node)) {
68
- const name = getCallName(node.expression);
82
+ const expr = unwrap(node.expression);
83
+ const name = getCallName(expr);
69
84
  const isKnownWrapper = config.functionWrappers.some(w => w.name === name);
70
- let resolvedFn = (0, callResolver_1.resolveFunctionFromCall)(node.expression, checker);
71
- // fallback: tracker.track(...)
72
- if (!resolvedFn && typescript_1.default.isPropertyAccessExpression(node.expression)) {
73
- const symbol = checker.getSymbolAtLocation(node.expression.name);
74
- if (symbol) {
75
- const decls = symbol.getDeclarations();
76
- if (decls?.length) {
77
- const d = decls[0];
78
- if (typescript_1.default.isMethodDeclaration(d) ||
79
- typescript_1.default.isFunctionDeclaration(d) ||
80
- typescript_1.default.isFunctionExpression(d) ||
81
- typescript_1.default.isArrowFunction(d)) {
82
- resolvedFn = d;
83
- }
84
- }
85
- }
86
- }
85
+ const isTrackingByType = (0, trackingDetector_1.isTrackingCall)(node, checker);
86
+ let resolvedFn = (0, callResolver_1.resolveFunctionFromCall)(expr, checker);
87
87
  const isAutoWrapper = resolvedFn && (0, functionAnalyzer_1.findTrackParamIndex)(resolvedFn) !== null;
88
- const isTracking = isKnownWrapper ||
89
- TRACKING_NAMES.has(name) ||
90
- name.startsWith("$") || // NUXT FIX
88
+ let isTracking = isKnownWrapper ||
89
+ isTrackingByType ||
90
+ name.startsWith("$") ||
91
91
  (isAutoWrapper &&
92
92
  resolvedFn &&
93
93
  !(0, boundary_1.isExternalFile)(resolvedFn.getSourceFile().fileName));
94
+ // fallback
95
+ if (!isTracking) {
96
+ if (typescript_1.default.isPropertyAccessExpression(expr) &&
97
+ expr.name.text === "track") {
98
+ isTracking = true;
99
+ }
100
+ else if (typescript_1.default.isIdentifier(expr) &&
101
+ expr.text === "track") {
102
+ isTracking = true;
103
+ }
104
+ }
94
105
  if (!isTracking) {
95
106
  typescript_1.default.forEachChild(node, visit);
96
107
  return;
97
108
  }
98
- if (!isKnownWrapper && isAutoWrapper && !TRACKING_NAMES.has(name)) {
109
+ // detect wrapper
110
+ if (!isKnownWrapper &&
111
+ isAutoWrapper &&
112
+ !isTrackingByType &&
113
+ !name.startsWith("track")) {
99
114
  detectedFunctionWrappers.add(name);
100
115
  }
101
116
  const paramMap = new Map(inheritedParamMap ?? []);
@@ -114,26 +129,22 @@ function scanSource(source, checker, config, visited = new Set(), depth = 0, inh
114
129
  if (resolvedFn) {
115
130
  const idx = (0, functionAnalyzer_1.findTrackParamIndex)(resolvedFn);
116
131
  if (idx !== null && node.arguments[idx]) {
117
- const res = (0, resolver_1.resolveNodeValue)(node.arguments[idx], checker, paramMap);
118
- if (res && res.values.length) {
119
- res.values.forEach(v => {
120
- if (isValidEvent(v))
121
- events.add(v);
122
- });
123
- }
132
+ const res = (0, resolver_1.resolveNodeValue)(unwrap(node.arguments[idx]), checker, paramMap);
133
+ res.values.forEach(v => {
134
+ if (isValidEvent(v))
135
+ events.add(v);
136
+ });
124
137
  handled = true;
125
138
  }
126
139
  }
127
140
  // FALLBACK
128
141
  if (!handled) {
129
142
  for (const arg of node.arguments) {
130
- const res = (0, resolver_1.resolveNodeValue)(arg, checker, paramMap);
131
- if (res && res.values.length) {
132
- res.values.forEach(v => {
133
- if (isValidEvent(v))
134
- events.add(v);
135
- });
136
- }
143
+ const res = (0, resolver_1.resolveNodeValue)(unwrap(arg), checker, paramMap);
144
+ res.values.forEach(v => {
145
+ if (isValidEvent(v))
146
+ events.add(v);
147
+ });
137
148
  }
138
149
  }
139
150
  // CROSS FILE
@@ -183,7 +194,7 @@ function scanSource(source, checker, config, visited = new Set(), depth = 0, inh
183
194
  continue;
184
195
  for (const el of param.name.elements) {
185
196
  const prop = el.name.getText();
186
- const isEvent = isPropUsedInTracking(fn, prop) ||
197
+ const isEvent = isPropUsedInTracking(fn, checker, prop) ||
187
198
  config.wrappers.some(w => w.name === tagName && w.prop === prop);
188
199
  if (!isEvent)
189
200
  continue;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isTrackingCall = isTrackingCall;
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) {
39
+ const expr = node.expression;
40
+ // fn(...)
41
+ if (typescript_1.default.isIdentifier(expr)) {
42
+ const type = checker.getTypeAtLocation(expr);
43
+ if (hasTrackLikeSignature(type, checker)) {
44
+ return true;
45
+ }
46
+ }
47
+ // obj.method(...)
48
+ 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
+ }
66
+ }
67
+ return false;
68
+ }
@@ -1,20 +1,11 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.processFile = processFile;
7
- const path_1 = __importDefault(require("path"));
8
4
  const universal_1 = require("./universal");
9
5
  function processFile(file, content) {
10
6
  const { code, deps } = (0, universal_1.parseUniversal)(content, file);
11
- const ext = path_1.default.extname(file);
12
- const virtualFile = /\.(vue|svelte|astro|html)$/i.test(file)
13
- ? file.replace(ext, "") + ".tsx"
14
- : file;
15
7
  return {
16
8
  content: code || "",
17
- virtualFile,
18
9
  deps: [...new Set(deps.filter(Boolean))],
19
10
  };
20
11
  }
@@ -15,7 +15,7 @@ function stripComments(input) {
15
15
  .replace(/\/\/.*$/gm, "");
16
16
  }
17
17
  /**
18
- * Extract JS expressions safely
18
+ * Extract JS expressions
19
19
  */
20
20
  function extractJS(input) {
21
21
  const result = [];
@@ -25,7 +25,6 @@ function extractJS(input) {
25
25
  let escape = false;
26
26
  while (i < len) {
27
27
  const ch = input[i];
28
- // STRING
29
28
  if (inString) {
30
29
  if (escape)
31
30
  escape = false;
@@ -41,95 +40,31 @@ function extractJS(input) {
41
40
  i++;
42
41
  continue;
43
42
  }
44
- // { ... }
45
43
  if (ch === "{") {
46
44
  let depth = 1;
47
45
  let j = i + 1;
48
- let innerStr = null;
49
- let innerEsc = false;
50
46
  while (j < len && depth > 0) {
51
- const c = input[j];
52
- if (innerStr) {
53
- if (innerEsc)
54
- innerEsc = false;
55
- else if (c === "\\")
56
- innerEsc = true;
57
- else if (c === innerStr)
58
- innerStr = null;
59
- j++;
60
- continue;
61
- }
62
- if (c === '"' || c === "'" || c === "`") {
63
- innerStr = c;
64
- j++;
65
- continue;
66
- }
67
- if (c === "{")
47
+ if (input[j] === "{")
68
48
  depth++;
69
- else if (c === "}")
49
+ else if (input[j] === "}")
70
50
  depth--;
71
51
  j++;
72
52
  }
73
53
  if (depth === 0) {
74
54
  const expr = input.slice(i + 1, j - 1).trim();
75
- if (expr &&
76
- (expr.includes("(") ||
77
- expr.includes("=") ||
78
- expr.includes(".") ||
79
- expr.includes("track"))) {
55
+ if (expr && /[a-zA-Z0-9_$]\s*\(/.test(expr)) {
80
56
  result.push(expr);
81
57
  }
82
58
  i = j;
83
59
  continue;
84
60
  }
85
61
  }
86
- // attr="..."
87
- if (ch === "=" && (input[i + 1] === '"' || input[i + 1] === "'")) {
88
- const quote = input[i + 1];
89
- let j = i + 2;
90
- let val = "";
91
- while (j < len) {
92
- const c = input[j];
93
- if (c === "\\" && input[j + 1]) {
94
- val += c + input[j + 1];
95
- j += 2;
96
- continue;
97
- }
98
- if (c === quote)
99
- break;
100
- val += c;
101
- j++;
102
- }
103
- if (val.trim() &&
104
- (val.includes("(") ||
105
- val.includes("=>") ||
106
- val.includes("track"))) {
107
- result.push(val.trim());
108
- }
109
- i = j + 1;
110
- continue;
111
- }
112
62
  i++;
113
63
  }
114
- // Vue / Svelte / JSX handlers
115
- const extra = [
116
- /@[\w-]+\s*=\s*["']([\s\S]*?)["']/g,
117
- /v-on:[\w-]+\s*=\s*["']([\s\S]*?)["']/g,
118
- /on:[\w-]+\s*=\s*{([\s\S]*?)}/g,
119
- /on\w+\s*=\s*{([\s\S]*?)}/g,
120
- ];
121
- for (const r of extra) {
122
- const m = input.matchAll(r);
123
- for (const x of m) {
124
- const v = x[1]?.trim();
125
- if (v)
126
- result.push(v);
127
- }
128
- }
129
64
  return result;
130
65
  }
131
66
  /**
132
- * Extract loose JS but less noisy
67
+ * Loose JS extractor
133
68
  */
134
69
  function extractLooseJS(input) {
135
70
  const result = [];
@@ -140,28 +75,31 @@ function extractLooseJS(input) {
140
75
  continue;
141
76
  if (l.startsWith("<"))
142
77
  continue;
143
- // strict filter
144
- if (l.includes("track") ||
145
- l.includes(".track(") ||
146
- l.includes("=>") ||
147
- l.startsWith("function") ||
148
- l.includes("(")) {
78
+ if (/[a-zA-Z0-9_$]\s*\(/.test(l)) {
149
79
  result.push(l);
150
80
  }
151
81
  }
152
82
  return result;
153
83
  }
154
84
  /**
155
- * Universal parser
85
+ * UNIVERSAL PARSER
86
+ * Support:
87
+ * - React / JSX
88
+ * - Vue
89
+ * - Svelte
90
+ * - Astro
91
+ * - HTML + JS
92
+ * - SSR
156
93
  */
157
94
  function parseUniversal(content, file) {
158
95
  const parts = [];
159
96
  const deps = [];
160
97
  const clean = stripComments(content);
161
- // Astro frontmatter
98
+ // ASTRO FRONTMATTER
162
99
  const fm = clean.match(/^---([\s\S]*?)---/);
163
- if (fm?.[1])
100
+ if (fm?.[1]) {
164
101
  parts.push(fm[1]);
102
+ }
165
103
  // <script src="">
166
104
  const scriptSrc = clean.matchAll(/<script\b[^>]*?\bsrc=["'](.+?)["'][^>]*>/g);
167
105
  for (const s of scriptSrc) {
@@ -171,29 +109,29 @@ function parseUniversal(content, file) {
171
109
  : path_1.default.resolve(path_1.default.dirname(file), src);
172
110
  deps.push(resolved);
173
111
  }
174
- // inline <script>
112
+ // INLINE <script>
175
113
  const scripts = clean.matchAll(/<script\b([^>]*)>([\s\S]*?)<\/script>/g);
176
114
  for (const m of scripts) {
177
115
  const attrs = m[1];
178
- // skip JSON / data
116
+ // skip JSON
179
117
  if (/type=["']application\/json/.test(attrs))
180
118
  continue;
181
119
  if (m[2].trim()) {
182
120
  parts.push(m[2]);
183
121
  }
184
122
  }
185
- // remove scripts
123
+ // REMOVE SCRIPTS → TEMPLATE PART
186
124
  const noScripts = clean.replace(/<script[\s\S]*?<\/script>/g, "");
187
- // loose JS
188
- const loose = extractLooseJS(noScripts);
189
- parts.push(...loose);
190
- // expressions
125
+ // LOOSE JS
126
+ parts.push(...extractLooseJS(noScripts));
127
+ // EXPRESSIONS
191
128
  const extracted = extractJS(clean);
192
129
  for (const e of extracted) {
193
130
  parts.push(e + ";");
194
131
  }
132
+ // RESULT
195
133
  return {
196
134
  code: [...new Set(parts)].join("\n"),
197
- deps,
135
+ deps: [...new Set(deps.filter(Boolean))],
198
136
  };
199
137
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eventra_dev/eventra-cli",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "Eventra CLI",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -14,6 +14,10 @@ type QueueItem = {
14
14
  virtual: string;
15
15
  };
16
16
 
17
+ function normalize(file: string) {
18
+ return path.resolve(file).replace(/\\/g, "/");
19
+ }
20
+
17
21
  export async function watch() {
18
22
  const config = await loadConfig();
19
23
  if (!config) return;
@@ -27,6 +31,7 @@ export async function watch() {
27
31
 
28
32
  const engine = new EventraEngine(process.cwd());
29
33
  const watchedDeps = new Set<string>();
34
+
30
35
  const cache = new Map<
31
36
  string,
32
37
  { content: string; deps: string[] }
@@ -37,18 +42,18 @@ export async function watch() {
37
42
  // COLLECT + CACHE
38
43
  for (const file of files) {
39
44
  try {
40
- const raw = await fs.readFile(file, "utf-8");
45
+ const abs = normalize(file);
46
+ const raw = await fs.readFile(abs, "utf-8");
41
47
 
42
- if (raw.length > 2_000_000) continue; // safeguard
48
+ if (raw.length > 2_000_000) continue;
43
49
 
44
- const parsed = processFile(file, raw);
50
+ const parsed = processFile(abs, raw);
45
51
 
46
- cache.set(file, parsed);
47
- toScan.add(file);
52
+ cache.set(abs, parsed);
53
+ toScan.add(abs);
48
54
 
49
55
  for (const dep of parsed.deps) {
50
- const absDep = path.resolve(dep);
51
- toScan.add(absDep);
56
+ toScan.add(normalize(dep));
52
57
  }
53
58
 
54
59
  } catch {
@@ -56,7 +61,7 @@ export async function watch() {
56
61
  }
57
62
  }
58
63
 
59
- // PRELOAD (TS PROGRAM)
64
+ // PRELOAD
60
65
  for (const file of toScan) {
61
66
  try {
62
67
  let parsed = cache.get(file);
@@ -64,10 +69,10 @@ export async function watch() {
64
69
  if (!parsed) {
65
70
  const raw = await fs.readFile(file, "utf-8");
66
71
  parsed = processFile(file, raw);
72
+ cache.set(file, parsed);
67
73
  }
68
74
 
69
75
  const virtual = getVirtualFile(file);
70
-
71
76
  engine.preloadFile?.(virtual, parsed.content);
72
77
 
73
78
  } catch {}
@@ -88,7 +93,7 @@ export async function watch() {
88
93
  engine.scanFile(virtual, parsed.content, config);
89
94
 
90
95
  for (const dep of parsed.deps) {
91
- watchedDeps.add(path.resolve(dep));
96
+ watchedDeps.add(normalize(dep));
92
97
  }
93
98
 
94
99
  } catch {}
@@ -120,29 +125,44 @@ export async function watch() {
120
125
  if (raw.length > 2_000_000) continue;
121
126
 
122
127
  const parsed = processFile(item.real, raw);
123
-
124
128
  cache.set(item.real, parsed);
125
129
 
126
130
  engine.updateFile(item.virtual, parsed.content, config);
127
131
 
128
- // DEPS
132
+ // DEPENDENCY DIFF
133
+ const nextDeps = new Set<string>();
134
+
129
135
  for (const dep of parsed.deps) {
130
- const absDep = path.resolve(dep);
136
+ nextDeps.add(normalize(dep));
137
+ }
131
138
 
132
- if (!watchedDeps.has(absDep)) {
133
- watcher.add(absDep);
134
- watchedDeps.add(absDep);
139
+ // add new deps
140
+ for (const dep of nextDeps) {
141
+ if (!watchedDeps.has(dep)) {
142
+ watcher.add(dep);
143
+ watchedDeps.add(dep);
135
144
  }
145
+ }
146
+
147
+ // remove old deps
148
+ for (const dep of [...watchedDeps]) {
149
+ if (!nextDeps.has(dep)) {
150
+ watcher.unwatch(dep);
151
+ watchedDeps.delete(dep);
152
+ }
153
+ }
136
154
 
155
+ // preload deps
156
+ for (const dep of nextDeps) {
137
157
  try {
138
- const depRaw = await fs.readFile(absDep, "utf-8");
139
- const depParsed = processFile(absDep, depRaw);
158
+ const raw = await fs.readFile(dep, "utf-8");
159
+ const parsedDep = processFile(dep, raw);
140
160
 
141
- cache.set(absDep, depParsed);
161
+ cache.set(dep, parsedDep);
142
162
 
143
- const depVirtual = getVirtualFile(absDep);
163
+ const virtual = getVirtualFile(dep);
144
164
 
145
- engine.updateFile(depVirtual, depParsed.content, config);
165
+ engine.updateFile(virtual, parsedDep.content, config);
146
166
  } catch {}
147
167
  }
148
168
 
@@ -174,7 +194,7 @@ export async function watch() {
174
194
 
175
195
  // SCHEDULER
176
196
  const schedule = (file: string) => {
177
- const abs = path.resolve(file);
197
+ const abs = normalize(file);
178
198
  const virtual = getVirtualFile(abs);
179
199
 
180
200
  console.log(chalk.gray(`change: ${file}`));
@@ -182,7 +202,7 @@ export async function watch() {
182
202
  queued.set(abs, { real: abs, virtual });
183
203
 
184
204
  if (timer) clearTimeout(timer);
185
- timer = setTimeout(run, 250);
205
+ timer = setTimeout(run, 200);
186
206
  };
187
207
 
188
208
  // WATCHER
@@ -196,7 +216,7 @@ export async function watch() {
196
216
  .on("add", schedule)
197
217
  .on("change", schedule)
198
218
  .on("unlink", async (file) => {
199
- const abs = path.resolve(file);
219
+ const abs = normalize(file);
200
220
 
201
221
  console.log(chalk.gray(`remove: ${file}`));
202
222
 
@@ -220,7 +240,7 @@ export async function watch() {
220
240
  console.error(chalk.red("Watcher error:"), err);
221
241
  });
222
242
 
223
- // WATCH DEPS
243
+ // WATCH DEPS INIT
224
244
  for (const dep of watchedDeps) {
225
245
  watcher.add(dep);
226
246
  }