@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 buildUsage
# Basic usage
ioc-arise generate
# With custom source and output
ioc-arise generate --source src --output src/container.gen.tsConfiguration 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 startLimitations
- Only detects classes using the
implementskeyword - Constructor parameters must be typed
- Circular dependencies are detected and warned about, but not automatically resolved
- Only analyzes TypeScript files (
.tsextension)
Contributing
Contributions are welcome! Please feel free to submit issues and pull requests.