proxydi
Version:
A typed hierarchical DI container that resolves circular dependencies via Proxy
174 lines (114 loc) • 6.99 kB
Markdown
# ProxyDI Developer Documentation
## For AI agents: Before You Start
**MANDATORY reading before working on this project:**
1. **Read the entire [README.md](../README.md)** — understand what the library does and how users interact with it
2. **Read all source files** in `src/` — understand implementation
3. **Read all tests** in `src/__tests__/` — understand expected behavior and edge cases
I want it because I want you have all library and use cases in your context, it's not too big, so just do it. But don't read any others content like other documentation documents.
**This must be done RIGHT AFTER YOU reads this document.** ProxyDI is a production library used in other projects. Changes have real impact. So you must have full picture.
### Running Tests
Always use `npm run test:ci` when running tests during refactoring.
After code changes, run `npm run coverage`. Maintain 100% coverage for all code branches.
### Updating CHANGELOG
After making changes, update CHANGELOG.md with the appropriate version and changes.
## Documentation Structure
**[Library Users Documentation](../README.md):** for developers using ProxyDI in their projects.
**[Library Developers Documentation](./proxydi.md):** files in this folder (`documentation/`) for contributors working on ProxyDI itself.
## Key Resources
- [How to Write User Documentation](./writing-user-documentation.md) — style guide for user documentation
- [How to Write Developer Documentation](./writing-developer-documentation.md) — style guide for developer project documentation``
- [Roadmap](./roadmap.md) — planned improvements and features
- [Bundler Examples TODO](./bundler-examples-todo.md) — tasks for creating bundler configuration examples
## Feature Documentation
- [@injectAll and ResolveScope](./injectAll.md) — dependency arrays and scope control
## Architecture Overview
```mermaid
graph TB
User[Using ProxyDI] --> Register[Register dependencies]
User --> Resolve[Resolve dependencies]
Register --> Container[ProxyDiContainer.ts]
Resolve --> Container
Container --> Injectable["@injectable
auto-injectable classes"]
Container --> Inject["@inject
field injections"]
Container --> InjectAll["@injectAll
array injections"]
Injectable --> AutoResolve[Auto-resolve on first use]
AutoResolve --> DirectInstance[Direct instance]
Inject --> InjectionProxy["makeInjectionProxy.ts
Auto-bake after first use"]
InjectAll --> InjectAllProxy["makeInjectAllProxy.ts
Dynamic array (permanent)"]
Container --> Hierarchy[Container hierarchy]
Hierarchy --> CheckOrigin{"Instance from
different container?"}
CheckOrigin -->|No - same container| DirectInstance
CheckOrigin -->|Yes - parent container| ResolveContext{resolveInContainerContext?}
ResolveContext -->|false| DirectInstance
ResolveContext -->|true| DependencyProxy["makeDependencyProxy.ts
Permanent Proxy"]
Container --> Middleware[Middleware system]
Middleware --> MiddlewareDecorator["@middleware"]
Middleware --> MiddlewareManager[MiddlewaresManager.ts]
style InjectionProxy fill:#51cf66,stroke:#2f9e44,color:#000
style InjectAllProxy fill:#ff6b6b,stroke:#c92a2a,color:#000
style DependencyProxy fill:#ff6b6b,stroke:#c92a2a,color:#000
style DirectInstance fill:#51cf66,stroke:#2f9e44,color:#000
```
- 🔴 Slow - Permanent Proxy (~100x slower)
- 🟢 Fast - Auto-baked or direct access
## Source Files Overview
**Core:**
- `ProxyDiContainer.ts` — main container implementation
- `types.ts` — TypeScript types and symbols
**Decorators:**
- `inject.decorator.ts` — `@inject` field decorator
- `injectable.decorator.ts` — `@injectable` class decorator
- `injectAll.decorator.ts` — `@injectAll` field decorator for dependency arrays
**Proxy Implementation:**
- `makeInjectionProxy.ts` — Proxy for `@inject` fields (auto-bakes after first use)
- `makeDependencyProxy.ts` — Proxy for `resolveInContainerContext` (permanent)
- `makeInjectAllProxy.ts` — Proxy for `@injectAll` arrays (permanent, dynamic)
**Middleware:**
- `middleware/middleware.decorator.ts` — `@middleware` decorator
- `middleware/MiddlewaresManager.ts` — middleware lifecycle management
- `middleware/middleware.api.ts` — middleware interfaces
**Utilities:**
- `resolveAll.ts` — wrapper for `container.resolveAll()`
- `presets.ts` — default container settings
## Test Files
All tests in `src/__tests__/`:
- `ProxyDiContainer.test.ts` — main container behavior (comprehensive coverage)
- `inject.test.ts` — `@inject` decorator tests
- `injectable.test.ts` — `@injectable` decorator tests
- `readme.test.ts` — examples from README (ensures docs stay correct)
## Architecture Decisions
### Why Proxy?
Enables circular dependency resolution without manual intervention. Different Proxy types have different lifecycle:
- Field injections (`@inject`) — auto-bake after first use (see `makeInjectionProxy.ts:30-32`)
- Context resolution — permanent Proxy (see `makeDependencyProxy.ts`)
### Why `resolveInContainerContext` is disabled by default?
Creates additional permanent Proxy for each parent dependency resolved from child. ~100x slower property access. See `ProxyDiContainer.ts:268-278`.
### Why `register(instance, Class)` is forbidden?
TypeScript overloads distinguish class constructors from instances. Conditional type `T extends new (...args: any[]) => any ? never : T` prevents ambiguity. See `ProxyDiContainer.ts:120-127`.
## Performance Characteristics
| Feature | Proxy Type | Baking | Performance Impact |
| ----------------------------- | --------------- | ---------------------- | ------------------ |
| `@inject` fields (default) | InjectionProxy | Auto-bake on first use | Minimal (one-time) |
| `@inject` fields (rewritable) | InjectionProxy | Never | ~100x slower |
| `resolveInContainerContext` | DependencyProxy | Never | ~100x slower |
See performance tests in `ProxyDiContainer.test.ts:962-994` (commented out).
## Related Projects
- [@proxydi/react](https://github.com/proxy-di/proxydi-react) — React wrapper
- [node-babel-examples](https://github.com/proxy-di/node-babel-examples) — Babel configuration examples
- [node-ts-examples](https://github.com/proxy-di/node-ts-examples) — TypeScript examples
## Contributing
Before making changes:
1. Read this document
2. Read [How to Write Documentation](./writing-documentation.md)
3. Check [README Improvement Proposals](./documentation-improvement-proposals.md) for planned changes
4. Ensure all tests pass
5. Update documentation if behavior changes
6. Add tests for new features
This is a production library. Be careful.