Skip to content

feat(watcher): merge @eggjs/watcher plugin into monorepo#5497

Merged
fengmk2 merged 4 commits intonextfrom
plugin-watcher
Sep 15, 2025
Merged

feat(watcher): merge @eggjs/watcher plugin into monorepo#5497
fengmk2 merged 4 commits intonextfrom
plugin-watcher

Conversation

@fengmk2
Copy link
Member

@fengmk2 fengmk2 commented Sep 14, 2025

Move @eggjs/watcher plugin from separate repository to plugins/watcher. Configure for monorepo with workspace dependencies and standard tsdown build.

  • Add watcher plugin to plugins directory
  • Configure package.json with workspace and catalog dependencies
  • Add standard tsdown.config.ts following plugin conventions
  • Update test files to use vitest imports
  • Add vitest.config.ts for test configuration
  • Update root tsconfig.json references
  • Add camelcase to pnpm catalog dependencies
  • Document watcher plugin in CLAUDE.md

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Introduced a pluggable file-watcher plugin with default and development modes, exposing watch/unwatch on app and agent. Supports custom event sources via configuration.
  • Documentation
    • Added comprehensive README, license, and changelog for the watcher plugin. Updated project docs to reference the development watcher.
  • Tests
    • Added extensive unit and integration tests covering default, custom, fuzzy matching, and development cluster scenarios.
  • Refactor
    • Improved type-safety; watcher config is now optional with updated typings.
  • Chores
    • Typecheck now pre-cleans before running. Adjusted workspace dependency resolution and project references.

Move @eggjs/watcher plugin from separate repository to plugins/watcher.
Configure for monorepo with workspace dependencies and standard tsdown build.

- Add watcher plugin to plugins directory
- Configure package.json with workspace and catalog dependencies
- Add standard tsdown.config.ts following plugin conventions
- Update test files to use vitest imports
- Add vitest.config.ts for test configuration
- Update root tsconfig.json references
- Add camelcase to pnpm catalog dependencies
- Document watcher plugin in CLAUDE.md

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 14, 2025

Walkthrough

Introduces a new @eggjs/watcher plugin with boot lifecycle, event sources (default and development), configuration, packaging, and tests. Integrates typed watcher access into development and mock agents. Adjusts Egg typings to make watcher config optional. Updates scripts to run clean before typecheck and workspace/catalog settings.

Changes

Cohort / File(s) Summary of changes
Repo scripts & workspace
package.json, pnpm-workspace.yaml, tsconfig.json
Typecheck now runs pre-clean; workspace catalog updated (remove @eggjs/watcher, add camelcase); add TS project reference for watcher plugin.
Egg package dependency & types
packages/egg/package.json, packages/egg/test/index.test-d.ts
Switch dependency @eggjs/watcher to workspace:*; update typings/tests to make config.watcher and some fields optional (`string
Development plugin integration
plugins/development/src/agent.ts, CLAUDE.md
Replace any-cast watcher access with typed agent.watcher; document watcher plugin in CLAUDE.md.
Mock agent typing fix
packages/mock/src/lib/parallel/agent.ts
Replace any-cast messenger access with typed agent.messenger.
Watcher plugin: packaging & docs
plugins/watcher/package.json, plugins/watcher/README.md, plugins/watcher/CHANGELOG.md, plugins/watcher/LICENSE, plugins/watcher/tsconfig.json, plugins/watcher/tsdown.config.ts, plugins/watcher/vitest.config.ts
Add new plugin package, exports map, build/test configs, license, changelog, and README.
Watcher plugin: entrypoints
plugins/watcher/src/index.ts, plugins/watcher/src/agent.ts, plugins/watcher/src/app.ts
Public re-exports; default-export Boot via app/agent entry modules.
Watcher plugin: config
plugins/watcher/src/config/config.default.ts, .../config.local.ts, .../config.unittest.ts
Provide default/local/unittest watcher configurations (type and eventSource paths).
Watcher plugin: core types & utils
plugins/watcher/src/lib/types.ts, plugins/watcher/src/lib/utils.ts
Define WatcherConfig, ChangeInfo, Egg module augmentation; add path helpers.
Watcher plugin: boot & engine
plugins/watcher/src/lib/boot.ts, plugins/watcher/src/lib/watcher.ts
Implement lifecycle Boot wiring app/agent.watcher; implement pluggable Watcher with watch API and event propagation.
Watcher plugin: event sources
plugins/watcher/src/lib/event-sources/base.ts, .../default.ts, .../development.ts, .../index.ts
Add BaseEventSource, a no-op default source, a fs.watch-based development source, and index re-exports.
Watcher plugin: tests
plugins/watcher/test/*.ts, plugins/watcher/test/fixtures/apps/*
Add unit/integration tests, utilities, and multiple app fixtures (default, custom event sources, development app) with routes/agent scripts and sample files.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer
  participant App as Egg App
  participant Boot as Watcher Boot
  participant Watcher as Watcher
  participant ES as EventSource (development)
  participant Router as App Router
  Dev->>App: start (env=local/unittest)
  App->>Boot: construct
  Boot->>Watcher: new Watcher(config)
  Note over Watcher,ES: Select event source by watcher.type
  Watcher->>ES: instantiate + subscribe(events)
  Boot->>App: attach app.watcher
  Boot->>App: didLoad() -> watcher.ready()

  Dev->>Router: GET /app-watch
  Router->>Watcher: watch([paths], listener)
  ES-->>Watcher: change/info/warn/error events (async)
  Watcher-->>Router: listener(ChangeInfo)
  Note over Router: Updates counters, logs

  Dev->>Router: GET /app-msg
  Router-->>Dev: count
Loading
sequenceDiagram
  autonumber
  actor Dev as Developer
  participant NPM as npm/pnpm
  Dev->>NPM: pnpm run typecheck
  NPM->>NPM: run "clean"
  alt clean succeeds
    NPM->>NPM: run "-r typecheck"
  else clean fails
    NPM-->>Dev: exit (typecheck not executed)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

I twitch my ears at files that change,
Tip-tap, I watch each path and range. 🐇
From default doze to dev awake,
I catch the flutter, ripple, quake.
Clean, then check—scripts hop in line—
Logs go thump-thump: everything’s fine. 🌙✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title accurately and concisely summarizes the primary change: merging the @eggjs/watcher plugin into the monorepo. The changeset adds a new plugins/watcher package, updates root and package manifests, TS config references, tests, and docs which align with the title. The phrasing is specific, clear, and appropriate for repository history.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch plugin-watcher

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@fengmk2 fengmk2 mentioned this pull request Sep 14, 2025
42 tasks
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Sep 14, 2025

Deploying egg with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7e46eac
Status:🚫  Build failed.

View logs

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Sep 14, 2025

Deploying egg-v3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7e46eac
Status:🚫  Build failed.

View logs

@socket-security
Copy link

socket-security bot commented Sep 14, 2025

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

@codecov
Copy link

codecov bot commented Sep 14, 2025

Codecov Report

❌ Patch coverage is 83.18584% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.34%. Comparing base (4064ffa) to head (7e46eac).
⚠️ Report is 1 commits behind head on next.

Files with missing lines Patch % Lines
...ugins/watcher/src/lib/event-sources/development.ts 73.17% 9 Missing and 2 partials ⚠️
plugins/watcher/src/lib/event-sources/default.ts 77.77% 2 Missing ⚠️
plugins/watcher/src/lib/utils.ts 71.42% 2 Missing ⚠️
plugins/watcher/src/lib/watcher.ts 95.45% 2 Missing ⚠️
packages/mock/src/lib/parallel/agent.ts 0.00% 1 Missing ⚠️
plugins/watcher/src/lib/boot.ts 90.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             next    #5497      +/-   ##
==========================================
+ Coverage   76.20%   76.34%   +0.14%     
==========================================
  Files         108      113       +5     
  Lines        5774     5885     +111     
  Branches     1215     1233      +18     
==========================================
+ Hits         4400     4493      +93     
- Misses       1199     1215      +16     
- Partials      175      177       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@fengmk2 fengmk2 marked this pull request as ready for review September 14, 2025 15:22
@fengmk2 fengmk2 requested a review from Copilot September 14, 2025 15:22
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR merges the @eggjs/watcher plugin from a separate repository into the main Eggjs monorepo under plugins/watcher. The watcher plugin provides file system watching capabilities and is a core component used by the development plugin for auto-reload functionality.

  • Move complete watcher plugin source code, tests, and documentation from external repo
  • Configure plugin for monorepo with workspace dependencies and standardized build tooling
  • Update dependent packages to use workspace reference instead of catalog reference

Reviewed Changes

Copilot reviewed 57 out of 60 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pnpm-workspace.yaml Remove external @eggjs/watcher from catalog and add camelcase dependency
plugins/watcher/* Complete watcher plugin implementation with TypeScript source, tests, configs
packages/egg/package.json Switch @eggjs/watcher dependency from catalog to workspace reference
plugins/development/src/agent.ts Remove FIXME comment and type casting after watcher merge
packages/mock/src/lib/parallel/agent.ts Remove unnecessary type casting
packages/egg/test/index.test-d.ts Update type expectations to handle optional watcher config
package.json Update typecheck script to clean before running
CLAUDE.md Document the merged watcher plugin
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 19

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugins/development/src/agent.ts (1)

80-99: Guard against missing watcher to avoid runtime crash.

If the watcher plugin isn’t enabled/booted, agent.watcher will be undefined and this throws at runtime. Add a null‑guard and bail early.

Apply this diff:

-    agent.watcher.watch(watchDirs, (info: any) => {
+    if (!agent.watcher) {
+      logger.warn('[agent:development] watcher plugin not enabled; skip reload watching');
+      return;
+    }
+    agent.watcher.watch(watchDirs, (info: any) => {
🧹 Nitpick comments (22)
packages/mock/src/lib/parallel/agent.ts (2)

71-75: Tiny typing improvement: give msg an explicit type

Helps catch action/data shape drift at compile time.

-    const msg = {
+    const msg: { action: 'egg-ready'; data: MockApplicationOptions } = {
       action: 'egg-ready',
       data: this.options,
     };

79-91: Clear cached listener sets after binding to free memory

After re-binding, the sets aren’t used again; clearing avoids holding unnecessary array refs.

   #bindEvents() {
     debug('bind cache events to agent');
     for (const args of this.#initOnListeners) {
       debug('on(%s), use cache and pass to agent', args);
       this._instance.on(args[0], args[1]);
       this.removeListener(args[0], args[1]);
     }
     for (const args of this.#initOnceListeners) {
       debug('once(%s), use cache and pass to agent', args);
       this._instance.once(args[0], args[1]);
       this.removeListener(args[0], args[1]);
     }
+    this.#initOnListeners.clear();
+    this.#initOnceListeners.clear();
   }
plugins/development/src/agent.ts (1)

41-56: Optional: skip setting up watch when reload is disabled.

You check reloadOnDebug inside the callback; we can avoid attaching watchers at all for lower overhead.

Apply this diff:

-    // watch dirs to reload worker, will debounce 200ms
+    // watch dirs to reload worker, will debounce 200ms
+    if (!config.reloadOnDebug) return;

Also applies to: 80-99

package.json (1)

33-33: Pre‑clean before typecheck is fine; expand clean to cover plugins’ dists.

Your root clean removes only packages/**/dist. Since watcher lives under plugins/, include that too.

Outside this hunk, update scripts.clean to:

"clean": "pnpm -r run clean && rimraf packages/**/dist plugins/**/dist"
plugins/watcher/test/fixtures/apps/watcher-type-default/config/config.unittest.js (1)

1-5: Fixture looks correct; consider adding 'use strict' for consistency.

Matches the default watcher type expected by tests. Optional: add 'use strict' to align with other fixtures (e.g., fuzzy custom).

+'use strict';
+
 exports.watcher = {
   type: 'default',
 };
 
 exports.keys = 'testkey';
plugins/watcher/tsdown.config.ts (1)

1-10: Tsdown config aligns with the standard; verify parity with plugins/development template.

Looks good: unbundled ESM, DTS, devExports. Please double‑check against plugins/development/tsdown.config.ts to keep all knobs in sync (platform/target/sourcemap, if the template has them).

 export default defineConfig({
   entry: 'src/**/*.ts',
   unbundle: true,
   dts: true,
   exports: {
     devExports: true,
   },
+  // Optional: keep parity with template if used there
+  // platform: 'node',
+  // target: 'node18',
+  // sourcemap: true,
 });
plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/package.json (1)

1-9: Minimal test plugin manifest is fine; mark private to avoid accidental publish.

Add "private": true to prevent accidental release from fixtures.

 {
   "name": "egg-watcher-custom",
+  "private": true,
   "eggPlugin": {
     "name": "watcherCustom",
     "dep": [
       "watcher"
     ]
   }
 }
packages/egg/test/index.test-d.ts (1)

47-48: Optional chaining on nested field: consider guarding eventSources as well (depends on typings).

If eventSources itself can be absent, prefer chaining there too; otherwise current assertion is fine. Please confirm with packages/egg/src/index.d.ts.

-expectType<string | undefined>(app.config.watcher?.eventSources.default);
+expectType<string | undefined>(app.config.watcher?.eventSources?.default);
plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/custom.js (2)

10-19: Make watch() idempotent to avoid timer leaks if called multiple times

If watch() is called repeatedly without an intervening unwatch(), multiple intervals will accumulate and emit duplicate change events.

Apply this minimal guard:

   watch(path) {
     this.emit('info', 'info12345');
     this.emit('warn', 'warn12345');
-    this._h = setInterval(() => {
+    if (this._h) clearInterval(this._h);
+    this._h = setInterval(() => {
       this.emit('change', {
         path,
         foo: this._options.foo,
       });
     }, 1000);
   }

21-25: Reset handle after clearInterval for correctness

After clearing, null out the handle so subsequent watch() calls can reliably detect prior state.

   unwatch() {
     if (this._h) {
       clearInterval(this._h);
+      this._h = null;
     }
   }
plugins/watcher/CHANGELOG.md (1)

1-8: Silence markdownlint for imported historical changelog formatting

This file preserves upstream history and intentionally mixes styles. Add a file-local disable to keep CI green without rewriting history.

 # Changelog
+
+<!-- markdownlint-disable MD003 MD004 MD007 MD010 MD034 MD036 -->
plugins/watcher/README.md (2)

55-55: Update the development mode link to the monorepo path

The current link points to the old repository. Use a relative link so it stays valid after moves/renames.

-There's a built-in [development mode](https://github.com/eggjs/watcher/blob/master/src/lib/event-sources/development.ts) which works in local(env is `local`). Once files on disk is modified it will emit a `change` event immediately.
+There's a built-in [development mode](./src/lib/event-sources/development.ts) which works in local (env is `local`). Once files on disk are modified it will emit a `change` event immediately.

76-83: Document optional isDirectory flag in change payload

Recent fixes added isDirectory; reflecting this improves DX and test expectations.

     // when aware of any change, emit a `change` event
-    // with an info object containing `path` property
-    // specifying the changed directory or file.
+    // with an info object containing `path` and optionally
+    // `isDirectory: boolean`, specifying the changed entry.
     this._h = setInterval(() => {
       this.emit('change', { path });
     }, 1000);
plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/package.json (1)

1-9: Mark fixture package as private to avoid accidental publish

File: plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/package.json

 {
   "name": "egg-watcher-custom",
+  "private": true,
   "eggPlugin": {
     "name": "watcherCustom",
     "dep": [
       "watcher"
     ]
   }
 }
plugins/watcher/src/config/config.default.ts (1)

1-23: Optional: avoid repeated getSourceDirname() calls.

Minor readability win; not required.

 export default {
   /**
    * watcher options
    */
-  watcher: {
+  watcher: {
+    // const base = path.join(getSourceDirname(), 'lib', 'event-sources');
+    // eventSources: { default: path.join(base, 'default.js'), development: path.join(base, 'development.js') }
   ...
plugins/watcher/src/lib/event-sources/default.ts (1)

7-13: Minor: prefer queueMicrotask over setImmediate for same‑turn deferral.

Not required, but slightly lighter when only ordering is needed.

-    setImmediate(() =>
+    queueMicrotask(() =>
       this.emit(
         'info',
         '[@eggjs/watcher] defaultEventSource watcher will NOT take effect'
       )
     );
plugins/watcher/test/development.test.ts (1)

56-57: Replace deprecated rmdirSync + redundant rmSync with a single recursive rmSync; avoid hard-coded waits

File: plugins/watcher/test/development.test.ts (lines 56–57)

-    fs.rmdirSync(file_path4);
-    fs.rmSync(file_path4, { force: true });
+    fs.rmSync(file_path4, { recursive: true, force: true });
  • For watcher flakiness: do not blindly increase 100ms→200ms; Vitest docs/community don’t recommend hard waits — prefer proper async synchronization (await file ops, use wait-for/poll helpers) or Vitest watch options (forceRerunTriggers / watchTriggerPatterns).
plugins/watcher/test/fixtures/apps/watcher-development-app/agent.js (1)

16-24: Guard unwatch: Watcher.unwatch is not implemented yet

Calling agent.watcher.unwatch will throw if exposed watcher lacks this API (currently commented out).

-  agent.messenger.on('agent-unwatch', function () {
-    agent.watcher.unwatch([file_path1, dir_path], listener);
-    agent.messenger.broadcast('agent-unwatch-success', 'agent unwatch success');
-  });
+  agent.messenger.on('agent-unwatch', function () {
+    if (typeof agent.watcher.unwatch === 'function') {
+      agent.watcher.unwatch([file_path1, dir_path], listener);
+      agent.messenger.broadcast('agent-unwatch-success', 'agent unwatch success');
+    } else {
+      agent.messenger.broadcast('agent-unwatch-success', 'agent unwatch skipped (not supported)');
+    }
+  });
plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/custom.js (1)

13-19: Avoid multiple intervals if watch() is called more than once

Clear any existing timer before creating a new one to prevent leaks.

   watch(path) {
     this.emit('info', 'info12345');
     this.emit('warn', 'warn12345');
+    if (this._h) clearInterval(this._h);
     this._h = setInterval(() => {
       this.emit('fuzzy-change', {
         path: '/home/admin',
         foo: this._options.foo,
       });
     }, 1000);
   }
plugins/watcher/test/development_cluster.test.ts (2)

53-58: Remove redundant rmdir; use rmSync recursive once

Simpler and avoids deprecated rmdir usage.

     fs.writeFileSync(file_path2, 'aaa');
     fs.writeFileSync(file_path3, 'aaa');
-    fs.mkdirSync(file_path4, { recursive: true });
-    fs.rmdirSync(file_path4);
-    fs.rmSync(file_path4, { force: true });
+    fs.mkdirSync(file_path4, { recursive: true });
+    fs.rmSync(file_path4, { recursive: true, force: true });

43-46: Reduce flakiness: increase waits slightly

100ms is tight on CI; consider 200–300ms.

Also applies to: 58-58, 97-99

plugins/watcher/src/lib/event-sources/development.ts (1)

54-56: Propagate fs.watch errors via warn events

Surface watcher errors instead of failing silently.

-      // 保存 handler,用于解除监听
+      // 监听底层错误并透出
+      handler.on('error', err => {
+        this.emit(
+          'warn',
+          '[@eggjs/watcher:DevelopmentEventSource] fs.watch error on %o: %s',
+          file,
+          err
+        );
+      });
+      // 保存 handler,用于解除监听
       this.#fileWatching.set(file, handler);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4064ffa and 7e46eac.

⛔ Files ignored due to path filters (2)
  • plugins/watcher/test/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (57)
  • CLAUDE.md (1 hunks)
  • package.json (1 hunks)
  • packages/egg/package.json (1 hunks)
  • packages/egg/test/index.test-d.ts (1 hunks)
  • packages/mock/src/lib/parallel/agent.ts (1 hunks)
  • plugins/development/src/agent.ts (1 hunks)
  • plugins/watcher/CHANGELOG.md (1 hunks)
  • plugins/watcher/LICENSE (1 hunks)
  • plugins/watcher/README.md (1 hunks)
  • plugins/watcher/package.json (1 hunks)
  • plugins/watcher/src/agent.ts (1 hunks)
  • plugins/watcher/src/app.ts (1 hunks)
  • plugins/watcher/src/config/config.default.ts (1 hunks)
  • plugins/watcher/src/config/config.local.ts (1 hunks)
  • plugins/watcher/src/config/config.unittest.ts (1 hunks)
  • plugins/watcher/src/index.ts (1 hunks)
  • plugins/watcher/src/lib/boot.ts (1 hunks)
  • plugins/watcher/src/lib/event-sources/base.ts (1 hunks)
  • plugins/watcher/src/lib/event-sources/default.ts (1 hunks)
  • plugins/watcher/src/lib/event-sources/development.ts (1 hunks)
  • plugins/watcher/src/lib/event-sources/index.ts (1 hunks)
  • plugins/watcher/src/lib/types.ts (1 hunks)
  • plugins/watcher/src/lib/utils.ts (1 hunks)
  • plugins/watcher/src/lib/watcher.ts (1 hunks)
  • plugins/watcher/test/development.test.ts (1 hunks)
  • plugins/watcher/test/development_cluster.test.ts (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/config/config.unittest.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/config/plugin.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/package.json (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/config/config.default.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/custom.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/package.json (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/config/config.unittest.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/config/plugin.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/package.json (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/config/config.default.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/custom.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/package.json (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-development-app/agent.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-development-app/app/router.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-development-app/config/config.unittest.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-development-app/package.json (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-development-app/tmp-agent.txt (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-development-app/tmp.txt (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-development-app/tmp/t1/t2/t3/t4/tmp.txt (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-development-app/tmp/tmp.txt (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-type-default/app.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-type-default/config/config.unittest.js (1 hunks)
  • plugins/watcher/test/fixtures/apps/watcher-type-default/package.json (1 hunks)
  • plugins/watcher/test/index.test.ts (1 hunks)
  • plugins/watcher/test/utils.ts (1 hunks)
  • plugins/watcher/test/watcher.test.ts (1 hunks)
  • plugins/watcher/tsconfig.json (1 hunks)
  • plugins/watcher/tsdown.config.ts (1 hunks)
  • plugins/watcher/vitest.config.ts (1 hunks)
  • pnpm-workspace.yaml (1 hunks)
  • tsconfig.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (13)
plugins/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place all Egg framework plugins under the plugins/ directory

Files:

  • plugins/watcher/test/utils.ts
  • plugins/watcher/test/fixtures/apps/watcher-development-app/tmp/t1/t2/t3/t4/tmp.txt
  • plugins/watcher/test/fixtures/apps/watcher-development-app/tmp/tmp.txt
  • plugins/watcher/LICENSE
  • plugins/watcher/test/index.test.ts
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/config/config.default.js
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/config/plugin.js
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/config/config.default.js
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/custom.js
  • plugins/watcher/test/fixtures/apps/watcher-development-app/tmp-agent.txt
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/package.json
  • plugins/watcher/test/fixtures/apps/watcher-development-app/package.json
  • plugins/watcher/test/fixtures/apps/watcher-type-default/app.js
  • plugins/watcher/tsconfig.json
  • plugins/watcher/test/fixtures/apps/watcher-type-default/package.json
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/package.json
  • plugins/watcher/test/fixtures/apps/watcher-development-app/config/config.unittest.js
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/custom.js
  • plugins/watcher/test/fixtures/apps/watcher-development-app/app/router.js
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/config/plugin.js
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/config/config.unittest.js
  • plugins/watcher/src/lib/event-sources/base.ts
  • plugins/watcher/test/development.test.ts
  • plugins/watcher/src/agent.ts
  • plugins/watcher/src/index.ts
  • plugins/watcher/src/lib/event-sources/index.ts
  • plugins/watcher/README.md
  • plugins/watcher/test/fixtures/apps/watcher-development-app/agent.js
  • plugins/watcher/src/app.ts
  • plugins/watcher/test/watcher.test.ts
  • plugins/watcher/src/config/config.unittest.ts
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/config/config.unittest.js
  • plugins/watcher/src/lib/event-sources/default.ts
  • plugins/watcher/test/fixtures/apps/watcher-development-app/tmp.txt
  • plugins/watcher/src/lib/boot.ts
  • plugins/watcher/test/fixtures/apps/watcher-type-default/config/config.unittest.js
  • plugins/watcher/src/lib/utils.ts
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/package.json
  • plugins/watcher/test/development_cluster.test.ts
  • plugins/watcher/src/lib/types.ts
  • plugins/watcher/src/config/config.default.ts
  • plugins/watcher/src/config/config.local.ts
  • plugins/watcher/tsdown.config.ts
  • plugins/development/src/agent.ts
  • plugins/watcher/vitest.config.ts
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/package.json
  • plugins/watcher/src/lib/watcher.ts
  • plugins/watcher/package.json
  • plugins/watcher/src/lib/event-sources/development.ts
  • plugins/watcher/CHANGELOG.md
packages/**/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use TypeScript for all source files in packages (no JavaScript source files)

Files:

  • packages/mock/src/lib/parallel/agent.ts
{packages,plugins}/**/test/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

{packages,plugins}/**/test/**/*.test.ts: Vitest test files should follow the naming pattern test/**/*.test.ts
In Vitest tests, import test functions from vitest and use Node.js built-in assert for assertions

Files:

  • plugins/watcher/test/index.test.ts
  • plugins/watcher/test/development.test.ts
  • plugins/watcher/test/watcher.test.ts
  • plugins/watcher/test/development_cluster.test.ts
plugins/**/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

plugins/**/package.json: Plugin package.json must include eggPlugin configuration
Plugin package.json must set type: module and define exports that point to TypeScript sources (e.g., ./src/index.ts, ./src/agent.ts, ./src/app.ts)
Plugin package.json must define publishConfig.exports mirroring exports to compiled dist/*.js and include files: ["dist"]
Plugin package.json must include scripts: build (tsdown), clean (rimraf dist), and prepublishOnly (npm run build)

Files:

  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/package.json
  • plugins/watcher/test/fixtures/apps/watcher-development-app/package.json
  • plugins/watcher/test/fixtures/apps/watcher-type-default/package.json
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/package.json
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/package.json
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/package.json
  • plugins/watcher/package.json
{packages,plugins,tools}/**/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

{packages,plugins,tools}/**/package.json: Use workspace:* for internal workspace dependencies
Use catalog: for external dependencies defined in pnpm-workspace.yaml

Files:

  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/package.json
  • plugins/watcher/test/fixtures/apps/watcher-development-app/package.json
  • plugins/watcher/test/fixtures/apps/watcher-type-default/package.json
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/package.json
  • packages/egg/package.json
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/package.json
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/package.json
  • plugins/watcher/package.json
{packages,plugins,tools}/**/tsconfig.json

📄 CodeRabbit inference engine (CLAUDE.md)

All sub-project tsconfig.json must extend the root tsconfig.json via "extends": "../../tsconfig.json" and include "baseUrl": "./"

Files:

  • plugins/watcher/tsconfig.json
packages/*/package.json

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use "workspace:*" for internal workspace dependencies in package.json

Files:

  • packages/egg/package.json
pnpm-workspace.yaml

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Define dependency versions via the catalog section in pnpm-workspace.yaml and reference them with "catalog:"

Add and manage external dependency versions in the catalog section of pnpm-workspace.yaml

Files:

  • pnpm-workspace.yaml
plugins/**/tsdown.config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

All future plugins must use the standard tsdown configuration template (based on plugins/development/tsdown.config.ts)

Files:

  • plugins/watcher/tsdown.config.ts
{packages,plugins,tools}/**/tsdown.config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Each sub-package should use tsdown for TypeScript builds with a tsdown.config.ts file

Files:

  • plugins/watcher/tsdown.config.ts
{packages,plugins}/**/vitest.config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Each package (except egg-bin) must include a vitest.config.ts for testing

Files:

  • plugins/watcher/vitest.config.ts
{tsconfig.json,packages/*/tsconfig.json}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Enable strict TypeScript mode across all packages

Files:

  • tsconfig.json
tsconfig.json

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Root tsconfig.json must include all packages in the references array

Files:

  • tsconfig.json
🧠 Learnings (22)
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to {packages,plugins}/**/test/**/*.test.ts : Vitest test files should follow the naming pattern test/**/*.test.ts

Applied to files:

  • plugins/watcher/test/index.test.ts
  • plugins/watcher/test/development.test.ts
  • plugins/watcher/test/watcher.test.ts
  • plugins/watcher/test/development_cluster.test.ts
  • plugins/watcher/vitest.config.ts
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to {packages,plugins}/**/test/**/*.test.ts : In Vitest tests, import test functions from vitest and use Node.js built-in assert for assertions

Applied to files:

  • plugins/watcher/test/index.test.ts
  • plugins/watcher/test/development.test.ts
  • plugins/watcher/test/watcher.test.ts
  • plugins/watcher/test/development_cluster.test.ts
📚 Learning: 2025-09-14T08:41:30.606Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.606Z
Learning: Applies to packages/**/test/**/*.test.ts : Name test files as test/**/*.test.ts and run them with Vitest

Applied to files:

  • plugins/watcher/test/index.test.ts
  • plugins/watcher/test/development.test.ts
  • plugins/watcher/test/watcher.test.ts
  • plugins/watcher/test/development_cluster.test.ts
  • plugins/watcher/vitest.config.ts
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to {packages,plugins}/**/vitest.config.ts : Each package (except egg-bin) must include a vitest.config.ts for testing

Applied to files:

  • plugins/watcher/test/index.test.ts
  • plugins/watcher/test/development.test.ts
  • plugins/watcher/test/watcher.test.ts
  • plugins/watcher/test/development_cluster.test.ts
  • plugins/watcher/vitest.config.ts
  • packages/egg/test/index.test-d.ts
📚 Learning: 2025-09-14T08:41:30.606Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.606Z
Learning: Applies to packages/**/test/**/*.test.ts : Use import { describe, it } from 'vitest' in tests

Applied to files:

  • plugins/watcher/test/index.test.ts
  • plugins/watcher/test/watcher.test.ts
  • plugins/watcher/vitest.config.ts
📚 Learning: 2025-09-14T08:41:30.606Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.606Z
Learning: Applies to packages/**/test/**/*.test.ts : Use Node.js built-in assert module for test assertions

Applied to files:

  • plugins/watcher/test/index.test.ts
  • plugins/watcher/test/watcher.test.ts
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to {packages,plugins,tools}/**/tsconfig.json : All sub-project tsconfig.json must extend the root tsconfig.json via "extends": "../../tsconfig.json" and include "baseUrl": "./"

Applied to files:

  • plugins/watcher/tsconfig.json
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to plugins/**/tsdown.config.ts : All future plugins must use the standard tsdown configuration template (based on plugins/development/tsdown.config.ts)

Applied to files:

  • plugins/watcher/tsconfig.json
  • plugins/watcher/tsdown.config.ts
📚 Learning: 2025-09-14T08:41:30.606Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.606Z
Learning: Applies to packages/*/tsconfig.json : All sub-project tsconfig.json files must extend from the root via "extends": "../../tsconfig.json"

Applied to files:

  • plugins/watcher/tsconfig.json
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to plugins/**/package.json : Plugin package.json must include eggPlugin configuration

Applied to files:

  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/package.json
  • packages/egg/package.json
  • plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/package.json
  • plugins/watcher/package.json
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to {packages,plugins,tools}/**/package.json : Use catalog: for external dependencies defined in pnpm-workspace.yaml

Applied to files:

  • packages/egg/package.json
  • pnpm-workspace.yaml
📚 Learning: 2025-09-14T08:41:30.606Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.606Z
Learning: Applies to packages/*/package.json : Use "workspace:*" for internal workspace dependencies in package.json

Applied to files:

  • packages/egg/package.json
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to {packages,plugins,tools}/**/package.json : Use workspace:* for internal workspace dependencies

Applied to files:

  • packages/egg/package.json
📚 Learning: 2025-09-14T08:41:30.606Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.606Z
Learning: Applies to pnpm-workspace.yaml : Define dependency versions via the catalog section in pnpm-workspace.yaml and reference them with "catalog:"

Applied to files:

  • pnpm-workspace.yaml
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to pnpm-workspace.yaml : Add and manage external dependency versions in the catalog section of pnpm-workspace.yaml

Applied to files:

  • pnpm-workspace.yaml
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to tools/egg-bin/test/**/*.test.ts : The egg-bin tool uses Mocha with test files named test/**/*.test.ts

Applied to files:

  • plugins/watcher/test/development.test.ts
  • plugins/watcher/test/watcher.test.ts
  • plugins/watcher/test/development_cluster.test.ts
  • packages/egg/test/index.test-d.ts
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to plugins/**/package.json : Plugin package.json must include scripts: build (tsdown), clean (rimraf dist), and prepublishOnly (npm run build)

Applied to files:

  • package.json
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to {packages,plugins,tools}/**/tsdown.config.ts : Each sub-package should use tsdown for TypeScript builds with a tsdown.config.ts file

Applied to files:

  • plugins/watcher/tsdown.config.ts
📚 Learning: 2025-09-14T08:41:30.606Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.606Z
Learning: Applies to packages/*/tsdown.config.ts : Each package must provide a tsdown.config.ts for unbundled ESM builds

Applied to files:

  • plugins/watcher/tsdown.config.ts
📚 Learning: 2025-09-14T08:41:30.606Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.606Z
Learning: Applies to tsconfig.json : Root tsconfig.json must include all packages in the references array

Applied to files:

  • tsconfig.json
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to plugins/**/package.json : Plugin package.json must define publishConfig.exports mirroring exports to compiled dist/*.js and include files: ["dist"]

Applied to files:

  • plugins/watcher/package.json
📚 Learning: 2025-09-14T14:28:36.647Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-14T14:28:36.647Z
Learning: Applies to plugins/**/package.json : Plugin package.json must set type: module and define exports that point to TypeScript sources (e.g., ./src/index.ts, ./src/agent.ts, ./src/app.ts)

Applied to files:

  • plugins/watcher/package.json
🧬 Code graph analysis (23)
plugins/watcher/test/utils.ts (3)
scripts/version.js (1)
  • __filename (9-9)
plugins/watcher/test/fixtures/apps/watcher-development-app/agent.js (1)
  • path (1-1)
plugins/watcher/test/fixtures/apps/watcher-development-app/app/router.js (1)
  • path (1-1)
plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/config/config.default.js (1)
plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/custom.js (1)
  • require (1-1)
plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/config/plugin.js (1)
plugins/watcher/test/fixtures/apps/watcher-custom-event-source/config/plugin.js (1)
  • path (1-1)
plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/config/config.default.js (1)
plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/custom.js (1)
  • require (1-1)
plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/custom.js (1)
plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/custom.js (1)
  • require (1-1)
plugins/watcher/test/fixtures/apps/watcher-development-app/app/router.js (2)
plugins/watcher/test/fixtures/apps/watcher-development-app/agent.js (3)
  • path (1-1)
  • file_path1 (3-3)
  • dir_path (4-4)
plugins/watcher/src/lib/watcher.ts (2)
  • info (101-117)
  • info (119-136)
plugins/watcher/test/fixtures/apps/watcher-custom-event-source/config/plugin.js (1)
plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/config/plugin.js (1)
  • path (3-3)
plugins/watcher/src/lib/event-sources/base.ts (1)
plugins/watcher/src/lib/event-sources/index.ts (1)
  • BaseEventSource (5-5)
plugins/watcher/test/development.test.ts (3)
plugins/watcher/test/fixtures/apps/watcher-development-app/agent.js (2)
  • file_path1 (3-3)
  • count (7-7)
plugins/watcher/test/fixtures/apps/watcher-development-app/app/router.js (1)
  • file_path1 (3-3)
plugins/watcher/test/utils.ts (1)
  • getFilePath (8-10)
plugins/watcher/src/agent.ts (1)
plugins/watcher/src/lib/boot.ts (1)
  • Boot (5-34)
plugins/watcher/test/fixtures/apps/watcher-development-app/agent.js (1)
plugins/watcher/test/fixtures/apps/watcher-development-app/app/router.js (3)
  • path (1-1)
  • file_path1 (3-3)
  • dir_path (4-4)
plugins/watcher/src/app.ts (1)
plugins/watcher/src/lib/boot.ts (1)
  • Boot (5-34)
plugins/watcher/test/watcher.test.ts (3)
plugins/watcher/test/utils.ts (1)
  • getFilePath (8-10)
plugins/watcher/src/lib/watcher.ts (2)
  • info (101-117)
  • info (119-136)
plugins/watcher/src/lib/types.ts (1)
  • ChangeInfo (18-26)
plugins/watcher/src/config/config.unittest.ts (1)
plugins/watcher/src/lib/types.ts (1)
  • WatcherConfig (5-16)
plugins/watcher/src/lib/boot.ts (1)
plugins/watcher/src/lib/watcher.ts (1)
  • Watcher (16-137)
plugins/watcher/src/lib/utils.ts (1)
scripts/version.js (1)
  • __filename (9-9)
plugins/watcher/test/development_cluster.test.ts (3)
plugins/watcher/test/fixtures/apps/watcher-development-app/agent.js (1)
  • file_path1 (3-3)
plugins/watcher/test/fixtures/apps/watcher-development-app/app/router.js (1)
  • file_path1 (3-3)
plugins/watcher/test/utils.ts (1)
  • getFilePath (8-10)
plugins/watcher/src/lib/types.ts (2)
plugins/watcher/src/lib/watcher.ts (1)
  • Watcher (16-137)
packages/egg/src/lib/types.ts (1)
  • EggAppConfig (97-271)
plugins/watcher/src/config/config.default.ts (2)
plugins/watcher/src/lib/utils.ts (1)
  • getSourceDirname (11-20)
plugins/watcher/src/lib/types.ts (1)
  • WatcherConfig (5-16)
plugins/watcher/src/config/config.local.ts (1)
plugins/watcher/src/lib/types.ts (1)
  • WatcherConfig (5-16)
plugins/development/src/agent.ts (2)
packages/egg/src/lib/core/base_hook_class.ts (1)
  • agent (31-37)
plugins/watcher/src/lib/watcher.ts (2)
  • info (101-117)
  • info (119-136)
plugins/watcher/src/lib/watcher.ts (4)
plugins/watcher/src/lib/types.ts (1)
  • ChangeInfo (18-26)
packages/egg/src/lib/types.ts (1)
  • EggAppConfig (97-271)
packages/utils/src/import.ts (1)
  • importModule (450-522)
plugins/watcher/src/lib/utils.ts (1)
  • isEqualOrParentPath (7-9)
plugins/watcher/src/lib/event-sources/development.ts (2)
plugins/watcher/src/lib/watcher.ts (2)
  • info (101-117)
  • info (119-136)
plugins/watcher/src/lib/types.ts (1)
  • ChangeInfo (18-26)
🪛 markdownlint-cli2 (0.17.2)
plugins/watcher/CHANGELOG.md

43-43: Bare URL used

(MD034, no-bare-urls)


45-45: Bare URL used

(MD034, no-bare-urls)


52-52: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


53-53: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


55-55: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


57-57: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


59-59: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


62-62: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


63-63: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


66-66: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


67-67: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


67-67: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


67-67: Hard tabs
Column: 1

(MD010, no-hard-tabs)


69-69: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


70-70: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


73-73: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


74-74: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


76-76: Unordered list style
Expected: asterisk; Actual: dash

(MD004, ul-style)


76-76: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


76-76: Hard tabs
Column: 1

(MD010, no-hard-tabs)


84-84: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


87-87: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


88-88: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


90-90: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


91-91: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


93-93: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


96-96: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


97-97: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


99-99: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


102-102: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


103-103: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


105-105: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


108-108: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


110-110: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


113-113: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


115-115: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


118-118: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


120-120: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


123-123: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


124-124: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


126-126: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


129-129: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


130-130: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


132-132: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


135-135: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


137-137: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


140-140: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Test egg-bin (windows-latest, 24)
  • GitHub Check: Test egg-bin (windows-latest, 22)
  • GitHub Check: Test egg-bin (macos-latest, 24)
  • GitHub Check: Test egg-bin (ubuntu-latest, 22)
  • GitHub Check: Test egg-bin (ubuntu-latest, 24)
  • GitHub Check: Test egg-bin (macos-latest, 22)
🔇 Additional comments (30)
packages/mock/src/lib/parallel/agent.ts (1)

75-75: Good: removed the unsafe cast; please confirm onMessage is public/stable

Directly using agent.messenger.onMessage(msg) improves type-safety. Verify that onMessage is part of the public Messenger typings across the repo’s pinned @eggjs/core version(s) to avoid relying on internals.

plugins/watcher/test/fixtures/apps/watcher-development-app/tmp.txt (1)

1-1: LGTM: fixture content is minimal and explicit.

Exact bytes ("aaa", no trailing newline) are fine for change-detection tests.

plugins/watcher/test/fixtures/apps/watcher-development-app/package.json (1)

1-3: LGTM: minimal package manifest for fixture app.

No additional fields are necessary for test resolution; default CommonJS semantics apply without "type".

plugins/watcher/test/fixtures/apps/watcher-development-app/tmp-agent.txt (1)

1-1: LGTM: agent-side fixture content is correct.

Matches tests that watch this file specifically.

plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/package.json (1)

1-3: LGTM: minimal manifest for fuzzy custom event-source fixture.

Sufficient for test isolation.

plugins/watcher/LICENSE (1)

1-21: LGTM: MIT license added for plugin.

Matches project licensing; no action needed.

plugins/watcher/test/fixtures/apps/watcher-custom-event-source/package.json (1)

1-3: LGTM: minimal manifest for custom event-source fixture.

Consistent with other test apps.

CLAUDE.md (1)

43-46: plugins/watcher/package.json verified — no changes required.
plugins/watcher/package.json has type: "module", an eggPlugin entry, exports -> ./src/.ts, publishConfig.exports -> ./dist/.js, files includes "dist", and scripts build (tsdown), clean (rimraf dist), prepublishOnly (npm run build).

pnpm-workspace.yaml (1)

62-62: Catalog entry added correctly — verification passed.

  • All consumer packages reference camelcase via "catalog:" (no semver usages found).
  • All workspace packages reference "@eggjs/watcher" with "workspace:*" and "@eggjs/watcher" is not present in pnpm-workspace.yaml.

rg printed PCRE2 compilation errors during the run; they do not change the OK results above.

plugins/watcher/test/fixtures/apps/watcher-development-app/tmp/tmp.txt (1)

1-1: Fixture OK.

Looks fine for exercising file change detection.

plugins/watcher/vitest.config.ts (1)

1-7: Vitest project config looks good.

20s timeout is reasonable for FS‑watch tests.

plugins/watcher/test/fixtures/apps/watcher-type-default/package.json (1)

1-3: Fixture metadata OK.

Sufficient for tests.

plugins/watcher/test/fixtures/apps/watcher-custom-event-source/config/plugin.js (1)

1-6: Custom plugin enablement looks correct.

Path resolution is correct relative to fixture.

plugins/watcher/test/fixtures/apps/watcher-custom-event-source/plugins/egg-watcher-custom/config/config.default.js (1)

1-7: Custom event source wiring LGTM.

Exports shape matches expected watcher config.

plugins/watcher/test/fixtures/apps/watcher-type-default/app.js (1)

1-3: Default‑type watcher fixture is fine.

No-Op handler is adequate for log‑based assertions.

plugins/watcher/test/fixtures/apps/watcher-development-app/config/config.unittest.js (1)

1-7: LGTM: correct dev-mode fixture.

env = 'local' with watcher.type = 'development' matches the development event source tests.

plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/config/config.unittest.js (1)

1-11: LGTM: custom event source options wired correctly.

watcher.type = 'custom' and watcherCustom.foo = 'bar' match the fuzzy-path test expectations.

plugins/watcher/src/app.ts (1)

1-3: LGTM: app entry re-exports Boot correctly

Named import + default re-export matches ./lib/boot.ts. No issues.

plugins/watcher/test/fixtures/apps/watcher-development-app/tmp/t1/t2/t3/t4/tmp.txt (1)

1-1: No review needed for binary/text fixture

Fixture content is fine as-is.

tsconfig.json (1)

38-42: Add watcher project reference — looks correct

Root references now include ./plugins/watcher per repo policy.

plugins/watcher/tsconfig.json (1)

1-6: LGTM: extends root config and sets baseUrl

Matches monorepo TypeScript conventions.

plugins/watcher/test/utils.ts (1)

1-10: Utility is correct and ESM-safe

Path derivation via import.meta.url is correct; function is minimal and clear.

plugins/watcher/src/lib/event-sources/base.ts (1)

3-6: Abstract contract looks good

Clear minimal interface for event sources; no issues.

plugins/watcher/src/agent.ts (1)

1-3: Consistent default export for agent entry — verified. package exports include "./agent": "./src/agent.ts" and publishConfig.exports include "./agent": "./dist/agent.js" in plugins/watcher/package.json.

plugins/watcher/src/index.ts (1)

1-3: Public surface re-exports verified

package.json "exports" includes "./lib/types", "./lib/watcher", and "./lib/event-sources" mapped to the corresponding src files — no changes required.

plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/plugins/egg-watcher-custom/config/config.default.js (1)

1-5: No change required — loader accepts module/class values

Watcher._init (src/lib/watcher.ts:33–40) accepts either a string (loaded via importModule) or a module/class (constructed directly), so require('../custom') is valid. The TS declaration at src/lib/types.ts:15 is too narrow — update to Record<string, string | typeof BaseEventSource> if you want type accuracy.

Likely an incorrect or invalid review comment.

plugins/watcher/test/fixtures/apps/watcher-custom-event-source/config/config.unittest.js (1)

1-9: LGTM – fixture config is minimal and correct.

watcher.type = 'custom' and watcherCustom are set as expected for the custom source; keys present.

plugins/watcher/test/fixtures/apps/watcher-custom-event-source-fuzzy/config/plugin.js (1)

5-8: LGTM – plugin enablement/path looks right.

plugins/watcher/src/lib/types.ts (1)

28-36: Typings look good

Augmentations and public types align with usage across watcher and tests.

plugins/watcher/package.json (1)

24-36: Package manifest meets plugin guidelines

  • eggPlugin present
  • ESM type with TS-source exports and publishConfig.exports to dist
  • scripts clean/build/prepublishOnly included
  • workspace/catalog usage correct

Also applies to: 72-96

Comment on lines +133 to 134
"@eggjs/watcher": "workspace:*",
"circular-json-for-egg": "catalog:",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Switch @eggjs/watcher to workspace: — correct for internal dependency*

This aligns with workspace/catalog rules.

Run this to verify workspace wiring and plugin metadata:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Check pnpm-workspace includes plugins/* …"
rg -nP '(?s)^packages:\s*(?:- .*\n)*\s*-+\s*plugins/\*' pnpm-workspace.yaml || { echo "Missing plugins/* in pnpm-workspace.yaml"; exit 1; }

echo "Check watcher plugin has package.json and eggPlugin metadata …"
test -f plugins/watcher/package.json
rg -n '"eggPlugin"' plugins/watcher/package.json || { echo "Missing eggPlugin field in plugins/watcher/package.json"; exit 1; }

echo "Check egg depends on @eggjs/watcher via workspace:* …"
rg -nP '"@eggjs/watcher"\s*:\s*"workspace:\*"' packages/egg/package.json

Length of output: 82


pnpm-workspace.yaml missing plugins/ — workspace: dependency won’t resolve**

  • Add "- plugins/" under packages: in pnpm-workspace.yaml so "@eggjs/watcher": "workspace:" in packages/egg/package.json (lines 133–134) can be resolved.
  • Verify plugins/watcher/package.json exists and contains an "eggPlugin" field.
🤖 Prompt for AI Agents
In packages/egg/package.json around lines 133–134, the dependency
"@eggjs/watcher": "workspace:*" will not resolve because pnpm-workspace.yaml
does not include the plugins/* glob; update pnpm-workspace.yaml by adding "-
plugins/*" under the packages: array so pnpm can find workspace packages, and
then verify that plugins/watcher/package.json exists and declares the required
"eggPlugin" field (add it if missing).

Comment on lines +2 to +3
import { getSourceDirname } from '../lib/utils.ts';
import type { WatcherConfig } from '../lib/types.ts';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

ESM import specifiers and dynamic import targets need .js extensions.

Using .ts in import specifiers will fail at runtime under NodeNext; also ensure eventSources point to concrete .js files for dynamic import.
This is a merge blocker.

-import { getSourceDirname } from '../lib/utils.ts';
-import type { WatcherConfig } from '../lib/types.ts';
+import { getSourceDirname } from '../lib/utils.js';
+import type { WatcherConfig } from '../lib/types.js';

   watcher: {
     type: 'default', // default event source
     eventSources: {
-      default: path.join(getSourceDirname(), 'lib', 'event-sources', 'default'),
-      development: path.join(
+      default: path.join(getSourceDirname(), 'lib', 'event-sources', 'default.js'),
+      development: path.join(
         getSourceDirname(),
         'lib',
         'event-sources',
-        'development'
+        'development.js'
       ),
     },
-  } as WatcherConfig,
+  } satisfies WatcherConfig,

Run to find any lingering .ts specifiers in source imports:

Also applies to: 14-21, 22-22


🏁 Script executed:

#!/bin/bash
rg -nP --type=ts -C1 "from\s+['\"].*\.ts['\"]" plugins/watcher/src

Length of output: 2200


ESM import specifiers and dynamic import targets must use .js — merge blocker.

Replace all .ts import specifiers with .js and ensure dynamic eventSources point to concrete .js files; update the config object to use satisfies WatcherConfig instead of as WatcherConfig. Affected locations (from ripgrep):

  • plugins/watcher/src/config/config.default.ts (lines 2–3)
  • plugins/watcher/src/lib/watcher.ts (lines 8–10)
  • plugins/watcher/src/lib/types.ts (line 3)
  • plugins/watcher/src/index.ts (lines 1–3)
  • plugins/watcher/src/lib/boot.ts (line 3)
  • plugins/watcher/src/app.ts (line 1)
  • plugins/watcher/src/agent.ts (line 1)
  • plugins/watcher/src/lib/event-sources/index.ts (lines 1–3)
  • plugins/watcher/src/lib/event-sources/development.ts (lines 5–6)
  • plugins/watcher/src/lib/event-sources/default.ts (line 1)

Fix all matches (change .ts.js, make eventSource paths concrete .js, and update the config typing), then verify under Node (NodeNext) and run the build/tests.

🤖 Prompt for AI Agents
In plugins/watcher/src/config/config.default.ts around lines 2–3, update ESM
import specifiers from .ts to .js and change the config typing from using "as
WatcherConfig" to "satisfies WatcherConfig"; then scan and fix the other listed
files (plugins/watcher/src/lib/watcher.ts lines 8–10, src/lib/types.ts line 3,
src/index.ts lines 1–3, src/lib/boot.ts line 3, src/app.ts line 1, src/agent.ts
line 1, src/lib/event-sources/index.ts lines 1–3,
src/lib/event-sources/development.ts lines 5–6, src/lib/event-sources/default.ts
line 1) replacing all .ts import specifiers with .js, ensure any dynamic
eventSources point to concrete .js file paths (no runtime .ts targets), and
update any config object assertions to use "satisfies WatcherConfig"; after
making these changes, run the project under Node (NodeNext) and execute the
build and tests to verify no import/runtime errors remain.

Comment on lines +5 to +6
type: 'development',
} as WatcherConfig,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use satisfies Partial<WatcherConfig> instead of a type assertion.

Avoids lying to the type system about missing eventSources while still letting default config provide it via deep‑merge.

-  } as WatcherConfig,
+  } satisfies Partial<WatcherConfig>,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type: 'development',
} as WatcherConfig,
type: 'development',
} satisfies Partial<WatcherConfig>,
🤖 Prompt for AI Agents
In plugins/watcher/src/config/config.local.ts around lines 5–6, the file
currently uses a type assertion ("as WatcherConfig") for the exported config
which falsely tells TypeScript the object satisfies the full interface; replace
that assertion with the TypeScript 4.9+ "satisfies Partial<WatcherConfig>"
operator so the object is checked as a partial (allowing missing eventSources)
while preserving the full WatcherConfig type for downstream use — update the
export to use "satisfies Partial<WatcherConfig>" instead of the "as" cast.

Comment on lines +1 to +7
import type { WatcherConfig } from '../lib/types.js';

export default {
watcher: {
type: 'development',
} as WatcherConfig,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid type-assertion by satisfying the type; also standardize import extension

Current code casts to WatcherConfig while omitting eventSources. Provide an empty map and use .ts for consistency with other files.

-import type { WatcherConfig } from '../lib/types.js';
+import type { WatcherConfig } from '../lib/types.ts';

 export default {
   watcher: {
     type: 'development',
-  } as WatcherConfig,
+    eventSources: {},
+  } as WatcherConfig,
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import type { WatcherConfig } from '../lib/types.js';
export default {
watcher: {
type: 'development',
} as WatcherConfig,
};
import type { WatcherConfig } from '../lib/types.ts';
export default {
watcher: {
type: 'development',
eventSources: {},
} as WatcherConfig,
};
🤖 Prompt for AI Agents
In plugins/watcher/src/config/config.unittest.ts lines 1-7, avoid the type
assertion and standardize the import extension: change the import to use
'../lib/types.ts' and make the exported object satisfy WatcherConfig by adding
an explicit empty eventSources map (e.g., eventSources: {}) under watcher, and
remove the trailing "as WatcherConfig" cast so the literal structurally matches
the type.

Comment on lines +3 to +4
import { Watcher } from './watcher.ts';

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix ESM import extension.

.ts here will break at runtime.

-import { Watcher } from './watcher.ts';
+import { Watcher } from './watcher.js';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { Watcher } from './watcher.ts';
import { Watcher } from './watcher.js';
🤖 Prompt for AI Agents
In plugins/watcher/src/lib/boot.ts around lines 3-4, the import uses a .ts
extension which will fail at runtime for ESM; remove the extension so the module
specifier is extensionless (import { Watcher } from './watcher') or, if your
runtime requires explicit JS specifiers, change it to the emitted .js file
(import { Watcher } from './watcher.js'); update the import accordingly to match
your build/runtime resolution.

Comment on lines +38 to +45
app.get('/agent-watch', async ctx => {
app.messenger.broadcast('agent-watch');
ctx.body = await new Promise(function (resolve) {
app.messenger.on('agent-watch-success', function (msg) {
resolve(msg);
});
});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid race by registering the listener before broadcasting; use once to prevent leaks.

Current order risks missing an immediate response and accumulates listeners across calls.

-  app.get('/agent-watch', async ctx => {
-    app.messenger.broadcast('agent-watch');
-    ctx.body = await new Promise(function (resolve) {
-      app.messenger.on('agent-watch-success', function (msg) {
-        resolve(msg);
-      });
-    });
-  });
+  app.get('/agent-watch', async ctx => {
+    const p = new Promise(resolve => {
+      app.messenger.once('agent-watch-success', msg => resolve(msg));
+    });
+    app.messenger.broadcast('agent-watch');
+    ctx.body = await p;
+  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
app.get('/agent-watch', async ctx => {
app.messenger.broadcast('agent-watch');
ctx.body = await new Promise(function (resolve) {
app.messenger.on('agent-watch-success', function (msg) {
resolve(msg);
});
});
});
app.get('/agent-watch', async ctx => {
const p = new Promise(resolve => {
app.messenger.once('agent-watch-success', msg => resolve(msg));
});
app.messenger.broadcast('agent-watch');
ctx.body = await p;
});
🤖 Prompt for AI Agents
In plugins/watcher/test/fixtures/apps/watcher-development-app/app/router.js
around lines 38 to 45, the code broadcasts 'agent-watch' before attaching a
listener which can miss immediate responses and accumulates listeners; change
the Promise to attach a one-time listener (use app.messenger.once or equivalent)
before calling app.messenger.broadcast('agent-watch') so the handler is
guaranteed to receive the next response and is automatically removed to prevent
listener leaks; keep the Promise to resolve with the message when the once
handler fires (optionally add a timeout inside the Promise if desired).

Comment on lines +47 to +54
app.get('/agent-unwatch', async ctx => {
app.messenger.broadcast('agent-unwatch');
ctx.body = await new Promise(function (resolve) {
app.messenger.on('agent-unwatch-success', function (msg) {
resolve(msg);
});
});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Repeat the safer pattern for /agent-unwatch.

-  app.get('/agent-unwatch', async ctx => {
-    app.messenger.broadcast('agent-unwatch');
-    ctx.body = await new Promise(function (resolve) {
-      app.messenger.on('agent-unwatch-success', function (msg) {
-        resolve(msg);
-      });
-    });
-  });
+  app.get('/agent-unwatch', async ctx => {
+    const p = new Promise(resolve => {
+      app.messenger.once('agent-unwatch-success', msg => resolve(msg));
+    });
+    app.messenger.broadcast('agent-unwatch');
+    ctx.body = await p;
+  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
app.get('/agent-unwatch', async ctx => {
app.messenger.broadcast('agent-unwatch');
ctx.body = await new Promise(function (resolve) {
app.messenger.on('agent-unwatch-success', function (msg) {
resolve(msg);
});
});
});
app.get('/agent-unwatch', async ctx => {
const p = new Promise(resolve => {
app.messenger.once('agent-unwatch-success', msg => resolve(msg));
});
app.messenger.broadcast('agent-unwatch');
ctx.body = await p;
});
🤖 Prompt for AI Agents
In plugins/watcher/test/fixtures/apps/watcher-development-app/app/router.js
around lines 47–54, the /agent-unwatch handler uses app.messenger.on and never
removes the listener (risking leaks/race conditions); change to use a one-time
listener (app.messenger.once) and add a short timeout fallback so the promise
resolves or rejects if no 'agent-unwatch-success' arrives (ensure the timeout
clears the listener and the listener clears the timeout), and surface any error
instead of hanging.

Comment on lines +56 to +63
app.get('/agent-msg', async ctx => {
app.messenger.broadcast('i-want-agent-file-changed-count');
ctx.body = await new Promise(function (resolve) {
app.messenger.on('agent-file-changed-count', function (msg) {
resolve(msg);
});
});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Repeat the safer pattern for /agent-msg.

-  app.get('/agent-msg', async ctx => {
-    app.messenger.broadcast('i-want-agent-file-changed-count');
-    ctx.body = await new Promise(function (resolve) {
-      app.messenger.on('agent-file-changed-count', function (msg) {
-        resolve(msg);
-      });
-    });
-  });
+  app.get('/agent-msg', async ctx => {
+    const p = new Promise(resolve => {
+      app.messenger.once('agent-file-changed-count', msg => resolve(msg));
+    });
+    app.messenger.broadcast('i-want-agent-file-changed-count');
+    ctx.body = await p;
+  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
app.get('/agent-msg', async ctx => {
app.messenger.broadcast('i-want-agent-file-changed-count');
ctx.body = await new Promise(function (resolve) {
app.messenger.on('agent-file-changed-count', function (msg) {
resolve(msg);
});
});
});
app.get('/agent-msg', async ctx => {
const p = new Promise(resolve => {
app.messenger.once('agent-file-changed-count', msg => resolve(msg));
});
app.messenger.broadcast('i-want-agent-file-changed-count');
ctx.body = await p;
});
🤖 Prompt for AI Agents
In plugins/watcher/test/fixtures/apps/watcher-development-app/app/router.js
around lines 56-63, the /agent-msg handler uses app.messenger.on and broadcasts
before attaching the listener which can leak listeners or miss messages; change
it to attach a one-time listener (app.messenger.once) before broadcasting and
wrap in a Promise that rejects/ resolves on a short timeout so the request
doesn't hang forever, ensuring the listener is removed automatically and the
broadcast happens after the listener is registered.

Comment on lines +1 to +7
import { test, expect } from 'vitest';

import * as watcher from '../src/index.ts';

test('should exports work', async () => {
expect(Object.keys(watcher).sort()).toMatchSnapshot();
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use Node.js assert instead of Vitest expect per repo testing guideline

Replace Vitest's expect(...).toMatchSnapshot() with Node's built-in assert and verify a stable subset of exports.

-import { test, expect } from 'vitest';
+import { test } from 'vitest';
+import assert from 'node:assert/strict';

 import * as watcher from '../src/index.ts';

 test('should exports work', async () => {
-  expect(Object.keys(watcher).sort()).toMatchSnapshot();
+  const keys = Object.keys(watcher).sort();
+  // Assert a stable subset to avoid snapshot churn
+  for (const k of ['Watcher', 'BaseEventSource', 'DefaultEventSource', 'DevelopmentEventSource']) {
+    assert.ok(keys.includes(k), `missing export: ${k}`);
+  }
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { test, expect } from 'vitest';
import * as watcher from '../src/index.ts';
test('should exports work', async () => {
expect(Object.keys(watcher).sort()).toMatchSnapshot();
});
import { test } from 'vitest';
import assert from 'node:assert/strict';
import * as watcher from '../src/index.ts';
test('should exports work', async () => {
const keys = Object.keys(watcher).sort();
// Assert a stable subset to avoid snapshot churn
for (const k of ['Watcher', 'BaseEventSource', 'DefaultEventSource', 'DevelopmentEventSource']) {
assert.ok(keys.includes(k), `missing export: ${k}`);
}
});
🤖 Prompt for AI Agents
In plugins/watcher/test/index.test.ts around lines 1 to 7, replace the Vitest
snapshot assertion with Node's built-in assert and check a stable subset of
exports: import/require assert, keep the test() from Vitest, compute
Object.keys(watcher).sort(), filter or pick the specific expected export names
(the stable subset) and use assert.deepStrictEqual(actualSubset, expectedArray)
to verify equality instead of expect(...).toMatchSnapshot().


describe('test/watcher.test.ts', () => {
let app: MockApplication;
afterEach(() => app && app.close());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Await app.close() in afterEach to avoid resource leaks

Not awaiting close can leave handles open between tests.

-  afterEach(() => app && app.close());
+  afterEach(async () => {
+    if (app) await app.close();
+  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
afterEach(() => app && app.close());
afterEach(async () => {
if (app) await app.close();
});
🤖 Prompt for AI Agents
In plugins/watcher/test/watcher.test.ts around line 11, the afterEach hook calls
app.close() without awaiting it which can leave handles open between tests;
change the hook to be async and await app.close() (guarding for app being
defined) so teardown completes before the next test runs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant