Initial Commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.DS_Store
|
||||||
|
|
||||||
|
node_modules/
|
||||||
12
.prettierrc
Normal file
12
.prettierrc
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"bracketSameLine": true,
|
||||||
|
"bracketSpacing": false,
|
||||||
|
"printWidth": 160,
|
||||||
|
"semi": true,
|
||||||
|
"singleAttributePerLine": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"useTabs": false
|
||||||
|
}
|
||||||
34
DependencyInjection/.gitignore
vendored
Normal file
34
DependencyInjection/.gitignore
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# dependencies (bun install)
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# output
|
||||||
|
out
|
||||||
|
dist
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# code coverage
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# logs
|
||||||
|
logs
|
||||||
|
_.log
|
||||||
|
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# caches
|
||||||
|
.eslintcache
|
||||||
|
.cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# IntelliJ based IDEs
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Finder (MacOS) folder config
|
||||||
|
.DS_Store
|
||||||
74
DependencyInjection/README.md
Normal file
74
DependencyInjection/README.md
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# Simple Dependency Injection Container
|
||||||
|
|
||||||
|
A learning project to understand how Dependency Injection works by building one from scratch.
|
||||||
|
|
||||||
|
Inspired by the Phenix RTS platform's DI system.
|
||||||
|
|
||||||
|
## Learning Goals
|
||||||
|
|
||||||
|
1. Understand how DI containers resolve dependencies
|
||||||
|
2. Learn about different lifecycle patterns (singleton, transient, factory)
|
||||||
|
3. Understand circular dependency detection
|
||||||
|
4. Learn about provider patterns
|
||||||
|
5. Understand type registration and resolution
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
We'll build this incrementally:
|
||||||
|
|
||||||
|
1. **Step 1**: Basic container with manual registration
|
||||||
|
2. **Step 2**: Constructor injection
|
||||||
|
3. **Step 3**: Singleton vs Transient lifecycles
|
||||||
|
4. **Step 4**: Circular dependency detection
|
||||||
|
5. **Step 5**: Provider pattern
|
||||||
|
6. **Step 6**: Named registrations
|
||||||
|
7. **Step 7**: Configuration-driven DI (like Phenix's di.json)
|
||||||
|
|
||||||
|
## Running the Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Step 1 - Basic
|
||||||
|
node step1-basic.js
|
||||||
|
|
||||||
|
# Step 2 - Constructor Injection
|
||||||
|
node step2-constructor-injection.js
|
||||||
|
|
||||||
|
# Step 3 - Lifecycles
|
||||||
|
node step3-lifecycles.js
|
||||||
|
|
||||||
|
# Step 4 - Circular Dependencies
|
||||||
|
node step4-circular-deps.js
|
||||||
|
|
||||||
|
# Step 5 - Providers
|
||||||
|
node step5-providers.js
|
||||||
|
|
||||||
|
# Step 6 - Named Registrations
|
||||||
|
node step6-named.js
|
||||||
|
|
||||||
|
# Step 7 - Configuration
|
||||||
|
node step7-config.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Concepts
|
||||||
|
|
||||||
|
### Dependency Injection
|
||||||
|
|
||||||
|
Instead of creating dependencies inside a class, they are "injected" from outside.
|
||||||
|
|
||||||
|
### Inversion of Control (IoC)
|
||||||
|
|
||||||
|
The container controls object creation and lifecycle, not your code.
|
||||||
|
|
||||||
|
### Service Locator vs DI
|
||||||
|
|
||||||
|
DI is better because dependencies are explicit in constructor signatures.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
Container
|
||||||
|
├── Registry (stores type registrations)
|
||||||
|
├── Resolver (resolves dependencies)
|
||||||
|
├── Lifecycle Manager (handles singleton/transient)
|
||||||
|
└── Provider System (custom creation logic)
|
||||||
|
```
|
||||||
17
DependencyInjection/package.json
Normal file
17
DependencyInjection/package.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "dependencyinjection",
|
||||||
|
"module": "index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"step:1": "bun run src/Step1",
|
||||||
|
"step:2": "bun run src/Step2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest",
|
||||||
|
"prettier": "3.6.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "5.9,3"
|
||||||
|
}
|
||||||
|
}
|
||||||
29
DependencyInjection/tsconfig.json
Normal file
29
DependencyInjection/tsconfig.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// Environment setup & latest features
|
||||||
|
"lib": ["ESNext"],
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "Preserve",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
|
||||||
|
// Bundler mode
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
// Best practices
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
|
||||||
|
// Some stricter flags (disabled by default)
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noPropertyAccessFromIndexSignature": false
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user