Skip to content

Conversation

@killagu
Copy link
Contributor

@killagu killagu commented Nov 18, 2025

…ncies

  • Add MiddlewareGraphHook to build injection relationships for controller middlewares
  • Support both class-level and method-level @Middleware annotations
  • Add test fixture app to verify middleware module references
  • Export ControllerInfoUtil and MethodInfoUtil from @eggjs/tegg

🤖 Generated with Claude Code

Checklist
  • npm test passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
Affected core subsystem(s)
Description of change

Summary by CodeRabbit

  • New Features

    • Added middleware graph integration supporting class- and method-level middleware injection
    • Registered a middleware hook with the global graph during config load
    • Exposed a new public utility export for controller metadata
  • Tests

    • Added fixture app and end-to-end tests validating middleware behavior and responses
  • Chores

    • Minor test adjustments and typing/capability tweaks to improve stability

…ncies

- Add MiddlewareGraphHook to build injection relationships for controller middlewares
- Support both class-level and method-level @Middleware annotations
- Add test fixture app to verify middleware module references
- Export ControllerInfoUtil and MethodInfoUtil from @eggjs/tegg

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

Co-Authored-By: Claude <[email protected]>
@coderabbitai
Copy link

coderabbitai bot commented Nov 18, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a public re-export MethodInfoUtil; registers a middlewareGraphHook with GlobalGraph during configDidLoad; implements middlewareGraphHook to inject middleware proto nodes from AOP metadata into the global graph; and adds test fixtures and tests exercising class- and method-level middleware AOP behavior.

Changes

Cohort / File(s) Summary
Core Library Export
core/controller-decorator/index.ts
Re-exports the default export from ./src/util/MethodInfoUtil as MethodInfoUtil.
Plugin: boot hook & registration
plugin/controller/app.ts
Imports GlobalGraph and middlewareGraphHook, and adds configDidLoad() to register middlewareGraphHook with GlobalGraph.
Plugin: middleware graph hook
plugin/controller/lib/MiddlewareGraphHook.ts
New module exporting middlewareGraphHook(globalGraph: GlobalGraph) that iterates module/controller proto nodes, reads AOP metadata for controller- and method-level middleware, resolves middleware proto nodes, and injects them into the global graph.
Test fixture app config & router
plugin/controller/test/fixtures/apps/middleware-graph-app/config/config.default.js, plugin/controller/test/fixtures/apps/middleware-graph-app/config/module.json, plugin/controller/test/fixtures/apps/middleware-graph-app/config/plugin.js, plugin/controller/test/fixtures/apps/middleware-graph-app/app/router.ts, plugin/controller/test/fixtures/apps/middleware-graph-app/package.json
Adds fixture app config, module list, plugin declarations, placeholder router, and app package.json used by tests.
Test fixture modules (advice & controller)
plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/advice/*, plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/package.json, plugin/controller/test/fixtures/apps/middleware-graph-app/modules/controller-module/*, plugin/controller/test/fixtures/apps/middleware-graph-app/modules/controller-module/package.json
Adds TestAdvice and AnotherAdvice implementing IAdvice, and TestController with class- and method-level @Middleware usage; adds module package.json files.
Tests
plugin/controller/test/http/middleware-aop.test.ts
New HTTP test suite that boots the fixture app, asserts module references, and verifies class-level and method-level middleware effects on responses.
Test adjustments / typing
plugin/controller/test/mcp/helper.test.ts, plugin/controller/test/mcp/mcp.test.ts, plugin/controller/test/mcp/mcpCluster.test.ts, plugin/mcp-proxy/test/proxy.test.ts
Removes explicit empty tools capability in client capabilities; relaxes typing by casting notification items to any when accessing non-text data.

Sequence Diagram(s)

sequenceDiagram
    participant App as Egg App
    participant Hook as ControllerAppBootHook
    participant GG as GlobalGraph
    participant MGH as middlewareGraphHook
    participant ModuleNodes as Module/Controller ProtoNodes
    participant AOP as AOP Metadata

    App->>Hook: configDidLoad()
    Hook->>GG: registerBuildHook(middlewareGraphHook)
    Note right of GG `#f0f4c3`: middlewareGraphHook registered

    GG->>MGH: invoke during graph build
    MGH->>ModuleNodes: iterate module & controller proto nodes
    loop per controller
        MGH->>AOP: read controller/method AOP metadata
        AOP-->>MGH: middleware classes list
        MGH->>ModuleNodes: resolve middleware proto nodes by class
        ModuleNodes-->>MGH: proto node(s) or undefined
        alt found
            MGH->>GG: addInject(middleware proto node)
        end
    end
    Note right of GG `#e8f5e9`: middleware proto nodes injected into graph
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review middleware proto node resolution and ClassProtoDescriptor checks in plugin/controller/lib/MiddlewareGraphHook.ts.
  • Verify lifecycle registration timing and null-safety around GlobalGraph.instance in plugin/controller/app.ts.
  • Validate test fixtures wiring (module.json, plugin.js, config) and test assertions in plugin/controller/test/http/middleware-aop.test.ts.
  • Confirm the exported MethodInfoUtil re-export does not cause API collisions.

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • akitaSummer

Poem

🐇 I hopped through nodes and metadata bright,
I stitched advice to controllers by night,
A hook registered, the graph took flight,
Middleware twined in order just right,
Tests applaud — the rabbit beams with delight.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 summarizes the main change: adding MiddlewareGraphHook to handle controller middleware dependencies, which aligns with the PR's primary objective and the substantial code additions in MiddlewareGraphHook.ts and related files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/aop_middleware_module_order

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 31692e7 and f7ce938.

📒 Files selected for processing (1)
  • plugin/mcp-proxy/test/proxy.test.ts (1 hunks)
⏰ 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). (7)
  • GitHub Check: Runner-macos (16)
  • GitHub Check: Runner-macos (20)
  • GitHub Check: Runner-macos (18)
  • GitHub Check: Runner-ubuntu (20)
  • GitHub Check: Runner-ubuntu (18)
  • GitHub Check: Runner-ubuntu (16)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (1)
plugin/mcp-proxy/test/proxy.test.ts (1)

46-48: Add a runtime check or use a specific type assertion instead of as any.

The SDK's CallToolResult content includes multiple types (ImageContent, AudioContent, Resource, ResourceLink, EmbeddedResource, etc.), and not all of them have a data property—Resource and ResourceLink types expose URI and metadata instead. The as any cast bypasses TypeScript's type checking, and the non-null assertion ! assumes data exists without verification, creating a potential runtime error if the test encounters a Resource or ResourceLink variant.

Verify whether this test actually exercises Resource/ResourceLink content types. If so, use a runtime check or type guard:

     } else {
-      notifications.push({
-        text: (item as any).data!.toString(),
-      });
+      if ('data' in item && item.data != null) {
+        notifications.push({
+          text: item.data.toString(),
+        });
+      }
     }

If this specific test only handles variants with data (ImageContent, AudioContent, EmbeddedResource), document the assumption as a comment to clarify scope.


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.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @killagu, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves how controller middlewares are handled within the application's dependency injection system. By introducing a dedicated graph hook, it ensures that middlewares, whether defined at the class or method level, are correctly integrated and their dependencies are resolved, leading to a more robust and predictable middleware execution flow.

Highlights

  • Middleware Dependency Graph: Introduced a new MiddlewareGraphHook to establish proper injection relationships for controller middlewares within the application's global dependency graph.
  • Flexible Middleware Application: Enhanced support for applying @Middleware annotations at both the class level (affecting all methods in a controller) and the method level (affecting specific controller actions).
  • Utility Exports: Exported ControllerInfoUtil and MethodInfoUtil from @eggjs/tegg to provide better access to controller and method metadata, which is crucial for the new middleware graph hook.
  • Comprehensive Testing: Added a new test fixture application specifically designed to verify the correct functioning and module references of the new middleware dependency resolution.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a MiddlewareGraphHook to automatically manage dependencies for controller middlewares, which is a great enhancement for the framework. The implementation correctly handles both class-level and method-level middlewares, and the addition of a comprehensive test suite is commendable. I've identified a potential performance issue in the middleware discovery logic and a flaky test case. My review includes suggestions to optimize the code and improve test reliability.

Comment on lines +29 to +70
function findMiddlewareProtoNodes(globalGraph: GlobalGraph, protoNode: GraphNode<ProtoNode, ProtoDependencyMeta>) {
const proto = protoNode.val.proto;
if (!ClassProtoDescriptor.isClassProtoDescriptor(proto)) {
return;
}

const middlewareClazzSet = new Set<EggProtoImplClass<IAdvice>>();

// Get AOP middlewares from controller class
const controllerAopMiddlewares = ControllerInfoUtil.getControllerAopMiddlewares(proto.clazz);
if (controllerAopMiddlewares && controllerAopMiddlewares.length > 0) {
for (const middlewareClazz of controllerAopMiddlewares) {
middlewareClazzSet.add(middlewareClazz);
}
}

// Get AOP middlewares from controller methods
const methods = MethodInfoUtil.getMethods(proto.clazz);
for (const methodName of methods) {
const methodAopMiddlewares = MethodInfoUtil.getMethodAopMiddlewares(proto.clazz, methodName);
if (methodAopMiddlewares && methodAopMiddlewares.length > 0) {
for (const middlewareClazz of methodAopMiddlewares) {
middlewareClazzSet.add(middlewareClazz);
}
}
}

if (middlewareClazzSet.size === 0) {
return;
}

const result: GraphNode<ProtoNode, ProtoDependencyMeta>[] = [];
for (const middlewareClazz of middlewareClazzSet) {
// Find the proto node for this middleware class
const middlewareProtoNode = findProtoNodeByClass(globalGraph, middlewareClazz);
if (middlewareProtoNode) {
result.push(middlewareProtoNode);
}
}

return result.length > 0 ? result : undefined;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The function findMiddlewareProtoNodes has a few areas for improvement:

  1. Inconsistent Return Type: It can return undefined or an array. It would be cleaner to always return an array (GraphNode[]), which would be empty if no middlewares are found. This simplifies the calling code by removing the need for a null check.
  2. Redundant Checks: The if (array && array.length > 0) pattern is partially redundant, as a for...of loop won't execute on an empty array. This can be simplified.

I've provided a suggestion that addresses these points to make the function more robust and easier to read.

function findMiddlewareProtoNodes(globalGraph: GlobalGraph, protoNode: GraphNode<ProtoNode, ProtoDependencyMeta>): GraphNode<ProtoNode, ProtoDependencyMeta>[] {
  const proto = protoNode.val.proto;
  if (!ClassProtoDescriptor.isClassProtoDescriptor(proto)) {
    return [];
  }

  const middlewareClazzSet = new Set<EggProtoImplClass<IAdvice>>();

  // Get AOP middlewares from controller class
  const controllerAopMiddlewares = ControllerInfoUtil.getControllerAopMiddlewares(proto.clazz);
  if (controllerAopMiddlewares) {
    for (const middlewareClazz of controllerAopMiddlewares) {
      middlewareClazzSet.add(middlewareClazz);
    }
  }

  // Get AOP middlewares from controller methods
  const methods = MethodInfoUtil.getMethods(proto.clazz);
  for (const methodName of methods) {
    const methodAopMiddlewares = MethodInfoUtil.getMethodAopMiddlewares(proto.clazz, methodName);
    if (methodAopMiddlewares) {
      for (const middlewareClazz of methodAopMiddlewares) {
        middlewareClazzSet.add(middlewareClazz);
      }
    }
  }

  if (middlewareClazzSet.size === 0) {
    return [];
  }

  const result: GraphNode<ProtoNode, ProtoDependencyMeta>[] = [];
  for (const middlewareClazz of middlewareClazzSet) {
    // Find the proto node for this middleware class
    const middlewareProtoNode = findProtoNodeByClass(globalGraph, middlewareClazz);
    if (middlewareProtoNode) {
      result.push(middlewareProtoNode);
    }
  }

  return result;
}

Comment on lines +72 to +83
function findProtoNodeByClass(
globalGraph: GlobalGraph,
clazz: EggProtoImplClass,
): GraphNode<ProtoNode, ProtoDependencyMeta> | undefined {
for (const protoNode of globalGraph.protoGraph.nodes.values()) {
const proto = protoNode.val.proto;
if (ClassProtoDescriptor.isClassProtoDescriptor(proto) && proto.clazz === clazz) {
return protoNode;
}
}
return undefined;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The findProtoNodeByClass function iterates over all prototypes in globalGraph.protoGraph for each middleware it needs to find. This can cause performance degradation in larger applications with many prototypes, as it results in a complexity of O(N) for each lookup.

To optimize this, consider creating a Map<EggProtoImplClass, GraphNode<ProtoNode, ProtoDependencyMeta>> of all prototypes once at the beginning of the middlewareGraphHook function. This would allow findProtoNodeByClass to perform an O(1) lookup, significantly improving performance.

import path from 'path';
import assert from 'assert';

describe('plugin/controller/test/http/middleware-graph-hook.test.ts', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The describe block name plugin/controller/test/http/middleware-graph-hook.test.ts is inconsistent with the test file name middleware-aop.test.ts. To avoid confusion, it's best to keep these consistent. Consider renaming the describe block to better reflect the file's name or the feature being tested.

Suggested change
describe('plugin/controller/test/http/middleware-graph-hook.test.ts', () => {
describe('plugin/controller/test/http/middleware-aop.test.ts', () => {

Comment on lines +8 to +10
beforeEach(() => {
mm(process.env, 'EGG_TYPESCRIPT', true);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The beforeEach hook sets EGG_TYPESCRIPT to true, but this is already done in the before hook. This makes the setup in beforeEach redundant. You can safely remove this beforeEach block.

Copy link

@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: 0

🧹 Nitpick comments (3)
plugin/controller/app.ts (1)

4-4: Guard assumptions around GlobalGraph.instance in configDidLoad

Registering the middlewareGraphHook in configDidLoad is the right place conceptually, but using GlobalGraph.instance! hard-codes the assumption that the global graph has already been created by the time this hook runs. If that ordering ever changes (e.g., plugin load order tweaks or reuse in a different context), this will throw at startup.

Consider either:

  • Adding a defensive check with a clear error message if GlobalGraph.instance is undefined, or
  • Documenting/centralizing the initialization order so this assumption is explicit and test-covered.

Also applies to: 15-15, 140-142

plugin/controller/test/http/middleware-aop.test.ts (1)

5-30: Tighten test bootstrapping to avoid redundant mocks

The test logic and expectations look solid, but the lifecycle can be simplified:

  • EGG_TYPESCRIPT is mocked in both beforeEach and before, while mm.restore() in afterEach resets all mocks. In practice, only one of these is needed; keeping it in before (before app creation) is usually sufficient.
  • The describe title references middleware-graph-hook.test.ts while the file name is middleware-aop.test.ts, which can be slightly confusing when scanning test output.

Consider removing the redundant beforeEach mock and aligning the describe string with the filename.

plugin/controller/lib/MiddlewareGraphHook.ts (1)

11-83: Middleware graph hook is conceptually correct; consider edge cases and minor refinements

The hook correctly discovers AOP middlewares from controller classes/methods and wires them into the graph, and the use of a Set avoids duplicate edges per controller–middleware pair. A few nuances worth calling out:

  • Module dependency cycles: Because addInject also adds module-level edges, a controller in module A depending on middleware in module B, where B already depends on A (via regular injects), will now form a cycle and can cause moduleGraph.loopPath() to fail the build. If cross-module advice depends back on controllers/services, this may surface as new “recursive deps” errors. It’s worth confirming whether such patterns are expected and, if so, whether middleware edges should perhaps be treated differently (e.g., separate edge type or optional in module topological sort).
  • Proto selection by class only: findProtoNodeByClass picks the first proto whose clazz matches. In a future where advice protos might be multi-instance or qualified, this could become ambiguous. If you ever introduce multiple protos for the same advice class, you may want a more specific selection strategy (e.g., by qualifiers or module).
  • Minor cleanup: The pre-check const middlewareModuleNode = globalGraph.findModuleNode(...) is only used as a presence guard; addInject re-resolves the module internally. This is fine for now, but if you care about perf in large graphs, you could either:
    • Let addInject handle the missing-module case entirely, or
    • Extend addInject’s API in the future to reuse the resolved module node.

Functionally this looks good for the scenarios covered by the new tests; the above are mostly robustness concerns for more complex module graphs.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between babcb80 and 6dec6da.

📒 Files selected for processing (14)
  • core/controller-decorator/index.ts (1 hunks)
  • plugin/controller/app.ts (3 hunks)
  • plugin/controller/lib/MiddlewareGraphHook.ts (1 hunks)
  • plugin/controller/test/fixtures/apps/middleware-graph-app/app/router.ts (1 hunks)
  • plugin/controller/test/fixtures/apps/middleware-graph-app/config/config.default.js (1 hunks)
  • plugin/controller/test/fixtures/apps/middleware-graph-app/config/module.json (1 hunks)
  • plugin/controller/test/fixtures/apps/middleware-graph-app/config/plugin.js (1 hunks)
  • plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/advice/AnotherAdvice.ts (1 hunks)
  • plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/advice/TestAdvice.ts (1 hunks)
  • plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/package.json (1 hunks)
  • plugin/controller/test/fixtures/apps/middleware-graph-app/modules/controller-module/TestController.ts (1 hunks)
  • plugin/controller/test/fixtures/apps/middleware-graph-app/modules/controller-module/package.json (1 hunks)
  • plugin/controller/test/fixtures/apps/middleware-graph-app/package.json (1 hunks)
  • plugin/controller/test/http/middleware-aop.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
plugin/controller/test/fixtures/apps/middleware-graph-app/modules/controller-module/TestController.ts (1)
core/controller-decorator/src/decorator/http/HTTPMethod.ts (1)
  • HTTPMethod (7-23)
plugin/controller/app.ts (2)
core/metadata/src/model/graph/GlobalGraph.ts (1)
  • GlobalGraph (38-272)
plugin/controller/lib/MiddlewareGraphHook.ts (1)
  • middlewareGraphHook (11-27)
plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/advice/AnotherAdvice.ts (1)
plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/advice/TestAdvice.ts (1)
  • Advice (8-19)
plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/advice/TestAdvice.ts (1)
plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/advice/AnotherAdvice.ts (1)
  • Advice (8-19)
plugin/controller/lib/MiddlewareGraphHook.ts (6)
core/metadata/src/model/graph/GlobalGraph.ts (2)
  • GlobalGraph (38-272)
  • proto (143-159)
core/common-util/src/Graph.ts (1)
  • GraphNode (10-54)
core/metadata/src/model/ProtoDescriptor/ClassProtoDescriptor.ts (1)
  • ClassProtoDescriptor (10-38)
core/types/core-decorator/model/EggPrototypeInfo.ts (1)
  • EggProtoImplClass (5-5)
core/controller-decorator/src/util/ControllerInfoUtil.ts (1)
  • ControllerInfoUtil (14-76)
core/controller-decorator/src/util/MethodInfoUtil.ts (1)
  • MethodInfoUtil (24-116)
⏰ 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). (9)
  • GitHub Check: Socket Security: Pull Request Alerts
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Analyze (typescript)
  • GitHub Check: Runner-ubuntu (18)
  • GitHub Check: Runner-ubuntu (20)
  • GitHub Check: Runner-macos (20)
  • GitHub Check: Runner-macos (18)
  • GitHub Check: Runner-ubuntu (16)
  • GitHub Check: Runner-macos (16)
🔇 Additional comments (13)
plugin/controller/test/fixtures/apps/middleware-graph-app/package.json (1)

1-3: LGTM! Minimal package.json appropriate for test fixture.

The minimal manifest correctly identifies the test fixture app.

core/controller-decorator/index.ts (1)

24-24: LGTM! Export follows established pattern.

The new export of MethodInfoUtil is consistent with the existing ControllerInfoUtil export on Line 23.

plugin/controller/test/fixtures/apps/middleware-graph-app/config/config.default.js (1)

1-13: LGTM! Standard Egg.js configuration for test fixture.

The configuration structure is correct and appropriate for a test environment.

plugin/controller/test/fixtures/apps/middleware-graph-app/modules/controller-module/package.json (1)

1-6: LGTM! Valid Egg module manifest.

The module configuration correctly identifies the controller-module for the test fixture.

plugin/controller/test/fixtures/apps/middleware-graph-app/app/router.ts (1)

1-3: LGTM! Valid placeholder router.

The empty router file correctly satisfies Egg.js requirements for the test fixture.

plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/package.json (1)

1-6: LGTM! Valid Egg module manifest.

The module configuration correctly identifies the advice-module for the test fixture.

plugin/controller/test/fixtures/apps/middleware-graph-app/config/module.json (1)

1-8: LGTM! Module registry correctly configured.

The module paths correctly reference both the advice-module and controller-module for the middleware graph test fixture.

plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/advice/AnotherAdvice.ts (2)

1-6: LGTM! Imports are correct.

All necessary imports for the AOP advice implementation are present.


8-18: LGTM! Advice implementation follows established pattern.

The implementation correctly wraps the next() call and mutates the response body, matching the pattern used in TestAdvice. The unused _ctx parameter is properly prefixed with an underscore.

plugin/controller/test/fixtures/apps/middleware-graph-app/config/plugin.js (1)

1-21: Fixture plugin config looks consistent

The four plugin entries are well-structured and match the expected Egg/tegg plugin wiring pattern for this test fixture; no issues from a test-config perspective.

plugin/controller/test/fixtures/apps/middleware-graph-app/modules/controller-module/TestController.ts (1)

1-35: Controller and middleware wiring aligns with test scenarios

The HTTPController, HTTPMethod, and Middleware decorations are consistent with the tests: class-level middleware on /class-middleware and additional method-level middleware on /method-middleware. Import paths also look correct relative to the advice module layout.

plugin/controller/test/fixtures/apps/middleware-graph-app/modules/advice-module/advice/TestAdvice.ts (2)

1-6: LGTM: Imports are correct.

All imports are necessary and properly sourced from the @eggjs/tegg packages.


8-19: LGTM: Clean advice implementation for testing.

The implementation correctly follows the IAdvice interface and mirrors the pattern established in AnotherAdvice.ts. The body null-check prevents mutation errors, and the distinct property name (adviceApplied) enables test verification of class-level middleware application.

Copy link
Contributor

@gxkl gxkl left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link

@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: 0

🧹 Nitpick comments (3)
plugin/controller/test/mcp/mcpCluster.test.ts (1)

41-49: as any in notification parsing reduces type-safety but is acceptable in tests

Casting item to any is a pragmatic way to placate the type system here, but it hides real shape mismatches. If you want to keep some safety, consider narrowing on the concrete non‑text variant (e.g., by checking a specific item.type that is known to carry data) or asserting just that item has a data field instead of the full object cast.

plugin/controller/test/mcp/mcp.test.ts (1)

41-49: Same as any pattern as cluster tests; consider a narrower assertion

This mirrors the cluster test helper and keeps runtime behavior, but using (item as any).data drops type guarantees. If you later extend MCP content types, a more explicit branch (e.g., checking for a known binary type or 'data' in item) would make failures easier to catch while preserving most of this convenience.

plugin/controller/test/mcp/helper.test.ts (1)

108-111: Omitting tools capability relies on SDK defaults; consider making intent explicit

Commenting out tools: {} means this test now depends on the MCP client’s default capabilities behavior. That’s probably fine given the current SDK, but it’s a bit implicit: if the SDK later requires explicit tool capabilities, this test will start failing in a non-obvious way. A brief comment explaining why tools is intentionally omitted, or an assertion around the negotiated capabilities, would make this more robust.

If you haven’t already, please double‑check the current MCP client docs to confirm that omitting capabilities.tools is the recommended pattern and won’t disable tool calls in future versions.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6dec6da and 31692e7.

📒 Files selected for processing (3)
  • plugin/controller/test/mcp/helper.test.ts (1 hunks)
  • plugin/controller/test/mcp/mcp.test.ts (1 hunks)
  • plugin/controller/test/mcp/mcpCluster.test.ts (1 hunks)
⏰ 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). (8)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Analyze (typescript)
  • GitHub Check: Runner-ubuntu (18)
  • GitHub Check: Runner-ubuntu (16)
  • GitHub Check: Runner-ubuntu (20)
  • GitHub Check: Runner-macos (16)
  • GitHub Check: Runner-macos (20)
  • GitHub Check: Runner-macos (18)

@killagu killagu merged commit 7ab3eae into master Nov 18, 2025
12 checks passed
@killagu killagu deleted the fix/aop_middleware_module_order branch November 18, 2025 08:40
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.

3 participants