Skip to content

Getting Started

Zero DecoratorsType-SafeAuto-Generated

IoC-Arise is a complete dependency injection solution for TypeScript:

📦 @notjustcoders/ioc-arise

CLI tool for analyzing code and generating containers. AST-powered analysis detects dependencies automatically.

⚡ @notjustcoders/di-container

Lightweight runtime DI container (~4KB, zero decorators). Use standalone or with generated code.

Terminal window
# Install CLI globally or as dev dependency
npm install -D @notjustcoders/ioc-arise
# The CLI will automatically add @notjustcoders/di-container as a dependency
  1. Install the CLI

    Terminal window
    npm install -D @notjustcoders/ioc-arise
  2. Create Your Services

    services/IUserService.ts
    export interface IUserService {
    getUser(id: string): Promise<User>;
    }
    // services/UserService.ts
    export class UserService implements IUserService {
    async getUser(id: string): Promise<User> {
    // Implementation
    }
    }
  3. Generate Container

    Terminal window
    npx @notjustcoders/ioc-arise generate
  4. Use the Container

    import { container } from "./container.gen";
    const userService = container.resolve('IUserService');
    const user = await userService.getUser('123');

The basic dependency injection pattern uses interfaces and their implementations:

classDiagram
    class IUserService {
        <<interface>>
        +getUser(id: string) Promise~User~
    }
    class UserService {
        +getUser(id: string) Promise~User~
    }
    
    IUserService <|.. UserService : implements

Key Points:

  • IUserService defines the contract (interface)
  • UserService implements the interface
  • The container resolves IUserService to UserService automatically

container.gen.ts - Ready-to-use container instance

import { Container } from '@notjustcoders/di-container';
import type { ContainerRegistry } from './container.gen.d';
import { userModule } from './modules/userModule.module';
export const container = new Container<ContainerRegistry>();
container.registerModule(userModule);

Benefits: ✅ All imports auto-generated • ✅ Modules automatically registered • ✅ Type-safe with ContainerRegistry • ✅ Full IntelliSense support

import { Container, Lifecycle } from '@notjustcoders/di-container';
// Define registry for type safety
interface ContainerRegistry {
'IUserService': IUserService;
'IUserRepository': IUserRepository;
}
const container = new Container<ContainerRegistry>();
// Manual registration (no code generation)
container.register('IUserService', {
useClass: UserService,
dependencies: ['IUserRepository'],
lifecycle: Lifecycle.Singleton
});
// Full type safety
const service = container.resolve('IUserService');
// ^? IUserService

When to use manual setup:

  • ✅ Small projects with few dependencies
  • ✅ Dynamic service registration at runtime
  • ✅ Full control over container configuration

When to use CLI (recommended):

  • ✅ Medium to large projects
  • ✅ Static dependency graphs
  • ✅ Want compile-time validation

See the @notjustcoders/di-container documentation for more details.

Organize your code into logical modules using ioc.config.json:

{
"sourceDir": "./src",
"outputPath": "./src/container.gen.ts",
"interface": "I*.ts",
"modules": {
"UserModule": ["user/**"],
"TodoModule": ["todo/**"]
}
}

This will generate separate module files:

src/
├── container.gen.ts # Main container
├── container.gen.d.ts # Type declarations
└── modules/
├── userModule.module.ts # User module registrations
└── todoModule.module.ts # Todo module registrations

Access services using string tokens:

const userService = container.resolve('IUserService');
const todoService = container.resolve('ITodoService');

One shared instance across the entire application:

/**
* @scope singleton
*/
export class UserRepository implements IUserRepository {
// ✅ Same instance reused everywhere
// ✅ Good for: Databases, configs, caches
// ✅ Better performance (one instantiation)
}

Use Cases: Database connections • Configuration services • Caching layers • Stateful services

Create an ioc.config.json file in your project root:

{
"sourceDir": "./src", // Source directory to analyze
"outputPath": "./src/container.gen.ts", // Output file path
"interface": "I*.ts", // Interface file pattern
"exclude": [ // Files to exclude
"node_modules",
"dist",
"**/*.test.ts"
],
"modules": { // Optional module grouping
"CoreModule": ["core/**"],
"UserModule": ["user/**"],
"TodoModule": ["todo/**"]
}
}

📚 Examples

Explore real-world examples including Clean Architecture, modules, and use cases.