@indigoai-us/hq-cloud 5.25.0 → 5.26.0

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 (44) hide show
  1. package/dist/bin/sync-runner.d.ts +100 -1
  2. package/dist/bin/sync-runner.d.ts.map +1 -1
  3. package/dist/bin/sync-runner.js +214 -16
  4. package/dist/bin/sync-runner.js.map +1 -1
  5. package/dist/bin/sync-runner.test.js +372 -1
  6. package/dist/bin/sync-runner.test.js.map +1 -1
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +3 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/sync/index.d.ts +11 -0
  12. package/dist/sync/index.d.ts.map +1 -0
  13. package/dist/sync/index.js +9 -0
  14. package/dist/sync/index.js.map +1 -0
  15. package/dist/sync/push-event.d.ts +110 -0
  16. package/dist/sync/push-event.d.ts.map +1 -0
  17. package/dist/sync/push-event.js +153 -0
  18. package/dist/sync/push-event.js.map +1 -0
  19. package/dist/sync/push-event.test.d.ts +15 -0
  20. package/dist/sync/push-event.test.d.ts.map +1 -0
  21. package/dist/sync/push-event.test.js +188 -0
  22. package/dist/sync/push-event.test.js.map +1 -0
  23. package/dist/sync/push-transport.d.ts +67 -0
  24. package/dist/sync/push-transport.d.ts.map +1 -0
  25. package/dist/sync/push-transport.js +66 -0
  26. package/dist/sync/push-transport.js.map +1 -0
  27. package/dist/watcher.d.ts +160 -0
  28. package/dist/watcher.d.ts.map +1 -1
  29. package/dist/watcher.js +298 -0
  30. package/dist/watcher.js.map +1 -1
  31. package/dist/watcher.test.d.ts +2 -0
  32. package/dist/watcher.test.d.ts.map +1 -0
  33. package/dist/watcher.test.js +334 -0
  34. package/dist/watcher.test.js.map +1 -0
  35. package/package.json +3 -2
  36. package/src/bin/sync-runner.test.ts +487 -1
  37. package/src/bin/sync-runner.ts +305 -9
  38. package/src/index.ts +17 -0
  39. package/src/sync/index.ts +19 -0
  40. package/src/sync/push-event.test.ts +224 -0
  41. package/src/sync/push-event.ts +208 -0
  42. package/src/sync/push-transport.ts +84 -0
  43. package/src/watcher.test.ts +388 -0
  44. package/src/watcher.ts +386 -0
package/dist/watcher.d.ts CHANGED
@@ -8,6 +8,90 @@
8
8
  */
9
9
  import type { EntityContext } from "./types.js";
10
10
  import type { UploadAuthor } from "./s3.js";
11
+ /**
12
+ * Injectable clock seam (US-001).
13
+ *
14
+ * Production code uses the host timers; tests inject a {@link FakeClock} so the
15
+ * debounce window can be advanced deterministically without real wall-clock
16
+ * sleeps. US-002 (real chokidar watcher) and US-003 (runner wiring) build on
17
+ * this same seam — keep the surface minimal and stable.
18
+ */
19
+ export interface Clock {
20
+ /** Schedule `fn` to run after `ms`. Returns an opaque handle. */
21
+ setTimeout(fn: () => void, ms: number): unknown;
22
+ /** Cancel a previously scheduled timeout. Safe to call with a stale handle. */
23
+ clearTimeout(handle: unknown): void;
24
+ /** Current epoch milliseconds. */
25
+ now(): number;
26
+ }
27
+ /** Real clock backed by host timers + Date.now. The production default. */
28
+ export declare const systemClock: Clock;
29
+ /**
30
+ * Deterministic clock for tests. Advance virtual time with {@link advance};
31
+ * any timers whose deadline has passed fire in scheduled order. No real timers
32
+ * are ever created, so a test using only this clock leaks nothing.
33
+ */
34
+ export declare class FakeClock implements Clock {
35
+ private current;
36
+ private nextId;
37
+ private timers;
38
+ now(): number;
39
+ setTimeout(fn: () => void, ms: number): unknown;
40
+ clearTimeout(handle: unknown): void;
41
+ /**
42
+ * Advance virtual time by `ms`, firing every timer whose deadline falls in
43
+ * the interval (in deadline order). Timers scheduled by a firing callback are
44
+ * honored within the same advance if their new deadline is still within the
45
+ * advanced window.
46
+ */
47
+ advance(ms: number): void;
48
+ /** Number of timers still pending — a leak check for tests. */
49
+ pendingTimerCount(): number;
50
+ }
51
+ /** A push pass to run when a debounced change settles. May be async. */
52
+ export type PushFn = () => void | Promise<void>;
53
+ export interface WatchPushDriverOptions {
54
+ /** Quiet window (ms) before a settled change triggers a push. */
55
+ debounceMs?: number;
56
+ /** Clock seam — defaults to {@link systemClock}; tests inject {@link FakeClock}. */
57
+ clock?: Clock;
58
+ /** Push pass to invoke when the window settles. */
59
+ push: PushFn;
60
+ }
61
+ /**
62
+ * The reusable debounce + coalesce + concurrency-guard core of event-driven
63
+ * push (US-001 seam).
64
+ *
65
+ * It is intentionally decoupled from chokidar and from S3: callers feed it
66
+ * synthetic or real change notifications via {@link notifyChange}, and it
67
+ * invokes the injected `push` fn at most once per quiet window. A push that is
68
+ * still in flight is never overlapped — a change arriving mid-push is collapsed
69
+ * and re-triggers a single follow-up pass after the next quiet window.
70
+ *
71
+ * US-002 wires a real chokidar watcher's events into {@link notifyChange};
72
+ * US-003 supplies the targeted-push `push` fn. Tests drive it directly with a
73
+ * {@link FakeClock} and a spy `push` fn (no real S3, no 10-minute sleep).
74
+ */
75
+ export declare class WatchPushDriver {
76
+ private readonly debounceMs;
77
+ private readonly clock;
78
+ private readonly push;
79
+ private timer;
80
+ private pushing;
81
+ private pendingWhilePushing;
82
+ private disposed;
83
+ constructor(opts: WatchPushDriverOptions);
84
+ /**
85
+ * Register a change. Resets the quiet window; the push fires `debounceMs`
86
+ * after the LAST change in a burst, coalescing the burst to one push.
87
+ */
88
+ notifyChange(): void;
89
+ private fire;
90
+ /** True while a push pass is executing. */
91
+ isPushing(): boolean;
92
+ /** Cancel any pending debounce timer; idempotent. Leaves no timers behind. */
93
+ dispose(): void;
94
+ }
11
95
  export declare class SyncWatcher {
12
96
  private watcher;
13
97
  private hqRoot;
@@ -23,4 +107,80 @@ export declare class SyncWatcher {
23
107
  private queueChange;
24
108
  private flush;
25
109
  }
110
+ /** Decision for a single path: emit a change for it, or ignore it. */
111
+ export type WatchPathFilter = (absolutePath: string, isDir?: boolean) => boolean;
112
+ /**
113
+ * Build the composite emit-decision predicate. Returns true when a change to
114
+ * `absolutePath` SHOULD wake the watcher (i.e. it survives every exclusion
115
+ * layer). Pure and chokidar-free so the matching logic is unit-testable
116
+ * directly.
117
+ *
118
+ * @param hqRoot sync root (== personal-vault root in personalMode).
119
+ * @param personalMode when true, also applies the personal-vault default
120
+ * exclusions and the excluded-top-level buckets.
121
+ */
122
+ export declare function createWatchPathFilter(hqRoot: string, personalMode?: boolean): WatchPathFilter;
123
+ export interface TreeWatcherOptions {
124
+ /** Sync root to watch (== personal-vault root in personalMode). */
125
+ hqRoot: string;
126
+ /** Quiet window (ms) before a settled burst emits one `changed` call. */
127
+ debounceMs?: number;
128
+ /** Apply personal-vault default + top-level exclusions. */
129
+ personalMode?: boolean;
130
+ /** Clock seam — defaults to {@link systemClock}; tests inject {@link FakeClock}. */
131
+ clock?: Clock;
132
+ /**
133
+ * Pre-built path filter override (test seam). When omitted, one is built
134
+ * from {@link createWatchPathFilter}.
135
+ */
136
+ pathFilter?: WatchPathFilter;
137
+ }
138
+ /**
139
+ * Chokidar-backed file watcher that emits a single debounced `changed` signal
140
+ * after a {@link debounceMs} quiet window, coalescing bursts. It honors the
141
+ * full exclusion stack via {@link createWatchPathFilter}, so excluded paths
142
+ * (`.env`, `output/`, `.git/`, `companies/` in personalMode, …) never emit.
143
+ *
144
+ * Lifecycle: {@link start} (idempotent), {@link stop}, {@link dispose}. Stop
145
+ * closes the chokidar watcher (releasing fds) and cancels any pending debounce
146
+ * timer. dispose() is stop() + permanent shutdown.
147
+ */
148
+ export declare class TreeWatcher {
149
+ private readonly hqRoot;
150
+ private readonly debounceMs;
151
+ private readonly clock;
152
+ private readonly shouldEmit;
153
+ private watcher;
154
+ private timer;
155
+ private listeners;
156
+ private disposed;
157
+ constructor(opts: TreeWatcherOptions);
158
+ /** Register a debounced-`changed` listener. Returns an unsubscribe fn. */
159
+ onChange(listener: () => void): () => void;
160
+ /**
161
+ * Begin watching. Idempotent — a second call while already running is a
162
+ * no-op (no second chokidar instance, no leaked fds).
163
+ */
164
+ start(): void;
165
+ /**
166
+ * Test/seam entry point: feed a raw filesystem path as if chokidar reported
167
+ * it. Applies the emit filter then arms the debounce. Real chokidar events
168
+ * route through here too.
169
+ */
170
+ handleEvent(absolutePath: string): void;
171
+ private arm;
172
+ private emit;
173
+ /** True while the chokidar watcher is active. */
174
+ isWatching(): boolean;
175
+ /** Number of pending debounce timers — a leak check for tests. */
176
+ pendingTimerCount(): number;
177
+ /**
178
+ * Stop watching: close the chokidar watcher (releasing fds) and cancel any
179
+ * pending debounce timer. Idempotent. The instance can be restarted with
180
+ * {@link start} unless {@link dispose} was called.
181
+ */
182
+ stop(): void;
183
+ /** Permanent shutdown: stop() + drop listeners; further events are no-ops. */
184
+ dispose(): void;
185
+ }
26
186
  //# sourceMappingURL=watcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAU5C,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,GAAG,CAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,CAAe;IAC9B,OAAO,CAAC,UAAU,CAAiD;IACnE,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,UAAU,CAAS;gBAEf,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,YAAY;IAOrE,KAAK,IAAI,IAAI;IAuBb,IAAI,IAAI,IAAI;IAWZ,OAAO,CAAC,WAAW;YAqBL,KAAK;CAgDpB"}
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"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"}
package/dist/watcher.js CHANGED
@@ -12,7 +12,140 @@ import { watch } from "chokidar";
12
12
  import { createIgnoreFilter, isWithinSizeLimit } from "./ignore.js";
13
13
  import { readJournal, writeJournal, hashFile, updateEntry } from "./journal.js";
14
14
  import { uploadFile, deleteRemoteFile } from "./s3.js";
15
+ import { isPersonalVaultExcluded } from "./personal-vault-exclusions.js";
16
+ import { PERSONAL_VAULT_EXCLUDED_TOP_LEVEL } from "./personal-vault.js";
15
17
  const DEBOUNCE_MS = 2000;
18
+ /** Real clock backed by host timers + Date.now. The production default. */
19
+ export const systemClock = {
20
+ setTimeout: (fn, ms) => setTimeout(fn, ms),
21
+ clearTimeout: (handle) => clearTimeout(handle),
22
+ now: () => Date.now(),
23
+ };
24
+ /**
25
+ * Deterministic clock for tests. Advance virtual time with {@link advance};
26
+ * any timers whose deadline has passed fire in scheduled order. No real timers
27
+ * are ever created, so a test using only this clock leaks nothing.
28
+ */
29
+ export class FakeClock {
30
+ current = 0;
31
+ nextId = 1;
32
+ timers = new Map();
33
+ now() {
34
+ return this.current;
35
+ }
36
+ setTimeout(fn, ms) {
37
+ const id = this.nextId++;
38
+ this.timers.set(id, { id, fireAt: this.current + Math.max(0, ms), fn });
39
+ return id;
40
+ }
41
+ clearTimeout(handle) {
42
+ if (typeof handle === "number")
43
+ this.timers.delete(handle);
44
+ }
45
+ /**
46
+ * Advance virtual time by `ms`, firing every timer whose deadline falls in
47
+ * the interval (in deadline order). Timers scheduled by a firing callback are
48
+ * honored within the same advance if their new deadline is still within the
49
+ * advanced window.
50
+ */
51
+ advance(ms) {
52
+ const target = this.current + ms;
53
+ while (true) {
54
+ const due = [...this.timers.values()]
55
+ .filter((t) => t.fireAt <= target)
56
+ .sort((a, b) => a.fireAt - b.fireAt || a.id - b.id);
57
+ if (due.length === 0)
58
+ break;
59
+ const next = due[0];
60
+ this.timers.delete(next.id);
61
+ this.current = Math.max(this.current, next.fireAt);
62
+ next.fn();
63
+ }
64
+ this.current = target;
65
+ }
66
+ /** Number of timers still pending — a leak check for tests. */
67
+ pendingTimerCount() {
68
+ return this.timers.size;
69
+ }
70
+ }
71
+ /**
72
+ * The reusable debounce + coalesce + concurrency-guard core of event-driven
73
+ * push (US-001 seam).
74
+ *
75
+ * It is intentionally decoupled from chokidar and from S3: callers feed it
76
+ * synthetic or real change notifications via {@link notifyChange}, and it
77
+ * invokes the injected `push` fn at most once per quiet window. A push that is
78
+ * still in flight is never overlapped — a change arriving mid-push is collapsed
79
+ * and re-triggers a single follow-up pass after the next quiet window.
80
+ *
81
+ * US-002 wires a real chokidar watcher's events into {@link notifyChange};
82
+ * US-003 supplies the targeted-push `push` fn. Tests drive it directly with a
83
+ * {@link FakeClock} and a spy `push` fn (no real S3, no 10-minute sleep).
84
+ */
85
+ export class WatchPushDriver {
86
+ debounceMs;
87
+ clock;
88
+ push;
89
+ timer = null;
90
+ pushing = false;
91
+ pendingWhilePushing = false;
92
+ disposed = false;
93
+ constructor(opts) {
94
+ this.debounceMs = opts.debounceMs ?? DEBOUNCE_MS;
95
+ this.clock = opts.clock ?? systemClock;
96
+ this.push = opts.push;
97
+ }
98
+ /**
99
+ * Register a change. Resets the quiet window; the push fires `debounceMs`
100
+ * after the LAST change in a burst, coalescing the burst to one push.
101
+ */
102
+ notifyChange() {
103
+ if (this.disposed)
104
+ return;
105
+ if (this.timer !== null) {
106
+ this.clock.clearTimeout(this.timer);
107
+ this.timer = null;
108
+ }
109
+ this.timer = this.clock.setTimeout(() => {
110
+ this.timer = null;
111
+ void this.fire();
112
+ }, this.debounceMs);
113
+ }
114
+ async fire() {
115
+ if (this.disposed)
116
+ return;
117
+ if (this.pushing) {
118
+ // A pass is in flight — collapse this trigger; re-arm after it settles.
119
+ this.pendingWhilePushing = true;
120
+ return;
121
+ }
122
+ this.pushing = true;
123
+ try {
124
+ await this.push();
125
+ }
126
+ finally {
127
+ this.pushing = false;
128
+ if (this.pendingWhilePushing && !this.disposed) {
129
+ this.pendingWhilePushing = false;
130
+ // Re-arm a fresh quiet window for the change(s) seen mid-push.
131
+ this.notifyChange();
132
+ }
133
+ }
134
+ }
135
+ /** True while a push pass is executing. */
136
+ isPushing() {
137
+ return this.pushing;
138
+ }
139
+ /** Cancel any pending debounce timer; idempotent. Leaves no timers behind. */
140
+ dispose() {
141
+ this.disposed = true;
142
+ if (this.timer !== null) {
143
+ this.clock.clearTimeout(this.timer);
144
+ this.timer = null;
145
+ }
146
+ this.pendingWhilePushing = false;
147
+ }
148
+ }
16
149
  export class SyncWatcher {
17
150
  watcher = null;
18
151
  hqRoot;
@@ -118,4 +251,169 @@ export class SyncWatcher {
118
251
  }
119
252
  }
120
253
  }
254
+ /**
255
+ * Build the composite emit-decision predicate. Returns true when a change to
256
+ * `absolutePath` SHOULD wake the watcher (i.e. it survives every exclusion
257
+ * layer). Pure and chokidar-free so the matching logic is unit-testable
258
+ * directly.
259
+ *
260
+ * @param hqRoot sync root (== personal-vault root in personalMode).
261
+ * @param personalMode when true, also applies the personal-vault default
262
+ * exclusions and the excluded-top-level buckets.
263
+ */
264
+ export function createWatchPathFilter(hqRoot, personalMode = false) {
265
+ const ignoreFilter = createIgnoreFilter(hqRoot);
266
+ const excludedTopLevel = new Set(PERSONAL_VAULT_EXCLUDED_TOP_LEVEL);
267
+ return (absolutePath, isDir = false) => {
268
+ const rel = path.relative(hqRoot, absolutePath).split(path.sep).join("/");
269
+ // The root itself, or anything outside it, is never an emit target.
270
+ if (rel === "" || rel.startsWith(".."))
271
+ return false;
272
+ // Layer 1: shared ignore stack (.hqignore/.gitignore/DEFAULT_IGNORES).
273
+ // createIgnoreFilter returns true = "sync this"; false = "ignored".
274
+ if (!ignoreFilter(absolutePath, isDir))
275
+ return false;
276
+ if (personalMode) {
277
+ // Layer 3: excluded top-level buckets (.git/companies/repos/workspace).
278
+ const topLevel = rel.split("/")[0];
279
+ if (excludedTopLevel.has(topLevel))
280
+ return false;
281
+ // Layer 2: personal-vault default exclusions (.env/output/.beads/…).
282
+ if (isPersonalVaultExcluded(rel, isDir))
283
+ return false;
284
+ }
285
+ return true;
286
+ };
287
+ }
288
+ /**
289
+ * Chokidar-backed file watcher that emits a single debounced `changed` signal
290
+ * after a {@link debounceMs} quiet window, coalescing bursts. It honors the
291
+ * full exclusion stack via {@link createWatchPathFilter}, so excluded paths
292
+ * (`.env`, `output/`, `.git/`, `companies/` in personalMode, …) never emit.
293
+ *
294
+ * Lifecycle: {@link start} (idempotent), {@link stop}, {@link dispose}. Stop
295
+ * closes the chokidar watcher (releasing fds) and cancels any pending debounce
296
+ * timer. dispose() is stop() + permanent shutdown.
297
+ */
298
+ export class TreeWatcher {
299
+ hqRoot;
300
+ debounceMs;
301
+ clock;
302
+ shouldEmit;
303
+ watcher = null;
304
+ timer = null;
305
+ listeners = new Set();
306
+ disposed = false;
307
+ constructor(opts) {
308
+ this.hqRoot = opts.hqRoot;
309
+ this.debounceMs = opts.debounceMs ?? DEBOUNCE_MS;
310
+ this.clock = opts.clock ?? systemClock;
311
+ this.shouldEmit =
312
+ opts.pathFilter ?? createWatchPathFilter(opts.hqRoot, opts.personalMode ?? false);
313
+ }
314
+ /** Register a debounced-`changed` listener. Returns an unsubscribe fn. */
315
+ onChange(listener) {
316
+ this.listeners.add(listener);
317
+ return () => this.listeners.delete(listener);
318
+ }
319
+ /**
320
+ * Begin watching. Idempotent — a second call while already running is a
321
+ * no-op (no second chokidar instance, no leaked fds).
322
+ */
323
+ start() {
324
+ if (this.disposed || this.watcher)
325
+ return;
326
+ this.watcher = watch(this.hqRoot, {
327
+ // chokidar passes a stats hint so dir-only gitignore patterns (`foo/`)
328
+ // match directory entries during the descent decision. `ignored`
329
+ // returns true to SKIP, so invert the emit predicate. The watched root
330
+ // itself must NEVER be ignored (shouldEmit returns false for it because
331
+ // it is not a valid emit target), or chokidar tears down the whole watch.
332
+ ignored: (filePath, stats) => {
333
+ if (path.resolve(filePath) === path.resolve(this.hqRoot))
334
+ return false;
335
+ return !this.shouldEmit(filePath, stats?.isDirectory());
336
+ },
337
+ persistent: true,
338
+ ignoreInitial: true,
339
+ awaitWriteFinish: {
340
+ stabilityThreshold: 500,
341
+ pollInterval: 100,
342
+ },
343
+ });
344
+ const onEvent = (absolutePath) => this.handleEvent(absolutePath);
345
+ this.watcher
346
+ .on("add", onEvent)
347
+ .on("change", onEvent)
348
+ .on("unlink", onEvent)
349
+ .on("addDir", onEvent)
350
+ .on("unlinkDir", onEvent)
351
+ .on("error", (err) => console.error("TreeWatcher error:", err));
352
+ }
353
+ /**
354
+ * Test/seam entry point: feed a raw filesystem path as if chokidar reported
355
+ * it. Applies the emit filter then arms the debounce. Real chokidar events
356
+ * route through here too.
357
+ */
358
+ handleEvent(absolutePath) {
359
+ if (this.disposed)
360
+ return;
361
+ // Defensive: chokidar's `ignored` already filtered, but a path that slips
362
+ // through (or a synthetic test event) is re-checked here.
363
+ if (!this.shouldEmit(absolutePath, false))
364
+ return;
365
+ this.arm();
366
+ }
367
+ arm() {
368
+ if (this.timer !== null) {
369
+ this.clock.clearTimeout(this.timer);
370
+ this.timer = null;
371
+ }
372
+ this.timer = this.clock.setTimeout(() => {
373
+ this.timer = null;
374
+ this.emit();
375
+ }, this.debounceMs);
376
+ }
377
+ emit() {
378
+ if (this.disposed)
379
+ return;
380
+ for (const l of this.listeners) {
381
+ try {
382
+ l();
383
+ }
384
+ catch (err) {
385
+ console.error("TreeWatcher listener error:", err);
386
+ }
387
+ }
388
+ }
389
+ /** True while the chokidar watcher is active. */
390
+ isWatching() {
391
+ return this.watcher !== null;
392
+ }
393
+ /** Number of pending debounce timers — a leak check for tests. */
394
+ pendingTimerCount() {
395
+ return this.timer === null ? 0 : 1;
396
+ }
397
+ /**
398
+ * Stop watching: close the chokidar watcher (releasing fds) and cancel any
399
+ * pending debounce timer. Idempotent. The instance can be restarted with
400
+ * {@link start} unless {@link dispose} was called.
401
+ */
402
+ stop() {
403
+ if (this.timer !== null) {
404
+ this.clock.clearTimeout(this.timer);
405
+ this.timer = null;
406
+ }
407
+ if (this.watcher) {
408
+ void this.watcher.close();
409
+ this.watcher = null;
410
+ }
411
+ }
412
+ /** Permanent shutdown: stop() + drop listeners; further events are no-ops. */
413
+ dispose() {
414
+ this.stop();
415
+ this.disposed = true;
416
+ this.listeners.clear();
417
+ }
418
+ }
121
419
  //# sourceMappingURL=watcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=watcher.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.test.d.ts","sourceRoot":"","sources":["../src/watcher.test.ts"],"names":[],"mappings":""}