This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
tegg is a TypeScript dependency injection framework and plugin system for Egg.js. It provides decorator-based dependency injection, lifecycle management, and modular architecture for building scalable Node.js applications.
# Install dependencies
npm install
# Run all tests across workspaces
npm test
# Run tests for a single package
npm test --workspace=core/metadata
npm test --workspace=plugin/tegg
# Run a single test file (from package directory)
cd core/metadata && npm test -- --grep "test name"
# Lint
npm run lint
npm run lint:fix
# Build TypeScript
npm run tsc
# Full CI (prepare + lint + test)
npm run ci
# Publish (requires permissions)
npm run bump # version bump with lerna
npm run pub # publish to npmThis is a Lerna monorepo with three workspace categories:
- core/: Core packages containing decorators, runtime, and utilities
- plugin/: Egg.js plugins that integrate tegg features
- standalone/: Standalone runtime without Egg.js dependency
| Package | Description |
|---|---|
@eggjs/tegg |
Main entry point, re-exports all decorator packages |
@eggjs/tegg-plugin |
Main Egg.js plugin for tegg integration |
@eggjs/core-decorator |
Core decorators: @ContextProto, @SingletonProto, @Inject |
@eggjs/tegg-types |
TypeScript type definitions |
@eggjs/tegg-metadata |
Metadata storage and graph building |
@eggjs/tegg-runtime |
Runtime container and object instantiation |
@eggjs/tegg-lifecycle |
Object lifecycle hooks |
Prototype Types (instantiation modes):
@ContextProto: One instance per request context@SingletonProto: One instance for entire application lifecycle@MultiInstanceProto: Multiple instances with different qualifiers
Access Levels:
AccessLevel.PRIVATE: Only accessible within the same moduleAccessLevel.PUBLIC: Accessible from other modules
Object Init Types:
ObjectInitType.CONTEXT: New instance per requestObjectInitType.SINGLETON: Single instance for app lifetimeObjectInitType.ALWAYS_NEW: New instance on every injection
- Decorators (
@ContextProto,@SingletonProto, etc.) register metadata on classes @eggjs/tegg-loaderscans and loads modules@eggjs/tegg-metadatabuilds a dependency graph (GlobalGraph, ModuleGraph)@eggjs/tegg-runtimeinstantiates objects based on the graph@Injectdecorator triggers dependency resolution at runtime
Objects can implement EggObjectLifecycle interface or use decorators:
@LifecyclePostConstruct/postConstruct()@LifecyclePreInject/preInject()@LifecyclePostInject/postInject()@LifecycleInit/init()@LifecyclePreDestroy/preDestroy()@LifecycleDestroy/destroy()
Always import from @eggjs/tegg - it re-exports everything needed:
// Core decorators and enums
import {
ContextProto,
SingletonProto,
Inject,
AccessLevel,
EggQualifier,
EggType,
} from '@eggjs/tegg';
// Subpath imports for specific features
import { Advice, Crosscut, Pointcut } from '@eggjs/tegg/aop';
import { DataSource } from '@eggjs/tegg/orm';
import { Schedule } from '@eggjs/tegg/schedule';
import { Transactional } from '@eggjs/tegg/transaction';Available subpaths: aop, orm, dal, schedule, transaction, ajv, helper, standalone
Use @eggjs/tegg/helper for internal APIs:
import {
ModuleConfigUtil,
LoaderFactory,
EggObjectLifeCycleContext,
EggObject,
} from '@eggjs/tegg/helper';For type-only imports, use @eggjs/tegg-types:
import type { EggPrototype, EggObject, EggObjectLifecycle } from '@eggjs/tegg-types';
import { AccessLevel, ObjectInitType } from '@eggjs/tegg-types';For decorator utilities, import from @eggjs/core-decorator:
import { PrototypeUtil, QualifierUtil, MetadataUtil } from '@eggjs/core-decorator';| If you're in... | Import decorators from | Import types from |
|---|---|---|
| Application code | @eggjs/tegg |
@eggjs/tegg |
plugin/* packages |
@eggjs/tegg |
@eggjs/tegg-types |
core/* packages |
@eggjs/core-decorator |
@eggjs/tegg-types |
Use @SingletonProto by default unless you need request-scoped state. Singleton objects are created once at startup, avoiding repeated instantiation overhead per request.
// Good: Stateless service as singleton
@SingletonProto()
export class UserRepository {
async findById(id: string) { /* ... */ }
}
// Use ContextProto only when you need request-specific state
@ContextProto()
export class RequestTracer {
@Inject()
ctx: EggContext; // needs access to current request
}Default is AccessLevel.PRIVATE. Only use AccessLevel.PUBLIC when the prototype genuinely needs to be accessed from other modules.
// Good: explicitly public for cross-module access
@SingletonProto({ accessLevel: AccessLevel.PUBLIC })
export class SharedConfigService { }
// Good: private by default, only used within module
@SingletonProto()
export class InternalHelper { }Constructors cannot be async. Use init() lifecycle hook for async setup like database connections or external service initialization.
@SingletonProto()
export class DatabaseClient implements EggObjectLifecycle {
private connection: Connection;
async init() {
// Async initialization here
this.connection = await createConnection();
}
async destroy() {
// Cleanup resources
await this.connection.close();
}
}Never use raw setTimeout, setInterval, or process.nextTick in @ContextProto objects. The context may be destroyed before the task completes. Use BackgroundTaskHelper instead.
@ContextProto()
export class OrderService {
@Inject()
backgroundTaskHelper: BackgroundTaskHelper;
async createOrder(data: OrderData) {
const order = await this.saveOrder(data);
// Safe async task that survives request lifecycle
this.backgroundTaskHelper.run(async () => {
await this.sendNotification(order);
});
return order;
}
}Avoid injecting ctx or app directly. Inject specific services or objects instead for better testability and clearer dependencies.
// Avoid
@ContextProto()
export class BadService {
@Inject()
ctx: Context; // too broad
async doSomething() {
return this.ctx.service.userService.find();
}
}
// Better
@ContextProto()
export class GoodService {
@Inject()
userService: UserService; // explicit dependency
async doSomething() {
return this.userService.find();
}
}- One module per bounded context or feature domain
- Keep modules focused and cohesive
- Use
AccessLevel.PUBLICsparingly to define clear module boundaries - Prefer injecting prototypes over direct module-to-module references
@ContextProtoobjects can inject any prototype type@SingletonProtoobjects can inject@ContextProtoobjects via Proxy mechanism:- tegg uses
AsyncLocalStorageto track the current request context - When SingletonProto injects ContextProto, a Proxy object is injected
- The Proxy resolves to the correct ContextProto instance from current context on each access
- Caveat: Accessing ContextProto from SingletonProto outside a request context will throw an error
- tegg uses
- Circular dependencies between prototypes are not allowed
- Circular dependencies between modules are not allowed
- TypeScript strict mode with
experimentalDecoratorsandemitDecoratorMetadataenabled - ESLint with
eslint-config-egg/typescript - Tests use Mocha and are located in
test/directories within each package - Test fixtures are in
test/fixtures/directories
This section is for contributors developing the tegg framework itself.
Before committing code, always run:
# 1. Lint check (required)
npm run lint
# 2. Run full CI: prepare-test + lint + test (required)
npm run ci
# 3. Verify TypeScript compilation for publishing (required for core packages)
npm run tsc:pubCI Pipeline (npm run ci) executes:
ut prepare-test- Prepare test fixturesut lint- ESLint checkut test- Run all tests across workspaces
Note: Some tests require MySQL. CI runs against MySQL 5.7. To run locally:
- macOS:
brew install mysql && brew services start mysql - Linux: Use Docker or native MySQL installation
When developing a new feature for tegg, create packages in this order:
1. core/types → Type definitions (interfaces, enums)
2. core/*-decorator → Decorators and metadata utilities
3. core/*-runtime → Runtime logic (if needed)
4. core/tegg → Re-export from main package (add to index.ts or create subpath)
5. plugin/* → Egg.js plugin integration
Dependency direction: types ← decorator ← runtime ← plugin
- Create package in
core/directory:
core/my-decorator/
├── package.json
├── tsconfig.json
├── tsconfig.pub.json
├── src/
│ ├── decorator/
│ │ └── MyDecorator.ts
│ └── util/
│ └── MyDecoratorInfoUtil.ts
├── index.ts # exports
└── test/
└── MyDecorator.test.ts
- Key dependencies in
package.json:
{
"dependencies": {
"@eggjs/core-decorator": "^3.x",
"@eggjs/tegg-types": "^3.x"
}
}- Decorator implementation pattern:
// src/decorator/MyDecorator.ts
import { PrototypeUtil } from '@eggjs/core-decorator';
import type { EggProtoImplClass } from '@eggjs/tegg-types';
export const MY_DECORATOR_META = Symbol('MY_DECORATOR_META');
export interface MyDecoratorParams {
name?: string;
}
export function MyDecorator(params?: MyDecoratorParams) {
return function(target: EggProtoImplClass) {
PrototypeUtil.setMetaData(target, MY_DECORATOR_META, params || {});
};
}- Add export to
core/tegg/:- For core features: add to
index.ts - For optional features: create new subpath file (e.g.,
myfeature.ts)
- For core features: add to
- Create package in
plugin/directory:
plugin/my-plugin/
├── package.json
├── tsconfig.json
├── tsconfig.pub.json
├── app.ts # Plugin entry point
├── config/
│ └── config.default.ts
├── lib/
│ ├── MyService.ts # Injectable services
│ └── MyHook.ts # Lifecycle hooks
├── typings/
│ └── index.d.ts # Type extensions for egg
└── test/
└── my-plugin.test.ts
- Key fields in
package.json:
{
"name": "@eggjs/tegg-my-plugin",
"eggPlugin": {
"name": "myPlugin",
"dependencies": ["tegg"]
},
"eggModule": {
"name": "teggMyPlugin"
},
"dependencies": {
"@eggjs/tegg": "^3.x",
"@eggjs/my-decorator": "^3.x" // if you have decorator package
}
}eggPlugin: Configuration for Egg.js plugin modeeggModule: Configuration for standalone mode (@eggjs/standalone), where the plugin runs as a module without Egg.js
- Plugin entry point (
app.ts):
import { Application } from 'egg';
export default class MyPluginAppHook {
private readonly app: Application;
constructor(app: Application) {
this.app = app;
}
configWillLoad() {
// Register hooks before module loading
}
async didLoad() {
// After modules are loaded
await this.app.moduleHandler.ready();
}
beforeClose() {
// Cleanup resources
}
}Pattern for wrapping external SDKs (e.g., database clients, API clients). See mcp-client plugin for a complete example.
Step 1: Create core wrapper package (core/my-client)
Wrap the third-party SDK with tegg-compatible interface (no tegg runtime dependency):
// core/my-client/src/MyClient.ts
import { ThirdPartySDK } from 'third-party-sdk';
import type { Logger } from '@eggjs/tegg';
export interface MyClientOptions {
logger: Logger;
// ... other options
}
// Extend the third-party SDK class directly
export class MyClient extends ThirdPartySDK {
protected logger: Logger;
constructor(options: MyClientOptions) {
super(options);
this.logger = options.logger;
}
async init() {
// Initialize connection
await super.connect();
}
}Step 2: Create Egg-specific subclass in plugin (plugin/my-plugin)
Extend the core wrapper to add tegg-specific features (e.g., context tracking):
// plugin/my-plugin/lib/EggMyClient.ts
import { Logger } from '@eggjs/tegg';
import { ContextHandler } from '@eggjs/tegg-runtime';
import { MyClient, MyClientOptions } from '@eggjs/my-client';
export interface EggMyClientOptions extends MyClientOptions {
// additional egg-specific options
}
// Extend the core wrapper class
export class EggMyClient extends MyClient {
constructor(options: EggMyClientOptions) {
super(options);
}
// Override methods to add tegg-specific behavior
async doSomething() {
const context = ContextHandler.getContext();
if (context) {
// Set context-specific data for tracing, logging, etc.
context.set('myClient.method', 'doSomething');
}
return super.doSomething();
}
}Step 3: Create factory for instantiation
Factory injects tegg dependencies and creates the client:
// plugin/my-plugin/lib/MyClientFactory.ts
import {
AccessLevel,
Inject,
Logger,
SingletonProto,
} from '@eggjs/tegg';
import { EggMyClient, EggMyClientOptions } from './EggMyClient';
@SingletonProto({
accessLevel: AccessLevel.PUBLIC,
name: 'myClientFactory',
})
export class MyClientFactory {
@Inject()
private readonly logger: Logger;
async build(options: Omit<EggMyClientOptions, 'logger'>): Promise<EggMyClient> {
const client = new EggMyClient({
...options,
logger: this.logger,
});
await client.init();
return client;
}
}Summary of the pattern:
third-party-sdk → core/my-client (MyClient extends SDK)
→ plugin/my-plugin (EggMyClient extends MyClient)
→ plugin/my-plugin (MyClientFactory creates EggMyClient)
This layered approach:
- Keeps core wrapper independent of tegg runtime
- Allows Egg-specific extensions (context tracking, tracing)
- Factory handles dependency injection (logger, config)
Step 4: Register lifecycle hooks in plugin (if needed):
// plugin/my-plugin/app.ts
import { Application } from 'egg';
import { MyPrototypeHook } from './lib/MyPrototypeHook';
export default class MyPluginAppHook {
private readonly app: Application;
private myHook: MyPrototypeHook;
constructor(app: Application) {
this.app = app;
}
configDidLoad() {
// Register prototype lifecycle hooks
this.myHook = new MyPrototypeHook();
this.app.eggPrototypeLifecycleUtil.registerLifecycle(this.myHook);
}
beforeClose() {
this.app.eggPrototypeLifecycleUtil.deleteLifecycle(this.myHook);
}
}Plugins can register hooks at different levels:
| Hook Registry | Purpose |
|---|---|
app.loadUnitLifecycleUtil |
Module loading/unloading |
app.eggPrototypeLifecycleUtil |
Prototype creation/destruction |
app.eggObjectLifecycleUtil |
Object instance creation/destruction |
app.eggContextLifecycleUtil |
Request context creation/destruction |
Use egg-mock for plugin testing:
import { app } from 'egg-mock/bootstrap';
describe('my-plugin', () => {
it('should work', async () => {
await app.mockModuleContextScope(async ctx => {
const myClient = await ctx.getEggObject(MyClient);
const result = await myClient.doSomething();
assert(result);
});
});
});Provides the fundamental decorators for dependency injection.
src/
├── decorator/
│ ├── ContextProto.ts # @ContextProto decorator
│ ├── SingletonProto.ts # @SingletonProto decorator
│ ├── MultiInstanceProto.ts # @MultiInstanceProto decorator
│ ├── Inject.ts # @Inject decorator
│ ├── Prototype.ts # Base prototype decorator logic
│ ├── InitTypeQualifier.ts # @InitTypeQualifier for disambiguation
│ ├── ModuleQualifier.ts # @ModuleQualifier for cross-module injection
│ └── EggQualifier.ts # @EggQualifier for egg ctx/app disambiguation
└── util/
├── PrototypeUtil.ts # Read/write prototype metadata
├── QualifierUtil.ts # Qualifier metadata operations
└── MetadataUtil.ts # General metadata utilities
Builds and manages the dependency graph for all modules and prototypes.
src/
├── model/
│ ├── graph/
│ │ ├── GlobalGraph.ts # Main dependency graph (modules + protos)
│ │ ├── GlobalModuleNode.ts # Module node in graph
│ │ ├── ProtoNode.ts # Prototype node in graph
│ │ └── ProtoSelector.ts # Logic for finding matching prototypes
│ ├── ModuleDescriptor.ts # Module metadata container
│ ├── LoadUnit.ts # LoadUnit interface (module instance)
│ └── EggPrototype.ts # Prototype metadata model
├── impl/
│ ├── EggPrototypeBuilder.ts # Builds EggPrototype from class
│ ├── EggPrototypeImpl.ts # EggPrototype implementation
│ └── ModuleLoadUnit.ts # LoadUnit implementation for modules
└── factory/
├── EggPrototypeFactory.ts # Creates prototypes from classes
└── LoadUnitFactory.ts # Manages LoadUnit instances
Key class: GlobalGraph - Manages two graphs:
moduleGraph: Vertices are modules, edges are module dependenciesprotoGraph: Vertices are prototypes, edges are injection dependencies
The build() method resolves all injection edges, sort() produces instantiation order.
Handles actual object instantiation and lifecycle management.
src/
├── model/
│ ├── EggObject.ts # EggObject interface and lifecycle utils
│ ├── EggContext.ts # Request context interface
│ ├── AbstractEggContext.ts # Base context implementation
│ └── LoadUnitInstance.ts # Runtime instance of a LoadUnit
├── impl/
│ ├── EggObjectImpl.ts # Creates and initializes object instances
│ ├── EggObjectUtil.ts # Injection and lifecycle utilities
│ ├── ModuleLoadUnitInstance.ts # LoadUnitInstance for modules
│ └── ContextObjectGraph.ts # Per-request object graph
└── factory/
├── EggObjectFactory.ts # Creates EggObject instances
├── EggContainerFactory.ts # Manages object containers
└── LoadUnitInstanceFactory.ts # Creates LoadUnitInstance
TypeScript type definitions organized by domain:
├── core-decorator/ # Types for core decorators
│ ├── enum/ # AccessLevel, ObjectInitType, EggType, etc.
│ └── model/ # EggPrototypeInfo, InjectObjectInfo, etc.
├── metadata/ # Types for metadata layer
├── runtime/ # Types for runtime layer
├── lifecycle/ # Lifecycle hook interfaces
└── controller-decorator/ # HTTP controller types
Main Egg.js plugin that integrates tegg into an Egg application.
├── app.ts # Plugin entry: lifecycle hooks (didLoad, beforeClose)
├── app/
│ ├── extend/
│ │ ├── application.ts # Extends app with getEggObject, moduleHandler
│ │ └── context.ts # Extends ctx with getEggObject, beginModuleScope
│ └── middleware/
│ └── tegg_ctx_lifecycle_middleware.ts # Creates EggContext per request
└── lib/
├── ModuleHandler.ts # Orchestrates module loading and initialization
├── EggModuleLoader.ts # Loads modules using tegg-loader
├── EggContextHandler.ts # Manages EggContext lifecycle
├── EggContextImpl.ts # EggContext implementation for Egg
├── EggCompatibleObject.ts # Wraps egg app/ctx objects as prototypes
└── EggCompatibleProtoImpl.ts # Makes egg objects injectable
Initialization flow in app.ts:
configWillLoad: Register middlewareconfigDidLoad: Setup EggContextHandler, ModuleHandlerdidLoad: Register hooks, callmoduleHandler.init()to load all modulesbeforeClose: Cleanup and destroy
Provides a standalone runtime for tegg that works without Egg.js. This enables using tegg's dependency injection in CLI tools, background workers, or any Node.js application.
├── src/
│ ├── Runner.ts # Main orchestrator: loads modules, manages lifecycle
│ ├── main.ts # Simple entry point: main() function
│ ├── EggModuleLoader.ts # Loads modules using tegg-loader
│ ├── StandaloneContext.ts # EggContext implementation for standalone
│ ├── StandaloneContextHandler.ts # AsyncLocalStorage-based context management
│ ├── StandaloneLoadUnit.ts # LoadUnit for inner objects (logger, config, etc.)
│ └── StandaloneInnerObjectProto.ts # EggPrototype for inner objects
└── index.ts # Exports all public APIs
The standalone package replicates Egg.js plugin functionality using pure Node.js primitives:
Key Differences from Egg.js Mode:
| Aspect | Egg.js Mode | Standalone Mode |
|---|---|---|
| Context storage | Egg.js request context | AsyncLocalStorage via StandaloneContextHandler |
| Context object | EggContextImpl (wraps Egg ctx) |
StandaloneContext (extends AbstractEggContext) |
| Inner objects | From app and ctx |
Manually provided via innerObjectHandlers |
| HTTP handling | Egg.js middleware | Not provided (bring your own) |
| Config loading | Egg.js config system | ModuleConfigUtil reads module.yml files |
Initialization Flow:
1. new Runner(cwd, options)
├── Read module references from cwd
├── Load module configs (module.default.yml, module.{env}.yml)
├── Register lifecycle hooks (AOP, DAL, etc.)
└── Create GlobalGraph instance
2. runner.init()
├── Register StandaloneContextHandler (AsyncLocalStorage)
├── Register StandaloneLoadUnit factory (for inner objects)
├── Load all modules via EggModuleLoader
│ ├── LoaderFactory.loadApp() → ModuleDescriptors
│ ├── GlobalGraph.create() → build dependency graph
│ ├── GlobalGraph.build() → resolve all injections
│ └── GlobalGraph.sort() → topological sort for init order
├── Create LoadUnitInstance for each LoadUnit
└── Find @Runner decorated class
3. runner.run()
├── Create StandaloneContext
├── ContextHandler.run(ctx, async () => {...})
│ └── Uses AsyncLocalStorage.run() internally
├── Get @Runner class instance via EggContainerFactory
├── Call runner.main()
└── Cleanup context on completion
4. runner.destroy()
├── Destroy all LoadUnitInstances
├── Destroy all LoadUnits
└── Unregister lifecycle hooks
Context Management Without Egg.js:
In Egg.js, each HTTP request has a context object (ctx). Standalone mode simulates this using AsyncLocalStorage:
// StandaloneContextHandler.ts
export class StandaloneContextHandler {
static storage = new AsyncLocalStorage<EggContext>();
static register() {
// Tell ContextHandler how to get/run context
ContextHandler.getContextCallback = () => {
return StandaloneContextHandler.storage.getStore();
};
ContextHandler.runInContextCallback = (context, fn) => {
return StandaloneContextHandler.storage.run(context, fn);
};
}
}This allows @ContextProto objects to work correctly - they are stored per-context in the AsyncLocalStorage.
Inner Objects (Replacing Egg.js app/ctx):
In Egg.js, objects like logger, config come from app or ctx. Standalone mode uses innerObjectHandlers:
// Runner creates these automatically:
this.innerObjects = {
moduleConfigs: [{ obj: new ModuleConfigs(...) }],
moduleConfig: [...], // per-module configs with qualifiers
runtimeConfig: [{ obj: { baseDir, name, env } }],
mysqlDataSourceManager: [{ obj: MysqlDataSourceManager.instance }],
};
// Users can add custom inner objects:
const runner = new Runner(cwd, {
innerObjectHandlers: {
logger: [{ obj: myLogger }],
customService: [{
obj: myService,
qualifiers: [{ attribute: 'type', value: 'production' }],
}],
},
});These inner objects are wrapped as StandaloneInnerObjectProto and registered in a special StandaloneLoadUnit, making them injectable via @Inject().
Basic Usage:
// main.ts
import { ContextProto, Inject, SingletonProto } from '@eggjs/tegg';
import { Runner, MainRunner } from '@eggjs/tegg/standalone';
@SingletonProto()
export class MyService {
async doSomething() {
return 'hello';
}
}
@ContextProto()
@Runner() // Mark as entry point
export class MyApp implements MainRunner<string> {
@Inject()
myService: MyService;
async main(): Promise<string> {
return await this.myService.doSomething();
}
}
// Run it
import { main } from '@eggjs/tegg-standalone';
const result = await main<string>(__dirname);
console.log(result); // 'hello'With Dependencies and Custom Objects:
import { main, Runner } from '@eggjs/tegg-standalone';
const result = await main(__dirname, {
// Environment name (affects config loading)
env: 'production',
// Application name
name: 'my-app',
// Additional module paths to load
dependencies: [
'/path/to/other/module',
{ baseDir: '/path/to/module', extraFilePattern: ['!**/test'] },
],
// Custom injectable objects
innerObjectHandlers: {
logger: [{ obj: myLogger }],
config: [{
obj: myConfig,
qualifiers: [{ attribute: 'env', value: 'production' }],
}],
},
// Disable module descriptor dump (default: true)
dump: false,
});Advanced: Manual Runner Control:
import { Runner, StandaloneContext } from '@eggjs/tegg-standalone';
const runner = new Runner(__dirname, options);
await runner.init();
// Custom context with pre-set values
const ctx = new StandaloneContext();
ctx.set('requestId', '12345');
// Run multiple times with different contexts
const result1 = await runner.run(ctx);
const result2 = await runner.run(new StandaloneContext());
// Cleanup when done
await runner.destroy();PreLoad for Faster Startup:
Use preLoad() to run lifecycle preLoad hooks before main(). This is useful for warming up caches or validating configuration:
import { preLoad, main } from '@eggjs/tegg-standalone';
// Run preLoad hooks (e.g., validate config, warm caches)
await preLoad(__dirname, dependencies);
// Then run main
const result = await main(__dirname, { dependencies });Plugins that support standalone mode need an eggModule field in package.json:
{
"name": "@eggjs/tegg-my-plugin",
"eggPlugin": {
"name": "myPlugin",
"dependencies": ["tegg"]
},
"eggModule": {
"name": "teggMyPlugin"
}
}The eggModule.name is used by standalone mode to identify the module. The plugin's prototypes will be loaded automatically when the plugin path is included in dependencies.
Plugins should avoid depending on Egg.js-specific APIs (app, ctx) directly. Instead:
- Use
@Inject()for dependencies - Use lifecycle hooks (
init(),destroy()) instead of Egg.js lifecycle - Provide factories that accept configuration via injection