Getting Started
This guide will help you install NeoSyringe and create your first container in 5 minutes.
Installation
pnpm add @djodjonx/neosyringe
pnpm add -D @djodjonx/neosyringe-pluginnpm install @djodjonx/neosyringe
npm install -D @djodjonx/neosyringe-pluginyarn add @djodjonx/neosyringe
yarn add -D @djodjonx/neosyringe-pluginPeer Dependencies
typescript>= 5.0 — including TypeScript 6unplugin(required for build plugin)
NeoSyringe is fully compatible with TypeScript 6. No changes needed in your tsconfig.json.
Configure Your Build
NeoSyringe works with all major bundlers via unplugin, or directly with tsc via ts-patch — no bundler required.
// vite.config.ts
import { defineConfig } from 'vite';
import { neoSyringePlugin } from '@djodjonx/neosyringe-plugin';
export default defineConfig({
plugins: [neoSyringePlugin.vite()]
});// rollup.config.js
import { neoSyringePlugin } from '@djodjonx/neosyringe-plugin';
export default {
plugins: [neoSyringePlugin.rollup()]
};// webpack.config.js
module.exports = {
plugins: [require('@djodjonx/neosyringe-plugin').webpack()]
};// esbuild.config.js
import { neoSyringePlugin } from '@djodjonx/neosyringe-plugin';
await esbuild.build({
plugins: [neoSyringePlugin.esbuild()]
});// tsconfig.json — no bundler needed, works with plain tsc
{
"compilerOptions": {
"plugins": [
{ "transform": "@djodjonx/neosyringe-plugin/transformer", "transformProgram": true }
]
}
}ts-patch setup
Install ts-patch and add a prepare script so it patches TypeScript automatically after npm/pnpm install:
pnpm add -D ts-patch @djodjonx/neosyringe-plugin// package.json
{
"scripts": {
"prepare": "ts-patch install -s"
}
}tsc and any tool that delegates to it (NestJS CLI's nest build, ts-node, etc.) will then pick up the transformer automatically.
Create Your First Container
Step 1: Define Your Services
Create pure TypeScript classes and interfaces. No decorators needed!
// services/logger.ts
export interface ILogger {
log(msg: string): void;
}
export class ConsoleLogger implements ILogger {
log(msg: string) {
console.log(`[LOG] ${msg}`);
}
}// services/user.service.ts
import type { ILogger } from './logger';
export class UserService {
constructor(private logger: ILogger) {}
createUser(name: string) {
this.logger.log(`Creating user: ${name}`);
return { id: crypto.randomUUID(), name };
}
}Step 2: Configure the Container
Best Practice
Put your container configuration in a dedicated file (e.g., container.ts). The plugin replaces the entire file content with generated code.
// container.ts
import { defineBuilderConfig, useInterface } from '@djodjonx/neosyringe';
import { ILogger, ConsoleLogger } from './services/logger';
import { UserService } from './services/user.service';
export const container = defineBuilderConfig({
name: 'AppContainer',
injections: [
// Bind interface to implementation
{ token: useInterface<ILogger>(), provider: ConsoleLogger },
// Autowire class (dependencies resolved automatically)
{ token: UserService }
]
});Step 3: Use the Container
// main.ts
import { container } from './container';
import { UserService } from './services/user.service';
// Resolve with full type safety - no type assertions!
const userService = container.resolve(UserService);
// Type: UserService ✅ (automatically inferred)
const user = userService.createUser('John Doe');
// Full auto-completion available!
console.log(user); // { id: 'xxx-xxx', name: 'John Doe' }Type Safety
The resolve() method automatically infers the return type from the token. No manual type assertions needed!
Project Structure
Recommended project structure:
src/
├── container.ts # ✅ Container configuration
├── services/
│ ├── logger.ts # Pure service
│ └── user.service.ts # Pure service
└── main.ts # Application entryTree Shaking
Import services directly instead of using barrel exports (index.ts) for better tree shaking in client-side code.
Development Mode
✅ The plugin works in dev mode with full HMR support!
The transform hook is called on every file change, so your container is regenerated instantly during development.
What's Next?
- Basic Usage - Learn all injection types
- Lifecycle - Singleton vs Transient
- Scoped Injections - Override parent tokens
- IDE Plugin - Real-time error detection
