The elegant type-safe module composable library
Yet another DI library when Awilix and Inversify already exist.
No reflect-metadata, Stage 3 decorators, and compile-time type safety without the dance.
TypeScript developers building applications with dependency injection
InversifyJS · TypeDI · TSyringe
A few things kept bothering me about the existing ones, in order of how much they hurt.
- *Type safety requires a special dance.* InversifyJS has ServiceIdentifier<T>, but it is really easy to break the typing. TypeDI tokens are untyped strings. NestJS suffers mostly same, unless you use full classes as dependency tokens. TSyringe infers from constructor metadata, but all of it relies on legacy "reflect-metadata" and decorators mechanism that (a) is soon to be gone, (b) requires additional wiring.
- *Async leaks into callers.* InversifyJS has container.getAsync() for providers that might have been initialized asynchronously. That means every call site needs to know whether what it's asking for was async. The complexity never stays contained. NestJS again gets this right: await everything at bootstrap, then get() is always synchronous. Initialized means ready.
- *Wiring is imperative.* InversifyJS has you call manually .bind(Token).to(Implementation) for every provider. It works, but it's ugly. NestJS figured out the right answer: declare what a module owns, what it needs, what it exposes, and let the container figure the rest out. That declarative model is the thing I wanted most, but it comes with an entire framework. NestJS gets hairy when your single app starts accepting just Nats JetStream in addition to HTTP.
- *reflect-metadata.* Every major TS DI library runs on TS "experimentalDecorators" plus a global runtime polyfill for TypeScript metadata. TC39 Stage 3 decorators shipped in TypeScript 5.0, and are soon to be natively supported in JS engines. No flags, no polyfills.
Ampulla is my attempt at fixing all four: injection<T>() tokens that carry their type intrinsically, a declarative @Module/@Injectable model lifted straight from NestJS, async-safe bootstrapping where container.get() is always synchronous, and TC39 decorators throughout.
It's intentionally just a DI container, not a framework. There is no HTTP server, no router, no CLI included. Optional adapters for Hono and H3 are included but tree-shakeable. The whole npm package has zero runtime dependencies.
Very early, 1.0.0 published just today. DI is not the most popular topic on HN, but existing DI in TypeScript is annoying enough that I had to publish something new.
GitHub: https://github.com/ukstv/ampulla | npm: npm install ampulla
Yet another DI library when Awilix and Inversify already exist.
npm-style versioning for AI system prompts, but unclear if it solves real pain.
Regex instead of AST parsing: 12ms dependency tree for 500 files versus 50ms+ for competitors.
Decouples exploit logic from execution profiles using dependency injection in C.
Zero-dependency TypeScript PDF engine with proper Arabic shaping beats pdfkit's native bindings.
DynamoDB ORM with clean types, but Dynamoose and TypeORM already do this well.