초기 사용자/피드백을 찾기 위해 Node용 데코레이터가 없는 DI 컨테이너인 Injectus를 만들었습니다.

작성자

카테고리:

← 피드로
DEV Community · Hossam Hamdy · 2026-07-02 개발(SW)

Hossam Hamdy

I’ve been building a dependency injection container for Node/TypeScript called Injectus, and I’m at the point where I’d rather have a handful of people actually try it and poke holes in it than keep polishing alone. It’s 0.2.x not “adopt this in prod tomorrow” young, but the core is solid and I want real usage before I push it further.

What it is: zero-dependency, decorator-free IoC container. No reflect-metadata, no emitDecoratorMetadata, no build config wrestling.

import { Injector, inject, InjectionToken } from "injectus";

const DB_URL = new InjectionToken<string>("DB_URL");

class Database {
  url = inject(DB_URL);
}

class UserService {
  db = inject(Database);
  findAll() {
    return this.db.url;
  }
}

const injector = Injector.create({
  providers: [
    { provide: DB_URL, useValue: "postgres://localhost/app" },
    Database,
    UserService,
  ],
});

injector.resolve(UserService).findAll();
await injector.dispose();

Enter fullscreen mode Exit fullscreen mode

Why I built it: I kept hitting the same friction with existing containers – decorators requiring specific tsconfig/build setups, string or symbol tokens silently colliding, and singleton/scoped lifetime mismatches only surfacing as bugs in production. Injectus’s actual differentiators:

  • Decorator-freeinject() works in field initializers and factory bodies, no metadata reflection required.
  • Identity-based tokens – classes and InjectionToken instances are the key, not their string description. Two tokens named "Logger" can’t collide.
  • Captive dependency detection – resolving a Singleton that depends on a Scoped binding throws CaptiveDependencyError at resolve time, not silently in prod.
  • Deterministic disposal – LIFO teardown via Symbol.asyncDispose, multiple failing disposers collected into one AggregateError, full dependency path exposed root-to-leaf on CircularDependencyError/CaptiveDependencyError.

It also benchmarks well against the two closest points of comparison – awilix (decorator-free) and tsyringe (decorator-based) – resolving the same dependency-graph shape in each case:

What’s honestly not done yet, so you know what you’re getting into:

  • No module system yet – (flat provider arrays only, for now)
  • No multi-injection – registering the same token twice currently shadows (last-write-wins)
  • No async init hooks / lifecycle ordering yet
  • No framework adapters (Express example exists, others don’t)

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다