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.0unplugin(required for build plugin)
Configure Your Bundler
NeoSyringe works with all major bundlers through unplugin.
// 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()]
});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
