Skip to content

feat(tegg-loader): route module discovery through shared loader fs#5970

Merged
killagu merged 1 commit into
nextfrom
feat/tegg-loader-shared-loader-fs
Jun 20, 2026
Merged

feat(tegg-loader): route module discovery through shared loader fs#5970
killagu merged 1 commit into
nextfrom
feat/tegg-loader-shared-loader-fs

Conversation

@killagu

@killagu killagu commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Motivation

Part of the bundle startup optimization (Theme F, EGG-130/136/138). @eggjs/tegg-loader imported globby directly for module discovery, so a bundled app's manifest-backed VFS (ManifestLoaderFS) could not serve tegg's discovery — only egg-core's. This routes tegg discovery through the shared @eggjs/loader-fs abstraction, satisfying "no private VFS inside tegg".

Scope

  • ModuleLoader: discovery now uses an injectable LoaderFS.glob (default RealLoaderFS, so normal startup is byte-for-byte unchanged). Module loading (LoaderUtil.loadFile + the __EGG_BUNDLE_MODULE_LOADER__ hook + dynamic-import fallback) is intentionally left untouched — RealLoaderFS.loadFile only returns the default export, which doesn't fit tegg's all-named-exports semantics.
  • LoaderFactory: thread an optional loaderFS through createLoader / loadApp (both the manifest decoratedFiles branch and the globby branch).
  • EggModuleLoader: reuse app.loader.loaderFS in buildAppGraph and loadModule. Normal mode → RealLoaderFS (zero regression); bundle mode → ManifestLoaderFS.
  • Drop the direct globby dependency from @eggjs/tegg-loader.

Tests

  • ModuleLoaderLoaderFS.test.ts (new) + LoaderFactoryManifest.test.ts (extended): discovery routes through the injected LoaderFS; precomputed files skip glob; default RealLoaderFS equivalence.
  • BundledDI.test.ts (runtime, new): cross-module DI (service → public repo → private persistence) resolves via manifest decoratedFiles with a glob-throwing LoaderFS, proving zero disk scan.
  • BundledAppBoot.test.ts (plugin, new): a full tegg app boots in manifest-consume mode (production fromBundlesetBundleStore path) and serves the controller → service → cross-module repo DI chain over HTTP; with an injected ManifestLoaderFS, core/framework discovery does zero disk globs.

Test evidence

vitest run tegg/core/loader tegg/core/runtime tegg/plugin/tegg30 passed | 2 skipped (94 tests), 0 failures. typecheck (loader/runtime/plugin), oxlint --type-aware, oxfmt, and --frozen-lockfile all clean.

Known follow-ups (out of scope here)

  • @eggjs/mock has no first-class loaderFS option, so BundledAppBoot injects it via the single-mode options passthrough with a cast. TODO: add loaderFS to MockOptions and drop the cast.
  • In consume mode EggModuleLoader.loadModule still globs each module dir from disk (manifest stores tegg decoratedFiles, not module dirs in core fileDiscovery). Pre-existing; a candidate for further bundle-startup optimization.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added support for injecting a custom filesystem abstraction into module/app discovery so bundled and manifest-driven boots can control how decorated files are discovered and loaded.
  • Tests
    • Added/updated Vitest coverage for injected filesystem behavior, manifest-based loading, precomputed-file paths, and cross-module dependency injection in runtime and bundle-mode scenarios.
  • Chores
    • Updated workspace dependencies to include the filesystem discovery abstraction.

Copilot AI review requested due to automatic review settings June 19, 2026 13:06

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d58a9b5f-6beb-44c0-9934-3312bc6b36a0

📥 Commits

Reviewing files that changed from the base of the PR and between 3e5cc84 and 39b261c.

📒 Files selected for processing (11)
  • tegg/core/loader/package.json
  • tegg/core/loader/src/LoaderFactory.ts
  • tegg/core/loader/src/impl/ModuleLoader.ts
  • tegg/core/loader/test/LoaderFactoryManifest.test.ts
  • tegg/core/loader/test/ModuleLoaderLoaderFS.test.ts
  • tegg/core/loader/test/ModuleLoaderManifest.test.ts
  • tegg/core/runtime/package.json
  • tegg/core/runtime/test/BundledDI.test.ts
  • tegg/plugin/tegg/package.json
  • tegg/plugin/tegg/src/lib/EggModuleLoader.ts
  • tegg/plugin/tegg/test/BundledAppBoot.test.ts
 ______________________________________________
< Cleaning up the mess Copilots left behind... >
 ----------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
📝 Walkthrough

Walkthrough

The PR replaces direct globby usage in ModuleLoader with an injectable LoaderFS abstraction. ModuleLoader and LoaderFactory gain optional loaderFS parameters, EggModuleLoader is wired to pass app.loader.loaderFS through both buildAppGraph and loadModule. New unit and integration tests validate the injected-glob, precomputed-files, manifest-backed bundle-mode boot, and cross-module DI paths.

Changes

LoaderFS Injection Through the Tegg Loader Stack

Layer / File(s) Summary
Dependency swap and LoaderFS contract wiring in core loader
tegg/core/loader/package.json, tegg/core/loader/src/LoaderFactory.ts, tegg/core/loader/src/impl/ModuleLoader.ts
Swaps the globby dependency for @eggjs/loader-fs, imports LoaderFS/RealLoaderFS, updates the LoaderCreator type to accept optional loaderFS?, extends the ModuleLoader constructor to accept ModuleLoaderOptions with injected LoaderFS (defaulting to RealLoaderFS), and switches file discovery in load() from globby(...) to this.loaderFS.glob(...).
LoaderFactory signature extension
tegg/core/loader/src/LoaderFactory.ts
Extends createLoader and loadApp to accept optional loaderFS? and threads it into both the ModuleLoaderClass constructor via options and the fallback createLoader path.
EggModuleLoader plugin wiring
tegg/plugin/tegg/package.json, tegg/plugin/tegg/src/lib/EggModuleLoader.ts
buildAppGraph and loadModule now read this.app.loader.loaderFS and pass it to LoaderFactory.loadApp and LoaderFactory.createLoader respectively. Adds @eggjs/core to plugin devDependencies.
ModuleLoader and LoaderFactory unit tests
tegg/core/loader/test/ModuleLoaderLoaderFS.test.ts, tegg/core/loader/test/LoaderFactoryManifest.test.ts, tegg/core/loader/test/ModuleLoaderManifest.test.ts, tegg/core/runtime/package.json
Adds comprehensive test suite with StubLoaderFS for injected-glob, precomputed-files bypass, default real-fs, and createModuleLoader forwarding. Extends manifest test with injected-LoaderFS case for non-manifest loadApp route. Updates existing manifest tests to use options-based ModuleLoader constructor. Adds @eggjs/loader-fs to runtime devDependencies.
BundledDI runtime integration test
tegg/core/runtime/test/BundledDI.test.ts
Loads multi-module fixtures entirely from a manifest using NoGlobLoaderFS (throws on glob) to confirm cross-module DI and GlobalGraph resolution never fall back to filesystem globbing; validates module name reading and end-to-end save/find via injected AppService.
BundledAppBoot plugin integration test
tegg/plugin/tegg/test/BundledAppBoot.test.ts
Two-phase boot test: Phase 1 collects the manifest in local mode; Phase 2 re-boots from ManifestStore.fromBundle using CountingFallbackLoaderFS to track loader routing. Asserts manifest shape, loader routing (core avoids real-fs globs, tegg modules trigger manifest-backed fallback globs within modules/), and end-to-end HTTP controller→service→cross-module repo DI→persistence chain.

Sequence Diagram(s)

sequenceDiagram
  participant Test
  participant EggApp
  participant EggModuleLoader
  participant LoaderFactory
  participant ManifestLoaderFS
  participant CountingFallbackLoaderFS

  Note over Test,CountingFallbackLoaderFS: Phase 1 — Local boot to collect manifest
  Test->>EggApp: boot(local mode)
  EggApp-->>Test: manifest data captured

  Note over Test,CountingFallbackLoaderFS: Phase 2 — Bundle mode boot from manifest
  Test->>EggApp: boot(ManifestStore.fromBundle + CountingFallbackLoaderFS)
  EggApp->>EggModuleLoader: buildAppGraph(loaderFS=ManifestLoaderFS)
  EggModuleLoader->>LoaderFactory: loadApp(..., loaderFS=ManifestLoaderFS)
  LoaderFactory->>ManifestLoaderFS: glob(pattern, cwd)
  ManifestLoaderFS-->>LoaderFactory: manifest-backed file list (no real-fs)
  EggModuleLoader->>LoaderFactory: createLoader(module, loaderFS=ManifestLoaderFS)
  LoaderFactory->>ManifestLoaderFS: glob(pattern, cwd=modules/)
  ManifestLoaderFS->>CountingFallbackLoaderFS: fallback glob inside modules/
  CountingFallbackLoaderFS-->>ManifestLoaderFS: real file list
  ManifestLoaderFS-->>LoaderFactory: file list
  Test->>EggApp: POST /app
  EggApp-->>Test: { success: true, traceId }
  Test->>EggApp: GET /app
  EggApp-->>Test: { app: { name, ... }, traceId }
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • eggjs/egg#5846: Modifies the same LoaderFactory.ts and ModuleLoader.ts files around manifest-derived precomputedFiles loading, which this PR extends with the LoaderFS abstraction.
  • eggjs/egg#5943: Introduces ManifestLoaderFS and wires EggLoader to use a manifest-backed LoaderFS, which this PR consumes via app.loader.loaderFS passed into EggModuleLoader.
  • eggjs/egg#5944: Extends the same loaderFS injection path through EggCore/EggLoader that this PR reads from this.app.loader.loaderFS in EggModuleLoader.

Suggested reviewers

  • jerryliang64
  • fengmk2
  • gxkl
  • akitaSummer

Poem

🐇 Hop, hop, no more globby calls!
The filesystem speaks through abstract walls,
loaderFS.glob now leads the way,
Manifests bundle the boot each day.
No falling back where none should tread,
The rabbit checks each path with care instead! 🌿

🚥 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 PR title directly and accurately summarizes the main change: routing module discovery through a shared loader-fs abstraction instead of globby.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tegg-loader-shared-loader-fs

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.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 19, 2026

Copy link
Copy Markdown

Deploying egg with  Cloudflare Pages  Cloudflare Pages

Latest commit: 39b261c
Status: ✅  Deploy successful!
Preview URL: https://f66faf87.egg-cci.pages.dev
Branch Preview URL: https://feat-tegg-loader-shared-load.egg-cci.pages.dev

View logs

@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.53%. Comparing base (b015dce) to head (39b261c).
⚠️ Report is 3 commits behind head on next.

Additional details and impacted files
@@            Coverage Diff             @@
##             next    #5970      +/-   ##
==========================================
+ Coverage   85.30%   85.53%   +0.22%     
==========================================
  Files         670      669       -1     
  Lines       19552    19828     +276     
  Branches     3863     3919      +56     
==========================================
+ Hits        16678    16959     +281     
+ Misses       2481     2478       -3     
+ Partials      393      391       -2     

☔ View full report in Codecov by Harness.
📢 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.

@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 integrates a file system abstraction (LoaderFS) into the loading mechanism of tegg to support bundle-mode application booting and cross-module dependency injection without relying on direct disk discovery. It replaces globby with loaderFS.glob in ModuleLoader and propagates loaderFS through LoaderFactory and EggModuleLoader. Additionally, comprehensive integration and unit tests are added to verify behavior in bundled environments. The review feedback suggests two improvements in the test files: using .ts extensions instead of .js for TypeScript imports in BundledDI.test.ts to maintain consistency, and avoiding broad substring checks with path separators in BundledAppBoot.test.ts by matching against exact path segments.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread tegg/core/runtime/test/BundledDI.test.ts Outdated
Comment thread tegg/plugin/tegg/test/BundledAppBoot.test.ts Outdated
@killagu killagu force-pushed the feat/tegg-loader-shared-loader-fs branch from 3b11a1a to ed1e41d Compare June 19, 2026 13:08
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 19, 2026

Copy link
Copy Markdown

Deploying egg-v3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 39b261c
Status: ✅  Deploy successful!
Preview URL: https://f107aedb.egg-v3.pages.dev
Branch Preview URL: https://feat-tegg-loader-shared-load.egg-v3.pages.dev

View logs

@socket-security

socket-security Bot commented Jun 19, 2026

Copy link
Copy Markdown

Dependency limit exceeded — report not shown.

This pull request scan exceeded the 10,000-dependency limit applied to this scan, so the results are incomplete and may be inaccurate. To avoid reporting false positives, Socket has not posted a report.

Upgrade your plan to raise the dependency limit and get complete reports, or view the partial scan in the dashboard.

Socket is always free for open source. If this is a non-commercial open source project, contact us to request a free Team account.

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

🧹 Nitpick comments (2)
tegg/plugin/tegg/test/BundledAppBoot.test.ts (1)

1-1: ⚡ Quick win

Rename this test file to lowercase-hyphen format.

BundledAppBoot.test.ts does not follow the repo filename convention; please rename it (for example, bundled-app-boot.test.ts).

As per coding guidelines, **/*: Keep file names lowercase with hyphens.

🤖 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 `@tegg/plugin/tegg/test/BundledAppBoot.test.ts` at line 1, Rename the test file
from BundledAppBoot.test.ts to bundled-app-boot.test.ts to follow the
repository's naming convention of using lowercase letters with hyphens for file
names. This applies to the entire file name and path.

Source: Coding guidelines

tegg/core/loader/test/ModuleLoaderLoaderFS.test.ts (1)

1-1: ⚡ Quick win

Rename this test file to lowercase-hyphen format.

ModuleLoaderLoaderFS.test.ts violates the repository naming convention; please rename it (for example, module-loader-loader-fs.test.ts) to keep consistency across tooling and package conventions.

As per coding guidelines, **/*: Keep file names lowercase with hyphens.

🤖 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 `@tegg/core/loader/test/ModuleLoaderLoaderFS.test.ts` at line 1, Rename the
test file ModuleLoaderLoaderFS.test.ts to use the lowercase-hyphen naming
convention. Convert the PascalCase filename to module-loader-loader-fs.test.ts
to align with the repository's file naming guidelines that require lowercase
file names with hyphens as separators. Update any import paths or references to
this file throughout the codebase to reflect the new filename.

Source: Coding guidelines

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

Nitpick comments:
In `@tegg/core/loader/test/ModuleLoaderLoaderFS.test.ts`:
- Line 1: Rename the test file ModuleLoaderLoaderFS.test.ts to use the
lowercase-hyphen naming convention. Convert the PascalCase filename to
module-loader-loader-fs.test.ts to align with the repository's file naming
guidelines that require lowercase file names with hyphens as separators. Update
any import paths or references to this file throughout the codebase to reflect
the new filename.

In `@tegg/plugin/tegg/test/BundledAppBoot.test.ts`:
- Line 1: Rename the test file from BundledAppBoot.test.ts to
bundled-app-boot.test.ts to follow the repository's naming convention of using
lowercase letters with hyphens for file names. This applies to the entire file
name and path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ae84d7ce-019d-4954-a742-3a17d5589fd4

📥 Commits

Reviewing files that changed from the base of the PR and between 0333c73 and 3b11a1a.

📒 Files selected for processing (10)
  • tegg/core/loader/package.json
  • tegg/core/loader/src/LoaderFactory.ts
  • tegg/core/loader/src/impl/ModuleLoader.ts
  • tegg/core/loader/test/LoaderFactoryManifest.test.ts
  • tegg/core/loader/test/ModuleLoaderLoaderFS.test.ts
  • tegg/core/runtime/package.json
  • tegg/core/runtime/test/BundledDI.test.ts
  • tegg/plugin/tegg/package.json
  • tegg/plugin/tegg/src/lib/EggModuleLoader.ts
  • tegg/plugin/tegg/test/BundledAppBoot.test.ts

Copilot AI review requested due to automatic review settings June 19, 2026 13:14
@killagu killagu force-pushed the feat/tegg-loader-shared-loader-fs branch from ed1e41d to 3e5cc84 Compare June 19, 2026 13:14

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Wire @eggjs/tegg-loader's module discovery through the shared
@eggjs/loader-fs abstraction instead of importing globby directly, so a
bundled app's manifest-backed VFS (ManifestLoaderFS) serves tegg
discovery too. Normal startup keeps using RealLoaderFS, so behavior is
unchanged.

- ModuleLoader: discovery uses an injectable LoaderFS.glob (default
  RealLoaderFS); module loading (LoaderUtil.loadFile + bundle hook) is
  left untouched.
- LoaderFactory: thread an optional loaderFS through createLoader/loadApp.
- EggModuleLoader: reuse app.loader.loaderFS in buildAppGraph and
  loadModule.
- drop the direct globby dependency from @eggjs/tegg-loader.

Tests:
- ModuleLoaderLoaderFS + LoaderFactoryManifest: discovery routes through
  the injected LoaderFS, precompute skips glob, default RealLoaderFS.
- BundledDI (runtime): cross-module DI resolves via manifest decoratedFiles
  with a glob-throwing LoaderFS, proving zero disk scan.
- BundledAppBoot (plugin): full app boots in manifest-consume mode and
  serves the controller -> service -> cross-module repo DI chain over HTTP;
  with an injected ManifestLoaderFS, core discovery does zero disk globs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@killagu killagu force-pushed the feat/tegg-loader-shared-loader-fs branch from 3e5cc84 to 39b261c Compare June 19, 2026 13:19
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@killagu killagu merged commit 34d8732 into next Jun 20, 2026
47 of 50 checks passed
@killagu killagu deleted the feat/tegg-loader-shared-loader-fs branch June 20, 2026 06:39
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