Thanks to visit codestin.com
Credit goes to github.com

Skip to content

A lightweight yet powerful dependency injection container for TypeScript applications, inspired by VS Code's instantiation service.

Notifications You must be signed in to change notification settings

lijunx/instantiation

Repository files navigation

TypeScript Dependency Injection Container

A lightweight yet powerful dependency injection container for TypeScript applications, inspired by VS Code's instantiation service.

Features

  • Hierarchical Service Containers: Create child containers that inherit from parent containers
  • Constructor-based Dependency Injection: Automatic injection via parameter decorators
  • Lazy Instantiation: Delay service creation until first use for performance
  • Cycle Detection: Automatically detect and prevent circular dependencies
  • Service Descriptors: Flexible service registration with instantiation metadata
  • Type Safety: Full TypeScript support with strict typing

Installation

Quick Start

1. Define Service Interface

interface ILogger {
  log(message: string): void
}

interface IUserService {
  getUser(id: string): Promise<User>
}

2. Create Service Identifiers

import { createDecorator } from 'di'

const ILogger = createDecorator<ILogger>('logger')
const IUserService = createDecorator<IUserService>('userService')

3. Implement Services

class ConsoleLogger implements ILogger {
  log(message: string): void {
    console.log(`[LOG] ${message}`)
  }
}

class UserService implements IUserService {
  constructor(@ILogger private logger: ILogger) {}

  async getUser(id: string): Promise<User> {
    this.logger.log(`Fetching user ${id}`)
    return { id, name: 'John Doe' }
  }
}

4. Register Services

import { ServiceCollection, SyncDescriptor, InstantiationService } from 'di'

const services = new ServiceCollection()
services.set(ILogger, new SyncDescriptor(ConsoleLogger))
services.set(IUserService, new SyncDescriptor(UserService))

const instantiationService = new InstantiationService(services)

5. Use Services

// Create instance with automatic dependency injection
const userService = instantiationService.createInstance(IUserService)

// Or use accessor pattern
const user = instantiationService.invokeFunction(async (accessor) => {
  const userService = accessor.get(IUserService)
  return await userService.getUser('123')
})

Advanced Usage

Lazy Instantiation

For performance-critical applications, you can enable lazy instantiation:

services.set(IHeavyService, new SyncDescriptor(HeavyService, [], true))

Hierarchical Containers

Create child containers that inherit services from parent containers:

const childServices = new ServiceCollection()
childServices.set(IChildService, new SyncDescriptor(ChildService))

const childContainer = instantiationService.createChild(childServices)

Manual Service Creation

// Create instance with additional arguments
const service = instantiationService.createInstance(MyService, arg1, arg2)

// Create instance from descriptor
const descriptor = new SyncDescriptor(MyService, [arg1])
const service = instantiationService.createInstance(descriptor)

API Reference

Core Classes

InstantiationService

Main service container that manages service instances and dependencies.

new InstantiationService(services?: ServiceCollection, strict?: boolean)

Methods:

  • createInstance<T>(descriptor: SyncDescriptor0<T>): T
  • createInstance<Ctor>(ctor: Ctor, ...args): InstanceType<Ctor>
  • invokeFunction<R>(fn: (accessor: ServicesAccessor) => R): R
  • createChild(services: ServiceCollection): IInstantiationService
  • dispose(): void

ServiceCollection

Registry for services and their descriptors.

new ServiceCollection(...entries: [ServiceIdentifier, any][])

Methods:

  • set<T>(id: ServiceIdentifier<T>, instanceOrDescriptor: T | SyncDescriptor<T>)
  • get<T>(id: ServiceIdentifier<T>): T | SyncDescriptor<T> | undefined
  • has(id: ServiceIdentifier): boolean

SyncDescriptor

Wrapper for service constructors with instantiation metadata.

new SyncDescriptor<T>(
  ctor: new (...args: any[]) => T,
  staticArguments?: unknown[],
  supportsDelayedInstantiation?: boolean
)

Utility Functions

createDecorator<T>(serviceId: string): ServiceIdentifier<T>

Creates a service identifier for dependency injection.

registerSingleton<T>(id: ServiceIdentifier<T>, ctor: new (...args: any[]) => T, supportsDelayedInstantiation?: boolean)

Convenience function for registering singleton services.

Development

Setup

# Install dependencies
pnpm install

# Run tests
pnpm test

# Fix linting issues
pnpm fix

# Type check
pnpm tsc --noEmit

Running Tests

# Run all tests
pnpm test

# Run specific test file
pnpm test graph.test.ts

# Run in watch mode
pnpm test --watch

Examples

Web Application Integration

// services.ts
export const IDatabaseService = createDecorator<IDatabaseService>('databaseService')
export const IAuthService = createDecorator<IAuthService>('authService')

// main.ts
import { InstantiationService } from 'di'
import { services } from './services'

const container = new InstantiationService(services)

// Use in route handlers
app.get('/users/:id', async (req, res) => {
  const user = await container.invokeFunction(async (accessor) => {
    const authService = accessor.get(IAuthService)
    const dbService = accessor.get(IDatabaseService)
    
    await authService.authenticate(req)
    return await dbService.getUser(req.params.id)
  })
  
  res.json(user)
})

Testing

import { InstantiationService, ServiceCollection } from 'di'

describe('UserService', () => {
  it('should fetch user', async () => {
    const services = new ServiceCollection()
    services.set(ILogger, new MockLogger())
    services.set(IUserService, new SyncDescriptor(UserService))

    const container = new InstantiationService(services)
    const userService = container.createInstance(IUserService)

    const user = await userService.getUser('123')
    expect(user.id).toBe('123')
  })
})

License

ISC

About

A lightweight yet powerful dependency injection container for TypeScript applications, inspired by VS Code's instantiation service.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published