Skip to content

Conversation

@fengmk2
Copy link
Member

@fengmk2 fengmk2 commented Sep 26, 2025

  • Migrate @eggjs/static repository to plugins/static
  • Update version to 4.0.0-beta.11
  • Replace ESLint with oxlint for linting
  • Add TypeScript type checking with tsc --noEmit
  • Configure tsdown for unbundled ESM build
  • Add peerDependencies for egg using workspace:*
  • Update tests to use vitest
  • Add koa-range and ylru to pnpm catalog

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a Static plugin to serve assets with HTTP Range support, caching, multi-folder support, and middleware ordering to run before body parsing.
  • Documentation

    • Added README, CHANGELOG and LICENSE for the Static plugin and updated static-related docs.
  • Tests

    • Added comprehensive tests for range requests, caching, multi-dir setups, and custom prefixes.
  • Chores

    • Added package/build/test configs, TypeScript references, workspace dependency updates, fixtures, and package script tweaks.

@fengmk2 fengmk2 requested a review from Copilot September 26, 2025 16:21
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 26, 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 new Egg static plugin (middleware, types, configs, boot), tests/fixtures, package/build tooling and docs; updates workspace/tsconfig and dependencies; replaces a generic defineConfig API with defineConfigFactory and adjusts related imports and tests.

Changes

Cohort / File(s) Summary
Static plugin core
plugins/static/src/app.ts, plugins/static/src/app/middleware/static.ts, plugins/static/src/types.ts, plugins/static/src/index.ts
New plugin boot that ensures middleware runs before bodyParser; middleware serves single/multiple dirs, applies conditional koa-range, optional LRU dynamic tracking; adds TypeScript types and module augmentation for EggAppConfig.
Static plugin configs & build
plugins/static/src/config/config.default.ts, plugins/static/src/config/config.prod.ts, plugins/static/package.json, plugins/static/tsconfig.json, plugins/static/tsdown.config.ts, plugins/static/vitest.config.ts, plugins/static/.gitignore
New default/prod config files, package metadata/exports, tsconfig/tsdown/vitest configs and plugin .gitignore.
Tests & fixtures
plugins/static/test/static.test.ts, plugins/static/test/fixtures/**/*
New Vitest suite covering serving, range support, caching, multi-dir and custom-prefix scenarios plus fixture apps/assets/configs/routes/controllers.
Docs & licensing
plugins/static/README.md, plugins/static/CHANGELOG.md, plugins/static/LICENSE, CLAUDE.md
Added README, changelog, MIT license, and top-level doc entry describing the static components.
Workspace & repo metadata
pnpm-workspace.yaml, tsconfig.json, package.json
Added plugins/static workspace reference, adjusted catalog/dependencies (add koa-range, @types/koa-range, ylru; removed some catalog entries), and broadened top-level clean script.
Egg package API & types
packages/egg/src/lib/types.ts, packages/egg/src/config/config.default.ts, packages/egg/package.json, packages/egg/src/lib/types.plugin.ts
Split previous generic defineConfig into defineConfig and defineConfigFactory; switched egg config usage to defineConfigFactory; replaced runtime imports of some plugins with triple-slash type references and switched some deps to workspace:* in package.json.
Misc package script cleanup
packages/extend2/package.json, plugins/development/package.json, plugins/watcher/package.json, tools/egg-bin/package.json
Removed various clean/pretest scripts and some devDependencies across packages.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant C as Client
    participant App as Egg App
    participant Boot as AppBoot
    participant Static as Static Middleware
    participant Router as Router

    rect rgba(230,245,255,0.8)
    note over Boot,App: Startup — AppBoot.configWillLoad ensures "static" inserted before "bodyParser"
    Boot->>App: configWillLoad()
    end

    C->>App: HTTP request
    activate App
    App->>Static: invoke static middleware
    alt request path matches any configured prefix
        Static->>Static: apply koa-range (conditional on prefix)
        alt file found in current dir
            Static-->>C: 200 or 206 (with Content-Range)
        else try next configured dir
            Static->>Static: next()
            Static-->>App: when all dirs exhausted
        end
    else no prefix match / non-static route
        App->>Router: forward request
        Router-->>C: route response
    end
    deactivate App
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

I hop where assets dance on disk and stream,
I place my cache, I honor every range,
Before the parser I take my cue,
Directories tried till one comes through.
Tests pass, carrots earned — a rabbit's little cheer. 🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.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 clearly summarizes the primary change of migrating the @eggjs/static plugin into the monorepo in a concise and specific manner that maps to the contents of the changeset.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch static-plugin

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.

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 migrates the @eggjs/static plugin from a separate repository into the main Egg.js monorepo under the plugins/ directory. The migration includes updating the build system to use tsdown, replacing ESLint with oxlint, and updating tests to use vitest.

Key changes:

  • Migrated @eggjs/static plugin from external repository to plugins/static/ directory
  • Updated build toolchain to use tsdown for unbundled ESM builds and oxlint for linting
  • Updated package dependency management to use workspace references and pnpm catalog

Reviewed Changes

Copilot reviewed 38 out of 40 changed files in this pull request and generated 2 comments.

File Description
pnpm-workspace.yaml Added koa-range and ylru dependencies to pnpm catalog
plugins/static/ Complete plugin migration with source code, tests, and configuration
packages/egg/package.json Updated @eggjs/static dependency to use workspace reference
packages/egg/src/lib/types.plugin.ts Updated type imports for the migrated static plugin
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

maxAge: number;
/**
* dynamic load file which not cached on initialization
* Default to `true
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

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

Missing closing backtick and quote in the comment. Should be 'Default to true'

Suggested change
* Default to `true
* Default to `true`

Copilot uses AI. Check for mistakes.
@cloudflare-workers-and-pages
Copy link

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

Deploying egg with  Cloudflare Pages  Cloudflare Pages

Latest commit: 5dfd58e
Status:🚫  Build failed.

View logs

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @fengmk2, 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 integrates the @eggjs/static plugin directly into the main monorepo, streamlining its development and maintenance. It also brings significant updates to the plugin's build and testing toolchain, adopting modern JavaScript ecosystem practices like oxlint, tsdown, and vitest. The core static file serving logic has been refined to support advanced features such as range requests and improved caching mechanisms, ensuring better performance and flexibility.

Highlights

  • Monorepo Migration: The @eggjs/static plugin has been migrated into the monorepo under plugins/static, changing its dependency resolution from a catalog entry to a workspace dependency.
  • Tooling Modernization: The plugin's development setup has been updated to use oxlint for linting (replacing ESLint), tsc --noEmit for TypeScript type checking, tsdown for unbundled ESM builds, and vitest for testing.
  • Dependency Updates: The package.json for @eggjs/static now includes koa-range and ylru as dependencies, and egg as a peer dependency using workspace:*.
  • Static Middleware Enhancements: The static middleware now correctly handles multiple static directories, range requests, and incorporates LRU caching for dynamic file loading.
  • Configuration and Types: New default and production configurations for the static plugin have been added, along with comprehensive TypeScript type definitions for static options.
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.

@cloudflare-workers-and-pages
Copy link

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

Deploying egg-v3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 5dfd58e
Status:🚫  Build failed.

View logs

@codecov
Copy link

codecov bot commented Sep 26, 2025

Codecov Report

❌ Patch coverage is 96.55172% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 77.15%. Comparing base (7123cc8) to head (5dfd58e).
⚠️ Report is 1 commits behind head on next.

Files with missing lines Patch % Lines
plugins/static/src/app.ts 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             next    #5548      +/-   ##
==========================================
+ Coverage   76.50%   77.15%   +0.64%     
==========================================
  Files         131      138       +7     
  Lines        4491     4649     +158     
  Branches      651      684      +33     
==========================================
+ Hits         3436     3587     +151     
- Misses        984      991       +7     
  Partials       71       71              

☔ 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.

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 successfully migrates the @eggjs/static plugin into the monorepo, including its source code, tests, and configurations. The changes are well-structured and the new test suite using vitest is comprehensive. I have a couple of suggestions for the new middleware implementation to enhance type safety and improve user experience by warning about deprecated options. Overall, this is a solid contribution to the project's structure.

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: 10

🧹 Nitpick comments (8)
plugins/static/test/fixtures/static-server-with-dirs/package.json (1)

1-3: Mark fixture package as private to avoid accidental publish/workspace pickup.

Add "private": true to this fixture’s package.json.

Apply this diff:

 {
+  "private": true,
   "name": "static"
 }
plugins/static/src/index.ts (1)

1-1: Re-export StaticConfig and StaticDirOptions
tsconfig uses NodeNext resolution, so import './types.js' correctly picks up types.ts. Add:

 import './types.js';
+export type { StaticConfig, StaticDirOptions } from './types.js';
plugins/static/test/fixtures/static-server/package.json (1)

1-3: Mark fixture package.json as private to avoid accidental publish

Add "private": true to prevent publishing test fixtures to npm.

Apply this diff:

 {
-  "name": "static-server"
+  "name": "static-server",
+  "private": true
 }
plugins/static/test/fixtures/static-server-with-dir/package.json (1)

1-3: Mark fixture package.json as private

Prevents accidental publish for test-only package.

Apply this diff:

 {
-  "name": "static"
+  "name": "static",
+  "private": true
 }
plugins/static/test/fixtures/static-server-custom/package.json (1)

1-3: Mark fixture package.json as private

Avoid publishing fixtures to npm.

Apply this diff:

 {
-  "name": "static"
+  "name": "static",
+  "private": true
 }
plugins/static/test/fixtures/static-server-dist/package.json (1)

1-3: Mark fixture package.json as private

Prevents accidental publish of test fixture.

Apply this diff:

 {
-  "name": "static"
+  "name": "static",
+  "private": true
 }
plugins/static/src/config/config.prod.ts (1)

3-7: Do not cast partial overrides as full StaticConfig.

This object only sets two fields but is asserted as the complete StaticConfig, masking typos or missing required fields (e.g., dir). Please type it as a Partial<StaticConfig> instead of lying to the compiler.

-import type { StaticConfig } from '../types.js';
-
-export default {
-  static: {
-    maxAge: 31536000,
-    buffer: true,
-  } as StaticConfig,
-};
+import type { StaticConfig } from '../types.js';
+
+const staticProdConfig: Partial<StaticConfig> = {
+  maxAge: 31536000,
+  buffer: true,
+};
+
+export default {
+  static: staticProdConfig,
+};
plugins/static/src/config/config.default.ts (1)

5-18: Provide an explicit return type and avoid the as StaticConfig cast

The loose arrow function plus as StaticConfig assertion hides future type drift and goes against our guideline to use explicit return types for exported APIs. Refactoring to name the function, declare its return type, and assign the static config through a typed variable keeps full type-check coverage without unchecked casts. As per coding guidelines.

Apply this diff:

-export default (appInfo: EggAppInfo) => {
-  return {
-    static: {
-      prefix: '/public/',
-      dir: path.join(appInfo.baseDir, 'app/public'),
-      // dirs: [ dir1, dir2 ] or [ dir1, { prefix: '/static2', dir: dir2 } ],
-      dirs: undefined,
-      // support lazy load
-      dynamic: true,
-      preload: false,
-      buffer: false,
-      maxFiles: 1000,
-    } as StaticConfig,
-  };
-};
+export default function config(appInfo: EggAppInfo): { static: StaticConfig } {
+  const staticConfig: StaticConfig = {
+    prefix: '/public/',
+    dir: path.join(appInfo.baseDir, 'app/public'),
+    // dirs: [ dir1, dir2 ] or [ dir1, { prefix: '/static2', dir: dir2 } ],
+    dirs: undefined,
+    // support lazy load
+    dynamic: true,
+    preload: false,
+    buffer: false,
+    maxFiles: 1000,
+  };
+
+  return {
+    static: staticConfig,
+  };
+}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7123cc8 and 1359b24.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (39)
  • packages/egg/package.json (1 hunks)
  • packages/egg/src/lib/types.plugin.ts (1 hunks)
  • plugins/static/.gitignore (1 hunks)
  • plugins/static/CHANGELOG.md (1 hunks)
  • plugins/static/LICENSE (1 hunks)
  • plugins/static/README.md (1 hunks)
  • plugins/static/package.json (1 hunks)
  • plugins/static/src/app.ts (1 hunks)
  • plugins/static/src/app/middleware/static.ts (1 hunks)
  • plugins/static/src/config/config.default.ts (1 hunks)
  • plugins/static/src/config/config.prod.ts (1 hunks)
  • plugins/static/src/index.ts (1 hunks)
  • plugins/static/src/types.ts (1 hunks)
  • plugins/static/test/fixtures/static-server-custom/app/assets/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-custom/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-custom/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/app/assets/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/config/plugin.js (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/app/public/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/config/plugin.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/app/public/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/config/plugin.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server/app/controller/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server/app/public/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server/app/router.js (1 hunks)
  • plugins/static/test/fixtures/static-server/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server/package.json (1 hunks)
  • plugins/static/test/static.test.ts (1 hunks)
  • plugins/static/tsconfig.json (1 hunks)
  • plugins/static/tsdown.config.ts (1 hunks)
  • plugins/static/vitest.config.ts (1 hunks)
  • pnpm-workspace.yaml (3 hunks)
  • tsconfig.json (1 hunks)
👮 Files not reviewed due to content moderation or server errors (7)
  • plugins/static/test/fixtures/static-server-custom/app/assets/foo.js
  • plugins/static/LICENSE
  • plugins/static/tsdown.config.ts
  • plugins/static/test/fixtures/static-server-dist/config/plugin.js
  • plugins/static/test/fixtures/static-server/config/config.default.js
  • plugins/static/test/fixtures/static-server/app/router.js
  • pnpm-workspace.yaml
🧰 Additional context used
📓 Path-based instructions (17)
**/test/fixtures/**

📄 CodeRabbit inference engine (AGENTS.md)

Put reusable test data under test/fixtures/

Files:

  • plugins/static/test/fixtures/static-server-with-dirs/app/public/foo.js
  • plugins/static/test/fixtures/static-server-with-dir/app/public/foo.js
  • plugins/static/test/fixtures/static-server-custom/app/assets/foo.js
  • plugins/static/test/fixtures/static-server-with-dirs/config/plugin.js
  • plugins/static/test/fixtures/static-server-with-dir/package.json
  • plugins/static/test/fixtures/static-server-custom/package.json
  • plugins/static/test/fixtures/static-server/config/config.default.js
  • plugins/static/test/fixtures/static-server-dist/config/plugin.js
  • plugins/static/test/fixtures/static-server-with-dir/config/config.default.js
  • plugins/static/test/fixtures/static-server/app/router.js
  • plugins/static/test/fixtures/static-server-dist/app/assets/foo.js
  • plugins/static/test/fixtures/static-server-dist/config/config.default.js
  • plugins/static/test/fixtures/static-server-dist/package.json
  • plugins/static/test/fixtures/static-server/package.json
  • plugins/static/test/fixtures/static-server/app/public/foo.js
  • plugins/static/test/fixtures/static-server/app/controller/foo.js
  • plugins/static/test/fixtures/static-server-with-dirs/package.json
  • plugins/static/test/fixtures/static-server-custom/config/config.default.js
  • plugins/static/test/fixtures/static-server-with-dir/config/plugin.js
  • plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js
plugins/**/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

plugins/**/package.json: Plugin package.json must include peerDependencies { "egg": "workspace:" }
Plugin package.json exports should point to TypeScript sources for development and publishConfig.exports should mirror to dist/
.js
Plugins must include scripts: build (tsdown), clean (rimraf dist), typecheck (tsc --noEmit), lint (oxlint --type-aware), lint:fix, test (runs lint:fix then vitest), prepublishOnly (build)

Files:

  • plugins/static/test/fixtures/static-server-with-dir/package.json
  • plugins/static/test/fixtures/static-server-custom/package.json
  • plugins/static/package.json
  • plugins/static/test/fixtures/static-server-dist/package.json
  • plugins/static/test/fixtures/static-server/package.json
  • plugins/static/test/fixtures/static-server-with-dirs/package.json
{packages,plugins,tools}/**/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

{packages,plugins,tools}/**/package.json: All packages must provide a typecheck script using "tsc --noEmit"
All packages must use oxlint for linting with the command "oxlint --type-aware" (no ESLint configs)

Files:

  • plugins/static/test/fixtures/static-server-with-dir/package.json
  • plugins/static/test/fixtures/static-server-custom/package.json
  • plugins/static/package.json
  • plugins/static/test/fixtures/static-server-dist/package.json
  • plugins/static/test/fixtures/static-server/package.json
  • packages/egg/package.json
  • plugins/static/test/fixtures/static-server-with-dirs/package.json
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.ts: Prefer TypeScript and ESM: write sources and exports in .ts (ESM-first) rather than CommonJS
Use two-space indentation, trailing commas, and semicolons (Prettier/oxlint defaults)
Name files in lowercase with hyphens (e.g., loader-context.ts)
Name classes in PascalCase
Name functions and variables in camelCase
Re-export types thoughtfully to keep the public API stable

Files:

  • plugins/static/src/config/config.default.ts
  • plugins/static/src/index.ts
  • plugins/static/src/app.ts
  • plugins/static/tsdown.config.ts
  • plugins/static/src/types.ts
  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
  • plugins/static/src/app/middleware/static.ts
  • plugins/static/src/config/config.prod.ts
  • packages/egg/src/lib/types.plugin.ts
{packages,plugins,tools}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

{packages,plugins,tools}/**/*.{ts,tsx}: Prefer interfaces over type aliases for object shapes in TypeScript
Use explicit return types for public APIs
Use readonly modifiers where appropriate
Avoid the any type; prefer unknown when the type is truly unknown

Files:

  • plugins/static/src/config/config.default.ts
  • plugins/static/src/index.ts
  • plugins/static/src/app.ts
  • plugins/static/tsdown.config.ts
  • plugins/static/src/types.ts
  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
  • plugins/static/src/app/middleware/static.ts
  • plugins/static/src/config/config.prod.ts
  • packages/egg/src/lib/types.plugin.ts
plugins/**/tsdown.config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

All plugins must use the standard tsdown config: entry: 'src/**/*.ts', unbundle: true, dts: true, exports.devExports: true

Files:

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

📄 CodeRabbit inference engine (CLAUDE.md)

Packages should use tsdown for builds (presence of tsdown.config.ts)

Files:

  • plugins/static/tsdown.config.ts
**/test/**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/test/**/*.test.ts: Place test suites following Vitest discovery: /test//*.test.ts
Mirror the repository test pattern when adding new suites

Files:

  • plugins/static/test/static.test.ts
{packages,plugins,tools}/**/test/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Test files should follow the pattern test/**/*.test.ts

Files:

  • plugins/static/test/static.test.ts
{packages,plugins,tools}/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

In Vitest tests, import from vitest (e.g., import { describe, it } from 'vitest') and use Node.js assert for assertions

Files:

  • plugins/static/test/static.test.ts
packages/*/package.json

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

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

Files:

  • packages/egg/package.json
plugins/**/vitest.config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

All new plugins must use Vitest and include vitest.config.ts

Files:

  • plugins/static/vitest.config.ts
{packages,plugins,tools,examples,site}/**/tsconfig.json

📄 CodeRabbit inference engine (CLAUDE.md)

{packages,plugins,tools,examples,site}/**/tsconfig.json: All sub-project tsconfig.json files must extend the root tsconfig.json ("extends": "../../tsconfig.json")
Enable TypeScript strict mode in all packages (compilerOptions.strict: true)

Files:

  • plugins/static/tsconfig.json
{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
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:"

Files:

  • pnpm-workspace.yaml
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/egg/src/lib/types.plugin.ts
🧠 Learnings (28)
📓 Common learnings
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/ : All Egg plugins must live under plugins/ and follow the standard plugin structure (src/, test/, package.json with eggPlugin, tsdown.config.ts)
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugin package.json must include peerDependencies { "egg": "workspace:*" }
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: Applies to **/*.ts : Re-export types thoughtfully to keep the public API stable

Applied to files:

  • plugins/static/src/index.ts
  • packages/egg/src/lib/types.plugin.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/*.{ts,tsx} : Use explicit return types for public APIs

Applied to files:

  • plugins/static/src/index.ts
  • plugins/static/src/types.ts
  • packages/egg/src/lib/types.plugin.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugin package.json exports should point to TypeScript sources for development and publishConfig.exports should mirror to dist/*.js

Applied to files:

  • plugins/static/package.json
  • plugins/static/tsdown.config.ts
  • plugins/static/tsconfig.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugins must include scripts: build (tsdown), clean (rimraf dist), typecheck (tsc --noEmit), lint (oxlint --type-aware), lint:fix, test (runs lint:fix then vitest), prepublishOnly (build)

Applied to files:

  • plugins/static/package.json
  • plugins/static/test/fixtures/static-server-dist/package.json
  • plugins/static/test/fixtures/static-server-with-dirs/package.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugin package.json must include peerDependencies { "egg": "workspace:*" }

Applied to files:

  • plugins/static/package.json
  • packages/egg/package.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/ : All Egg plugins must live under plugins/ and follow the standard plugin structure (src/, test/, package.json with eggPlugin, tsdown.config.ts)

Applied to files:

  • plugins/static/package.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/tsdown.config.ts : All plugins must use the standard tsdown config: entry: 'src/**/*.ts', unbundle: true, dts: true, exports.devExports: true

Applied to files:

  • plugins/static/tsdown.config.ts
  • plugins/static/tsconfig.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/tsdown.config.ts : Packages should use tsdown for builds (presence of tsdown.config.ts)

Applied to files:

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

Applied to files:

  • plugins/static/tsdown.config.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to plugins/**/vitest.config.ts : All new plugins must use Vitest and include vitest.config.ts

Applied to files:

  • plugins/static/tsdown.config.ts
  • plugins/static/vitest.config.ts
  • plugins/static/tsconfig.json
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to packages/{egg,core,utils,mock,cluster,koa,supertest,extend2}/vitest.config.ts : Each package (except cookies) should include a Vitest configuration file vitest.config.ts

Applied to files:

  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/*.test.ts : In Vitest tests, import from vitest (e.g., import { describe, it } from 'vitest') and use Node.js assert for assertions

Applied to files:

  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: For features affecting HTTP or process orchestration, add regression tests that exercise both the CommonJS and TypeScript example apps

Applied to files:

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

Applied to files:

  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to tools/egg-bin/test/**/*.test.ts : egg-bin uses Mocha; test files follow test/**/*.test.ts

Applied to files:

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

Applied to files:

  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to packages/cookies/test/**/*.test.ts : cookies package uses Mocha; test files follow test/**/*.test.ts

Applied to files:

  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: Applies to **/test/**/*.test.ts : Place test suites following Vitest discovery: **/test/**/*.test.ts

Applied to files:

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

Applied to files:

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

Applied to files:

  • packages/egg/package.json
  • pnpm-workspace.yaml
📚 Learning: 2025-09-14T08:41:30.618Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.618Z
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:

  • packages/egg/package.json
  • pnpm-workspace.yaml
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Use pnpm catalog mode: external deps referenced as "catalog:" and internal workspace deps as "workspace:*"

Applied to files:

  • packages/egg/package.json
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to {packages,plugins,tools,examples,site}/**/tsconfig.json : All sub-project tsconfig.json files must extend the root tsconfig.json ("extends": "../../tsconfig.json")

Applied to files:

  • plugins/static/tsconfig.json
  • tsconfig.json
📚 Learning: 2025-09-14T08:41:30.618Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.618Z
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/static/tsconfig.json
  • tsconfig.json
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to {packages,plugins,tools,examples,site}/**/tsconfig.json : Enable TypeScript strict mode in all packages (compilerOptions.strict: true)

Applied to files:

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

Applied to files:

  • tsconfig.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to packages/{egg,core}/tsconfig.json : packages/egg and packages/core must have strict mode enabled in their tsconfig.json

Applied to files:

  • packages/egg/src/lib/types.plugin.ts
🧬 Code graph analysis (13)
plugins/static/test/fixtures/static-server-with-dirs/config/plugin.js (1)
plugins/static/test/fixtures/static-server-custom/config/config.default.js (1)
  • exports (4-4)
plugins/static/src/config/config.default.ts (1)
plugins/static/src/types.ts (1)
  • StaticConfig (46-57)
plugins/static/test/fixtures/static-server-dist/config/plugin.js (1)
plugins/static/test/fixtures/static-server-custom/config/config.default.js (1)
  • exports (4-4)
plugins/static/test/fixtures/static-server-with-dir/config/config.default.js (1)
plugins/static/src/config/config.default.ts (1)
  • appInfo (5-19)
plugins/static/src/app.ts (1)
packages/core/src/egg.ts (1)
  • EggCore (95-543)
plugins/static/tsdown.config.ts (1)
packages/egg/src/lib/types.ts (1)
  • defineConfig (109-111)
plugins/static/src/types.ts (1)
packages/egg/src/lib/types.ts (1)
  • EggAppConfig (113-287)
plugins/static/test/static.test.ts (2)
scripts/version.js (2)
  • __filename (11-11)
  • __dirname (12-12)
packages/egg/test/utils.ts (1)
  • MockApplication (24-24)
plugins/static/vitest.config.ts (1)
packages/egg/src/lib/types.ts (1)
  • defineConfig (109-111)
plugins/static/src/app/middleware/static.ts (2)
plugins/static/src/types.ts (2)
  • StaticConfig (46-57)
  • StaticDirOptions (3-39)
packages/koa-static-cache/src/index.ts (1)
  • staticCache (139-321)
plugins/static/src/config/config.prod.ts (1)
plugins/static/src/types.ts (1)
  • StaticConfig (46-57)
plugins/static/test/fixtures/static-server-custom/config/config.default.js (2)
plugins/static/test/fixtures/static-server-with-dir/config/config.default.js (1)
  • path (1-1)
plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js (1)
  • path (1-1)
plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js (1)
plugins/static/src/config/config.default.ts (1)
  • appInfo (5-19)
🪛 GitHub Check: Test (ubuntu-latest, 22, plugins)
plugins/static/test/static.test.ts

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 GitHub Check: Test (macos-latest, 22, plugins)
plugins/static/test/static.test.ts

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 markdownlint-cli2 (0.18.1)
plugins/static/README.md

20-20: Bare URL used

(MD034, no-bare-urls)


22-22: Bare URL used

(MD034, no-bare-urls)


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

(MD007, ul-indent)


30-30: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


31-31: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


32-32: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


35-35: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


36-36: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


37-37: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


40-40: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


41-41: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


44-44: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


45-45: Hard tabs
Column: 1

(MD010, no-hard-tabs)

⏰ 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). (16)
  • GitHub Check: Test (ubuntu-latest, 24, plugins)
  • GitHub Check: Test (macos-latest, 24, plugins)
  • GitHub Check: Test (windows-latest, 24, packages)
  • GitHub Check: Test (ubuntu-latest, 22, packages)
  • GitHub Check: Test (macos-latest, 24, packages)
  • GitHub Check: Test (windows-latest, 22, packages)
  • GitHub Check: Test (macos-latest, 22, tools)
  • GitHub Check: Test (windows-latest, 24, plugins)
  • GitHub Check: Test (windows-latest, 22, plugins)
  • GitHub Check: Test (ubuntu-latest, 24, packages)
  • GitHub Check: Test egg-bin (windows-latest, 24)
  • GitHub Check: Test egg-bin (macos-latest, 22)
  • GitHub Check: Test egg-bin (windows-latest, 22)
  • GitHub Check: Test egg-bin (ubuntu-latest, 24)
  • GitHub Check: Test egg-bin (macos-latest, 24)
  • GitHub Check: Test egg-bin (ubuntu-latest, 22)
🔇 Additional comments (15)
plugins/static/.gitignore (1)

1-11: LGTM on ignore patterns

Ignore list matches the plugin's workspace layout and keeps build artifacts, fixtures, and temp files out of VCS.

packages/egg/package.json (1)

133-133: Switch to workspace dependency aligns with the new plugin location

Pointing @eggjs/static to workspace:* keeps the core package synced with the in-repo plugin and matches our workspace policy. Based on learnings.

plugins/static/test/fixtures/static-server/app/controller/foo.js (1)

3-7: LGTM for fixture handler.

Simple CJS controller is fine for test fixtures; response fields are set correctly.

plugins/static/test/fixtures/static-server-custom/config/config.default.js (1)

6-9: Summary mismatch: dynamic/preload/buffer not present.

The AI summary mentions dynamic, preload, and buffer, but the code only sets prefix and dir. Confirm defaults suffice for this fixture or add explicit flags if tests expect them.

plugins/static/test/fixtures/static-server-with-dir/app/public/foo.js (1)

1-1: LGTM for static asset.

Appropriate minimal test fixture asset.

plugins/static/test/fixtures/static-server-with-dirs/config/plugin.js (1)

1-1: LGTM: plugin enabled for fixture.

exports.static = true is correct for the fixture setup.

plugins/static/test/fixtures/static-server-with-dirs/app/public/foo.js (1)

1-1: LGTM for static asset.

Minimal fixture asset is fine.

plugins/static/CHANGELOG.md (1)

10-12: Node.js ≥22.18.0 requirement is consistent across CHANGELOG, package.json engines, and CI matrix.

plugins/static/test/fixtures/static-server/app/public/foo.js (1)

1-1: LGTM for fixture asset

Simple static asset is fine.

tsconfig.json (1)

56-60: Added plugins/static to TS project references — looks good

Reference placement and JSON structure are correct.

packages/egg/src/lib/types.plugin.ts (1)

14-14: Add missing clean script in plugin package.json

plugins/static/package.json: add
"clean": "rimraf dist"
under scripts to meet plugin standards.

⛔ Skipped due to learnings
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugins must include scripts: build (tsdown), clean (rimraf dist), typecheck (tsc --noEmit), lint (oxlint --type-aware), lint:fix, test (runs lint:fix then vitest), prepublishOnly (build)
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugin package.json exports should point to TypeScript sources for development and publishConfig.exports should mirror to dist/*.js
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to tools/egg-bin/test/**/*.test.ts : egg-bin uses Mocha; test files follow test/**/*.test.ts
plugins/static/test/fixtures/static-server-dist/app/assets/foo.js (1)

1-1: Fixture asset looks good

The minimal script is all this fixture needs—no issues spotted.

plugins/static/test/fixtures/static-server-with-dir/config/plugin.js (1)

1-1: Plugin flag wiring looks right

Confirming the fixture exposes the static plugin exactly as expected.

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

1-8: Vitest config matches project conventions

Timeout and test globs line up with the repo’s testing standards—looks good.

plugins/static/test/fixtures/static-server-dist/config/config.default.js (1)

1-8: Fixture config matches the expected dist/static layout

The prefix, directory, and buffering options align with the other static server fixtures. Looks good to me.

Comment on lines +27 to +42
- prefix: `'/public/'`
- dir: `path.join(appInfo.baseDir, 'app/public')`
- dynamic: `true`
- preload: `false`
- maxAge: `31536000` in prod env, `0` in other envs
- buffer: `true` in prod env, `false` in other envs

`@eggjs/static` provides one more option:

- maxFiles: the maximum value of cache items, only effective when dynamic is true, default is `1000`.

**All static files in `$baseDir/app/public` can be visited with prefix `/public`, and all the files are lazy loaded.**

- In non-production environment, assets won't be cached, your modification can take effect immediately.
- In production environment, `@eggjs/static` will cache the assets after visited, you need to restart the process to update the assets.
- Dir default is `$baseDir/app/public` but you can also define **multiple directory** by use `dir: [dir1, dir2, ...]` or `dir: [dir1, { prefix: '/static2', dir: dir2 }]`, static server will use all these directories.
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 | 🟠 Major

Fix markdownlint violations in list indentation

Each list item here is preceded by a hard tab, so markdownlint reports MD010/MD007 failures and the docs lint step will keep failing. Please replace the tabs with spaces (two spaces after the hyphen is fine) so the list renders correctly and the lint job passes. Based on static analysis hints.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

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

(MD007, ul-indent)


30-30: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


31-31: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


32-32: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


35-35: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


36-36: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


37-37: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


40-40: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


41-41: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🤖 Prompt for AI Agents
In plugins/static/README.md around lines 27 to 42, several list items use hard
tabs before the hyphen which causes markdownlint MD010/MD007 failures; replace
each leading tab with spaces (use a single space or two spaces after the hyphen
for list content, e.g., "-  prefix: ..." or "- prefix: ..." consistently) across
that block so the items are space-indented, and ensure nested/continued lines
follow standard Markdown list spacing to resolve the lint errors.

Comment on lines +11 to +16
const index = app.config.coreMiddleware.indexOf('bodyParser');
if (index === -1) {
app.config.coreMiddleware.push('static');
} else {
app.config.coreMiddleware.splice(index, 0, 'static');
}
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 | 🟠 Major

Prevent duplicate static middleware registrations

coreMiddleware may already contain 'static' (either from user config or legacy defaults). Injecting another 'static' entry without deduplication registers the middleware twice, so every non-static request now pays for two static passes and apps that already positioned the middleware correctly end up with redundant work. Please drop any existing 'static' entry before re‑inserting it ahead of bodyParser.

-    const index = app.config.coreMiddleware.indexOf('bodyParser');
-    if (index === -1) {
-      app.config.coreMiddleware.push('static');
-    } else {
-      app.config.coreMiddleware.splice(index, 0, 'static');
-    }
+    const middlewares = app.config.coreMiddleware;
+    const existingIndex = middlewares.indexOf('static');
+    if (existingIndex !== -1) {
+      middlewares.splice(existingIndex, 1);
+    }
+    const bodyParserIndex = middlewares.indexOf('bodyParser');
+    if (bodyParserIndex === -1) {
+      middlewares.push('static');
+    } else {
+      middlewares.splice(bodyParserIndex, 0, 'static');
+    }
📝 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
const index = app.config.coreMiddleware.indexOf('bodyParser');
if (index === -1) {
app.config.coreMiddleware.push('static');
} else {
app.config.coreMiddleware.splice(index, 0, 'static');
}
const middlewares = app.config.coreMiddleware;
const existingIndex = middlewares.indexOf('static');
if (existingIndex !== -1) {
middlewares.splice(existingIndex, 1);
}
const bodyParserIndex = middlewares.indexOf('bodyParser');
if (bodyParserIndex === -1) {
middlewares.push('static');
} else {
middlewares.splice(bodyParserIndex, 0, 'static');
}
🤖 Prompt for AI Agents
In plugins/static/src/app.ts around lines 11 to 16, the code can insert a
duplicate 'static' into app.config.coreMiddleware; before inserting, remove any
existing 'static' entries from coreMiddleware, then compute the index of
'bodyParser' and insert 'static' ahead of it (or push if bodyParser not
present). Ensure you remove all occurrences of 'static' (e.g., filter or loop to
splice) before performing the splice or push so the middleware is deduplicated
and only inserted once.

Comment on lines +55 to +57
if (newOptions.prefix) {
prefixes.push(newOptions.prefix);
}
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 | 🟠 Major

Restore range support for empty-prefix static mounts.

Skipping falsy prefixes drops range handling when prefix is '', so assets mounted at root lose HTTP range functionality (regression from prior behavior). Normalize the prefix and always record it.

-    if (newOptions.prefix) {
-      prefixes.push(newOptions.prefix);
-    }
+    const normalizedPrefix = (newOptions.prefix ?? '').replace(/\/*$/, '/');
+    prefixes.push(normalizedPrefix);
📝 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
if (newOptions.prefix) {
prefixes.push(newOptions.prefix);
}
const normalizedPrefix = (newOptions.prefix ?? '').replace(/\/*$/, '/');
prefixes.push(normalizedPrefix);
🤖 Prompt for AI Agents
In plugins/static/src/app/middleware/static.ts around lines 55 to 57, the code
skips falsy prefixes which drops support for an explicit empty-string prefix and
breaks range handling for assets mounted at root; instead, normalize the prefix
value to a string (e.g. default to '' when undefined/null) and always push that
normalized prefix into the prefixes array so empty-string mounts are preserved
and range handling remains enabled.

Comment on lines 12 to 38
prefix: string;
/**
* cache max age in `seconds`
* Default to `0` on development, `31536000` on production
*/
maxAge: number;
/**
* dynamic load file which not cached on initialization
* Default to `true
*/
dynamic: boolean;
/**
* caches the assets on initialization or not,
* always work together with `options.dynamic`
* Default to `false`
*/
preload: boolean;
/**
* buffer the file content or not
* Default to `false` on development, `true` on production
*/
buffer: boolean;
/**
* max files count in store
* Default to `1000`
*/
maxFiles: number;
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 | 🟠 Major

Keep static config properties optional for consumers

By redeclaring prefix, maxAge, dynamic, preload, buffer, and maxFiles as required, the augmented EggAppConfig['static'] now forces every app to specify these fields explicitly even when relying on the documented defaults from @eggjs/koa-static-cache. This breaks existing TypeScript configs that only override a subset of options. Please leave these members optional (matching StaticCacheOptions) so downstream configs remain valid.

-  prefix: string;
+  prefix?: string;
@@
-  maxAge: number;
+  maxAge?: number;
@@
-  dynamic: boolean;
+  dynamic?: boolean;
@@
-  preload: boolean;
+  preload?: boolean;
@@
-  buffer: boolean;
+  buffer?: boolean;
@@
-  maxFiles: number;
+  maxFiles?: number;
📝 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
prefix: string;
/**
* cache max age in `seconds`
* Default to `0` on development, `31536000` on production
*/
maxAge: number;
/**
* dynamic load file which not cached on initialization
* Default to `true
*/
dynamic: boolean;
/**
* caches the assets on initialization or not,
* always work together with `options.dynamic`
* Default to `false`
*/
preload: boolean;
/**
* buffer the file content or not
* Default to `false` on development, `true` on production
*/
buffer: boolean;
/**
* max files count in store
* Default to `1000`
*/
maxFiles: number;
prefix?: string;
/**
* cache max age in `seconds`
* Default to `0` on development, `31536000` on production
*/
maxAge?: number;
/**
* dynamic load file which not cached on initialization
* Default to `true
*/
dynamic?: boolean;
/**
* caches the assets on initialization or not,
* always work together with `options.dynamic`
* Default to `false`
*/
preload?: boolean;
/**
* buffer the file content or not
* Default to `false` on development, `true` on production
*/
buffer?: boolean;
/**
* max files count in store
* Default to `1000`
*/
maxFiles?: number;
🤖 Prompt for AI Agents
In plugins/static/src/types.ts around lines 12 to 38, the properties prefix,
maxAge, dynamic, preload, buffer and maxFiles were declared as required which
forces downstream apps to specify them; change the declarations to be optional
to match @eggjs/koa-static-cache defaults — either mark each property with ? or
better reuse the upstream type (e.g. import StaticCacheOptions and make
EggAppConfig['static'] extend or be Partial<StaticCacheOptions> plus any
plugin-specific fields) so consumers can override only a subset of options.

Comment on lines +8 to +10
dir: [path.join(appInfo.baseDir, '/app/public'), path.join(appInfo.baseDir, '/dist/static')],
buffer: true,
},
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 | 🔴 Critical

Remove the leading slash when joining fixture dirs

path.join(appInfo.baseDir, '/app/public') treats the second argument as absolute, so the baseDir is dropped and we end up serving /app/public from the filesystem root. Same for the /dist/static join. That breaks the fixture and any tests relying on it.

Apply this diff:

-      dir: [path.join(appInfo.baseDir, '/app/public'), path.join(appInfo.baseDir, '/dist/static')],
+      dir: [
+        path.join(appInfo.baseDir, 'app/public'),
+        path.join(appInfo.baseDir, 'dist/static'),
+      ],
📝 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
dir: [path.join(appInfo.baseDir, '/app/public'), path.join(appInfo.baseDir, '/dist/static')],
buffer: true,
},
dir: [
path.join(appInfo.baseDir, 'app/public'),
path.join(appInfo.baseDir, 'dist/static'),
],
buffer: true,
},
🤖 Prompt for AI Agents
In plugins/static/test/fixtures/static-server-with-dir/config/config.default.js
around lines 8 to 10, the path.join calls use leading slashes which make the
second argument absolute and drop appInfo.baseDir; change
path.join(appInfo.baseDir, '/app/public') to path.join(appInfo.baseDir,
'app/public') and path.join(appInfo.baseDir, '/dist/static') to
path.join(appInfo.baseDir, 'dist/static') so the fixture serves from the
intended project-relative directories.

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

🧹 Nitpick comments (4)
plugins/static/CHANGELOG.md (1)

29-46: Replace hard tabs in the summary list

The bullets under “Summary by CodeRabbit” are tab-indented, which violates the markdown style (MD007/MD010) and will keep markdownlint failing. Switch to space indentation.

--	- **New Features**
--		- Updated package to `@eggjs/static`
--		- Enhanced TypeScript support
--		- Improved static file serving configuration
--
--	- **Chores**
--		- Updated GitHub Actions workflows
--		- Modernized project configuration
--		- Updated Node.js version support to 18.19.0, 20, and 22
--
--	- **Documentation**
--		- Updated README with new package details
--		- Simplified changelog and documentation
--
--	- **Refactor**
--		- Migrated from CommonJS to ES modules
--		- Restructured project file organization
+-  **New Features**
+    - Updated package to `@eggjs/static`
+    - Enhanced TypeScript support
+    - Improved static file serving configuration
+
+-  **Chores**
+    - Updated GitHub Actions workflows
+    - Modernized project configuration
+    - Updated Node.js version support to 18.19.0, 20, and 22
+
+-  **Documentation**
+    - Updated README with new package details
+    - Simplified changelog and documentation
+
+-  **Refactor**
+    - Migrated from CommonJS to ES modules
+    - Restructured project file organization
plugins/static/src/config/config.prod.ts (1)

3-8: Avoid asserting a partial config as full StaticConfig

The as StaticConfig assertion hides that this file only overrides a subset of fields (e.g., no dir). Using satisfies Partial<StaticConfig> keeps the override honest while preserving type safety.

 export default {
   static: {
     maxAge: 31536000,
     buffer: true,
-  } as StaticConfig,
+  } satisfies Partial<StaticConfig>,
 };
plugins/static/README.md (1)

55-55: Make the support link descriptive

Markdownlint flags “[here]” as non-descriptive. Please expand the anchor text so readers (and accessibility tools) know where it leads.

Apply this diff:

-Please open an issue [here](https://github.com/eggjs/egg/issues).
+Please open an issue on the [eggjs/egg issue tracker](https://github.com/eggjs/egg/issues).

Based on static analysis hints.

plugins/static/src/config/config.default.ts (1)

5-18: Add explicit return type to exported config

This default export is part of the plugin’s public surface, but it relies on inference plus an as cast for typing. Declaring the return type directly improves readability and eliminates the cast.

-export default (appInfo: EggAppInfo) => {
-  return {
-    static: {
-      prefix: '/public/',
-      dir: path.join(appInfo.baseDir, 'app/public'),
-      // dirs: [ dir1, dir2 ] or [ dir1, { prefix: '/static2', dir: dir2 } ],
-      dirs: undefined,
-      // support lazy load
-      dynamic: true,
-      preload: false,
-      buffer: false,
-      maxFiles: 1000,
-    } as StaticConfig,
-  };
-};
+export default (appInfo: EggAppInfo): { static: StaticConfig } => ({
+  static: {
+    prefix: '/public/',
+    dir: path.join(appInfo.baseDir, 'app/public'),
+    // dirs: [ dir1, dir2 ] or [ dir1, { prefix: '/static2', dir: dir2 } ],
+    dirs: undefined,
+    // support lazy load
+    dynamic: true,
+    preload: false,
+    buffer: false,
+    maxFiles: 1000,
+  },
+});

As per coding guidelines

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7123cc8 and 6e665d6.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (40)
  • CLAUDE.md (2 hunks)
  • packages/egg/package.json (1 hunks)
  • packages/egg/src/lib/types.plugin.ts (1 hunks)
  • plugins/static/.gitignore (1 hunks)
  • plugins/static/CHANGELOG.md (1 hunks)
  • plugins/static/LICENSE (1 hunks)
  • plugins/static/README.md (1 hunks)
  • plugins/static/package.json (1 hunks)
  • plugins/static/src/app.ts (1 hunks)
  • plugins/static/src/app/middleware/static.ts (1 hunks)
  • plugins/static/src/config/config.default.ts (1 hunks)
  • plugins/static/src/config/config.prod.ts (1 hunks)
  • plugins/static/src/index.ts (1 hunks)
  • plugins/static/src/types.ts (1 hunks)
  • plugins/static/test/fixtures/static-server-custom/app/assets/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-custom/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-custom/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/app/assets/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/config/plugin.js (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/app/public/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/config/plugin.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/app/public/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/config/plugin.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server/app/controller/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server/app/public/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server/app/router.js (1 hunks)
  • plugins/static/test/fixtures/static-server/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server/package.json (1 hunks)
  • plugins/static/test/static.test.ts (1 hunks)
  • plugins/static/tsconfig.json (1 hunks)
  • plugins/static/tsdown.config.ts (1 hunks)
  • plugins/static/vitest.config.ts (1 hunks)
  • pnpm-workspace.yaml (3 hunks)
  • tsconfig.json (1 hunks)
👮 Files not reviewed due to content moderation or server errors (6)
  • plugins/static/test/fixtures/static-server-with-dir/package.json
  • plugins/static/.gitignore
  • plugins/static/test/fixtures/static-server-with-dirs/app/public/foo.js
  • plugins/static/test/fixtures/static-server-custom/app/assets/foo.js
  • plugins/static/test/fixtures/static-server/app/public/foo.js
  • plugins/static/test/fixtures/static-server-dist/config/plugin.js
🧰 Additional context used
📓 Path-based instructions (17)
**/test/fixtures/**

📄 CodeRabbit inference engine (AGENTS.md)

Put reusable test data under test/fixtures/

Files:

  • plugins/static/test/fixtures/static-server-dist/config/config.default.js
  • plugins/static/test/fixtures/static-server/app/router.js
  • plugins/static/test/fixtures/static-server-with-dir/config/plugin.js
  • plugins/static/test/fixtures/static-server/package.json
  • plugins/static/test/fixtures/static-server-with-dir/config/config.default.js
  • plugins/static/test/fixtures/static-server-dist/package.json
  • plugins/static/test/fixtures/static-server-dist/config/plugin.js
  • plugins/static/test/fixtures/static-server-dist/app/assets/foo.js
  • plugins/static/test/fixtures/static-server-custom/config/config.default.js
  • plugins/static/test/fixtures/static-server-with-dirs/package.json
  • plugins/static/test/fixtures/static-server-custom/package.json
  • plugins/static/test/fixtures/static-server-with-dirs/config/plugin.js
  • plugins/static/test/fixtures/static-server/app/controller/foo.js
  • plugins/static/test/fixtures/static-server-with-dirs/app/public/foo.js
  • plugins/static/test/fixtures/static-server-with-dir/package.json
  • plugins/static/test/fixtures/static-server-custom/app/assets/foo.js
  • plugins/static/test/fixtures/static-server/app/public/foo.js
  • plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js
  • plugins/static/test/fixtures/static-server-with-dir/app/public/foo.js
  • plugins/static/test/fixtures/static-server/config/config.default.js
packages/*/package.json

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

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

Files:

  • packages/egg/package.json
{packages,plugins,tools}/**/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

{packages,plugins,tools}/**/package.json: All packages must provide a typecheck script using "tsc --noEmit"
All packages must use oxlint for linting with the command "oxlint --type-aware" (no ESLint configs)

Files:

  • packages/egg/package.json
  • plugins/static/test/fixtures/static-server/package.json
  • plugins/static/test/fixtures/static-server-dist/package.json
  • plugins/static/package.json
  • plugins/static/test/fixtures/static-server-with-dirs/package.json
  • plugins/static/test/fixtures/static-server-custom/package.json
  • plugins/static/test/fixtures/static-server-with-dir/package.json
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.ts: Prefer TypeScript and ESM: write sources and exports in .ts (ESM-first) rather than CommonJS
Use two-space indentation, trailing commas, and semicolons (Prettier/oxlint defaults)
Name files in lowercase with hyphens (e.g., loader-context.ts)
Name classes in PascalCase
Name functions and variables in camelCase
Re-export types thoughtfully to keep the public API stable

Files:

  • plugins/static/vitest.config.ts
  • plugins/static/src/app.ts
  • plugins/static/src/config/config.prod.ts
  • plugins/static/test/static.test.ts
  • plugins/static/src/types.ts
  • plugins/static/src/index.ts
  • packages/egg/src/lib/types.plugin.ts
  • plugins/static/src/config/config.default.ts
  • plugins/static/src/app/middleware/static.ts
  • plugins/static/tsdown.config.ts
plugins/**/vitest.config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

All new plugins must use Vitest and include vitest.config.ts

Files:

  • plugins/static/vitest.config.ts
{packages,plugins,tools}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

{packages,plugins,tools}/**/*.{ts,tsx}: Prefer interfaces over type aliases for object shapes in TypeScript
Use explicit return types for public APIs
Use readonly modifiers where appropriate
Avoid the any type; prefer unknown when the type is truly unknown

Files:

  • plugins/static/vitest.config.ts
  • plugins/static/src/app.ts
  • plugins/static/src/config/config.prod.ts
  • plugins/static/test/static.test.ts
  • plugins/static/src/types.ts
  • plugins/static/src/index.ts
  • packages/egg/src/lib/types.plugin.ts
  • plugins/static/src/config/config.default.ts
  • plugins/static/src/app/middleware/static.ts
  • plugins/static/tsdown.config.ts
plugins/**/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

plugins/**/package.json: Plugin package.json must include peerDependencies { "egg": "workspace:" }
Plugin package.json exports should point to TypeScript sources for development and publishConfig.exports should mirror to dist/
.js
Plugins must include scripts: build (tsdown), clean (rimraf dist), typecheck (tsc --noEmit), lint (oxlint --type-aware), lint:fix, test (runs lint:fix then vitest), prepublishOnly (build)

Files:

  • plugins/static/test/fixtures/static-server/package.json
  • plugins/static/test/fixtures/static-server-dist/package.json
  • plugins/static/package.json
  • plugins/static/test/fixtures/static-server-with-dirs/package.json
  • plugins/static/test/fixtures/static-server-custom/package.json
  • plugins/static/test/fixtures/static-server-with-dir/package.json
{packages,plugins,tools,examples,site}/**/tsconfig.json

📄 CodeRabbit inference engine (CLAUDE.md)

{packages,plugins,tools,examples,site}/**/tsconfig.json: All sub-project tsconfig.json files must extend the root tsconfig.json ("extends": "../../tsconfig.json")
Enable TypeScript strict mode in all packages (compilerOptions.strict: true)

Files:

  • plugins/static/tsconfig.json
**/test/**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/test/**/*.test.ts: Place test suites following Vitest discovery: /test//*.test.ts
Mirror the repository test pattern when adding new suites

Files:

  • plugins/static/test/static.test.ts
{packages,plugins,tools}/**/test/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Test files should follow the pattern test/**/*.test.ts

Files:

  • plugins/static/test/static.test.ts
{packages,plugins,tools}/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

In Vitest tests, import from vitest (e.g., import { describe, it } from 'vitest') and use Node.js assert for assertions

Files:

  • plugins/static/test/static.test.ts
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/egg/src/lib/types.plugin.ts
plugins/**/tsdown.config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

All plugins must use the standard tsdown config: entry: 'src/**/*.ts', unbundle: true, dts: true, exports.devExports: true

Files:

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

📄 CodeRabbit inference engine (CLAUDE.md)

Packages should use tsdown for builds (presence of tsdown.config.ts)

Files:

  • plugins/static/tsdown.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
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:"

Files:

  • pnpm-workspace.yaml
🧠 Learnings (29)
📓 Common learnings
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/ : All Egg plugins must live under plugins/ and follow the standard plugin structure (src/, test/, package.json with eggPlugin, tsdown.config.ts)
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugin package.json must include peerDependencies { "egg": "workspace:*" }

Applied to files:

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

Applied to files:

  • packages/egg/package.json
  • plugins/static/package.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to packages/{egg,core}/tsconfig.json : packages/egg and packages/core must have strict mode enabled in their tsconfig.json

Applied to files:

  • packages/egg/package.json
  • packages/egg/src/lib/types.plugin.ts
  • plugins/static/package.json
  • plugins/static/src/app/middleware/static.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Use pnpm catalog mode: external deps referenced as "catalog:" and internal workspace deps as "workspace:*"

Applied to files:

  • packages/egg/package.json
📚 Learning: 2025-09-14T08:41:30.618Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.618Z
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:

  • packages/egg/package.json
  • pnpm-workspace.yaml
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to plugins/**/vitest.config.ts : All new plugins must use Vitest and include vitest.config.ts

Applied to files:

  • plugins/static/vitest.config.ts
  • plugins/static/tsconfig.json
  • plugins/static/tsdown.config.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to packages/{egg,core,utils,mock,cluster,koa,supertest,extend2}/vitest.config.ts : Each package (except cookies) should include a Vitest configuration file vitest.config.ts

Applied to files:

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

Applied to files:

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

Applied to files:

  • plugins/static/vitest.config.ts
  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: Applies to **/test/**/*.test.ts : Place test suites following Vitest discovery: **/test/**/*.test.ts

Applied to files:

  • plugins/static/vitest.config.ts
  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/*.test.ts : In Vitest tests, import from vitest (e.g., import { describe, it } from 'vitest') and use Node.js assert for assertions

Applied to files:

  • plugins/static/vitest.config.ts
  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to {packages,plugins,tools,examples,site}/**/tsconfig.json : All sub-project tsconfig.json files must extend the root tsconfig.json ("extends": "../../tsconfig.json")

Applied to files:

  • plugins/static/tsconfig.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/tsdown.config.ts : All plugins must use the standard tsdown config: entry: 'src/**/*.ts', unbundle: true, dts: true, exports.devExports: true

Applied to files:

  • plugins/static/tsconfig.json
  • plugins/static/tsdown.config.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugin package.json exports should point to TypeScript sources for development and publishConfig.exports should mirror to dist/*.js

Applied to files:

  • plugins/static/tsconfig.json
  • plugins/static/package.json
  • plugins/static/tsdown.config.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to {packages,plugins,tools,examples,site}/**/tsconfig.json : Enable TypeScript strict mode in all packages (compilerOptions.strict: true)

Applied to files:

  • plugins/static/tsconfig.json
📚 Learning: 2025-09-14T08:41:30.618Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.618Z
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/static/tsconfig.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/tsdown.config.ts : Packages should use tsdown for builds (presence of tsdown.config.ts)

Applied to files:

  • plugins/static/tsconfig.json
  • plugins/static/tsdown.config.ts
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: For features affecting HTTP or process orchestration, add regression tests that exercise both the CommonJS and TypeScript example apps

Applied to files:

  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to tools/egg-bin/test/**/*.test.ts : egg-bin uses Mocha; test files follow test/**/*.test.ts

Applied to files:

  • plugins/static/test/static.test.ts
  • CLAUDE.md
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to packages/cookies/test/**/*.test.ts : cookies package uses Mocha; test files follow test/**/*.test.ts

Applied to files:

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

Applied to files:

  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: Applies to **/*.ts : Re-export types thoughtfully to keep the public API stable

Applied to files:

  • plugins/static/src/index.ts
  • packages/egg/src/lib/types.plugin.ts
  • plugins/static/tsdown.config.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/*.{ts,tsx} : Use explicit return types for public APIs

Applied to files:

  • packages/egg/src/lib/types.plugin.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/ : All Egg plugins must live under plugins/ and follow the standard plugin structure (src/, test/, package.json with eggPlugin, tsdown.config.ts)

Applied to files:

  • plugins/static/package.json
  • CLAUDE.md
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugins must include scripts: build (tsdown), clean (rimraf dist), typecheck (tsc --noEmit), lint (oxlint --type-aware), lint:fix, test (runs lint:fix then vitest), prepublishOnly (build)

Applied to files:

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

Applied to files:

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

Applied to files:

  • tsconfig.json
📚 Learning: 2025-09-14T08:41:30.618Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.618Z
Learning: Applies to packages/egg/src/app/extend/** : Place framework extensions (context, helper, request, response) under packages/egg/src/app/extend/

Applied to files:

  • CLAUDE.md
🧬 Code graph analysis (12)
plugins/static/src/app.ts (1)
packages/core/src/egg.ts (1)
  • EggCore (95-543)
plugins/static/test/fixtures/static-server-with-dir/config/config.default.js (1)
plugins/static/src/config/config.default.ts (1)
  • appInfo (5-19)
plugins/static/src/config/config.prod.ts (1)
plugins/static/src/types.ts (1)
  • StaticConfig (46-57)
plugins/static/test/static.test.ts (2)
scripts/version.js (2)
  • __filename (11-11)
  • __dirname (12-12)
packages/egg/test/utils.ts (1)
  • MockApplication (24-24)
plugins/static/src/types.ts (1)
packages/egg/src/lib/types.ts (1)
  • EggAppConfig (113-287)
plugins/static/src/config/config.default.ts (1)
plugins/static/src/types.ts (1)
  • StaticConfig (46-57)
plugins/static/test/fixtures/static-server-custom/config/config.default.js (2)
plugins/static/test/fixtures/static-server-with-dir/config/config.default.js (1)
  • path (1-1)
plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js (1)
  • path (1-1)
plugins/static/test/fixtures/static-server-with-dirs/config/plugin.js (1)
plugins/static/test/fixtures/static-server-custom/config/config.default.js (1)
  • exports (4-4)
plugins/static/src/app/middleware/static.ts (2)
plugins/static/src/types.ts (2)
  • StaticConfig (46-57)
  • StaticDirOptions (3-39)
packages/koa-static-cache/src/index.ts (1)
  • staticCache (139-321)
plugins/static/tsdown.config.ts (1)
packages/egg/src/lib/types.ts (1)
  • defineConfig (109-111)
plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js (1)
plugins/static/src/config/config.default.ts (1)
  • appInfo (5-19)
plugins/static/test/fixtures/static-server/config/config.default.js (1)
plugins/static/test/fixtures/static-server-custom/config/config.default.js (1)
  • exports (4-4)
🪛 markdownlint-cli2 (0.18.1)
plugins/static/README.md

55-55: Link text should be descriptive

(MD059, descriptive-link-text)

plugins/static/CHANGELOG.md

20-20: Bare URL used

(MD034, no-bare-urls)


22-22: Bare URL used

(MD034, no-bare-urls)


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

(MD007, ul-indent)


30-30: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


31-31: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


32-32: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


35-35: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


36-36: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


37-37: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


40-40: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


41-41: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


44-44: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


45-45: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD003, heading-style)


73-73: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


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

(MD007, ul-indent)


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

(MD003, heading-style)


79-79: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


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

(MD007, ul-indent)


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

(MD003, heading-style)


85-85: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


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

(MD007, ul-indent)


88-88: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


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

(MD007, ul-indent)


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

(MD003, heading-style)


94-94: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


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

(MD007, ul-indent)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)

🪛 GitHub Check: Test (windows-latest, 22, plugins)
plugins/static/test/static.test.ts

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 GitHub Check: Test (windows-latest, 24, plugins)
plugins/static/test/static.test.ts

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 GitHub Check: Test (macos-latest, 22, plugins)
plugins/static/test/static.test.ts

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 GitHub Check: Test (ubuntu-latest, 22, plugins)
plugins/static/test/static.test.ts

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 GitHub Check: Test (macos-latest, 24, plugins)
plugins/static/test/static.test.ts

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 GitHub Check: Test (ubuntu-latest, 24, plugins)
plugins/static/test/static.test.ts

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

⏰ 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). (2)
  • GitHub Check: Test egg-bin (windows-latest, 22)
  • GitHub Check: Test egg-bin (windows-latest, 24)
🔇 Additional comments (24)
plugins/static/tsconfig.json (1)

1-6: Config extends root as required

Extending the root tsconfig and scoping baseUrl locally matches the repo guidelines for plugin subprojects.

plugins/static/test/fixtures/static-server-custom/package.json (1)

1-3: Fixture package metadata is fine

The minimal package manifest is sufficient for the fixture setup.

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

1-8: Vitest config aligns with discovery rules

Including the plugin test glob and extended timeout satisfies the testing guidelines.

pnpm-workspace.yaml (1)

44-170: Catalog additions look consistent

Adding @types/koa-range, koa-range, and ylru to the catalog keeps dependency versions centralized as required.

plugins/static/tsdown.config.ts (1)

1-10: Standard tsdown config in place

The entry, unbundle, dts, and devExports settings match the mandated plugin build configuration.

plugins/static/test/fixtures/static-server/app/controller/foo.js (1)

1-7: Controller fixture behaves correctly

The controller sets body, type, and status explicitly—ideal for the route fixture.

plugins/static/test/fixtures/static-server-custom/config/config.default.js (1)

1-12: Custom static dir fixture is sound

Deriving the static directory from info.baseDir and exposing the custom prefix follows the pattern used elsewhere.

plugins/static/test/fixtures/static-server-dist/config/config.default.js (1)

1-9: Dist static config mirrors expectations

Returning the static config with buffer enabled matches the dist-serving test scenario.

plugins/static/test/fixtures/static-server-with-dir/config/plugin.js (1)

1-1: LGTM – fixture toggles static plugin inline

Enabling the plugin via boolean keeps the fixture lean and aligns with Egg's plugin toggles.

CLAUDE.md (1)

42-61: Appreciate the CLAUDE.md updates

Calling out the new static plugin and its koa-static-cache dependency helps future AI assistance stay accurate.

plugins/static/test/fixtures/static-server-dist/package.json (1)

1-3: LGTM – fixture manifest stays minimal

Keeping only the name keeps the fixture light and avoids needless dependencies.

plugins/static/test/fixtures/static-server-with-dirs/config/plugin.js (1)

1-1: LGTM – fixture enables static plugin

The boolean toggle mirrors Egg’s built-in plugin enablement.

plugins/static/test/fixtures/static-server-with-dir/app/public/foo.js (1)

1-1: LGTM – fixture asset in place

The stubbed console log is perfect for exercising the static directory lookup.

plugins/static/src/types.ts (1)

19-22: Close the unbalanced quote in the default description

The trailing backtick/quote is still missing from the earlier review; fixing it keeps the JSDoc tidy.

-   * Default to `true
+   * Default to `true`
plugins/static/test/fixtures/static-server/app/router.js (1)

1-5: LGTM – fixture route wiring is clear

Mapping /foo/bar straight to foo.bar keeps the controller hookup explicit for the scenario under test.

plugins/static/LICENSE (1)

1-21: MIT license header confirmed

Content matches the canonical MIT template adopted across the repo.

packages/egg/package.json (1)

129-134: Internal deps switched to workspace scope

Using workspace:* keeps these packages aligned with internal builds and follows the workspace dependency convention.

Based on learnings

plugins/static/test/fixtures/static-server/package.json (1)

1-3: Fixture metadata looks good

Minimal package name is sufficient for the fixture and matches existing patterns.

plugins/static/test/fixtures/static-server-with-dirs/package.json (1)

1-3: Fixture package json aligned

Naming mirrors the other fixtures and keeps the setup light.

plugins/static/test/fixtures/static-server-dist/app/assets/foo.js (1)

1-1: Asset fixture acknowledged

The simple script is enough to exercise static asset serving in tests.

tsconfig.json (1)

57-60: New project reference wired up

Adding plugins/static ensures the root build graph sees the new plugin package.

plugins/static/test/fixtures/static-server/config/config.default.js (1)

1-3: Fixture config initialized

Providing keys keeps the test app booting without warnings.

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

1-1: Type augmentation import in place

Side-effect import guarantees the module augmentation is registered for consumers.

plugins/static/src/app/middleware/static.ts (1)

11-66: Tighten the app type instead of casting to any.

Line 65 still drops to as any just to reach coreLogger. Please extend the signature to include coreLogger (importing the proper logger type) and call app.coreLogger.info(...) directly—no any. This keeps the middleware type-safe and aligns with our TypeScript guidelines. You’ll also need to add the relevant logger type dependency (e.g., egg-logger) to devDependencies.

-import type { EggCore, Context, Next } from '@eggjs/core';
+import type { EggCore, Context, Next } from '@eggjs/core';
+import type { EggLogger } from 'egg-logger';
@@
-export default (options: StaticConfig, app: EggCore) => {
+export default (options: StaticConfig, app: EggCore & { coreLogger: EggLogger }) => {
@@
-    (app as any).coreLogger.info('[@eggjs/static] starting static serve %s -> %s', newOptions.prefix, newOptions.dir);
+    app.coreLogger.info('[@eggjs/static] starting static serve %s -> %s', newOptions.prefix, newOptions.dir);

Comment on lines +13 to +14
/// <reference types="@eggjs/static" />
/// <reference types="@eggjs/onerror" />
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 | 🟠 Major

Triple-slash directives must come before imports

In TypeScript, triple-slash directives only take effect when they appear before any top-level statements (including import declarations). Because these directives come after several imports, they’re treated as regular comments and the intended type augmentations from @eggjs/static and @eggjs/onerror never load. Please move them to the top of the file (ahead of the imports) so the plugin config typings remain available.

+/// <reference types="@eggjs/static" />
+/// <reference types="@eggjs/onerror" />
 // import plugins types
 import '@eggjs/watcher';
 import '@eggjs/jsonp';
@@
-import '@eggjs/view';
-
-/// <reference types="@eggjs/static" />
-/// <reference types="@eggjs/onerror" />
+import '@eggjs/view';
📝 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
/// <reference types="@eggjs/static" />
/// <reference types="@eggjs/onerror" />
/// <reference types="@eggjs/static" />
/// <reference types="@eggjs/onerror" />
// import plugins types
import '@eggjs/watcher';
import '@eggjs/jsonp';
import '@eggjs/view';
🤖 Prompt for AI Agents
In packages/egg/src/lib/types.plugin.ts around lines 13 to 14, the triple-slash
reference directives for @eggjs/static and @eggjs/onerror are placed after
top-level imports so they are treated as comments and their type augmentations
don’t load; move those two /// <reference types="..."> lines to the very top of
the file before any import or other top-level statements so TypeScript will
apply the directive-based typings for the plugin config.

Comment on lines +50 to +65
"devDependencies": {
"@eggjs/tsconfig": "workspace:*",
"@types/koa-compose": "catalog:",
"@types/koa-range": "catalog:",
"@eggjs/mock": "workspace:*",
"oxlint": "catalog:",
"tsdown": "catalog:",
"typescript": "catalog:",
"vitest": "catalog:"
},
"scripts": {
"build": "tsdown",
"typecheck": "tsc --noEmit",
"lint": "oxlint --type-aware",
"lint:fix": "npm run lint -- --fix",
"test": "npm run lint:fix && vitest run",
"ci": "vitest run --coverage",
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 | 🟠 Major

Add the required clean script (and dependency).

Per the plugin package.json guidelines, every plugin must ship a clean script using rimraf dist. Please add both the script and the matching rimraf devDependency so the workflow is complete.

   "devDependencies": {
     "@eggjs/tsconfig": "workspace:*",
     "@types/koa-compose": "catalog:",
     "@types/koa-range": "catalog:",
     "@eggjs/mock": "workspace:*",
     "oxlint": "catalog:",
+    "rimraf": "catalog:",
     "tsdown": "catalog:",
     "typescript": "catalog:",
     "vitest": "catalog:"
   },
   "scripts": {
+    "clean": "rimraf dist",
     "build": "tsdown",
     "typecheck": "tsc --noEmit",
     "lint": "oxlint --type-aware",
📝 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
"devDependencies": {
"@eggjs/tsconfig": "workspace:*",
"@types/koa-compose": "catalog:",
"@types/koa-range": "catalog:",
"@eggjs/mock": "workspace:*",
"oxlint": "catalog:",
"tsdown": "catalog:",
"typescript": "catalog:",
"vitest": "catalog:"
},
"scripts": {
"build": "tsdown",
"typecheck": "tsc --noEmit",
"lint": "oxlint --type-aware",
"lint:fix": "npm run lint -- --fix",
"test": "npm run lint:fix && vitest run",
"ci": "vitest run --coverage",
"devDependencies": {
"@eggjs/tsconfig": "workspace:*",
"@types/koa-compose": "catalog:",
"@types/koa-range": "catalog:",
"@eggjs/mock": "workspace:*",
"oxlint": "catalog:",
"rimraf": "catalog:",
"tsdown": "catalog:",
"typescript": "catalog:",
"vitest": "catalog:"
},
"scripts": {
"clean": "rimraf dist",
"build": "tsdown",
"typecheck": "tsc --noEmit",
"lint": "oxlint --type-aware",
"lint:fix": "npm run lint -- --fix",
"test": "npm run lint:fix && vitest run",
"ci": "vitest run --coverage",
🤖 Prompt for AI Agents
In plugins/static/package.json around lines 50 to 66, the package is missing the
required clean script and its dependency; add "rimraf" as a devDependency
(matching the repository's versioning style, e.g., "catalog:" or the workspace
pattern used elsewhere) and add a "clean" script in "scripts" with the command
"rimraf dist" so the package conforms to the plugin package.json guidelines.

Comment on lines 4 to 7
private readonly app;
constructor(app: EggCore) {
this.app = app;
}
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 | 🟠 Major

Annotate the app field with its type

Declaring the field without a type widens it to any, which undermines the type safety we get from typing the constructor parameter. Please annotate the property so the AppBoot implementation stays type-safe.

-  private readonly app;
+  private readonly app: EggCore;
📝 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
private readonly app;
constructor(app: EggCore) {
this.app = app;
}
private readonly app: EggCore;
constructor(app: EggCore) {
this.app = app;
}
🤖 Prompt for AI Agents
In plugins/static/src/app.ts around lines 4 to 7, the private readonly app field
is declared without a type (implicitly any); annotate it as private readonly
app: EggCore to match the constructor parameter and preserve type-safety, and
ensure EggCore is imported/available in this file if not already.

Comment on lines +11 to +16
const index = app.config.coreMiddleware.indexOf('bodyParser');
if (index === -1) {
app.config.coreMiddleware.push('static');
} else {
app.config.coreMiddleware.splice(index, 0, 'static');
}
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 | 🟠 Major

Prevent duplicate static middleware registrations

If a user already lists static in coreMiddleware, this logic will insert a second copy, causing the middleware to run twice on every request. Add a guard before the insertion to keep the list deduplicated.

-    const index = app.config.coreMiddleware.indexOf('bodyParser');
-    if (index === -1) {
-      app.config.coreMiddleware.push('static');
-    } else {
-      app.config.coreMiddleware.splice(index, 0, 'static');
-    }
+    const { coreMiddleware } = app.config;
+    if (coreMiddleware.includes('static')) return;
+    const index = coreMiddleware.indexOf('bodyParser');
+    if (index === -1) {
+      coreMiddleware.push('static');
+    } else {
+      coreMiddleware.splice(index, 0, 'static');
+    }
📝 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
const index = app.config.coreMiddleware.indexOf('bodyParser');
if (index === -1) {
app.config.coreMiddleware.push('static');
} else {
app.config.coreMiddleware.splice(index, 0, 'static');
}
const { coreMiddleware } = app.config;
if (coreMiddleware.includes('static')) return;
const index = coreMiddleware.indexOf('bodyParser');
if (index === -1) {
coreMiddleware.push('static');
} else {
coreMiddleware.splice(index, 0, 'static');
}
🤖 Prompt for AI Agents
In plugins/static/src/app.ts around lines 11 to 16, the code may insert a
duplicate 'static' entry into app.config.coreMiddleware; before pushing or
splicing, check whether app.config.coreMiddleware already contains 'static'
(e.g., use includes() or indexOf !== -1) and only perform the push/splice when
it is not present so the middleware list remains deduplicated.

Comment on lines +7 to +9
prefix: '/public',
dir: [path.join(appInfo.baseDir, '/app/public'), path.join(appInfo.baseDir, '/dist/static')],
buffer: true,
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 | 🔴 Critical

Fix static dir join to avoid escaping baseDir

Because the second argument to path.join starts with /, Node resolves it to an absolute path (e.g., /app/public), so the fixture stops reading from the intended appInfo.baseDir and may even try to create directories at the filesystem root. Please drop the leading slash on both entries so they stay under the fixture’s base directory.

Apply this diff:

-      dir: [path.join(appInfo.baseDir, '/app/public'), path.join(appInfo.baseDir, '/dist/static')],
+      dir: [path.join(appInfo.baseDir, 'app/public'), path.join(appInfo.baseDir, 'dist/static')],
📝 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
prefix: '/public',
dir: [path.join(appInfo.baseDir, '/app/public'), path.join(appInfo.baseDir, '/dist/static')],
buffer: true,
prefix: '/public',
dir: [path.join(appInfo.baseDir, 'app/public'), path.join(appInfo.baseDir, 'dist/static')],
buffer: true,
🤖 Prompt for AI Agents
In plugins/static/test/fixtures/static-server-with-dir/config/config.default.js
around lines 7 to 9, the path.join calls use second arguments that start with a
leading slash so Node treats them as absolute paths; remove the leading '/' from
both '/app/public' and '/dist/static' so path.join(appInfo.baseDir,
'app/public') and path.join(appInfo.baseDir, 'dist/static') resolve under
appInfo.baseDir and the fixture reads/writes inside the fixture directory
instead of the filesystem root.

Comment on lines +9 to +13
path.join(appInfo.baseDir, '/app/public'),
{
prefix: '/static',
dir: path.join(appInfo.baseDir, '/dist/static'),
},
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 | 🔴 Critical

Fix directory resolution

Line 9 and Line 12 pass absolute paths ('/app/public', '/dist/static') into path.join, which discards appInfo.baseDir and resolves to /app/public and /dist/static on the host filesystem. The fixture will never serve the intended assets. Please join relative segments so the baseDir is preserved.

-        path.join(appInfo.baseDir, '/app/public'),
+        path.join(appInfo.baseDir, 'app/public'),
@@
-          dir: path.join(appInfo.baseDir, '/dist/static'),
+          dir: path.join(appInfo.baseDir, 'dist/static'),
📝 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
path.join(appInfo.baseDir, '/app/public'),
{
prefix: '/static',
dir: path.join(appInfo.baseDir, '/dist/static'),
},
path.join(appInfo.baseDir, 'app/public'),
{
prefix: '/static',
dir: path.join(appInfo.baseDir, 'dist/static'),
},
🤖 Prompt for AI Agents
In plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js
around lines 9 to 13, the code uses path.join(appInfo.baseDir, '/app/public')
and path.join(appInfo.baseDir, '/dist/static') which discard appInfo.baseDir due
to the leading slash; change these to join relative segments so the baseDir is
preserved — e.g. path.join(appInfo.baseDir, 'app', 'public') and
path.join(appInfo.baseDir, 'dist', 'static') (or at minimum remove the leading
slashes: 'app/public' and 'dist/static') so the fixture serves assets from the
intended project directories.

Comment on lines 16 to 23
let app: MockApplication;
beforeEach(async () => {
app = mock.app({
baseDir: 'static-server',
});
await app.ready();
});

afterEach(() => app.close());

it('should get exists js file', () => {
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 | 🔴 Critical

Guard cleanup when setup fails

When mock.app fails (as seen in CI), app stays undefined and afterEach throws “Cannot read properties of undefined (reading 'close')”, masking the real failure. Make the cleanup async, check app before closing, and reset it afterwards; please apply the same pattern to the other suites in this file.

Apply this diff:

-    let app: MockApplication;
+    let app: MockApplication | undefined;
@@
-    afterEach(() => app.close());
+    afterEach(async () => {
+      if (app) {
+        await app.close();
+        app = undefined;
+      }
+    });

Based on pipeline failure logs.

📝 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
let app: MockApplication;
beforeEach(async () => {
app = mock.app({
baseDir: 'static-server',
});
await app.ready();
});
afterEach(() => app.close());
it('should get exists js file', () => {
let app: MockApplication | undefined;
beforeEach(async () => {
app = mock.app({
baseDir: 'static-server',
});
await app.ready();
});
afterEach(async () => {
if (app) {
await app.close();
app = undefined;
}
});
it('should get exists js file', () => {
🧰 Tools
🪛 GitHub Check: Test (windows-latest, 22, plugins)

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 GitHub Check: Test (windows-latest, 24, plugins)

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 GitHub Check: Test (macos-latest, 22, plugins)

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 GitHub Check: Test (ubuntu-latest, 22, plugins)

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 GitHub Check: Test (macos-latest, 24, plugins)

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🪛 GitHub Check: Test (ubuntu-latest, 24, plugins)

[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25


[failure] 24-24: test/static.test.ts > test/static.test.ts > serve public > should get exists js file
TypeError: Cannot read properties of undefined (reading 'close')
❯ test/static.test.ts:24:25

🤖 Prompt for AI Agents
In plugins/static/test/static.test.ts around lines 16 to 26, the afterEach
cleanup assumes app is defined which causes “Cannot read properties of undefined
(reading 'close')” when mock.app setup fails; make the teardown async, guard
that app is defined before calling await app.close(), and set app =
undefined/null after closing so subsequent tests/suites don't reuse a failed
instance; apply the same async guarded teardown pattern to the other test suites
in this file.

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

🧹 Nitpick comments (2)
plugins/schedule/src/config/config.default.ts (1)

3-13: Restore static type checking for plugin config

Replacing defineConfig with as PartialEggConfig strips the compiler of any structural checks—future typos or wrong value shapes will now silently pass. Keep the runtime change (plain object export), but retain typing by binding the object to PartialEggConfig (or using satisfies). For example:

-import { type PartialEggConfig } from 'egg';
-
-export default {
+import { type PartialEggConfig } from 'egg';
+
+const config: PartialEggConfig = {
   customLogger: {
     scheduleLogger: {
       consoleLevel: 'NONE',
       file: 'egg-schedule.log',
     },
   },
   schedule: {
     directory: [],
   },
-} as PartialEggConfig;
+};
+
+export default config;

This preserves the new style while keeping compile-time safety.

packages/egg/test/lib/core/loader/load_plugin.test.ts (1)

59-61: Make the assertion path-separator agnostic

Dropping the Windows guard lets us keep verifying the plugin path everywhere by splitting on path.sep and checking for the onerror segment, instead of relying on a POSIX-only regex.

-    if (process.platform !== 'win32') {
-      assert.match(appLoader.plugins.onerror.path!, /\/onerror\//);
-    }
+    const onerrorPathSegments = appLoader.plugins.onerror.path!.split(path.sep);
+    assert(onerrorPathSegments.includes('onerror'));
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e665d6 and d58dcc4.

⛔ Files ignored due to path filters (3)
  • packages/egg/test/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
  • packages/egg/test/lib/__snapshots__/define_config.test.ts.snap is excluded by !**/*.snap
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (21)
  • package.json (1 hunks)
  • packages/egg/src/config/config.default.ts (1 hunks)
  • packages/egg/src/lib/types.ts (1 hunks)
  • packages/egg/test/lib/core/loader/load_plugin.test.ts (1 hunks)
  • packages/egg/test/lib/define_config.test.ts (3 hunks)
  • packages/extend2/package.json (0 hunks)
  • plugins/development/package.json (0 hunks)
  • plugins/schedule/src/config/config.default.ts (2 hunks)
  • plugins/static/package.json (1 hunks)
  • plugins/static/src/app.ts (1 hunks)
  • plugins/static/src/app/middleware/static.ts (1 hunks)
  • plugins/static/src/config/config.default.ts (1 hunks)
  • plugins/static/src/config/config.prod.ts (1 hunks)
  • plugins/static/src/index.ts (1 hunks)
  • plugins/static/src/types.ts (1 hunks)
  • plugins/static/test/fixtures/static-server-custom/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/config/config.default.js (1 hunks)
  • plugins/static/test/static.test.ts (1 hunks)
  • plugins/static/vitest.config.ts (1 hunks)
  • plugins/watcher/package.json (0 hunks)
  • tools/egg-bin/package.json (0 hunks)
💤 Files with no reviewable changes (4)
  • plugins/development/package.json
  • packages/extend2/package.json
  • tools/egg-bin/package.json
  • plugins/watcher/package.json
🚧 Files skipped from review as they are similar to previous changes (6)
  • plugins/static/src/config/config.default.ts
  • plugins/static/test/fixtures/static-server-custom/config/config.default.js
  • plugins/static/src/app.ts
  • plugins/static/test/fixtures/static-server-dist/config/config.default.js
  • plugins/static/src/types.ts
  • plugins/static/package.json
🧰 Additional context used
📓 Path-based instructions (9)
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/egg/src/lib/types.ts
  • packages/egg/src/config/config.default.ts
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.ts: Prefer TypeScript and ESM: write sources and exports in .ts (ESM-first) rather than CommonJS
Use two-space indentation, trailing commas, and semicolons (Prettier/oxlint defaults)
Name files in lowercase with hyphens (e.g., loader-context.ts)
Name classes in PascalCase
Name functions and variables in camelCase
Re-export types thoughtfully to keep the public API stable

Files:

  • packages/egg/src/lib/types.ts
  • packages/egg/src/config/config.default.ts
  • packages/egg/test/lib/define_config.test.ts
  • plugins/static/src/app/middleware/static.ts
  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/schedule/src/config/config.default.ts
  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
  • plugins/static/src/index.ts
  • plugins/static/src/config/config.prod.ts
{packages,plugins,tools}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

{packages,plugins,tools}/**/*.{ts,tsx}: Prefer interfaces over type aliases for object shapes in TypeScript
Use explicit return types for public APIs
Use readonly modifiers where appropriate
Avoid the any type; prefer unknown when the type is truly unknown

Files:

  • packages/egg/src/lib/types.ts
  • packages/egg/src/config/config.default.ts
  • packages/egg/test/lib/define_config.test.ts
  • plugins/static/src/app/middleware/static.ts
  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/schedule/src/config/config.default.ts
  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
  • plugins/static/src/index.ts
  • plugins/static/src/config/config.prod.ts
packages/egg/src/config/**

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

Store default configurations and plugin configs under packages/egg/src/config/

Files:

  • packages/egg/src/config/config.default.ts
packages/**/test/**/*.test.ts

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

packages/**/test/**/*.test.ts: Name test files as test/**/*.test.ts and run them with Vitest
Use import { describe, it } from 'vitest' in tests
Use Node.js built-in assert module for test assertions

Files:

  • packages/egg/test/lib/define_config.test.ts
  • packages/egg/test/lib/core/loader/load_plugin.test.ts
**/test/**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/test/**/*.test.ts: Place test suites following Vitest discovery: /test//*.test.ts
Mirror the repository test pattern when adding new suites

Files:

  • packages/egg/test/lib/define_config.test.ts
  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/static/test/static.test.ts
{packages,plugins,tools}/**/test/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Test files should follow the pattern test/**/*.test.ts

Files:

  • packages/egg/test/lib/define_config.test.ts
  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/static/test/static.test.ts
{packages,plugins,tools}/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

In Vitest tests, import from vitest (e.g., import { describe, it } from 'vitest') and use Node.js assert for assertions

Files:

  • packages/egg/test/lib/define_config.test.ts
  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/static/test/static.test.ts
plugins/**/vitest.config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

All new plugins must use Vitest and include vitest.config.ts

Files:

  • plugins/static/vitest.config.ts
🧠 Learnings (18)
📓 Common learnings
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/ : All Egg plugins must live under plugins/ and follow the standard plugin structure (src/, test/, package.json with eggPlugin, tsdown.config.ts)
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to tools/egg-bin/test/**/*.test.ts : egg-bin uses Mocha; test files follow test/**/*.test.ts

Applied to files:

  • packages/egg/test/lib/define_config.test.ts
  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to packages/{egg,core,utils,mock,cluster,koa,supertest,extend2}/vitest.config.ts : Each package (except cookies) should include a Vitest configuration file vitest.config.ts

Applied to files:

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

Applied to files:

  • packages/egg/test/lib/define_config.test.ts
  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/*.test.ts : In Vitest tests, import from vitest (e.g., import { describe, it } from 'vitest') and use Node.js assert for assertions

Applied to files:

  • packages/egg/test/lib/define_config.test.ts
  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to packages/{egg,core}/tsconfig.json : packages/egg and packages/core must have strict mode enabled in their tsconfig.json

Applied to files:

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

Applied to files:

  • packages/egg/test/lib/core/loader/load_plugin.test.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/ : All Egg plugins must live under plugins/ and follow the standard plugin structure (src/, test/, package.json with eggPlugin, tsdown.config.ts)

Applied to files:

  • packages/egg/test/lib/core/loader/load_plugin.test.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to plugins/**/vitest.config.ts : All new plugins must use Vitest and include vitest.config.ts

Applied to files:

  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: For features affecting HTTP or process orchestration, add regression tests that exercise both the CommonJS and TypeScript example apps

Applied to files:

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

Applied to files:

  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: Applies to **/test/**/*.test.ts : Place test suites following Vitest discovery: **/test/**/*.test.ts

Applied to files:

  • plugins/static/test/static.test.ts
  • plugins/static/vitest.config.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to packages/cookies/test/**/*.test.ts : cookies package uses Mocha; test files follow test/**/*.test.ts

Applied to files:

  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/test/**/*.test.ts : Test files should follow the pattern test/**/*.test.ts

Applied to files:

  • plugins/static/vitest.config.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugins must include scripts: build (tsdown), clean (rimraf dist), typecheck (tsc --noEmit), lint (oxlint --type-aware), lint:fix, test (runs lint:fix then vitest), prepublishOnly (build)

Applied to files:

  • package.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/package.json : All packages must provide a typecheck script using "tsc --noEmit"

Applied to files:

  • package.json
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: Applies to **/*.ts : Re-export types thoughtfully to keep the public API stable

Applied to files:

  • plugins/static/src/index.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/*.{ts,tsx} : Use explicit return types for public APIs

Applied to files:

  • plugins/static/src/index.ts
🧬 Code graph analysis (7)
packages/egg/src/lib/types.ts (4)
packages/egg/src/lib/egg.ts (1)
  • config (564-566)
packages/core/src/loader/egg_loader.ts (1)
  • config (1003-1007)
packages/core/src/egg.ts (1)
  • config (307-309)
packages/egg/src/lib/core/base_hook_class.ts (1)
  • config (19-21)
packages/egg/src/config/config.default.ts (1)
packages/egg/src/lib/types.ts (2)
  • defineConfigFactory (119-121)
  • PartialEggConfig (86-86)
packages/egg/test/lib/define_config.test.ts (1)
packages/egg/src/lib/types.ts (1)
  • defineConfigFactory (119-121)
plugins/static/src/app/middleware/static.ts (2)
plugins/static/src/types.ts (2)
  • StaticConfig (46-57)
  • StaticDirOptions (3-39)
packages/koa-static-cache/src/index.ts (1)
  • staticCache (139-321)
plugins/schedule/src/config/config.default.ts (1)
packages/egg/src/lib/types.ts (1)
  • PartialEggConfig (86-86)
plugins/static/test/static.test.ts (1)
packages/supertest/src/test.ts (1)
  • expect (77-132)
plugins/static/src/config/config.prod.ts (1)
packages/egg/src/lib/types.ts (1)
  • PartialEggConfig (86-86)
🪛 GitHub Actions: CI
package.json

[error] 1-1: pnpm install --frozen-lockfile failed: lockfile is not up to date with package.json (specifiers in the lockfile don't match). 1 dependencies were added: rimraf@catalog.

⏰ 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). (1)
  • GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (2)
plugins/static/src/app/middleware/static.ts (1)

55-57: Restore range support for root prefixes. Line 55 skips falsy prefixes, so a configured empty-string prefix (mount at /) never reaches prefixes, and Range headers stop working for root static assets—a regression from prior behavior. Normalize the prefix and always record it before composing the middleware.

-    if (newOptions.prefix) {
-      prefixes.push(newOptions.prefix);
-    }
+    const normalizedPrefix = (newOptions.prefix ?? '').replace(/\/*$/, '/');
+    prefixes.push(normalizedPrefix);
plugins/static/test/static.test.ts (1)

13-22: Guard app teardown when setup fails

Line 21 still blindly calls app.close(). When mock.app throws, the hook runs with app undefined and reproduces the CI failure (TypeError: Cannot read properties of undefined (reading 'close')). Please make app optional, guard before closing, reset it, and mirror the same guarded teardown across the other suites in this file so setup errors don’t mask root causes.

-    let app: MockApplication;
+    let app: MockApplication | undefined;
@@
-    afterAll(() => app.close());
+    afterAll(async () => {
+      if (app) {
+        await app.close();
+        app = undefined;
+      }
+    });

Based on pipeline failure logs.

- Migrate @eggjs/static repository to plugins/static
- Update version to 4.0.0-beta.11
- Replace ESLint with oxlint for linting
- Add TypeScript type checking with tsc --noEmit
- Configure tsdown for unbundled ESM build
- Add peerDependencies for egg using workspace:*
- Update tests to use vitest
- Add koa-range and ylru to pnpm catalog

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

Co-Authored-By: Claude <noreply@anthropic.com>
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: 2

🧹 Nitpick comments (1)
plugins/static/CHANGELOG.md (1)

29-46: Replace the tab-indented bullet list with space-indented Markdown

The sub-bullets inside the “Summary by CodeRabbit” block are prefixed with hard tabs, which trips markdownlint (MD010/MD007) and renders inconsistently on GitHub. Please swap the tabs for two-space indentation (or remove the autogenerated block if it’s not needed) so the list formats correctly and the lint job stays green.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 140cae9 and 5dfd58e.

⛔ Files ignored due to path filters (3)
  • packages/egg/test/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
  • packages/egg/test/lib/__snapshots__/define_config.test.ts.snap is excluded by !**/*.snap
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (50)
  • CLAUDE.md (2 hunks)
  • package.json (1 hunks)
  • packages/egg/package.json (1 hunks)
  • packages/egg/src/config/config.default.ts (1 hunks)
  • packages/egg/src/lib/types.plugin.ts (1 hunks)
  • packages/egg/src/lib/types.ts (1 hunks)
  • packages/egg/test/lib/core/loader/load_plugin.test.ts (1 hunks)
  • packages/egg/test/lib/define_config.test.ts (3 hunks)
  • packages/extend2/package.json (0 hunks)
  • plugins/development/package.json (0 hunks)
  • plugins/schedule/src/config/config.default.ts (2 hunks)
  • plugins/static/.gitignore (1 hunks)
  • plugins/static/CHANGELOG.md (1 hunks)
  • plugins/static/LICENSE (1 hunks)
  • plugins/static/README.md (1 hunks)
  • plugins/static/package.json (1 hunks)
  • plugins/static/src/app.ts (1 hunks)
  • plugins/static/src/app/middleware/static.ts (1 hunks)
  • plugins/static/src/config/config.default.ts (1 hunks)
  • plugins/static/src/config/config.prod.ts (1 hunks)
  • plugins/static/src/index.ts (1 hunks)
  • plugins/static/src/types.ts (1 hunks)
  • plugins/static/test/fixtures/static-server-custom/app/assets/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-custom/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-custom/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/app/assets/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/config/plugin.js (1 hunks)
  • plugins/static/test/fixtures/static-server-dist/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/app/public/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/config/plugin.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dir/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/app/public/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/config/plugin.js (1 hunks)
  • plugins/static/test/fixtures/static-server-with-dirs/package.json (1 hunks)
  • plugins/static/test/fixtures/static-server/app/controller/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server/app/public/foo.js (1 hunks)
  • plugins/static/test/fixtures/static-server/app/router.js (1 hunks)
  • plugins/static/test/fixtures/static-server/config/config.default.js (1 hunks)
  • plugins/static/test/fixtures/static-server/package.json (1 hunks)
  • plugins/static/test/static.test.ts (1 hunks)
  • plugins/static/tsconfig.json (1 hunks)
  • plugins/static/tsdown.config.ts (1 hunks)
  • plugins/static/vitest.config.ts (1 hunks)
  • plugins/watcher/package.json (0 hunks)
  • pnpm-workspace.yaml (3 hunks)
  • tools/egg-bin/package.json (0 hunks)
  • tsconfig.json (1 hunks)
💤 Files with no reviewable changes (4)
  • plugins/development/package.json
  • plugins/watcher/package.json
  • tools/egg-bin/package.json
  • packages/extend2/package.json
✅ Files skipped from review due to trivial changes (7)
  • CLAUDE.md
  • plugins/static/test/fixtures/static-server/app/public/foo.js
  • plugins/static/test/fixtures/static-server/package.json
  • plugins/static/tsconfig.json
  • plugins/static/LICENSE
  • plugins/static/test/fixtures/static-server-dist/package.json
  • plugins/static/test/fixtures/static-server-dist/app/assets/foo.js
🚧 Files skipped from review as they are similar to previous changes (23)
  • plugins/static/test/fixtures/static-server-dist/config/plugin.js
  • plugins/static/test/fixtures/static-server-with-dirs/package.json
  • plugins/static/.gitignore
  • plugins/static/test/fixtures/static-server/app/controller/foo.js
  • plugins/static/tsdown.config.ts
  • plugins/static/test/fixtures/static-server-with-dirs/config/plugin.js
  • plugins/static/test/fixtures/static-server-with-dirs/app/public/foo.js
  • packages/egg/src/config/config.default.ts
  • plugins/static/test/fixtures/static-server-with-dir/config/plugin.js
  • pnpm-workspace.yaml
  • plugins/static/test/fixtures/static-server-custom/config/config.default.js
  • packages/egg/package.json
  • tsconfig.json
  • plugins/static/package.json
  • plugins/schedule/src/config/config.default.ts
  • plugins/static/src/config/config.prod.ts
  • plugins/static/test/fixtures/static-server-with-dir/config/config.default.js
  • plugins/static/test/fixtures/static-server/app/router.js
  • plugins/static/test/fixtures/static-server-custom/package.json
  • plugins/static/test/fixtures/static-server-with-dir/app/public/foo.js
  • plugins/static/src/types.ts
  • plugins/static/src/app.ts
  • plugins/static/test/fixtures/static-server-dist/config/config.default.js
🧰 Additional context used
📓 Path-based instructions (11)
**/test/fixtures/**

📄 CodeRabbit inference engine (AGENTS.md)

Put reusable test data under test/fixtures/

Files:

  • plugins/static/test/fixtures/static-server-custom/app/assets/foo.js
  • plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js
  • plugins/static/test/fixtures/static-server-with-dir/package.json
  • plugins/static/test/fixtures/static-server/config/config.default.js
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/egg/src/lib/types.plugin.ts
  • packages/egg/src/lib/types.ts
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.ts: Prefer TypeScript and ESM: write sources and exports in .ts (ESM-first) rather than CommonJS
Use two-space indentation, trailing commas, and semicolons (Prettier/oxlint defaults)
Name files in lowercase with hyphens (e.g., loader-context.ts)
Name classes in PascalCase
Name functions and variables in camelCase
Re-export types thoughtfully to keep the public API stable

Files:

  • packages/egg/src/lib/types.plugin.ts
  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/static/src/index.ts
  • plugins/static/src/app/middleware/static.ts
  • plugins/static/vitest.config.ts
  • plugins/static/test/static.test.ts
  • packages/egg/src/lib/types.ts
  • packages/egg/test/lib/define_config.test.ts
  • plugins/static/src/config/config.default.ts
{packages,plugins,tools}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

{packages,plugins,tools}/**/*.{ts,tsx}: Prefer interfaces over type aliases for object shapes in TypeScript
Use explicit return types for public APIs
Use readonly modifiers where appropriate
Avoid the any type; prefer unknown when the type is truly unknown

Files:

  • packages/egg/src/lib/types.plugin.ts
  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/static/src/index.ts
  • plugins/static/src/app/middleware/static.ts
  • plugins/static/vitest.config.ts
  • plugins/static/test/static.test.ts
  • packages/egg/src/lib/types.ts
  • packages/egg/test/lib/define_config.test.ts
  • plugins/static/src/config/config.default.ts
packages/**/test/**/*.test.ts

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

packages/**/test/**/*.test.ts: Name test files as test/**/*.test.ts and run them with Vitest
Use import { describe, it } from 'vitest' in tests
Use Node.js built-in assert module for test assertions

Files:

  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • packages/egg/test/lib/define_config.test.ts
**/test/**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/test/**/*.test.ts: Place test suites following Vitest discovery: /test//*.test.ts
Mirror the repository test pattern when adding new suites

Files:

  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/static/test/static.test.ts
  • packages/egg/test/lib/define_config.test.ts
{packages,plugins,tools}/**/test/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Test files should follow the pattern test/**/*.test.ts

Files:

  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/static/test/static.test.ts
  • packages/egg/test/lib/define_config.test.ts
{packages,plugins,tools}/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

In Vitest tests, import from vitest (e.g., import { describe, it } from 'vitest') and use Node.js assert for assertions

Files:

  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/static/test/static.test.ts
  • packages/egg/test/lib/define_config.test.ts
plugins/**/vitest.config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

All new plugins must use Vitest and include vitest.config.ts

Files:

  • plugins/static/vitest.config.ts
plugins/**/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

plugins/**/package.json: Plugin package.json must include peerDependencies { "egg": "workspace:" }
Plugin package.json exports should point to TypeScript sources for development and publishConfig.exports should mirror to dist/
.js
Plugins must include scripts: build (tsdown), clean (rimraf dist), typecheck (tsc --noEmit), lint (oxlint --type-aware), lint:fix, test (runs lint:fix then vitest), prepublishOnly (build)

Files:

  • plugins/static/test/fixtures/static-server-with-dir/package.json
{packages,plugins,tools}/**/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

{packages,plugins,tools}/**/package.json: All packages must provide a typecheck script using "tsc --noEmit"
All packages must use oxlint for linting with the command "oxlint --type-aware" (no ESLint configs)

Files:

  • plugins/static/test/fixtures/static-server-with-dir/package.json
🧠 Learnings (19)
📓 Common learnings
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/ : All Egg plugins must live under plugins/ and follow the standard plugin structure (src/, test/, package.json with eggPlugin, tsdown.config.ts)
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugin package.json must include peerDependencies { "egg": "workspace:*" }
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to tools/egg-bin/test/**/*.test.ts : egg-bin uses Mocha; test files follow test/**/*.test.ts
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to packages/{egg,core,utils,mock,cluster,koa,supertest,extend2}/vitest.config.ts : Each package (except cookies) should include a Vitest configuration file vitest.config.ts
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to packages/{egg,core}/tsconfig.json : packages/egg and packages/core must have strict mode enabled in their tsconfig.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/*.{ts,tsx} : Use explicit return types for public APIs

Applied to files:

  • packages/egg/src/lib/types.plugin.ts
  • plugins/static/src/index.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to packages/{egg,core}/tsconfig.json : packages/egg and packages/core must have strict mode enabled in their tsconfig.json

Applied to files:

  • packages/egg/src/lib/types.plugin.ts
  • plugins/static/src/app/middleware/static.ts
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: Applies to **/*.ts : Re-export types thoughtfully to keep the public API stable

Applied to files:

  • packages/egg/src/lib/types.plugin.ts
  • plugins/static/src/index.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/ : All Egg plugins must live under plugins/ and follow the standard plugin structure (src/, test/, package.json with eggPlugin, tsdown.config.ts)

Applied to files:

  • packages/egg/src/lib/types.plugin.ts
  • packages/egg/test/lib/core/loader/load_plugin.test.ts
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: Applies to **/*.ts : Prefer TypeScript and ESM: write sources and exports in .ts (ESM-first) rather than CommonJS

Applied to files:

  • packages/egg/src/lib/types.plugin.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugin package.json exports should point to TypeScript sources for development and publishConfig.exports should mirror to dist/*.js

Applied to files:

  • packages/egg/src/lib/types.plugin.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to tools/egg-bin/test/**/*.test.ts : egg-bin uses Mocha; test files follow test/**/*.test.ts

Applied to files:

  • packages/egg/test/lib/core/loader/load_plugin.test.ts
  • plugins/static/test/static.test.ts
  • packages/egg/test/lib/define_config.test.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to plugins/**/vitest.config.ts : All new plugins must use Vitest and include vitest.config.ts

Applied to files:

  • plugins/static/vitest.config.ts
  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to packages/{egg,core,utils,mock,cluster,koa,supertest,extend2}/vitest.config.ts : Each package (except cookies) should include a Vitest configuration file vitest.config.ts

Applied to files:

  • plugins/static/vitest.config.ts
  • plugins/static/test/static.test.ts
  • packages/egg/test/lib/define_config.test.ts
📚 Learning: 2025-09-14T08:41:30.618Z
Learnt from: CR
PR: eggjs/egg#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T08:41:30.618Z
Learning: Applies to packages/**/test/**/*.test.ts : Name test files as test/**/*.test.ts and run them with Vitest

Applied to files:

  • plugins/static/vitest.config.ts
  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: Applies to **/test/**/*.test.ts : Place test suites following Vitest discovery: **/test/**/*.test.ts

Applied to files:

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

Applied to files:

  • plugins/static/vitest.config.ts
  • plugins/static/test/static.test.ts
  • packages/egg/test/lib/define_config.test.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/*.test.ts : In Vitest tests, import from vitest (e.g., import { describe, it } from 'vitest') and use Node.js assert for assertions

Applied to files:

  • plugins/static/vitest.config.ts
  • plugins/static/test/static.test.ts
  • packages/egg/test/lib/define_config.test.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/test/**/*.test.ts : Test files should follow the pattern test/**/*.test.ts

Applied to files:

  • plugins/static/vitest.config.ts
📚 Learning: 2025-09-18T07:56:17.417Z
Learnt from: CR
PR: eggjs/egg#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T07:56:17.417Z
Learning: For features affecting HTTP or process orchestration, add regression tests that exercise both the CommonJS and TypeScript example apps

Applied to files:

  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-26T12:42:04.197Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.197Z
Learning: Applies to packages/cookies/test/**/*.test.ts : cookies package uses Mocha; test files follow test/**/*.test.ts

Applied to files:

  • plugins/static/test/static.test.ts
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to plugins/**/package.json : Plugins must include scripts: build (tsdown), clean (rimraf dist), typecheck (tsc --noEmit), lint (oxlint --type-aware), lint:fix, test (runs lint:fix then vitest), prepublishOnly (build)

Applied to files:

  • package.json
📚 Learning: 2025-09-26T12:42:04.198Z
Learnt from: CR
PR: eggjs/egg#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-26T12:42:04.198Z
Learning: Applies to {packages,plugins,tools}/**/package.json : All packages must provide a typecheck script using "tsc --noEmit"

Applied to files:

  • package.json
🧬 Code graph analysis (6)
plugins/static/src/app/middleware/static.ts (2)
plugins/static/src/types.ts (2)
  • StaticConfig (46-57)
  • StaticDirOptions (3-39)
packages/koa-static-cache/src/index.ts (1)
  • staticCache (139-321)
plugins/static/test/static.test.ts (1)
packages/supertest/src/test.ts (1)
  • expect (77-132)
packages/egg/src/lib/types.ts (4)
packages/egg/src/lib/egg.ts (1)
  • config (564-566)
packages/core/src/loader/egg_loader.ts (1)
  • config (1003-1007)
packages/core/src/egg.ts (1)
  • config (307-309)
packages/egg/src/lib/core/base_hook_class.ts (1)
  • config (19-21)
packages/egg/test/lib/define_config.test.ts (1)
packages/egg/src/lib/types.ts (1)
  • defineConfigFactory (119-121)
plugins/static/test/fixtures/static-server/config/config.default.js (1)
plugins/static/test/fixtures/static-server-custom/config/config.default.js (1)
  • exports (4-6)
plugins/static/src/config/config.default.ts (1)
packages/egg/src/lib/types.ts (2)
  • defineConfigFactory (119-121)
  • PartialEggConfig (86-86)
🪛 markdownlint-cli2 (0.18.1)
plugins/static/README.md

55-55: Link text should be descriptive

(MD059, descriptive-link-text)

plugins/static/CHANGELOG.md

20-20: Bare URL used

(MD034, no-bare-urls)


22-22: Bare URL used

(MD034, no-bare-urls)


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

(MD007, ul-indent)


30-30: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


31-31: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


32-32: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


35-35: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


36-36: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


37-37: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


40-40: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


41-41: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


44-44: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD007, ul-indent)


45-45: Hard tabs
Column: 1

(MD010, no-hard-tabs)


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

(MD003, heading-style)


73-73: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


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

(MD007, ul-indent)


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

(MD003, heading-style)


79-79: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


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

(MD007, ul-indent)


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

(MD003, heading-style)


85-85: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


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

(MD007, ul-indent)


88-88: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


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

(MD007, ul-indent)


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

(MD003, heading-style)


94-94: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


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

(MD007, ul-indent)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD003, heading-style)


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

(MD007, ul-indent)


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

(MD003, heading-style)


138-138: 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). (18)
  • GitHub Check: Test (windows-latest, 24, packages)
  • GitHub Check: Test (ubuntu-latest, 24, plugins)
  • GitHub Check: Test (windows-latest, 22, packages)
  • GitHub Check: Test (macos-latest, 24, plugins)
  • GitHub Check: Test (windows-latest, 22, tools)
  • GitHub Check: Test (macos-latest, 24, packages)
  • GitHub Check: Test (windows-latest, 24, plugins)
  • GitHub Check: Test (windows-latest, 22, plugins)
  • GitHub Check: Test (macos-latest, 22, tools)
  • GitHub Check: Test (ubuntu-latest, 22, plugins)
  • GitHub Check: Test (ubuntu-latest, 24, packages)
  • GitHub Check: Test (ubuntu-latest, 22, packages)
  • GitHub Check: Test egg-bin (ubuntu-latest, 24)
  • GitHub Check: Test egg-bin (ubuntu-latest, 22)
  • GitHub Check: Test egg-bin (windows-latest, 24)
  • GitHub Check: Test egg-bin (macos-latest, 24)
  • GitHub Check: Test egg-bin (macos-latest, 22)
  • GitHub Check: Cloudflare Pages: egg-v3
🔇 Additional comments (3)
packages/egg/src/lib/types.plugin.ts (1)

1-14: Move triple-slash references before the imports

Triple-slash directives must be the very first top-level statements; where they sit now (after the imports) they’re ignored, so the static/onerror plugin augmentations never register. Please hoist them above the import block.

+/// <reference types="@eggjs/static" />
+/// <reference types="@eggjs/onerror" />
 // import plugins types
 import '@eggjs/watcher';
 import '@eggjs/jsonp';
 import '@eggjs/i18n';
 import '@eggjs/security';
 import '@eggjs/session';
 import '@eggjs/logrotator';
 import '@eggjs/multipart';
 import '@eggjs/view';
-
-/// <reference types="@eggjs/static" />
-/// <reference types="@eggjs/onerror" />
plugins/static/test/fixtures/static-server-with-dirs/config/config.default.js (1)

9-13: Fix absolute path joins so fixtures resolve correctly

Line 9 and Line 12 pass absolute segments ('/app/public', '/dist/static') into path.join, which strips appInfo.baseDir and resolves to /app/public and /dist/static on the host. The fixture never sees the intended assets. Drop the leading slash so the join stays under the fixture’s base directory.

-        path.join(appInfo.baseDir, '/app/public'),
+        path.join(appInfo.baseDir, 'app/public'),
@@
-          dir: path.join(appInfo.baseDir, '/dist/static'),
+          dir: path.join(appInfo.baseDir, 'dist/static'),
packages/egg/src/lib/types.ts (1)

55-57: Restore range handling for root-mounted static assets

Skipping falsy prefixes drops the empty-string ('') mount that serves files from the app root, so range requests stop working for that configuration. Normalize the prefix (as staticCache already does) and always record it so range support stays intact.

-    if (newOptions.prefix) {
-      prefixes.push(newOptions.prefix);
-    }
+    const normalizedPrefix = (newOptions.prefix ?? '').replace(/\/*$/, '/');
+    prefixes.push(normalizedPrefix);
+    newOptions.prefix = normalizedPrefix;

Comment on lines +55 to +56
Please open an issue [here](https://github.com/eggjs/egg/issues).

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 | 🟠 Major

Use descriptive link text to unblock markdownlint

Line 55 still uses “here” as the link label, which triggers markdownlint’s MD059 rule and will keep the docs lint job red. Please switch to descriptive text so the pipeline passes.

-Please open an issue [here](https://github.com/eggjs/egg/issues).
+Please open an issue on the [egg repository issue tracker](https://github.com/eggjs/egg/issues).

Based on static analysis hints

📝 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
Please open an issue [here](https://github.com/eggjs/egg/issues).
Please open an issue on the [egg repository issue tracker](https://github.com/eggjs/egg/issues).
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

55-55: Link text should be descriptive

(MD059, descriptive-link-text)

🤖 Prompt for AI Agents
In plugins/static/README.md around lines 55-56, the link text uses the
non-descriptive word "here" which violates markdownlint MD059; update the link
label to descriptive text (e.g., "open an issue" or "file an issue on GitHub")
by replacing the "[here](...)" with a meaningful phrase that clearly describes
the destination while keeping the same URL so the markdownlint rule passes.

Comment on lines +13 to +22
let app: MockApplication;
beforeAll(async () => {
app = mock.app({
baseDir: getFixtures('static-server'),
});
await app.ready();
});

afterAll(() => 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 | 🟠 Major

Guard teardown when app setup fails

If mock.app() throws (as happened in CI), app stays undefined and afterAll crashes while calling close(), hiding the real failure. Make the fixture variable optional, guard the close, and reset it afterwards; please mirror the same fix for the other suites in this file.

-    let app: MockApplication;
+    let app: MockApplication | undefined;
@@
-    afterAll(() => app.close());
+    afterAll(async () => {
+      if (app) {
+        await app.close();
+        app = undefined;
+      }
+    });
📝 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
let app: MockApplication;
beforeAll(async () => {
app = mock.app({
baseDir: getFixtures('static-server'),
});
await app.ready();
});
afterAll(() => app.close());
let app: MockApplication | undefined;
beforeAll(async () => {
app = mock.app({
baseDir: getFixtures('static-server'),
});
await app.ready();
});
afterAll(async () => {
if (app) {
await app.close();
app = undefined;
}
});
🤖 Prompt for AI Agents
In plugins/static/test/static.test.ts around lines 13 to 22, the test fixture
variable `app` can remain undefined if mock.app() throws, causing afterAll to
crash on app.close(); make the fixture variable optional (e.g., let app?:
MockApplication), guard the teardown by checking if app is defined before
calling app.close(), and reset app to undefined after closing; apply the same
change to the other test suites in this file so all afterAll blocks safely
handle failed setup.

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