@notjustcoders/ioc-arise v1.0.4
IoC Arise
A command-line tool that automatically generates type-safe IoC (Inversion of Control) containers for TypeScript projects. It analyzes your classes, detects dependencies, and creates a container file with proper instantiation order.
Table of Contents
- Features
- Installation
- Usage
- Configuration File
- Examples
- Usage in Your Code
- Development
- Limitations
- Contributing
Features
- š Automatic Detection: Finds all classes implementing specific interfaces
- š§ Dependency Analysis: Parses constructor dependencies from TypeScript code
- š Topological Sorting: Ensures correct instantiation order
- š”ļø Type Safety: Generates fully typed container with IDE autocompletion
- š« No Decorators: Pure static analysis, no runtime registration needed
- ā ļø Circular Dependency Detection: Warns about dependency cycles
Installation
# Install globally
npm install -g @notjustcoders/ioc-arise
# Or use with npx
npx @notjustcoders/ioc-arise --help
# For development
pnpm install
pnpm run build
Usage
# Basic usage
ioc-arise generate
# With custom source and output
ioc-arise generate --source src --output src/container.gen.ts
Configuration File
You can create an ioc.config.json
file in the same directory as your source code to set default options. CLI arguments will override config file settings.
{
"source": "src",
"output": "container.gen.ts",
"interface": "I[A-Z].*",
"exclude": [
"**/*.test.ts",
"**/*.spec.ts",
"**/node_modules/**"
],
"checkCycles": false,
"verbose": true
}
Config File Location
The config file should be placed in the same directory as your source code. For example, if your source directory is src
, place ioc.config.json
in the src
directory.
Priority Order
- CLI arguments (highest priority)
- Config file settings
- Default values (lowest priority)
Examples
Basic Example
Directory structure:
minimal-todo/
āāā entities/Todo.ts
āāā repositories/
ā āāā ITodoRepository.ts
ā āāā InMemoryTodoRepository.ts
āāā services/
ā āāā ITodoService.ts
ā āāā TodoService.ts
āāā ioc.config.json
āāā container.gen.ts (generated)
Configuration (ioc.config.json
):
{
"source": ".",
"output": "container.gen.ts"
}
Generated container:
// ... imports and lazy initialization functions ...
export const container = {
get ITodoService(): TodoService {
return getTodoService();
},
get ITodoRepository(): InMemoryTodoRepository {
return getInMemoryTodoRepository();
},
};
export type Container = typeof container;
Multi-Module Example
Directory structure:
simple-modules/
āāā user/
ā āāā User.ts
ā āāā IUserRepository.ts
ā āāā UserRepository.ts
ā āāā IUserService.ts
ā āāā UserService.ts
āāā todo/
ā āāā Todo.ts
ā āāā ITodoRepository.ts
ā āāā TodoRepository.ts
ā āāā ITodoService.ts
ā āāā TodoService.ts
āāā ioc.config.json
āāā container.gen.ts (generated)
Configuration (ioc.config.json
):
{
"source": ".",
"output": "container.gen.ts",
"modules": {
"UserModule": ["user/**"],
"TodoModule": ["todo/**"]
}
}
Generated container:
// ... imports ...
// Module container functions
function createUserModuleContainer() {
// ... lazy initialization variables ...
// Lazy initialization for UserModule services
return {
get IUserService(): UserService { /* ... */ },
get IUserRepository(): UserRepository { /* ... */ }
};
}
function createTodoModuleContainer(userModuleContainer) {
// ... lazy initialization variables ...
// TodoModule with cross-module dependencies
return {
get ITodoService(): TodoService { /* ... */ },
get ITodoRepository(): TodoRepository { /* ... */ }
};
}
// Module instantiation with dependency injection
const userModuleContainer = createUserModuleContainer();
const todoModuleContainer = createTodoModuleContainer(userModuleContainer);
export const container = {
userModule: userModuleContainer,
todoModule: todoModuleContainer
};
export type Container = typeof container;
See the examples/
directory for complete working examples.
Usage in Your Code
import { container } from './container.gen';
// Basic usage
const todoService = container.ITodoService;
const todos = await todoService.getAllTodos();
// Multi-module usage
const userService = container.userModule.IUserService;
const todoService = container.todoModule.ITodoService;
Development
# Run in development mode
pnpm run dev
# Build for production
pnpm run build
# Run built version
pnpm run start
Limitations
- Only detects classes using the
implements
keyword - Constructor parameters must be typed
- Circular dependencies are detected and warned about, but not automatically resolved
- Only analyzes TypeScript files (
.ts
extension)
Contributing
Contributions are welcome! Please feel free to submit issues and pull requests.