-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
feat(koa-static-cache): migrate @eggjs/koa-static-cache to monorepo #5546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Merge @eggjs/koa-static-cache repository as package at packages/koa-static-cache - Update version to 7.0.0-beta.11 - Replace ESLint with oxlint using --type-aware flag - Add tsc --noEmit for type checking - Convert tests to use Vitest with ES module imports - Configure tsdown for unbundled ESM builds - Add missing dependencies to pnpm-workspace.yaml catalog - Update all dependencies to use workspace and catalog references - Add package to root tsconfig.json references BREAKING CHANGE: koa-static-cache is now part of the monorepo and uses ES modules
|
Warning Rate limit exceeded@fengmk2 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 14 minutes and 28 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (10)
Note Other AI code review bot(s) detectedCodeRabbit 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. WalkthroughAdds a new public export entry in Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Client
participant KoaApp as Koa App
participant Middleware as staticCache()
participant FS as File System
participant Store as FileManager
rect rgba(0,128,96,0.06)
Note over KoaApp,Middleware: Initialization (optional preload)
KoaApp->>Middleware: app.use(staticCache(options))
alt preload enabled
Middleware->>FS: read directory
FS-->>Middleware: file stats & buffers
Middleware->>Store: set(path, FileMeta)
end
end
rect rgba(0,64,128,0.06)
Note over Client,Middleware: Request handling
Client->>KoaApp: GET /path
KoaApp->>Middleware: invoke
alt matches prefix/alias & method allowed
Middleware->>Store: get(path)
alt cache hit
Middleware-->>Client: 200 or 304 with headers/body
else cache miss and dynamic enabled
Middleware->>FS: loadFile(path)
FS-->>Middleware: FileMeta
Middleware->>Store: set(path, FileMeta)
Middleware-->>Client: 200 with headers/body
else cache miss and dynamic disabled
Middleware-->>KoaApp: pass through
end
else not matched
Middleware-->>KoaApp: pass through
end
end
Note right of Middleware: handles ETag/If-None-Match, Cache-Control, Last-Modified, optional gzip / precompiled gzip
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
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. Comment |
Summary of ChangesHello @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 significantly refactors the Highlights
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this 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/koa-static-cache package from its separate repository into the main eggjs monorepo as a new package. The migration involves updating the package to use ES modules, replacing ESLint with oxlint, converting tests to Vitest, and configuring tsdown for unbundled ESM builds. The package version has been updated to 7.0.0-beta.11, representing a breaking change as it now uses ES modules.
Key Changes
- Migration of koa-static-cache as a new monorepo package
- Conversion to ES modules with tsdown build configuration
- Test migration from traditional Node.js test framework to Vitest
- Addition of new dependencies to the monorepo's catalog system
Reviewed Changes
Copilot reviewed 12 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
pnpm-workspace.yaml |
Added missing dependencies to catalog for the migrated package |
packages/koa-static-cache/vitest.config.ts |
Vitest configuration for the new package |
packages/koa-static-cache/tsdown.config.ts |
Build configuration using tsdown for unbundled ESM output |
packages/koa-static-cache/tsconfig.json |
TypeScript configuration extending root config |
packages/koa-static-cache/test/index.test.ts |
Comprehensive test suite converted to use Vitest and ES module imports |
packages/koa-static-cache/src/index.ts |
Main static cache middleware implementation with TypeScript interfaces |
packages/koa-static-cache/package.json |
Package configuration with ES module setup and monorepo dependencies |
packages/koa-static-cache/README.md |
Documentation for the static cache middleware |
packages/koa-static-cache/LICENSE |
MIT license file |
packages/koa-static-cache/CHANGELOG.md |
Complete version history and changelog |
packages/koa-static-cache/.gitignore |
Git ignore rules for the package |
packages/egg/package.json |
Updated exports to include new types.plugin module |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
| filter?: FileFilter | string[]; | ||
| /** | ||
| * dynamic load file which not cached on initialization | ||
| * Default to `false |
Copilot
AI
Sep 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing closing quote in JSDoc comment. Should be 'Default to false'
| * Default to `false | |
| * Default to `false` |
| return this.store ? this.store.get(key) : this.map![key]; | ||
| } | ||
|
|
||
| set(key: string, value: FileMeta) { | ||
| if (this.store) { | ||
| return this.store.set(key, value); | ||
| } | ||
| this.map![key] = value; |
Copilot
AI
Sep 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use of non-null assertion operator (!) assumes this.map is always defined when this.store is not available. Consider adding a guard clause or initializing this.map in the constructor to make this safer.
| return this.store ? this.store.get(key) : this.map![key]; | |
| } | |
| set(key: string, value: FileMeta) { | |
| if (this.store) { | |
| return this.store.set(key, value); | |
| } | |
| this.map![key] = value; | |
| if (this.store) { | |
| return this.store.get(key); | |
| } | |
| if (!this.map) { | |
| // Defensive: should never happen, but avoids runtime error | |
| return undefined; | |
| } | |
| return this.map[key]; | |
| } | |
| set(key: string, value: FileMeta) { | |
| if (this.store) { | |
| return this.store.set(key, value); | |
| } | |
| if (!this.map) { | |
| // Defensive: should never happen, but avoids runtime error | |
| this.map = Object.create(null); | |
| } | |
| this.map[key] = value; |
| } else { | ||
| this.map = store || Object.create(null); | ||
| } | ||
| } | ||
|
|
||
| get(key: string) { | ||
| return this.store ? this.store.get(key) : this.map![key]; | ||
| } | ||
|
|
||
| set(key: string, value: FileMeta) { | ||
| if (this.store) { | ||
| return this.store.set(key, value); | ||
| } | ||
| this.map![key] = value; |
Copilot
AI
Sep 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use of non-null assertion operator (!) assumes this.map is always defined when this.store is not available. Consider adding a guard clause or initializing this.map in the constructor to make this safer.
| } else { | |
| this.map = store || Object.create(null); | |
| } | |
| } | |
| get(key: string) { | |
| return this.store ? this.store.get(key) : this.map![key]; | |
| } | |
| set(key: string, value: FileMeta) { | |
| if (this.store) { | |
| return this.store.set(key, value); | |
| } | |
| this.map![key] = value; | |
| this.map = Object.create(null); | |
| } else { | |
| this.map = store || Object.create(null); | |
| } | |
| } | |
| get(key: string) { | |
| return this.store ? this.store.get(key) : this.map[key]; | |
| } | |
| set(key: string, value: FileMeta) { | |
| if (this.store) { | |
| return this.store.set(key, value); | |
| } | |
| this.map[key] = value; |
|
No dependency changes detected. Learn more about Socket for GitHub. 👍 No dependency changes detected in pull request |
There was a problem hiding this 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/koa-static-cache package into the monorepo, updating its dependencies, build tooling, and tests. The changes are well-structured and comprehensive. My review includes a few points for improvement: a high-severity performance issue related to blocking I/O in the dynamic file loading logic, a medium-severity suggestion to improve the robustness of a test case, and a minor typo fix in the README documentation.
| if (!stats) return await next(); | ||
| if (!stats.isFile()) return await next(); | ||
|
|
||
| file = loadFile(filename, dir, options, files); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The loadFile function uses synchronous file system operations (statSync and readFileSync), which will block the Node.js event loop. When running in dynamic mode, this function is called from within an async middleware, which can lead to significant performance degradation under load. It's crucial to use asynchronous I/O operations here.
I recommend creating an async version of loadFile that uses fs.promises.stat and fs.promises.readFile, and then await it here. The synchronous version can be kept for the initial preload phase, which is not asynchronous.
|
|
||
| #### Using a LRU cache to avoid OOM when dynamic mode enabled | ||
|
|
||
| You can pass in a lru cache instance which has tow methods: `get(key)` and `set(key, value)`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| .get('/test/index.test.ts') | ||
| .expect(200) | ||
| .expect('Cache-Control', 'public, max-age=0') | ||
| .expect('Content-Type', /video\/mp2t/); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test asserts that a .ts file has the content type video/mp2t. This is due to a known issue in the mime-types library. While the test currently passes because of this, it's brittle as it depends on incorrect behavior from a dependency. It would be more robust to either test with a file that has a common and correctly identified MIME type (like .txt or .html), or to mock mime.lookup to control the returned MIME type for the test.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## next #5546 +/- ##
==========================================
+ Coverage 76.21% 76.50% +0.28%
==========================================
Files 130 131 +1
Lines 4390 4491 +101
Branches 631 651 +20
==========================================
+ Hits 3346 3436 +90
- Misses 973 984 +11
Partials 71 71 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (7)
packages/koa-static-cache/README.md (2)
39-47: Docs: use ESM imports in examples (package is ESM).Examples use require(), but package.json is ESM-only ("type": "module"). Prefer ESM import, and optionally show CJS interop via createRequire/dynamic import.
Proposed snippet:
import path from 'node:path'; import { staticCache } from '@eggjs/koa-static-cache'; app.use( staticCache(path.join(process.cwd(), 'public'), { maxAge: 365 * 24 * 60 * 60, }) );Optionally add CJS note:
// CommonJS interop const { createRequire } = require('node:module'); const require = createRequire(__filename); const { staticCache } = require('@eggjs/koa-static-cache');
26-27: Clarify CJS support claim.Text says “support CommonJS and ESM both” but this release is ESM-only. Reword and/or add a CJS interop note.
packages/koa-static-cache/CHANGELOG.md (1)
32-57: Consider normalizing list indentation to satisfy markdownlint.The auto-generated block uses tabs; optional to reformat to spaces if you gate on markdownlint.
packages/koa-static-cache/package.json (1)
31-46: Align devDependencies with catalog where available.Switch @types entries to “catalog:” (present in catalog). Keep ylru as-is unless you add it to catalog.
Apply this diff:
"devDependencies": { @@ - "@types/fs-readdir-recursive": "^1.1.3", - "@types/mime-types": "^2.1.4", + "@types/fs-readdir-recursive": "catalog:", + "@types/mime-types": "catalog:",Based on learnings
packages/koa-static-cache/test/index.test.ts (2)
11-11: Close servers to avoid descriptor leaks across testsImport afterAll so you can close long-lived servers created in this file.
-import { describe, it } from 'vitest'; +import { describe, it, afterAll } from 'vitest';
37-37: Ensure servers are closed after testsCreate servers are never closed; under Vitest 3’s parallelism this can cause flaky port usage and FD leaks.
Add the following near the bottom of the file (after server declarations):
afterAll(() => { try { server.close(); } catch {} try { server2.close(); } catch {} try { server3.close(); } catch {} try { server5.close(); } catch {} });Also applies to: 49-49, 61-61, 86-86
packages/koa-static-cache/src/index.ts (1)
285-301: Minor: precompiled .gz lookup shouldn’t append “.gz” to URL keyIf an aliased or prefixed path maps to a gz file on disk, the keying as filename + '.gz' assumes a sibling entry; fine for preload but can miss dynamic .gz when not preloaded. Optional: try direct disk check when usePrecompiledGzip is true and gzFile not in cache.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (13)
packages/egg/package.json(2 hunks)packages/koa-static-cache/.gitignore(1 hunks)packages/koa-static-cache/CHANGELOG.md(1 hunks)packages/koa-static-cache/LICENSE(1 hunks)packages/koa-static-cache/README.md(1 hunks)packages/koa-static-cache/package.json(1 hunks)packages/koa-static-cache/src/index.ts(1 hunks)packages/koa-static-cache/test/index.test.ts(1 hunks)packages/koa-static-cache/tsconfig.json(1 hunks)packages/koa-static-cache/tsdown.config.ts(1 hunks)packages/koa-static-cache/vitest.config.ts(1 hunks)pnpm-workspace.yaml(4 hunks)tsconfig.json(1 hunks)
🧰 Additional context used
📓 Path-based instructions (16)
packages/*/package.json
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use "workspace:*" for internal workspace dependencies in package.json
Files:
packages/egg/package.jsonpackages/koa-static-cache/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.jsonpackages/koa-static-cache/package.json
pnpm-workspace.yaml
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Define dependency versions via the catalog section in pnpm-workspace.yaml and reference them with "catalog:"
Files:
pnpm-workspace.yaml
**/*.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/koa-static-cache/vitest.config.tspackages/koa-static-cache/src/index.tspackages/koa-static-cache/tsdown.config.tspackages/koa-static-cache/test/index.test.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/koa-static-cache/vitest.config.tspackages/koa-static-cache/src/index.tspackages/koa-static-cache/tsdown.config.tspackages/koa-static-cache/test/index.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/koa-static-cache/src/index.ts
packages/*/tsconfig.json
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
All sub-project tsconfig.json files must extend from the root via "extends": "../../tsconfig.json"
Files:
packages/koa-static-cache/tsconfig.json
{tsconfig.json,packages/*/tsconfig.json}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Enable strict TypeScript mode across all packages
Files:
packages/koa-static-cache/tsconfig.jsontsconfig.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:
packages/koa-static-cache/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
packages/*/tsdown.config.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Each package must provide a tsdown.config.ts for unbundled ESM builds
Files:
packages/koa-static-cache/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:
packages/koa-static-cache/tsdown.config.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/koa-static-cache/test/index.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/koa-static-cache/test/index.test.ts
{packages,plugins,tools}/**/test/**/*.test.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Test files should follow the pattern test/**/*.test.ts
Files:
packages/koa-static-cache/test/index.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/koa-static-cache/test/index.test.ts
🧠 Learnings (25)
📚 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/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:
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/**/package.json : Plugin package.json must include peerDependencies { "egg": "workspace:*" }
Applied to files:
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 {packages,plugins,tools}/**/*.{ts,tsx} : Use explicit return types for public APIs
Applied to files:
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:
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:
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:
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 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/koa-static-cache/vitest.config.tspackages/koa-static-cache/tsconfig.jsonpackages/koa-static-cache/tsdown.config.tspackages/koa-static-cache/test/index.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:
packages/koa-static-cache/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 : Name test files as test/**/*.test.ts and run them with Vitest
Applied to files:
packages/koa-static-cache/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/koa-static-cache/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:
packages/koa-static-cache/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/koa-static-cache/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:
packages/koa-static-cache/vitest.config.tspackages/koa-static-cache/test/index.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:
packages/koa-static-cache/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 : Mirror the repository test pattern when adding new suites
Applied to files:
packages/koa-static-cache/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/*/tsconfig.json : All sub-project tsconfig.json files must extend from the root via "extends": "../../tsconfig.json"
Applied to files:
packages/koa-static-cache/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 : All sub-project tsconfig.json files must extend the root tsconfig.json ("extends": "../../tsconfig.json")
Applied to files:
packages/koa-static-cache/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:
packages/koa-static-cache/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,plugins,tools}/**/tsdown.config.ts : Packages should use tsdown for builds (presence of tsdown.config.ts)
Applied to files:
packages/koa-static-cache/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 packages/*/tsdown.config.ts : Each package must provide a tsdown.config.ts for unbundled ESM builds
Applied to files:
packages/koa-static-cache/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/**/tsdown.config.ts : All plugins must use the standard tsdown config: entry: 'src/**/*.ts', unbundle: true, dts: true, exports.devExports: true
Applied to files:
packages/koa-static-cache/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:
packages/koa-static-cache/test/index.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:
packages/koa-static-cache/test/index.test.ts
🧬 Code graph analysis (3)
packages/koa-static-cache/vitest.config.ts (1)
packages/egg/src/lib/types.ts (1)
defineConfig(109-111)
packages/koa-static-cache/tsdown.config.ts (1)
packages/egg/src/lib/types.ts (1)
defineConfig(109-111)
packages/koa-static-cache/test/index.test.ts (1)
packages/koa-static-cache/src/index.ts (1)
staticCache(139-321)
🪛 markdownlint-cli2 (0.18.1)
packages/koa-static-cache/README.md
26-26: Bare URL used
(MD034, no-bare-urls)
packages/koa-static-cache/CHANGELOG.md
28-28: Bare URL used
(MD034, no-bare-urls)
30-30: Bare URL used
(MD034, no-bare-urls)
37-37: Unordered list indentation
Expected: 2; Actual: 1
(MD007, ul-indent)
37-37: Hard tabs
Column: 1
(MD010, no-hard-tabs)
38-38: Unordered list indentation
Expected: 2; Actual: 1
(MD007, ul-indent)
38-38: Hard tabs
Column: 1
(MD010, no-hard-tabs)
39-39: Unordered list indentation
Expected: 2; Actual: 1
(MD007, ul-indent)
39-39: Hard tabs
Column: 1
(MD010, no-hard-tabs)
42-42: Unordered list indentation
Expected: 2; Actual: 1
(MD007, ul-indent)
42-42: Hard tabs
Column: 1
(MD010, no-hard-tabs)
43-43: Unordered list indentation
Expected: 2; Actual: 1
(MD007, ul-indent)
43-43: 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)
47-47: Unordered list indentation
Expected: 2; Actual: 1
(MD007, ul-indent)
47-47: Hard tabs
Column: 1
(MD010, no-hard-tabs)
48-48: Unordered list indentation
Expected: 2; Actual: 1
(MD007, ul-indent)
48-48: Hard tabs
Column: 1
(MD010, no-hard-tabs)
51-51: Unordered list indentation
Expected: 2; Actual: 1
(MD007, ul-indent)
51-51: Hard tabs
Column: 1
(MD010, no-hard-tabs)
52-52: Unordered list indentation
Expected: 2; Actual: 1
(MD007, ul-indent)
52-52: Hard tabs
Column: 1
(MD010, no-hard-tabs)
53-53: Unordered list indentation
Expected: 2; Actual: 1
(MD007, ul-indent)
53-53: Hard tabs
Column: 1
(MD010, no-hard-tabs)
54-54: Unordered list indentation
Expected: 2; Actual: 1
(MD007, ul-indent)
54-54: Hard tabs
Column: 1
(MD010, no-hard-tabs)
63-63: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
66-66: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
67-67: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
68-68: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
69-69: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
71-71: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
74-74: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
75-75: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
77-77: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
80-80: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
81-81: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
82-82: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
84-84: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
87-87: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
89-89: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
92-92: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
93-93: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
95-95: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
98-98: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
100-100: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
103-103: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
105-105: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
108-108: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
110-110: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
113-113: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
115-115: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
118-118: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
120-120: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
123-123: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
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)
134-134: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
136-136: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
139-139: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
141-141: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
144-144: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
146-146: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
149-149: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
151-151: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
154-154: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
156-156: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
159-159: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
161-161: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
164-164: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
166-166: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
169-169: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
170-170: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
172-172: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
175-175: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
176-176: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
177-177: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
178-178: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
180-180: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
183-183: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
185-185: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
188-188: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
190-190: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
193-193: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
194-194: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
196-196: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
199-199: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
200-200: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
202-202: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
205-205: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
206-206: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
208-208: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
211-211: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
212-212: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
213-213: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
215-215: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
218-218: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
220-220: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
223-223: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
224-224: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
225-225: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
227-227: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
230-230: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
231-231: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
233-233: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
236-236: Unordered list indentation
Expected: 0; Actual: 1
(MD007, ul-indent)
238-238: Heading style
Expected: atx; Actual: setext
(MD003, heading-style)
241-241: Unordered list indentation
Expected: 0; Actual: 1
(MD007, ul-indent)
🪛 GitHub Check: CodeQL
packages/koa-static-cache/src/index.ts
[failure] 162-162: Polynomial regular expression used on uncontrolled data
This regular expression that depends on library input may run slow on strings with many repetitions of '/'.
This regular expression that depends on library input may run slow on strings with many repetitions of '/'.
[failure] 334-334: Potential file system race condition
The file may have changed since it was checked.
⏰ 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). (13)
- GitHub Check: Socket Security: Pull Request Alerts
- GitHub Check: Test egg-bin (windows-latest, 24)
- GitHub Check: Test egg-bin (windows-latest, 22)
- GitHub Check: Test egg-bin (macos-latest, 24)
- GitHub Check: Test egg-bin (macos-latest, 22)
- GitHub Check: Test egg-bin (ubuntu-latest, 24)
- GitHub Check: Test egg-bin (ubuntu-latest, 22)
- GitHub Check: Test packages (ubuntu-latest, 24)
- GitHub Check: Test packages (macos-latest, 22)
- GitHub Check: Test packages (macos-latest, 24)
- GitHub Check: Test packages (ubuntu-latest, 22)
- GitHub Check: Test packages (windows-latest, 24)
- GitHub Check: Test packages (windows-latest, 22)
🔇 Additional comments (11)
packages/egg/package.json (1)
50-51: LGTM – new export paths are wired correctly
./lib/types.pluginis now exposed consistently in both runtime and source exports, matching the existing pattern for lib modules.Also applies to: 100-101
packages/koa-static-cache/LICENSE (1)
1-22: License looks correct.MIT text and attributions are fine.
tsconfig.json (1)
54-57: Good addition to project references.Including ./packages/koa-static-cache in root references aligns TS project refs.
packages/koa-static-cache/.gitignore (1)
1-11: Reasonable ignores.Covers node, build, test artifacts. Retaining .eslintcache ignore is harmless.
pnpm-workspace.yaml (1)
8-190: Catalog entries added correctly.New deps are defined in catalog. Ensure all packages reference them with "catalog:" tokens.
If any package.json still pins versions for these deps, switch to "catalog:" (see comment on package.json in this PR). Based on learnings
packages/koa-static-cache/CHANGELOG.md (1)
8-13: Engines note matches package.json.Dropping Node < 20.19.0 here aligns with engines in package.json.
packages/koa-static-cache/package.json (1)
57-66: Export mapping strategy is acceptable.Using source export in dev and publishConfig.exports to dist is fine with tsdown/Vitest.
Confirm tests run without prebuilding (vitest should transpile TS via Vite). If not, consider pointing exports to dist during dev as well.
packages/koa-static-cache/tsdown.config.ts (1)
3-10: LGTM: tsdown config matches our standard unbundled ESM setupEntry, unbundle, dts, and devExports are correctly configured.
Based on learnings
packages/koa-static-cache/vitest.config.ts (1)
3-7: LGTM: Vitest discovery pattern is correctConfig aligns with our test layout conventions.
Based on learnings
packages/koa-static-cache/src/index.ts (2)
162-166: Regex micro-optimization not required; false-positive risk from static analysisThe trailing-slash and leading-slash regexes here are linear-time and operate on trusted config (options.prefix). No action needed.
If you still want to harden, replace with slice checks:
- options.prefix = (options.prefix ?? '').replace(/\/*$/, '/'); + let prefix = options.prefix ?? ''; + while (prefix.endsWith('/')) prefix = prefix.slice(0, -1); + options.prefix = prefix + '/';
239-266: Header casing and semantics are OK
- Vary: Accept-Encoding set when gzip enabled.
- Cache-Control fallback uses maxAge; cacheControl function handled in loadFile.
- ETag and Content-MD5 align with tests.
Please confirm we’re intentionally exposing Content-MD5 (non-standard/deprecated) for backwards compat with existing clients.
| "dependencies": { | ||
| "@eggjs/compressible": "^3.0.0", | ||
| "fs-readdir-recursive": "^1.1.0", | ||
| "mime-types": "^2.1.35", | ||
| "utility": "catalog:" | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Use pnpm catalog tokens for external deps.
Per workspace policy, reference versions via “catalog:”. The catalog already defines these.
Apply this diff:
"dependencies": {
- "@eggjs/compressible": "^3.0.0",
- "fs-readdir-recursive": "^1.1.0",
- "mime-types": "^2.1.35",
+ "@eggjs/compressible": "catalog:",
+ "fs-readdir-recursive": "catalog:",
+ "mime-types": "catalog:",
"utility": "catalog:"
},As per coding guidelines
📝 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.
| "dependencies": { | |
| "@eggjs/compressible": "^3.0.0", | |
| "fs-readdir-recursive": "^1.1.0", | |
| "mime-types": "^2.1.35", | |
| "utility": "catalog:" | |
| }, | |
| "dependencies": { | |
| "@eggjs/compressible": "catalog:", | |
| "fs-readdir-recursive": "catalog:", | |
| "mime-types": "catalog:", | |
| "utility": "catalog:" | |
| }, |
🤖 Prompt for AI Agents
In packages/koa-static-cache/package.json around lines 25 to 30, several
external dependencies are pinned to explicit versions instead of using the
workspace pnpm catalog tokens; replace the version strings for
"@eggjs/compressible", "fs-readdir-recursive", and "mime-types" with their
corresponding catalog tokens (e.g., "catalog:@eggjs/compressible",
"catalog:fs-readdir-recursive", "catalog:mime-types") so all external deps
reference the catalog as required by workspace policy.
| You can pass in a lru cache instance which has tow methods: `get(key)` and `set(key, value)`. | ||
|
|
||
| ```js | ||
| const LRU = require('lru-cache'); | ||
| const files = new LRU({ max: 1000 }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo: “tow methods” → “two methods”.
Minor docs nit.
Apply this diff:
-You can pass in a lru cache instance which has tow methods: `get(key)` and `set(key, value)`.
+You can pass in an LRU cache instance which has two methods: `get(key)` and `set(key, value)`.📝 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.
| You can pass in a lru cache instance which has tow methods: `get(key)` and `set(key, value)`. | |
| ```js | |
| const LRU = require('lru-cache'); | |
| const files = new LRU({ max: 1000 }); | |
| You can pass in an LRU cache instance which has two methods: `get(key)` and `set(key, value)`. |
🤖 Prompt for AI Agents
In packages/koa-static-cache/README.md around lines 127 to 131, fix the typo in
the sentence "You can pass in a lru cache instance which has tow methods:
`get(key)` and `set(key, value)`." by changing "tow" to "two" so it reads "two
methods"; update the line in the README accordingly.
| const fullpath = path.join(dir, filename); | ||
| // files that can be accessed should be under options.dir | ||
| if (!fullpath.startsWith(dir)) { | ||
| return await next(); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix path traversal check (startsWith on joined paths is unsafe)
Using startsWith on a joined path allows bypasses like /var/www-bad. Resolve and compare via path.relative to guarantee containment.
- const fullpath = path.join(dir, filename);
- // files that can be accessed should be under options.dir
- if (!fullpath.startsWith(dir)) {
- return await next();
- }
+ const fullpath = path.resolve(dir, filename);
+ // ensure path stays under dir (prevent traversal)
+ const rel = path.relative(dir, fullpath);
+ if (rel.startsWith('..') || path.isAbsolute(rel)) {
+ return await next();
+ }| const stats = statSync(filename); | ||
| const buffer = readFileSync(filename); | ||
|
|
||
| obj.cacheControl = typeof options.cacheControl === 'function' ? options.cacheControl(filename) : options.cacheControl; // if cacheControl is a function, it will be called with the filename | ||
| obj.maxAge = (typeof obj.maxAge === 'number' ? obj.maxAge : options.maxAge) || 0; | ||
| obj.type = obj.mime = mime.lookup(pathname) || 'application/octet-stream'; | ||
| obj.mtime = stats.mtime; | ||
| obj.length = stats.size; | ||
| obj.md5 = crypto.createHash('md5').update(buffer).digest('base64'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid TOCTOU and reduce mismatch between size/md5/mtime
Current order can read a different file version than was stat’ed; also length should come from the buffer to stay consistent.
- const stats = statSync(filename);
- const buffer = readFileSync(filename);
+ const buffer = readFileSync(filename);
+ const stats = statSync(filename);
@@
- obj.length = stats.size;
+ obj.length = buffer.length;Note: loadFile runs on the request path in dynamic mode; the sync I/O will block the event loop under load. Consider an async load path (stream hashing via crypto and fs.promises) for dynamic mode while keeping sync for preload.
📝 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.
| const stats = statSync(filename); | |
| const buffer = readFileSync(filename); | |
| obj.cacheControl = typeof options.cacheControl === 'function' ? options.cacheControl(filename) : options.cacheControl; // if cacheControl is a function, it will be called with the filename | |
| obj.maxAge = (typeof obj.maxAge === 'number' ? obj.maxAge : options.maxAge) || 0; | |
| obj.type = obj.mime = mime.lookup(pathname) || 'application/octet-stream'; | |
| obj.mtime = stats.mtime; | |
| obj.length = stats.size; | |
| obj.md5 = crypto.createHash('md5').update(buffer).digest('base64'); | |
| const buffer = readFileSync(filename); | |
| const stats = statSync(filename); | |
| obj.cacheControl = | |
| typeof options.cacheControl === 'function' | |
| ? options.cacheControl(filename) | |
| : options.cacheControl; // if cacheControl is a function, it will be called with the filename | |
| obj.maxAge = (typeof obj.maxAge === 'number' ? obj.maxAge : options.maxAge) || 0; | |
| obj.type = obj.mime = mime.lookup(pathname) || 'application/octet-stream'; | |
| obj.mtime = stats.mtime; | |
| obj.length = buffer.length; | |
| obj.md5 = crypto.createHash('md5').update(buffer).digest('base64'); |
🧰 Tools
🪛 GitHub Check: CodeQL
[failure] 334-334: Potential file system race condition
The file may have changed since it was checked.
🤖 Prompt for AI Agents
In packages/koa-static-cache/src/index.ts around lines 333 to 341, the code
currently stats the file then reads it which can cause TOCTOU (time-of-check vs
time-of-use) and mismatch between stats.size and the actual buffer length; fix
by opening the file descriptor and using fstat on that fd, then read the file
contents from the same fd (so stat and read refer to the identical inode state),
compute md5 from the buffer and set length from buffer.byteLength, set mtime
from the fstat result, and finally close the fd; additionally, for dynamic mode
consider implementing an async path that streams and hashes via crypto with
fs.promises to avoid blocking the event loop while keeping the existing
synchronous preload behavior.
| { | ||
| "extends": "../../tsconfig.json", | ||
| "compilerOptions": { | ||
| "baseUrl": "./" | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Enable strict mode explicitly in package tsconfig.
To comply with repo guidelines, set compilerOptions.strict: true here (don’t rely on inheritance).
Apply this diff:
{
"extends": "../../tsconfig.json",
"compilerOptions": {
+ "strict": true,
"baseUrl": "./"
}
}As per coding guidelines
📝 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.
| { | |
| "extends": "../../tsconfig.json", | |
| "compilerOptions": { | |
| "baseUrl": "./" | |
| } | |
| } | |
| { | |
| "extends": "../../tsconfig.json", | |
| "compilerOptions": { | |
| "strict": true, | |
| "baseUrl": "./" | |
| } | |
| } |
🤖 Prompt for AI Agents
In packages/koa-static-cache/tsconfig.json around lines 1 to 6, the package
tsconfig currently relies on inherited compiler settings but must explicitly
enable strict mode; add "strict": true to the "compilerOptions" object (do not
rely on inheritance) so the file contains a top-level compilerOptions.strict set
to true.
There was a problem hiding this 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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
plugins/schedule/package.json (1)
70-77: Add the requiredcleanscript.Per the plugin package.json guidelines, we need a
cleanscript (usuallyrimraf dist). Please reintroduce it to keep the plugin consistent with the monorepo standard."scripts": { + "clean": "rimraf dist", "build": "tsdown", "typecheck": "tsc --noEmit",
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/koa-static-cache/package.json(1 hunks)packages/koa-static-cache/test/index.test.ts(1 hunks)plugins/schedule/package.json(1 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
packages/*/package.json
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use "workspace:*" for internal workspace dependencies in package.json
Files:
packages/koa-static-cache/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/koa-static-cache/package.jsonplugins/schedule/package.json
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/schedule/package.json
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/koa-static-cache/test/index.test.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/koa-static-cache/test/index.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/koa-static-cache/test/index.test.ts
{packages,plugins,tools}/**/test/**/*.test.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Test files should follow the pattern test/**/*.test.ts
Files:
packages/koa-static-cache/test/index.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/koa-static-cache/test/index.test.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/koa-static-cache/test/index.test.ts
🧠 Learnings (7)
📚 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/koa-static-cache/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/koa-static-cache/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/*/package.json : Use "workspace:*" for internal workspace dependencies in package.json
Applied to files:
packages/koa-static-cache/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/cookies/test/**/*.test.ts : cookies package uses Mocha; test files follow test/**/*.test.ts
Applied to files:
packages/koa-static-cache/test/index.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/koa-static-cache/test/index.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: For features affecting HTTP or process orchestration, add regression tests that exercise both the CommonJS and TypeScript example apps
Applied to files:
packages/koa-static-cache/test/index.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:
packages/koa-static-cache/test/index.test.ts
🧬 Code graph analysis (1)
packages/koa-static-cache/test/index.test.ts (1)
packages/koa-static-cache/src/index.ts (1)
staticCache(139-321)
⏰ 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). (13)
- GitHub Check: Test egg-bin (windows-latest, 24)
- GitHub Check: Test egg-bin (windows-latest, 22)
- GitHub Check: Test egg-bin (macos-latest, 24)
- GitHub Check: Test egg-bin (macos-latest, 22)
- GitHub Check: Test egg-bin (ubuntu-latest, 24)
- GitHub Check: Test packages (macos-latest, 24)
- GitHub Check: Test packages (ubuntu-latest, 22)
- GitHub Check: Test egg-bin (ubuntu-latest, 22)
- GitHub Check: Test packages (windows-latest, 24)
- GitHub Check: Test packages (windows-latest, 22)
- GitHub Check: Test packages (ubuntu-latest, 24)
- GitHub Check: Test packages (macos-latest, 22)
- GitHub Check: Cloudflare Pages: egg-v3
🔇 Additional comments (1)
packages/koa-static-cache/package.json (1)
38-48: Use catalog tokens for devDependenciesPer the monorepo catalog policy, external packages should be referenced through
catalog:. Please align the remaining devDependencies with that convention.- "@types/fs-readdir-recursive": "^1.1.3", - "@types/mime-types": "^2.1.4", + "@types/fs-readdir-recursive": "catalog:", + "@types/mime-types": "catalog:", @@ - "ylru": "^2.0.0" + "ylru": "catalog:"[ suggest_essential_refactor ]
As per coding guidelines
| "test": "npm run lint:fix && vitest run", | ||
| "ci": "vitest run --coverage", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid auto-fixing during npm run test
Running lint:fix inside the test script mutates sources before tests execute, which is risky for CI and local runs. Swap it for the non-mutating lint command.
- "test": "npm run lint:fix && vitest run",
+ "test": "npm run lint && vitest run",📝 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.
| "test": "npm run lint:fix && vitest run", | |
| "ci": "vitest run --coverage", | |
| "test": "npm run lint && vitest run", | |
| "ci": "vitest run --coverage", |
🤖 Prompt for AI Agents
In packages/koa-static-cache/package.json around lines 54-55 the "test" script
runs "npm run lint:fix && vitest run", which auto-mutes source files before
tests; change it to use the non-mutating lint command (e.g., "npm run lint &&
vitest run" or the equivalent lint script that doesn't apply fixes) so tests run
against unmodified sources; update the "test" script accordingly and leave the
"ci" script unchanged.
| const server = app.listen(); | ||
| await request(server).get('/src/index.ts').expect(200); | ||
| }); | ||
|
|
||
| it('should default options.dir works fine', async () => { | ||
| const app = new Koa(); | ||
| app.use( | ||
| staticCache({ | ||
| dir: path.join(__dirname, '..'), | ||
| }) | ||
| ); | ||
| const server = app.listen(); | ||
| await request(server).get('/src/index.ts').expect(200); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Close app.listen() servers in tests
app.listen() starts a live server that never gets closed here (and the same pattern repeats throughout the suite), so the handles stay open and Vitest will hang/flake once enough of these accumulate. Supertest can drive the Koa callback directly—no need to spin up a listener. Please update each case to avoid leaking sockets.
- const server = app.listen();
- await request(server).get('/src/index.ts').expect(200);
+ await request(app.callback()).get('/src/index.ts').expect(200);Apply the same fix anywhere else this pattern appears in the file.
🤖 Prompt for AI Agents
In packages/koa-static-cache/test/index.test.ts around lines 124 to 136, the
tests call app.listen() which starts real servers and leaks sockets; replace
usage of request(server) with request(app.callback()) (or pass app.callback()
directly into supertest) so no listener is created, and remove or close any
app.listen() calls; apply this same change wherever app.listen() is used in this
test file so tests no longer spin up real servers or leak handles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
package.json (1)
40-42: Use pnpm workspace filters for CI scripts
All packages, tools, and plugins definetest:covand include a localvitest.config.ts, so invoking tests via workspace filters will honor each config:- "ci:packages": "pnpm run test:cov packages/*", - "ci:tools": "pnpm run test:cov tools/*", - "ci:plugins": "pnpm run test:cov plugins/*", + "ci:packages": "pnpm -r --filter \"./packages/*\" run test:cov", + "ci:tools": "pnpm -r --filter \"./tools/*\" run test:cov", + "ci:plugins": "pnpm -r --filter \"./plugins/*\" run test:cov",.github/workflows/ci.yml (1)
82-84: Run tests per-package to respect Vitest configs
Replace your CI step with:- run: pnpm run ci:${{ matrix.filter }} + run: pnpm -r --filter "./${{ matrix.filter }}/*" run testOnce you’ve added per-package coverage scripts (e.g.
test:cov), switch torun test:covor userun test -- --coverage.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.github/workflows/ci.yml(2 hunks)package.json(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 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-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:
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/{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:
package.json
⏰ 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). (13)
- GitHub Check: Test (ubuntu-latest, 24, packages)
- GitHub Check: Test (windows-latest, 22, tools)
- GitHub Check: Test (ubuntu-latest, 24, plugins)
- GitHub Check: Test (ubuntu-latest, 22, plugins)
- GitHub Check: Test (ubuntu-latest, 22, packages)
- GitHub Check: Test (macos-latest, 24, packages)
- GitHub Check: Test (windows-latest, 24, packages)
- GitHub Check: Test egg-bin (windows-latest, 22)
- GitHub Check: Test egg-bin (ubuntu-latest, 24)
- GitHub Check: Test (macos-latest, 22, plugins)
- GitHub Check: Test egg-bin (windows-latest, 24)
- GitHub Check: Test egg-bin (macos-latest, 22)
- GitHub Check: Test egg-bin (ubuntu-latest, 22)
🔇 Additional comments (2)
.github/workflows/ci.yml (2)
51-51: Job rename looks goodRenaming the job to test is clear and consistent with the new matrix split.
63-64: Concurrency group expansion is correctIncluding matrix.filter in the concurrency key prevents cross-scope cancellations. Good call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
package.json(1 hunks)packages/egg/test/lib/plugins/schedule.test.ts(0 hunks)scripts/ci.js(1 hunks)
💤 Files with no reviewable changes (1)
- packages/egg/test/lib/plugins/schedule.test.ts
🧰 Additional context used
🧠 Learnings (6)
📚 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-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:
package.jsonscripts/ci.js
📚 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:
scripts/ci.js
📚 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:
scripts/ci.js
📚 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:
scripts/ci.js
📚 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:
scripts/ci.js
🪛 GitHub Check: CodeQL
scripts/ci.js
[warning] 24-24: Shell command built from environment values
This shell command depends on an uncontrolled file name.
[warning] 24-24: Indirect uncontrolled command line
This command depends on an unsanitized command-line argument.
⏰ 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). (20)
- GitHub Check: Socket Security: Pull Request Alerts
- GitHub Check: Test (ubuntu-latest, 22, tools)
- GitHub Check: Test (ubuntu-latest, 24, plugins)
- GitHub Check: Test (windows-latest, 24, plugins)
- GitHub Check: Test (windows-latest, 22, plugins)
- GitHub Check: Test (windows-latest, 24, packages)
- GitHub Check: Test (ubuntu-latest, 24, packages)
- GitHub Check: Test (ubuntu-latest, 22, plugins)
- GitHub Check: Test (windows-latest, 24, tools)
- GitHub Check: Test (ubuntu-latest, 22, packages)
- GitHub Check: Test (macos-latest, 24, plugins)
- GitHub Check: Test (windows-latest, 22, packages)
- GitHub Check: Test (macos-latest, 24, packages)
- GitHub Check: Test egg-bin (windows-latest, 24)
- GitHub Check: Test egg-bin (windows-latest, 22)
- GitHub Check: Test egg-bin (macos-latest, 24)
- GitHub Check: Test egg-bin (ubuntu-latest, 24)
- GitHub Check: Test egg-bin (macos-latest, 22)
- GitHub Check: Test egg-bin (ubuntu-latest, 22)
- GitHub Check: Cloudflare Pages: egg-v3
🔇 Additional comments (2)
package.json (1)
40-42: LGTM; confirm build still runs after matrixed CI scriptsThe new ci:* scripts align with the matrix (packages/tools/plugins). Ensure the previous postci build step is still executed in CI, since postci only runs after the plain “ci” script. Options:
- Trigger a separate build step in the workflow after the matrix job, or
- Chain build in each ci:* script (less ideal due to duplicate work).
scripts/ci.js (1)
7-14: Per-package Vitest configs are already honored
Root vitest.config.ts uses defineConfig({ test: { projects: ['packages/','plugins/','tools/*'] } }), which loads each package’s own vitest.config.ts; a separate defineWorkspace call isn’t needed.Likely an incorrect or invalid review comment.

BREAKING CHANGE: koa-static-cache is now part of the monorepo and uses ES modules
Summary by CodeRabbit
New Features
Documentation
Tests
Chores