@kyoheig3/tneedle
v0.0.3
Published
Type-safe dependency injection resolver for tsyringe
Maintainers
Readme
tneedle
English | 日本語
Type-safe dependency injection resolver for tsyringe.
Features
- Lightweight wrapper around
tsyringecontainer - Type-safe access to registered instances
- Unique
Symboltokens for each resolver (no token conflicts) - Late binding support with
register()method - Works with interfaces (no decorators required)
Installation
npm install @kyoheig3/tneedle tsyringe reflect-metadataPeer Dependencies
tsyringe^4.0.0reflect-metadata^0.1.13 || ^0.2.0
Setup
Import reflect-metadata at your application entry point:
import "reflect-metadata";Usage
Basic Usage
import { createResolver } from "@kyoheig3/tneedle";
// Define your interface
interface UserRepository {
findById(id: string): Promise<User | null>;
save(user: User): Promise<void>;
}
// Create a resolver
export const userRepo = createResolver<UserRepository>();
// Register implementation at app startup
userRepo.register({
findById: async (id) => {
/* ... */
},
save: async (user) => {
/* ... */
},
});
// Use anywhere in your app
const user = await userRepo.findById("123");With Initial Value
const config = createResolver({
apiUrl: "https://api.example.com",
timeout: 5000,
});
// Immediately accessible
console.log(config.apiUrl);
// Can be overridden later
config.register({
apiUrl: "https://staging.example.com",
timeout: 10000,
});Clean Architecture Example
// domain/repositories.ts
export const userRepository = createResolver<UserRepository>();
export const orderRepository = createResolver<OrderRepository>();
// infrastructure/setup.ts
import { userRepository, orderRepository } from "../domain/repositories";
export function setupRepositories(api: ApiClient) {
userRepository.register(new UserRepositoryImpl(api));
orderRepository.register(new OrderRepositoryImpl(api));
}
// application/usecase.ts
import { userRepository } from "../domain/repositories";
export async function getUserProfile(userId: string) {
return userRepository.findById(userId);
}API
createResolver<T>(instance?: T | null): Resolver<T>
Creates a new resolver for type T.
Parameters:
instance- Optional initial instance to register
Returns:
- A
Resolver<T>proxy with all properties ofTplus aregistermethod
Throws:
Errorif properties are accessed beforeregister()is called (when no initial instance provided)
Resolver<T>
type Resolver<T extends object> = T & {
register: (instance: T) => void;
};