Skip to content

feat(core): add manifest-backed loader fs#5943

Merged
killagu merged 5 commits into
nextfrom
agent/egg-dev/1539d7a6
May 28, 2026
Merged

feat(core): add manifest-backed loader fs#5943
killagu merged 5 commits into
nextfrom
agent/egg-dev/1539d7a6

Conversation

@killagu

@killagu killagu commented May 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add ManifestLoaderFS, a manifest-first LoaderFS implementation backed by StartupManifest discovery/resolve data and the bundled module loader.
  • Wire EggLoader to use ManifestLoaderFS for bundled stores and manifest-backed startup while keeping real filesystem fallback.
  • Include package metadata files in generated manifest discovery and add tests for manifest-backed glob/stat/readJSON/loadFile, plugin metadata, and fallback behavior.

Tests

  • pnpm exec vitest run packages/core/test/loader/loader_fs.test.ts packages/core/test/loader/manifest_loader_fs.test.ts packages/core/test/loader/file_loader.test.ts packages/core/test/loader/manifest_coverage.test.ts packages/core/test/loader/manifest_roundtrip.test.ts --testTimeout 20000
  • pnpm --filter @eggjs/core typecheck
  • pnpm exec oxlint packages/core/src/loader/loader_fs.ts packages/core/test/loader/manifest_loader_fs.test.ts --type-aware

Issue: EGG-98

Summary by CodeRabbit

  • New Features

    • Manifest-backed filesystem access for loading files and bundled modules; loader now prefers manifest entries when available.
  • Refactor

    • Plugin package.json reading and path checks now go through the abstracted loader and honor manifest-backed files.
    • Startup manifest generation records discovered package.json basenames and avoids duplicate discovery.
  • Tests

    • Added/expanded tests covering manifest-backed loading, globbing, JSON parsing, bundled module loading, and regressions.

Review Change Stack

Copilot AI review requested due to automatic review settings May 10, 2026 02:31
@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds ManifestLoaderFS (manifest-backed LoaderFS) with manifest-resolution, bundled-module loading, and multimatch-based globbing; integrates it into EggLoader initialization, switches plugin package.json reads to loaderFS APIs, records discovered package.json into manifest.fileDiscovery, and adds tests and a re-export.

Changes

Manifest-Based Filesystem Loading

Layer / File(s) Summary
ManifestLoaderFS API
packages/core/src/loader/loader_fs.ts
New ManifestLoaderFS implements LoaderFS with manifest-aware exists(), stat(), realpath(), readJSON(), glob(), and loadFile(), delegating to RealLoaderFS when unmapped.
Manifest lookup & resolution internals
packages/core/src/loader/loader_fs.ts
Core manifest lookup, resolveCache/fileDiscovery resolution, bundled-module key derivation, absolute↔manifest-relative conversions, and directory listing for glob candidates.
Glob helpers & multimatch integration
packages/core/src/loader/loader_fs.ts, packages/core/package.json
Candidate enumeration and filtering, alternation/ignore normalization for multimatch; adds multimatch dependency.
EggLoader integration and convention collection
packages/core/src/loader/egg_loader.ts
EggLoader selects/wraps ManifestLoaderFS when a ManifestStore matches baseDir; plugin package.json reads now use loaderFS.exists/loaderFS.readJSON; adds #collectConventionFile to record discovered package.json into manifest.fileDiscovery.
Tests and coverage
packages/core/test/loader/manifest_loader_fs.test.ts, packages/core/test/loader/manifest_coverage.test.ts
Vitest suite validating manifest-backed exists/stat/realpath/glob/readJSON/loadFile, fallback behaviour and precedence, plus assertion that package.json is recorded in manifest.fileDiscovery.
Public re-export
packages/core/src/index.ts
Re-exports ManifestLoaderFS from the loader filesystem module.

Sequence Diagram(s)

sequenceDiagram
  participant EggLoader
  participant ManifestStore
  participant ManifestLoaderFS
  participant RealLoaderFS
  EggLoader->>ManifestStore: lookup manifest for baseDir
  alt manifest exists
    EggLoader->>ManifestLoaderFS: construct with manifest + RealLoaderFS fallback
  else no manifest
    EggLoader->>RealLoaderFS: use RealLoaderFS or provided loaderFS
  end
  EggLoader->>ManifestLoaderFS: loaderFS.exists(package.json)
  EggLoader->>ManifestLoaderFS: loaderFS.readJSON(package.json)
  EggLoader->>ManifestStore: collectConventionFile -> update manifest.fileDiscovery
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • eggjs/egg#5936: Related LoaderFS abstraction work threaded through EggLoader.
  • eggjs/egg#5867: Introduced the global bundle-module loader hook consumed by ManifestLoaderFS.
  • eggjs/egg#5886: Related manifest-driven file-loading tests and coverage changes.

Suggested reviewers

  • fengmk2
  • gxkl
  • jerryliang64
  • akitaSummer

Poem

🐰 I hopped through manifests neat and small,
Peeked at package.json within the hall,
I matched the globs and wrapped the default light,
When files hide in bundles I bring them to sight,
A hopping loader, ready for the call!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding a manifest-backed loader filesystem implementation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/egg-dev/1539d7a6

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

❤️ Share

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

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces ManifestLoaderFS, a filesystem abstraction that enables loading files from a manifest or bundle map with a fallback to the physical filesystem. It integrates this into EggLoader to facilitate bundled application support. The review feedback identifies critical limitations in the custom globToRegExp implementation, specifically regarding character classes and wildcards within groups. Additionally, it is recommended to enhance createVirtualStats by including standard fs.Stats date properties to prevent potential runtime errors in external libraries.

Comment thread packages/core/src/loader/loader_fs.ts Outdated
Comment thread packages/core/src/loader/loader_fs.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
packages/core/src/loader/egg_loader.ts (1)

653-660: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep plugin export-path probing on loaderFS too.

This now reads package.json through the manifest abstraction, but #formatPluginPathFromPackageJSON() still probes exports.import/require with utility.exists(). In manifest-only startup, that check sees no real file and can wrongly fall back to eggPlugin.exports.typescript, so bundled plugins resolve to a path that is not actually present in the manifest.

Suggested fix
-      if (exports.typescript && isSupportTypeScript() && !(await exists(realPluginPath))) {
+      if (exports.typescript && isSupportTypeScript() && !this.loaderFS.exists(realPluginPath)) {
         // if require/import path not exists, use typescript path for development stage
         realPluginPath = path.join(pluginPath, exports.typescript);
         debug('[formatPluginPathFromPackageJSON] use typescript path %o', realPluginPath);
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/loader/egg_loader.ts` around lines 653 - 660, The plugin
export-path probing currently uses a plain filesystem check inside
`#formatPluginPathFromPackageJSON` which calls utility.exists() and thus misses
manifest-only files; update `#formatPluginPathFromPackageJSON` to use the loaderFS
abstraction (this.loaderFS.exists) when probing exports.import/exports.require
and any path checks so that package.json -> plugin.path resolution honors the
manifest-only startup. Ensure the method still handles both import/require keys
and returns the same plugin.path behavior, referencing plugin.path, pkg, and
`#formatPluginPathFromPackageJSON` in your change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/loader/loader_fs.ts`:
- Around line 88-99: Summary: ManifestLoaderFS.glob returns relative paths when
options.absolute is true if cwd is relative. Fix: keep using cwdRel =
this.#toRelative(...) for manifest lookup but resolve the caller-supplied cwd to
an absolute path before joining when options?.absolute is set; e.g., compute an
absolute cwd (path.resolve(cwd)) and use that in the matched.map((file) =>
path.join(absCwd, file)) so behaviour matches RealLoaderFS.glob; update the glob
method (symbols: glob, cwd, cwdRel, `#toRelative`, filterManifestGlob,
`#fallback.glob`, options.absolute) accordingly.

---

Outside diff comments:
In `@packages/core/src/loader/egg_loader.ts`:
- Around line 653-660: The plugin export-path probing currently uses a plain
filesystem check inside `#formatPluginPathFromPackageJSON` which calls
utility.exists() and thus misses manifest-only files; update
`#formatPluginPathFromPackageJSON` to use the loaderFS abstraction
(this.loaderFS.exists) when probing exports.import/exports.require and any path
checks so that package.json -> plugin.path resolution honors the manifest-only
startup. Ensure the method still handles both import/require keys and returns
the same plugin.path behavior, referencing plugin.path, pkg, and
`#formatPluginPathFromPackageJSON` in your change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5895165b-2f77-4cc2-a6b4-459e7e37142e

📥 Commits

Reviewing files that changed from the base of the PR and between 0dec2c9 and 6fc9b6c.

📒 Files selected for processing (4)
  • packages/core/src/loader/egg_loader.ts
  • packages/core/src/loader/loader_fs.ts
  • packages/core/test/loader/manifest_coverage.test.ts
  • packages/core/test/loader/manifest_loader_fs.test.ts

Comment thread packages/core/src/loader/loader_fs.ts
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 10, 2026

Copy link
Copy Markdown

Deploying egg with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9400d37
Status: ✅  Deploy successful!
Preview URL: https://e43f68d8.egg-cci.pages.dev
Branch Preview URL: https://agent-egg-dev-1539d7a6.egg-cci.pages.dev

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 10, 2026

Copy link
Copy Markdown

Deploying egg-v3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9400d37
Status: ✅  Deploy successful!
Preview URL: https://4c57997e.egg-v3.pages.dev
Branch Preview URL: https://agent-egg-dev-1539d7a6.egg-v3.pages.dev

View logs

@killagu
killagu force-pushed the agent/egg-dev/1539d7a6 branch from 6fc9b6c to f7dc977 Compare May 10, 2026 02:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 adds a manifest-first filesystem abstraction for Egg’s loader pipeline so bundled or manifest-backed startups can resolve/scan/load files using StartupManifest data (and the bundle module loader) with a real filesystem fallback.

Changes:

  • Introduces ManifestLoaderFS (manifest-first LoaderFS) supporting manifest-backed exists/stat/realpath/glob/readJSON/loadFile.
  • Wires EggLoader to select ManifestLoaderFS automatically for bundle stores and for manifest-backed startup flows, while keeping a real FS fallback.
  • Extends manifest generation to include package.json in conventional discovery, plus adds/updates tests for manifest-backed behavior and plugin metadata inclusion.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

File Description
packages/core/src/loader/loader_fs.ts Adds ManifestLoaderFS implementation and manifest-backed glob/matching helpers.
packages/core/src/loader/egg_loader.ts Integrates ManifestLoaderFS selection/wrapping and collects package.json into manifest discovery; switches plugin package.json reads to loaderFS.
packages/core/test/loader/manifest_loader_fs.test.ts Adds new unit tests covering manifest-backed FS behavior and fallback/priority rules.
packages/core/test/loader/manifest_coverage.test.ts Asserts plugin package metadata (package.json) is included in manifest fileDiscovery.

Comment thread packages/core/src/loader/loader_fs.ts Outdated
Comment thread packages/core/src/loader/loader_fs.ts
Comment thread packages/core/test/loader/manifest_loader_fs.test.ts
@killagu
killagu force-pushed the agent/egg-dev/1539d7a6 branch from f7dc977 to aba2f64 Compare May 10, 2026 02:39
Copilot AI review requested due to automatic review settings May 10, 2026 02:41
@killagu
killagu force-pushed the agent/egg-dev/1539d7a6 branch from aba2f64 to 5aff2fd Compare May 10, 2026 02:41

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
packages/core/src/loader/loader_fs.ts (1)

89-102: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

absolute: true still returns relative paths when caller passes a relative cwd.

At Line 90, cwd keeps the caller-supplied value verbatim. When options.absolute is set on Line 98, path.join(cwd, file) on Line 99 yields a relative result, diverging from RealLoaderFS.glob() which goes through globby.sync(...) and returns absolute paths under the same options. This is a behavioral mismatch in what's intended to be a drop-in replacement.

Resolve cwd to an absolute path at the source so both manifest lookup and the join produce consistent results.

🔧 Suggested fix
   glob(patterns: string | string[], options?: LoaderFSGlobOptions): string[] {
-    const cwd = options?.cwd === undefined ? process.cwd() : String(options.cwd);
+    const cwd = path.resolve(options?.cwd === undefined ? process.cwd() : String(options.cwd));
     const cwdRel = this.#toRelative(cwd);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/loader/loader_fs.ts` around lines 89 - 102, The glob method
currently uses the caller-supplied cwd verbatim which causes path.join(cwd,
file) in the absolute branch to produce relative paths; change glob to resolve
cwd to an absolute path up-front (e.g., using path.resolve or similar) before
calling this.#toRelative and this.#listManifestFilesUnder so that both manifest
lookup and the matched.map((file) => path.join(cwd, file)) produce absolute
paths; update references in glob that use cwd (including the cwdRel assignment
and the manifest lookup) so the rest of the method and filterManifestGlob
behavior remain correct and consistent with RealLoaderFS.glob.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/core/src/loader/loader_fs.ts`:
- Around line 89-102: The glob method currently uses the caller-supplied cwd
verbatim which causes path.join(cwd, file) in the absolute branch to produce
relative paths; change glob to resolve cwd to an absolute path up-front (e.g.,
using path.resolve or similar) before calling this.#toRelative and
this.#listManifestFilesUnder so that both manifest lookup and the
matched.map((file) => path.join(cwd, file)) produce absolute paths; update
references in glob that use cwd (including the cwdRel assignment and the
manifest lookup) so the rest of the method and filterManifestGlob behavior
remain correct and consistent with RealLoaderFS.glob.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ec452c67-5f10-4098-a746-998b4a94c070

📥 Commits

Reviewing files that changed from the base of the PR and between 6fc9b6c and f7dc977.

📒 Files selected for processing (5)
  • packages/core/package.json
  • packages/core/src/loader/egg_loader.ts
  • packages/core/src/loader/loader_fs.ts
  • packages/core/test/loader/manifest_coverage.test.ts
  • packages/core/test/loader/manifest_loader_fs.test.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/core/test/loader/manifest_coverage.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/core/test/loader/manifest_loader_fs.test.ts
  • packages/core/src/loader/egg_loader.ts

@codecov

codecov Bot commented May 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.58974% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.29%. Comparing base (d37b278) to head (9400d37).

Files with missing lines Patch % Lines
packages/core/src/loader/loader_fs.ts 92.92% 15 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             next    #5943      +/-   ##
==========================================
+ Coverage   85.21%   85.29%   +0.08%     
==========================================
  Files         669      670       +1     
  Lines       19320    19549     +229     
  Branches     3792     3868      +76     
==========================================
+ Hits        16464    16675     +211     
- Misses       2464     2482      +18     
  Partials      392      392              

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

@killagu
killagu force-pushed the agent/egg-dev/1539d7a6 branch from 5aff2fd to 44f3c9a Compare May 10, 2026 02:49
Copilot AI review requested due to automatic review settings May 28, 2026 05:57
@killagu
killagu force-pushed the agent/egg-dev/1539d7a6 branch from 44f3c9a to 356c006 Compare May 28, 2026 05:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

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

Comment thread packages/core/src/loader/loader_fs.ts
Comment thread packages/core/src/loader/loader_fs.ts Outdated
@killagu
killagu force-pushed the agent/egg-dev/1539d7a6 branch from 356c006 to 0d758fe Compare May 28, 2026 06:30
Copilot AI review requested due to automatic review settings May 28, 2026 06:35
@killagu
killagu force-pushed the agent/egg-dev/1539d7a6 branch from 0d758fe to 21d3094 Compare May 28, 2026 06:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

@killagu
killagu force-pushed the agent/egg-dev/1539d7a6 branch from 21d3094 to b4a598b Compare May 28, 2026 06:41
Copilot AI review requested due to automatic review settings May 28, 2026 07:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comment thread packages/core/src/loader/loader_fs.ts
Comment thread packages/core/src/loader/egg_loader.ts Outdated
Copilot AI review requested due to automatic review settings May 28, 2026 12:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Comment thread packages/core/src/loader/egg_loader.ts
Comment thread packages/core/test/loader/egg_loader.test.ts
Comment thread packages/core/test/loader/egg_loader.test.ts
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.

2 participants