Skip to content

feat(typings): add shared bundle module loader types#5897

Open
killagu wants to merge 12 commits intonextfrom
egg-15-typings
Open

feat(typings): add shared bundle module loader types#5897
killagu wants to merge 12 commits intonextfrom
egg-15-typings

Conversation

@killagu
Copy link
Copy Markdown
Contributor

@killagu killagu commented Apr 26, 2026

Summary

Adds a new @eggjs/typings workspace package to own shared bundle module loader typing, including BundleModuleLoader and the globalThis.__EGG_BUNDLE_MODULE_LOADER__ augmentation.

This lets @eggjs/utils consume the shared type package instead of owning a local global view or depending on @eggjs/core typings, while @eggjs/core keeps its global.d.ts as a thin import of the shared package.

Also updates AGENTS.md, CLAUDE.md, and the repo wiki for the new shared type-only package responsibility.

Test plan

  • pnpm install
  • pnpm --filter=@eggjs/typings run typecheck
  • pnpm --filter=@eggjs/utils run typecheck
  • pnpm --filter=@eggjs/core run typecheck
  • pnpm exec vitest run packages/utils/test/bundle-import.test.ts --bail 1 --retry 0
  • pnpm -r --if-present run typecheck
  • pnpm exec oxlint --type-aware --type-check --quiet (0 errors, existing warnings only)
  • pnpm exec oxfmt --check AGENTS.md CLAUDE.md tsconfig.json packages/core/package.json packages/core/src/global.d.ts packages/utils/package.json packages/utils/src/import.ts packages/typings/package.json packages/typings/tsconfig.json packages/typings/tsdown.config.ts packages/typings/src/index.ts wiki/index.md wiki/log.md wiki/packages/typings.md
  • pnpm --filter=@eggjs/typings exec tsdown
  • pnpm --filter=@eggjs/utils exec tsdown
  • pnpm --filter=@eggjs/core exec tsdown
  • pnpm exec vitest run packages/egg/test/cluster1/app_worker.test.ts --bail 1 --retry 0

Note: root pnpm run typecheck still exits before typechecking at ut run clean with ERROR Script 'clean' not found in package.json, same local utoo issue observed in PR #5867. The direct recursive workspace typecheck above passed.

Summary by CodeRabbit

  • New Features

    • Introduced a new shared typings package for standardized type definitions across Egg.js modules.
  • Bug Fixes

    • Improved HTTP request handling reliability in test suite with better timeout and error recovery.
  • Tests

    • Added comprehensive test coverage for bundle module loading functionality.
  • Documentation

    • Updated project documentation with new package information and changelog entry.
  • Chores

    • Updated package dependencies to include the new typings package.

killagu and others added 11 commits April 21, 2026 23:15
Add `setBundleModuleLoader()` which intercepts `importModule()` BEFORE
`importResolve()` so bundled apps can redirect module lookups to an
in-bundle map without the source files existing on disk. Reuses the
existing `__esModule` double-default and `importDefaultOnly` handling.

State is stored on `globalThis.__EGG_BUNDLE_MODULE_LOADER__` so that
bundled and external copies of @eggjs/utils share the same loader —
required because a bundled entry and the external egg framework may
resolve to different module instances.

Required by the upcoming @eggjs/egg-bundler to bootstrap a bundled
Egg app without filesystem discovery.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

📝 Walkthrough

Walkthrough

This PR introduces @eggjs/typings, a new shared type-only package, with exported BundleModuleLoader type and global declaration. It integrates this package into @eggjs/core and @eggjs/utils, adds bundle module loader support to importModule(), updates test harness socket handling, and documents the new package.

Changes

Cohort / File(s) Summary
Typings Package Foundation
packages/typings/package.json, packages/typings/src/index.ts, packages/typings/tsconfig.json, packages/typings/tsdown.config.ts
New @eggjs/typings package with BundleModuleLoader type and __EGG_BUNDLE_MODULE_LOADER__ global declaration, including build and TypeScript configuration.
Core Package Integration
packages/core/package.json, packages/core/src/global.d.ts, packages/core/tsdown.config.ts
Added @eggjs/typings dependency to core, imported typings in global definition file for ambient type availability, and configured tsdown to ignore the new dependency.
Utils Package Bundle Loader
packages/utils/package.json, packages/utils/src/import.ts, packages/utils/tsdown.config.ts
Added @eggjs/typings dependency and implemented setBundleModuleLoader() function with bundle loader support in importModule(), including path normalization and export unwrapping logic; tsdown configured to ignore the new dependency.
Bundle Loader Testing
packages/utils/test/bundle-import.test.ts
New comprehensive test suite covering bundle loader registration, module resolution fallback, export unwrapping with __esModule detection, and Windows path normalization scenarios.
Test Harness Improvements
packages/egg/test/cluster1/app_worker.test.ts
Refactored rawRequest TCP handler to use unified settle() mechanism instead of dual gating; normalized CRLF to LF in 400-bad-request assertion; added socket timeout destruction and partial response capture on timeout.
Project Configuration & Documentation
AGENTS.md, tsconfig.json, wiki/index.md, wiki/log.md, wiki/packages/typings.md
Updated project map and TypeScript references to include new typings package; added changelog entry and wiki documentation page describing the package purpose and API contracts.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • jerryliang64
  • fengmk2
  • gxkl

Poem

🐰 A typings home, so fresh and new,
Where shared contracts help us through,
Bundle loaders dance with care,
Path normalization fills the air,
Types flow free—hop hop hooray!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.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 'feat(typings): add shared bundle module loader types' is clear, specific, and accurately summarizes the main change—introducing a new @eggjs/typings package with shared bundle module loader types.
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 egg-15-typings

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
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Apr 26, 2026

Deploying egg with  Cloudflare Pages  Cloudflare Pages

Latest commit: 48f44cb
Status: ✅  Deploy successful!
Preview URL: https://c2427fff.egg-cci.pages.dev
Branch Preview URL: https://egg-15-typings.egg-cci.pages.dev

View logs

@killagu killagu marked this pull request as ready for review April 26, 2026 12:46
Copilot AI review requested due to automatic review settings April 26, 2026 12:46
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.50%. Comparing base (0b6c9fb) to head (48f44cb).

Additional details and impacted files
@@            Coverage Diff             @@
##             next    #5897      +/-   ##
==========================================
- Coverage   85.52%   85.50%   -0.02%     
==========================================
  Files         662      662              
  Lines       18863    18875      +12     
  Branches     3658     3662       +4     
==========================================
+ Hits        16132    16140       +8     
- Misses       2360     2362       +2     
- Partials      371      373       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new shared package, @eggjs/typings, to house type-only contracts and global augmentations, starting with the BundleModuleLoader. The @eggjs/utils package has been updated to utilize this loader within importModule, enabling interception of module resolution for bundled applications. Furthermore, the PR includes refactored socket handling in cluster tests for better reliability and cross-platform line-ending normalization. I have no feedback to provide as there were no review comments to evaluate.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Apr 26, 2026

Deploying egg-v3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 48f44cb
Status: ✅  Deploy successful!
Preview URL: https://2d6d5052.egg-v3.pages.dev
Branch Preview URL: https://egg-15-typings.egg-v3.pages.dev

View logs

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new workspace package @eggjs/typings to centralize shared, cross-package type-only contracts for bundled module loading, and updates @eggjs/utils / @eggjs/core to consume those shared typings plus related repo documentation.

Changes:

  • Introduce packages/typings exporting BundleModuleLoader and the globalThis.__EGG_BUNDLE_MODULE_LOADER__ global augmentation.
  • Update @eggjs/utils to depend on @eggjs/typings, re-export the type, and keep importModule() bundle-loader behavior + add/maintain tests.
  • Update @eggjs/core to include the shared ambient declarations via a global.d.ts shim, and refresh wiki/agent docs.

Reviewed changes

Copilot reviewed 15 out of 17 changed files in this pull request and generated no comments.

Show a summary per file
File Description
wiki/packages/typings.md New wiki page documenting the purpose/scope of @eggjs/typings.
wiki/log.md Changelog entry for adding the shared typings package.
wiki/index.md Adds Typings to the wiki package index.
tsconfig.json Adds project reference for the new packages/typings.
packages/utils/test/bundle-import.test.ts Adds Vitest coverage for bundle loader interception / normalization behavior.
packages/utils/test/snapshots/index.test.ts.snap Updates exported-symbol snapshot to include setBundleModuleLoader.
packages/utils/src/import.ts Switches to shared BundleModuleLoader type + re-export; bundle loader normalization/hook logic.
packages/utils/package.json Adds @eggjs/typings workspace dependency.
packages/typings/tsdown.config.ts Build entry for the new typings package.
packages/typings/tsconfig.json Extends root TS config for the new package.
packages/typings/src/index.ts Defines BundleModuleLoader and global augmentation.
packages/typings/package.json Defines the new @eggjs/typings package metadata/exports.
packages/egg/test/cluster1/app_worker.test.ts Makes raw HTTP response assertion resilient to CRLF differences; improves raw socket request settling.
packages/core/src/global.d.ts Adds a thin ambient import shim for @eggjs/typings.
packages/core/package.json Adds @eggjs/typings workspace dependency.
CLAUDE.md Notes the new home for shared type-only contracts.
AGENTS.md Notes packages/typings responsibility in repo structure.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
packages/egg/test/cluster1/app_worker.test.ts (1)

143-176: LGTM — settle() gate cleanly prevents double settlement.

The unified settle(callback) helper correctly guards end, error, close, and setTimeout against multiple resolution paths, clears the timer via socket.setTimeout(0), and includes the partial response in the timeout error to aid debugging. Destroying the socket on timeout is the right call to free the FD promptly.

One small optional thought: on the 'error' path you may also want to socket.destroy() defensively — in practice Node's net will emit close after error, so this is purely belt-and-suspenders and not required.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/egg/test/cluster1/app_worker.test.ts` around lines 143 - 176, Add
defensive socket.destroy() inside the rawRequest error handler: in the
socket.on('error', (err) => ...) callback (inside the rawRequest function and
alongside the existing call to settle), call socket.destroy() before invoking
settle to ensure the file descriptor is freed promptly even if Node would later
emit 'close'; keep the existing settle(...) logic and error rejection unchanged.
CLAUDE.md (1)

9-9: Consider dropping this bullet from CLAUDE.md.

This is general repo guidance (already captured in AGENTS.md line 12), not a Claude-specific import or override. Keeping it here duplicates content and grows CLAUDE.md away from being a thin pointer. As per coding guidelines, "Use CLAUDE.md only for Claude Code specific imports or overrides" and "Keep CLAUDE.md file thin and focused".

♻️ Suggested removal
 - Keep shared repository guidance in `AGENTS.md`.
 - Keep this file thin and use it only for Claude Code specific imports or overrides.
-- Shared Egg type-only contracts live in `packages/typings` (`@eggjs/typings`).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` at line 9, Remove the duplicate guidance bullet in CLAUDE.md that
states "Shared Egg type-only contracts live in `packages/typings`
(`@eggjs/typings`)"—this content is general repo guidance already present in
AGENTS.md and should not live in the Claude-specific overrides; edit CLAUDE.md
to delete that bullet so the file remains thin and focused only on
Claude-specific imports/overrides.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/package.json`:
- Line 46: The dependency '@eggjs/typings' must remain in
packages/core/package.json (it’s required at install time for the ambient import
in packages/core/src/global.d.ts: import '@eggjs/typings'; which is erased at
build time), but tsdown flags it as unused; update tsdown configs to whitelist
it by adding unused.ignore = ['@eggjs/typings'] in
packages/core/tsdown.config.ts and packages/utils/tsdown.config.ts (mirror the
pattern used in packages/koa/tsdown.config.ts and
packages/supertest/tsdown.config.ts) so the unused-dependency check no longer
fails while keeping the dependency in dependencies.

In `@packages/utils/package.json`:
- Around line 38-40: The build fails because `@eggjs/typings` is only used as a
TypeScript type (e.g., BundleModuleLoader referenced in src/import.ts) and
tsdown flags it as an unused runtime dependency; update tsdown config the same
way as for packages/core by adding `@eggjs/typings` to the unused-deps whitelist
in tsdown.config.ts for the utils package (or the shared config) so tsdown
ignores type-only imports from `@eggjs/typings` when checking packages/utils.

---

Nitpick comments:
In `@CLAUDE.md`:
- Line 9: Remove the duplicate guidance bullet in CLAUDE.md that states "Shared
Egg type-only contracts live in `packages/typings` (`@eggjs/typings`)"—this
content is general repo guidance already present in AGENTS.md and should not
live in the Claude-specific overrides; edit CLAUDE.md to delete that bullet so
the file remains thin and focused only on Claude-specific imports/overrides.

In `@packages/egg/test/cluster1/app_worker.test.ts`:
- Around line 143-176: Add defensive socket.destroy() inside the rawRequest
error handler: in the socket.on('error', (err) => ...) callback (inside the
rawRequest function and alongside the existing call to settle), call
socket.destroy() before invoking settle to ensure the file descriptor is freed
promptly even if Node would later emit 'close'; keep the existing settle(...)
logic and error rejection unchanged.
🪄 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: 1ff7c241-00fb-4829-b86d-736346ca1f84

📥 Commits

Reviewing files that changed from the base of the PR and between 0b6c9fb and 0bd2d9a.

⛔ Files ignored due to path filters (1)
  • packages/utils/test/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (16)
  • AGENTS.md
  • CLAUDE.md
  • packages/core/package.json
  • packages/core/src/global.d.ts
  • packages/egg/test/cluster1/app_worker.test.ts
  • packages/typings/package.json
  • packages/typings/src/index.ts
  • packages/typings/tsconfig.json
  • packages/typings/tsdown.config.ts
  • packages/utils/package.json
  • packages/utils/src/import.ts
  • packages/utils/test/bundle-import.test.ts
  • tsconfig.json
  • wiki/index.md
  • wiki/log.md
  • wiki/packages/typings.md

Comment thread packages/core/package.json
Comment on lines +38 to +40
"dependencies": {
"@eggjs/typings": "workspace:*"
},
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.

⚠️ Potential issue | 🔴 Critical

Build failure here likely shares the root cause flagged on packages/core/package.json.

BundleModuleLoader is consumed from @eggjs/typings only as a type in src/import.ts (and erased at build time under verbatimModuleSyntax), so tsdown's unused-dep check will flag it the same way it does for @eggjs/core. Apply the same tsdown.config.ts whitelist fix here. See the consolidated comment on packages/core/package.json for details.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/utils/package.json` around lines 38 - 40, The build fails because
`@eggjs/typings` is only used as a TypeScript type (e.g., BundleModuleLoader
referenced in src/import.ts) and tsdown flags it as an unused runtime
dependency; update tsdown config the same way as for packages/core by adding
`@eggjs/typings` to the unused-deps whitelist in tsdown.config.ts for the utils
package (or the shared config) so tsdown ignores type-only imports from
`@eggjs/typings` when checking packages/utils.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/egg/test/cluster1/app_worker.test.ts (1)

44-44: Optional: consider asserting on the raw body too.

Normalizing CRLF→LF on both sides makes the assertion resilient to line-ending differences in the wire response, which is the intent. If the goal is also to lock down the on-the-wire format (the server response in packages/egg/src/lib/application.ts is built with explicit \r\n separators in headers but the HTML template uses \n), an additional assert.equal(body, DEFAULT_BAD_REQUEST_HTML) (without normalization) would catch accidental line-ending regressions in the body. Non-blocking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/egg/test/cluster1/app_worker.test.ts` at line 44, Add an extra
assertion to verify the raw on-the-wire response body in addition to the
normalized check: after the existing assert.equal(body.replaceAll('\r\n', '\n'),
DEFAULT_BAD_REQUEST_HTML.replaceAll('\r\n', '\n')), add a second assertion
asserting body === DEFAULT_BAD_REQUEST_HTML (i.e. assert.equal(body,
DEFAULT_BAD_REQUEST_HTML)) so accidental CRLF/LF regressions in the produced
response are caught; locate this in app_worker.test.ts around the existing
assert.equal call that references body and DEFAULT_BAD_REQUEST_HTML.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/egg/test/cluster1/app_worker.test.ts`:
- Line 44: Add an extra assertion to verify the raw on-the-wire response body in
addition to the normalized check: after the existing
assert.equal(body.replaceAll('\r\n', '\n'),
DEFAULT_BAD_REQUEST_HTML.replaceAll('\r\n', '\n')), add a second assertion
asserting body === DEFAULT_BAD_REQUEST_HTML (i.e. assert.equal(body,
DEFAULT_BAD_REQUEST_HTML)) so accidental CRLF/LF regressions in the produced
response are caught; locate this in app_worker.test.ts around the existing
assert.equal call that references body and DEFAULT_BAD_REQUEST_HTML.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 243654d3-7163-421f-bf28-cdd36a4276c1

📥 Commits

Reviewing files that changed from the base of the PR and between 0bd2d9a and 48f44cb.

📒 Files selected for processing (3)
  • packages/core/tsdown.config.ts
  • packages/egg/test/cluster1/app_worker.test.ts
  • packages/utils/tsdown.config.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/core/tsdown.config.ts
  • packages/utils/tsdown.config.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