目录
Gxkl

feat(service-worker): standalone service worker runtime (#6022)

Summary

Adds a standalone service-worker host for running tegg HTTP controllers and MCP tools without starting an Egg application. The same controller metadata and registration core now serve both the Egg node-HTTP host and Fetch-compatible runtimes, with a runnable Node/Cloudflare example.

Architecture

  • Extracts @eggjs/controller-runtime as the host-neutral controller library. Egg transport remains in @eggjs/controller-plugin; Fetch transport lives in @eggjs/service-worker-controller; @eggjs/service-worker is the host facade over StandaloneApp.
  • HTTP and MCP registration use the same collect-then-finalize model. Egg finalizes both from @LoadUnitInstanceLifecycleProto providers when CONTROLLER_LOAD_UNIT is created; the Fetch host finalizes once while building routes on the first event.
  • Controller middleware supports dependency-injected Advice through the existing @Middleware(AdviceClass) form. The controller runtime invokes around() at the bound HTTP/MCP invocation boundary and preserves AbstractControllerAdvice.middleware() compatibility, while explicit @Pointcut remains owned by the independent AOP plugin.
  • Framework extension hooks are declarative and per app: controller graph weaving is registered by a scanned inner object, and mcp-proxy injects the current EggMcpRouter instead of writing to a static hook registry.

Standalone runtime

  • Supports Node serve(), embedded handleEvent(), and Cloudflare module-worker entries.
  • Supports Fetch Request/Response, parameter binding, binary and streaming bodies, multiple Set-Cookie headers, request-scope stream draining, host-provided error mapping, and background tasks.
  • Exposes MCP stateless Streamable HTTP with fresh SDK server/transport instances per request, controller and method middleware, authentication, DNS-rebinding options, and host-registered transport providers.
  • Keeps mutable runtime state isolated through each app’s TeggScope bag.

Bundle and module loading

  • Promotes TeggManifest to the shared tegg type surface and uses the shared ManifestLoaderFS overlay in both Egg and standalone hosts.
  • ModuleLoader.createModuleLoader() retains the selected file view in the current app scope, so later dynamic loaders such as DAL discovery read manifest-indexed files in a bundle without expanding multi-instance callback context.
  • Adds standalone support to egg-bin bundle, including TypeScript metadata scanning in a loader-enabled child process and Cloudflare-compatible worker output.
  • Keeps the example minimal: main.ts is the Node entry and worker.ts is the Cloudflare entry.

Validation

  • Focused controller graph, mcp-proxy registration, standalone HTTP, and standalone MCP suites: 46 tests.
  • Typechecked controller-runtime, controller-plugin, mcp-proxy-plugin, and service-worker-controller.
  • The current pushed revision is green across CI on Linux/macOS/Windows with Node 22/24, CodeQL, examples/cnpmcore E2E, typecheck, and package checks.

Documentation

Updates the service-worker, controller Advice, module-plugin lifecycle, LoaderFS/bundler, local CI, package README, and minimal-example documentation to match the final runtime contracts.


Co-authored-by: Claude Fable 5 noreply@anthropic.com

4天前1697次提交

English | 简体中文

NPM version NPM quality NPM download Node.js Version FOSSA Status

Continuous Integration Test coverage Known Vulnerabilities Open Collective backers and sponsors

Features

  • Built-in Process Management
  • Plugin System
  • Framework Customization
  • Lots of plugins

Quickstart

Follow the commands listed below.

$ corepack enable utoo
$ mkdir showcase && cd showcase
$ ut create egg@beta
$ ut install
$ ut run dev
$ open http://localhost:7001

Node.js >= 22.18.0 required.

Monorepo Structure

This project is structured as a utoo monorepo with the following packages:

  • packages/egg - Main Eggjs framework
  • examples/helloworld-commonjs - CommonJS example application
  • examples/helloworld-typescript - TypeScript example application
  • site - Documentation website

The monorepo uses utoo catalog mode for centralized dependency management, ensuring consistent versions across all packages.

Development Commands

# Install dependencies for all packages
ut install --from pnpm

# Build all packages
ut run build

# Test all packages
ut run test

# Run specific package commands
ut --filter=egg run test
ut --filter=@examples/helloworld-typescript run dev
ut --filter=site run dev

Local External Services

Some DAL, ORM, Redis, and ecosystem benchmark paths need local MySQL and Redis services. Start the repository-aligned Docker services before running those tests on a clean machine:

ut run dev:services:start

This starts MySQL 8 and Redis 7, matching the main CI service versions, and creates the databases used by local DAL/ORM/e2e fixtures: test, apple, banana, test_runtime_datasource, test_runtime_dao, test_dal_plugin, test_dal_standalone, cnpmcore, and cnpmcore_unittest.

Useful commands:

ut run dev:services:status
ut run dev:services:stop
ut run dev:services:reset

The default host ports are 127.0.0.1:3306 for MySQL and 127.0.0.1:6379 for Redis. If either port is already used, the start command stops before changing containers. Keep using the existing service if it is compatible with CI, or stop it and run the command again. You can change Docker host ports with EGG_DEV_SERVICES_MYSQL_PORT and EGG_DEV_SERVICES_REDIS_PORT; however, the full DAL/ORM/Redis local test path still expects the default host ports.

Image overrides are available for compatibility checks:

EGG_DEV_SERVICES_MYSQL_IMAGE=mysql:5.7 ut run dev:services:start
EGG_DEV_SERVICES_REDIS_IMAGE=redis:7 ut run dev:services:start

Run ut run dev:services:reset before switching MySQL image families, for example between MySQL 8 and MySQL 5.7, because MySQL data directories are not downgrade-compatible across major versions.

Current hard-coded service assumptions:

  • Redis plugin fixtures under plugins/redis/test/fixtures/apps/**/config.* use 127.0.0.1:6379; skipped Redis plugin tests become runnable when that port is available.
  • Session Redis fixtures under plugins/session/test/fixtures/redis-session/config/config.default.js use 127.0.0.1:6379.
  • DAL runtime tests in tegg/core/dal-runtime/test/DataSource.test.ts and tegg/core/dal-runtime/test/DAO.test.ts use local MySQL on port 3306.
  • DAL module fixtures in tegg/plugin/dal/test/fixtures/apps/dal-app/modules/dal/module.yml and tegg/standalone/standalone/test/fixtures/dal-*/module.yml use local MySQL on port 3306.
  • ORM fixtures in tegg/plugin/orm/test/fixtures/prepare.js and tegg/plugin/orm/test/fixtures/apps/orm-app/config/config.default.ts use local MySQL on port 3306.

Documentations

Contributors

contributors

How to Contribute

Please let us know how can we help. Do check out issues for bug reports or suggestions first.

To become a contributor, please follow our contributing guide, and review the repository guidelines for day-to-day development tips.

Sponsors and Backers

sponsors backers

License

MIT

FOSSA Status

邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号