npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dp-ioc2

v1.0.1

Published

简单、强大的基于TypeScript的IOC容器库,支持依赖注入、单例、参数校验等功能

Readme

dp-ioc

简单、强大的基于TypeScript的IOC库。

一、安装 [ Installation ]

  • npm i dp-ioc

二、快速开始

import { Inject, Injectable, Provider } from "dp-ioc";

//定义一个可注入类
@Injectable()
class Person {
    name = "rajan"
    dance() {
        return  this.name + " dance";
    }
}


// 注入到其他类中
class ClassRoom {

    @Inject(Person)
    public person:Person;
}

// 使用,(通过Provider函数进行实例化 )
let classRoom = Provider<ClassRoom>(ClassRoom);
console.log(classRoom.person.name); // rajan
console.log(classRoom.person.dance); // rajan dance 

注意,使用了依赖注入的类,在应用时必须通过Provider进行实例化

三、高级用法

3.1 单例

import { Single, Injectable } from "dp-ioc";

@Single()
@Injectable()
class Person {
    name = "rajan"
    dance() {
        return  this.name + " dance";
    }
}

3.2 多层注入

import { Single, Injectable,Inject,Provider } from "dp-ioc";

@Injectable()
class Person {
    name = "rajan"
    dance() {
        return  this.name + " dance";
    }
}

@Injectable()
class ClassRoom {
    name = "room 001"
    @Inject(Person)
    person:Person
}

class School {

    @Inject(ClassRoom)
    classRoom:ClassRoom;
}

let school = Provider<School>(School);

3.3 构造传参

本库支持实例化Injectable可注入对象时,传入实例化的参数

import { Single, Injectable,Inject,Provider,Constructor } from "dp-ioc";

@Injectable()
class Person {
    name = "rajan"
    age = 0;

    //ioc 容器实例化该类时,setPersonBasicInfo方法将会被执行
    @Constructor()
    setPersonBasicInfo(name:string,age:number){
        this.name = name;
        this.age = age;
    } 

    dance() {
        return  this.name + " dance";
    }

}

//注入
class ClassRoom {
    name = "room 001"

    @Inject(Person,["小明",18])
    person:Person
}

// 实例化
let classRoom = Provider<ClassRoom>(ClassRoom);
console.log(classRoom.person.name,classRoom.person.age); // 小明 18

3.4 支持继承依赖

import { Single, Injectable,Inject,Provider,Constructor } from "dp-ioc";

@Injectable()
class Human {
    age = 0;
    name = "";
}

class Student extends Human {
    dance():string{
        return this.name + "dance";
    }
}

class classRoom {
    @Inject(Student)
    public Student: Student;
}

3.5 序列化和反序列

在实际项目开发中,某些对象可能需要序列化为字符串以便存储,传输。本库支持将序列化之后的对象还原为依赖对象。

import { Single, Injectable,Inject,Provider,Constructor } from "dp-ioc";

@Injectable()
class Person {
    age = 0;
    name = "";
    dance():string{
        return this.name + "dance";
    }
}

class ClassRoom {

    @Inject(Student)
    public Student: Student;
}

let classRoom = Provider<ClassRoom>(ClassRoom);

let classRoomStr = JSON.stringify(classRoom); // 序列化为字符串

classRoom = Provider<ClassRoom>(ClassRoom,JSON.parse(classRoomStr)); // 反序列化为依赖对象

3.6 参数校验 (ParamValidate)

本库支持方法参数自动校验,支持 class-validator(对象参数)和 joi(非对象参数)两种校验方式。IOC 容器会自动判断参数类型并选择相应的校验方式。

3.6.1 使用 Joi 校验非对象参数

import { Injectable, Inject, Provider, ParamValidate } from "dp-ioc";
import Joi from "joi";

@Injectable()
class UserService {
    // 校验字符串参数
    getUserById(@ParamValidate(undefined, Joi.string().min(3).required()) id: string) {
        return `User ${id}`;
    }
    
    // 校验数字参数
    calculate(
        @ParamValidate(undefined, Joi.number().min(0).required()) a: number,
        @ParamValidate(undefined, Joi.number().min(1).required()) b: number
    ) {
        return a / b;
    }
}

class App {
    @Inject(UserService)
    userService: UserService;
}

const app = Provider<App>(App);
app.userService.getUserById("123"); // ✅ 通过
// app.userService.getUserById("12"); // ❌ 抛出 IOCValidationError

3.6.2 使用 class-validator 校验对象参数

import { Injectable, Inject, Provider, ParamValidate } from "dp-ioc";
import { IsString, IsNumber, MinLength, Min } from "class-validator";

// 定义校验类
class CreateUserDto {
    @IsString()
    @MinLength(3)
    name!: string;

    @IsNumber()
    @Min(18)
    age!: number;
}

@Injectable()
class UserService {
    async createUser(@ParamValidate(CreateUserDto) user: CreateUserDto) {
        return `Created user: ${user.name}, age: ${user.age}`;
    }
}

class App {
    @Inject(UserService)
    userService: UserService;
}

const app = Provider<App>(App);

// ✅ 使用类实例
const user = new CreateUserDto();
user.name = "John";
user.age = 25;
await app.userService.createUser(user);

// ✅ 使用普通对象(会自动转换为类实例)
await app.userService.createUser({ name: "John", age: 25 });

// ❌ 校验失败会抛出 IOCValidationError
// await app.userService.createUser({ name: "Jo", age: 17 });

3.6.3 混合使用

import { Injectable, Inject, Provider, ParamValidate } from "dp-ioc";
import Joi from "joi";
import { IsString, MinLength } from "class-validator";

class UserDto {
    @IsString()
    @MinLength(3)
    name!: string;
}

@Injectable()
class UserService {
    async updateUser(
        @ParamValidate(undefined, Joi.string().min(3).required()) userId: string,
        @ParamValidate(UserDto) userData: UserDto
    ) {
        return `Updated user ${userId} with name ${userData.name}`;
    }
}

3.6.4 错误处理

import { IOCValidationError } from "dp-ioc";

try {
    app.userService.getUserById("12");
} catch (error) {
    if (error instanceof IOCValidationError) {
        console.error("参数校验失败:", error.message);
        console.error("详细错误:", error.errors);
    }
}

注意

  • 参数校验在方法调用前自动执行
  • 如果校验失败,会抛出 IOCValidationError 异常
  • 参数校验在 Before hook 之前执行
  • 对象参数自动使用 class-validator,非对象参数使用 joi

3.7 方法拦截器 (Interceptor)

拦截器可以完全控制方法的执行流程,包括修改参数、修改返回值、处理错误等。注意:拦截器不能与 Before 和 After 同时使用。

3.7.1 基本使用

import { Injectable, Inject, Provider, Interceptor } from "dp-ioc";

@Injectable()
class Service {
    @Interceptor((args: any[], obj: any, targetFn: Function, done: Function) => {
        // args: 方法调用的参数列表
        // obj: 方法所属的对象实例
        // targetFn: 原始的目标方法
        // done: 回调函数,用于处理错误或返回结果 (err, result) => void
        
        // 可以修改参数
        const modifiedArgs = args.map((arg: number) => arg * 2);
        
        // 调用原始方法
        try {
            const result = targetFn.apply(obj, modifiedArgs);
            done(null, result);
        } catch (error) {
            done(error, null);
        }
    })
    calculate(a: number, b: number): number {
        return a + b;
    }
}

class App {
    @Inject(Service)
    service: Service;
}

const app = Provider<App>(App);
const result = await app.service.calculate(2, 3);
// 参数被修改为 4 和 6,所以结果是 10
console.log(result); // 10

3.7.2 修改返回值

@Injectable()
class Service {
    @Interceptor((args: any[], obj: any, targetFn: Function, done: Function) => {
        const result = targetFn.apply(obj, args);
        // 修改返回值
        done(null, result * 2);
    })
    add(a: number, b: number): number {
        return a + b;
    }
}

3.7.3 处理异步方法

@Injectable()
class Service {
    @Interceptor((args: any[], obj: any, targetFn: Function, done: Function) => {
        Promise.resolve(targetFn.apply(obj, args))
            .then(result => done(null, result))
            .catch(err => done(err, null));
    })
    async asyncMethod(value: string): Promise<string> {
        return new Promise(resolve => {
            setTimeout(() => resolve(`async_${value}`), 100);
        });
    }
}

3.7.4 错误处理

@Injectable()
class Service {
    @Interceptor((args: any[], obj: any, targetFn: Function, done: Function) => {
        try {
            const result = targetFn.apply(obj, args);
            done(null, result);
        } catch (error) {
            // 捕获并处理错误
            done(new Error(`Intercepted error: ${error}`), null);
        }
    })
    throwError(): void {
        throw new Error("Original error");
    }
}

3.7.5 与参数校验配合使用

import { Injectable, Inject, Provider, Interceptor, ParamValidate } from "dp-ioc";
import Joi from "joi";

@Injectable()
class Service {
    @Interceptor((args: any[], obj: any, targetFn: Function, done: Function) => {
        // 拦截器在参数校验之后执行
        const result = targetFn.apply(obj, args);
        done(null, result);
    })
    test(@ParamValidate(undefined, Joi.string().min(3).required()) value: string): string {
        return value;
    }
}

注意

  • 拦截器不能与 Before 和 After 同时使用,否则会抛出错误
  • 拦截器在参数校验之后执行
  • 拦截器可以完全控制方法的执行流程
  • done 回调函数:第一个参数是错误(如果有),第二个参数是结果

四、支持

如果在使用过程中,遇到问题,请到github仓库反馈,仓库地址