Wondering what’s next for npm?Check out our public roadmap! »

@ts-ioc/core
TypeScript icon, indicating that this package has built-in type declarations

4.0.5 • Public • Published

packaged @ts-ioc/core

This repo is for distribution on npm. The source for this module is in the main repo.

@ts-ioc/core is AOP, Ioc container, via typescript decorator.

version 2+ of tsioc

builder

build: npm run build
 
//build with version:
npm run build -- --setvs=4.0.0-beta
 
//deploy: 
./deploy.cmd
//or
 npm run build -- --deploy=true
 

Install

 
npm install @ts-ioc/core
 
// in browser
npm install @ts-ioc/platform-browser
 
// in server
npm install @ts-ioc/platform-server

add extends modules

use aop

 
// install aop
npm install @ts-ioc/aop
 
 
import { AopModule } from '@ts-ioc/aop';
// in server
import { ContainerBuilder } from '@ts-ioc/platform-server'
// in browser
import { ContainerBuilder } from '@ts-ioc/platform-browser'
 
let builder = new ContainerBuilder();
 
let container = build.create();
 
container.use(AopModule);
 

use aop logs

// install aop logs
npm install @ts-ioc/logs
 
import { LogModule } from '@ts-ioc/logs';
// in server
import { ContainerBuilder } from '@ts-ioc/platform-server'
// in browser
import { ContainerBuilder } from '@ts-ioc/platform-browser'
 
let builder = new ContainerBuilder();
 
let container = build.create();
 
container.use(LogModule);
 

Documentation

class name First char must be UpperCase.

Ioc

  1. Register one class will auto register depdence class (must has a class decorator).

  2. get Instance can auto create constructor param. (must has a class decorator or register in container).

Has decorators

  1. @Abstract abstract class decorator.
  2. @AutoRun class, method decorator, use to define the class auto run (via a method or not) after registered.
  3. @AutoWried property or param decorator, use to auto wried type instance or value to the instance of one class with the decorator.
  4. @Component class decortator, use to define the class. it can setting provider to some token, singleton or not. it will execute ComponentLifecycle hooks when create a instance .
  5. @Inject property or param decorator, use to auto wried type instance or value to the instance of one class with the decorator.
  6. @Injectable class decortator, use to define the class. it can setting provider to some token, singleton or not.
  7. @IocExt class decortator, use to define the class is Ioc extends module. it will auto run after registered to helper your to setup module.
  8. @Method method decorator.
  9. @Param param decorator, use to auto wried type instance or value to the instance of one class with the decorator.
  10. @Singleton class decortator, use to define the class is singleton.
  11. @Providers Providers decorator, for class. use to add private ref service for the class.
  12. @Refs Refs decorator, for class. use to define the class as a service for target.

AOP

It's a dynamic aop base on ioc.

define a Aspect class, must with decorator:

  • @Aspect Aspect decorator, define for class. use to define class as aspect. it can setting provider to some token, singleton or not.

  • @Before(matchstring|RegExp) method decorator, aop Before advice decorator.

  • @After(matchstring|RegExp) method decorator, aop after advice decorator.

  • @Around(matchstring|RegExp) method decorator, aop around advice decorator.

  • @AfterThrowing(matchstring|RegExp) method decorator, aop AfterThrowing advice decorator.

  • @AfterReturning(matchstring|RegExp) method decorator, aop AfterReturning advice decorator.

  • @Pointcut(matchstring|RegExp) method decorator, aop Pointcut advice decorator.

see simples

DIModule and boot

DI Module manager, application bootstrap. base on AOP.

  • @DIModule DIModule decorator, use to define class as DI Module.
  • @Annotation Annotation decorator, use to define class build metadata config.

see activity build boot simple

mvc boot simple

 
import { DIModule, ApplicationBuilder } from '@ts-ioc/bootstrap';
 
 
export class TestService {
    testFiled = 'test';
    test() {
        console.log('test');
    }
}
 
@DIModule({
    providers: [
        { provide: 'mark', useFactory: () => 'marked' },
        TestService
    ],
    exports: [
 
    ]
})
export class ModuleA {
 
}
 
@Injectable
export class ClassSevice {
    @Inject('mark')
    mark: string;
    state: string;
    start() {
        console.log(this.mark);
    }
}
 
@Aspect
export class Logger {
 
    @Around('execution(*.start)')
    log() {
        console.log('start........');
    }
}
 
 
@DIModule({
    imports: [
        AopModule,
        Logger,
        ModuleA
    ],
    exports: [
        ClassSevice
    ],
    bootstrap: ClassSevice
})
export class ModuleB {
 
}
 
ApplicationBuilder.create(__dirname)
    .bootstrap(ModuleB)

Activites

create Container

let builder = new ContainerBuilder();
 
// 1. via create.
let container = builder.create();
 
// 2. via build.
//with BuildOptions to auto register module.
let container = await builder.build({
  files: [__dirname +'/controller/**/*.ts', __dirname + '/*.model.js'],
  moudles:['node-modules-name', ClassType]
});
 
// 3. via syncBuild
let container = builder.syncBuild({
  moudles:['node-modules-name', ClassType]
});
 

init & register Container

see interface IContainer

// 1.  you can load modules by self
await builder.loadModule(container, {
  files: [__dirname +'/controller/**/*.ts', __dirname + '/*.model.js'],
  moudles:['node-modules-name', ClassType]
});
// 2. load sync
builder.syncLoadModule(container, {
  moudles:['node-modules-name', ClassType]
});
 
// 3. use modules
container.use(...modules);
 
// 4. register a class
container.register(Person);
 
// 5. register a factory;
container.register(Person, (container)=> {
    ...
    return new Person(...);
});
 
// 6. register with keyword
container.register('keyword', Perosn);
 
// 8. register with alais
container.register(new Registration(Person, aliasname));
 

get instance of type

// 8. get instance use get method of container.
    /**
     * resolve type instance with token and param provider.
     *
     * @template T
     * @param {Token<T>} token 
     * @param {...ProviderTypes[]} providers 
     * @returns {T} 
     * @memberof IResolver
     */
    resolve<T>(tokenToken<T>, ...providersProviderTypes[])T;
    /**
     * Retrieves an instance from the container based on the provided token.
     *
     * @template T
     * @param {Token<T>} token 
     * @param {string} [alias] 
     * @param {...ProviderTypes[]} providers 
     * @returns {T} 
     * @memberof IContainer
     */
    get<T>(tokenToken<T>, alias?: string, ...providersProviderTypes[])T;
 
    /**
     * resolve token value in this container only.
     *
     * @template T
     * @param {Token<T>} token 
     * @param {...ProviderTypes[]} providers 
     * @returns {T} 
     * @memberof IContainer
     */
    resolveValue<T>(tokenToken<T>, ...providersProviderTypes[])T;
 
    /**
     * get service or target reference service.
     *
     * @template T
     * @param {Token<T>} token servive token.
     * @param {...ProviderTypes[]} providers 
     * @returns {T} 
     * @memberof IContainer
     */
    getService<T>(tokenToken<T>, ...providersProviderTypes[])T;
 
    /**
     * get service or target reference service.
     *
     * @template T
     * @param {Token<T>} token servive token.
     * @param {(Token<any> | Token<any>[])} [target] service refrence target.
     * @param {...ProviderTypes[]} providers 
     * @returns {T} 
     * @memberof IContainer
     */
    getService<T>(tokenToken<T>, targetToken<any> | Token<any>[], ...providersProviderTypes[])T;
 
    /**
     * get service or target reference service.
     *
     * @template T
     * @param {Token<T>} token servive token.
     * @param {(Token<any> | Token<any>[])} [target] service refrence target.
     * @param {RefTokenFac<T>} toRefToken 
     * @param {...ProviderTypes[]} providers 
     * @returns {T} 
     * @memberof IContainer
     */
    getService<T>(tokenToken<T>, targetToken<any> | Token<any>[], toRefTokenRefTokenFac<T>, ...providersProviderTypes[])T;
 
    /**
     * get service or target reference service.
     *
     * @template T
     * @param {Token<T>} token servive token.
     * @param {(Token<any> | Token<any>[])} [target] service refrence target.
     * @param {(boolean | Token<T>)} defaultToken
     * @param {...ProviderTypes[]} providers 
     * @returns {T} 
     * @memberof IContainer
     */
    getService<T>(tokenToken<T>, targetToken<any> | Token<any>[], defaultTokenboolean | Token<T>, ...providersProviderTypes[])T;
 
    /**
     * get service or target reference service.
     *
     * @template T
     * @param {Token<T>} token servive token.
     * @param {(Token<any> | Token<any>[])} [target] service refrence target.
     * @param {RefTokenFac<T>} toRefToken 
     * @param {(boolean | Token<T>)} defaultToken
     * @param {...ProviderTypes[]} providers 
     * @returns {T} 
     * @memberof IContainer
     */
    getService<T>(tokenToken<T>, targetToken<any> | Token<any>[], toRefTokenRefTokenFac<T>, defaultTokenboolean | Token<T>, ...providersProviderTypes[])T;
 
    /**
     * get target reference service.
     *
     * @template T
     * @param {ReferenceToken<T>} [refToken] reference service Registration Injector
     * @param {(Token<any> | Token<any>[])} target  the service reference to.
     * @param {Token<T>} [defaultToken] default service token.
     * @param {...ProviderTypes[]} providers 
     * @returns {T} 
     * @memberof IContainer
     */
    getRefService<T>(refTokenReferenceToken<T>, targetToken<any> | Token<any>[], defaultToken?: Token<T>, ...providersProviderTypes[])T
 
 
//get simple person
let person = container.get(Person);
//get colloge person
let person = container.get(Person, 'Colloge');
 
// resolve with providers
container.resolve(Person, ...providers);
 

Invoke method

you can use yourself MethodAccessor by implement IMethodAccessor, register MethodAccessorToken with your MethodAccessor in container, see interface IMethodAccessor.

 
@Injectable
class Person {
    constructor() {
 
    }
    say() {
        return 'I love you.'
    }
}
 
@Injectable
class Child extends Person {
    constructor() {
        super();
    }
    say() {
        return 'Mama';
    }
}
 
class MethodTest {
    constructor() {
 
    }
 
    @Method
    sayHello(person: Person) {
        return person.say();
    }
}
 
class MethodTest2 {
    constructor() {
 
    }
 
    @Method()
    sayHello( @Inject(Child) person: Person) {
        return person.say();
    }
}
 
class MethodTest3 {
    constructor() {
 
    }
 
    @Method
    sayHello( @Inject(Child) personA: Person, personB: Person) {
        return personA.say() + ''  + personB.say();
    }
}
 
@Injectable
class Geet {
    constructor(private name: string){
 
    }
 
    print(hi?:string){
        return `${hi}, from ${this.name}`;
    }
}
 
container.register(Geet);
 
container.invoke(Geet, 'print', null,
{hi: 'How are you.', name:'zhou' },
{ hi: (container: IContainer)=> 'How are you.' }, ... },
{ hi:{type: Token<any>, value: any |(container: IContainer)=>any }},
Provider.createParam('name', 'zhou'),
Provider.create('hi', value:'Hello'),
// or use ProviderMap.
...
)
 
container.resolve(Geet,
{name: 'zhou' },
{ name: (container: IContainer)=>any } },
{name:{type: Token<any>, value: any|(container: IContainer)=>any }})
 
 
 
container.register(MethodTest);
container.invoke(MethodTest, 'sayHello')
    .then(data =>{
        console.log(data);
    });
 
container.register(MethodTest2);
container.invoke(MethodTest2, 'sayHello')
    .then(data =>{
        console.log(data);
    });
 
container.register(MethodTest3);
container.invoke(MethodTest3, 'sayHello')
    .then(data =>{
        console.log(data);
    });
 
 
 
 

Use Demo

 
import { Method, ContainerBuilder, AutoWired, Injectable, Singleton, IContainer, ParameterMetadata, Param, Aspect } from '@ts-ioc/core';
 
 
export class SimppleAutoWried {
    constructor() {
    }
 
    @AutoWired
    dateProperty: Date;
}
 
@Singleton
export class Person {
    name = 'testor';
}
// > v0.3.5 all class decorator can depdence.
@Singleton
// @Injectable
export class RoomService {
    constructor() {
 
    }
    @AutoWired
    current: Date;
}
 
@Injectable()
export class ClassRoom {
    constructor(public service: RoomService) {
 
    }
}
 
export abstract class Student {
    constructor() {
    }
    abstract sayHi(): string;
}
 
@Injectable({ provide: Student })
export class MiddleSchoolStudent extends Student {
    constructor() {
        super();
    }
    sayHi() {
        return 'I am a middle school student';
    }
}
 
@Injectable()
export class MClassRoom {
    @AutoWired(MiddleSchoolStudent)
    leader: Student;
    constructor() {
 
    }
}
 
 
@Injectable({ provide: Student, alias: 'college' })
export class CollegeStudent extends Student {
    constructor() {
        super();
    }
    sayHi() {
        return 'I am a college student';
    }
}
 
@Injectable
export class CollegeClassRoom {
    constructor(
        @Param(CollegeStudent)
        @AutoWired(CollegeStudent)
        public leader: Student) {
 
    }
}
 
 
@Injectable
export class InjMClassRoom {
    // @Inject(MiddleSchoolStudent)
    @Inject
    // @Inject({ type: MiddleSchoolStudent })
    // @Inject({ provider: MiddleSchoolStudent })
    leader: Student;
    constructor() {
 
    }
}
 
 
export interface IClassRoom {
    leader: Student;
}
 
@Injectable
export class InjCollegeClassRoom {
    constructor(
        // all below decorator can work, also @AutoWired, @Param is.
        // @Inject(new Registration(Student, 'college')) // need CollegeStudent also register.
        @Inject(CollegeStudent)
        // @Inject({ provider: CollegeStudent })
        // @Inject({ provider: Student, alias: 'college' }) //need CollegeStudent also register.
        // @Inject({ type: CollegeStudent })
        public leader: Student
    ) {
 
    }
}
 
@Injectable
export class InjCollegeAliasClassRoom {
    constructor(
        // all below decorator can work, also @AutoWired, @Param is.
        @Inject(new Registration(Student, 'college')) // need CollegeStudent also register.
        // @Inject(CollegeStudent)
        // @Inject({ provider: CollegeStudent })
        // @Inject({ provider: Student, alias: 'college' }) // need CollegeStudent also register.
        // @Inject({ type: CollegeStudent })
        public leader: Student
    ) {
 
    }
}
 
 
@Injectable('StringClassRoom')
export class StingMClassRoom {
    // @Inject(MiddleSchoolStudent)
    @Inject
    // @Inject({ type: MiddleSchoolStudent })
    leader: Student;
    constructor() {
 
    }
}
 
export class StringIdTest {
    constructor(@Inject('StringClassRoom') public room: IClassRoom) {
 
    }
}
 
export const CollClassRoom = Symbol('CollegeClassRoom');
 
@Injectable(CollClassRoom)
export class SymbolCollegeClassRoom {
 
    @Inject(CollegeStudent)
    leader: Student;
    constructor() {
 
    }
}
 
export class SymbolIdest {
    @Inject(CollClassRoom)
    public room: IClassRoom
    constructor() {
 
    }
}
 
@Injectable
class MethodTestPerson {
    say() {
        return 'hello word.'
    }
}
 
class MethodTest {
 
    @Method
    sayHello(person: MethodTestPerson) {
        return person.say();
    }
}
 
 
// 1. Custom register one class will auto inject depdence class (must has a class decorator).
 
let builder = new ContainerBuilder();
let container = builder.create();
 
 
container.register(MethodTest);
container.invoke(MethodTest, 'sayHello')
    .then(data =>{
        console.log(data);
    });
 
container.register(SimppleAutoWried);
let instance = container.get(SimppleAutoWried);
console.log(instance.dateProperty);
 
 
container.register(ClassRoom);
let room = container.get(ClassRoom);
console.log(room.service.current);
 
container.register(MiddleSchoolStudent);
container.register(CollegeStudent);
 
let student = container.get(Student);
console.log(student.sayHi());
 
let student2 = container.get(new Registration(Student, 'college'));
 
console.log(student2.sayHi());
 
let student3 = container.get(Student, 'college'));
 
console.log(student3.sayHi());
 
 
builder.build({
    files: __dirname + '/*{.ts,.js}'
})
    .then(container => {
        let instance = container.get(Student);
        console.log(instance.sayHi());
 
        let instance2 = container.get(new Registration(Student, 'college'));
        console.log(instance2.sayHi());
 
        let instance3 = container.get(Student, 'college');
        console.log(instance3.sayHi())
    });
 
 
 

Extend decorator

see interface LifeScope You can extend yourself decorator via:

  1. createClassDecorator
/**
 * create class decorator
 *
 * @export
 * @template T metadata type.
 * @param {string} name decorator name.
 * @param {MetadataAdapter} [adapter]  metadata adapter
 * @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
 * @returns {*} 
 */
export function createClassDecorator<T extends ClassMetadata>(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends<T>): IClassDecorator<T>
  1. createClassMethodDecorator
/**
 * create method decorator.
 *
 * @export
 * @template T metadata type.
 * @param {string} name decorator name.
 * @param {MetadataAdapter} [adapter]  metadata adapter
 * @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
 * @returns
 */
export function createMethodDecorator<T extends MethodMetadata>
  1. createClassMethodDecorator
/**
 * create decorator for class and method.
 *
 * @export
 * @template T
 * @param {string} name 
 * @param {MetadataAdapter} [adapter]  metadata adapter
 * @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
 * @returns {IClassMethodDecorator<T>} 
 */
export function createClassMethodDecorator<T extends TypeMetadata>(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends<T>): IClassMethodDecorator<T>
  1. createParamDecorator
/**
 * create parameter decorator.
 *
 * @export
 * @template T metadata type.
 * @param {string} name decorator name.
 * @param {MetadataAdapter} [adapter]  metadata adapter
 * @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
 * @returns
 */
export function createParamDecorator<T extends ParameterMetadata>
 
  1. createPropDecorator
/**
 * create property decorator.
 *
 * @export
 * @template T metadata type.
 * @param {string} name decorator name.
 * @param {MetadataAdapter} [adapter]  metadata adapter
 * @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
 * @returns
 */
export function createPropDecorator<T extends PropertyMetadata>(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends<T>): IPropertyDecorator<T>
  1. createParamPropDecorator
/**
 * create parameter or property decorator
 *
 * @export
 * @template T
 * @param {string} name 
 * @param {MetadataAdapter} [adapter]  metadata adapter
 * @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
 * @returns {IParamPropDecorator<T>} 
 */
export function createParamPropDecorator<T extends ParamPropMetadata>(
    name: string,
    adapter?: MetadataAdapter,
    metadataExtends?: MetadataExtends<T>): IParamPropDecorator<T>
  1. createDecorator
/**
 * create dectorator for class params props methods.
 *
 * @export
 * @template T
 * @param {string} name 
 * @param {MetadataAdapter} [adapter]  metadata adapter
 * @param {MetadataExtends<T>} [metadataExtends] add extents for metadata.
 * @returns {*} 
 */
export function createDecorator<T>(name: string, adapter?: MetadataAdapter, metadataExtends?: MetadataExtends<T>): any

Demo fo extends yourself decorator

 
//eg.
// 1. create decorator
export interface IControllerDecorator<T extends ControllerMetadata> extends IClassDecorator<T> {
    (routePrefix: string, provide?: Registration<any> | string, alias?: string): ClassDecorator;
    (target: Function): void;
}
export const Controller: IControllerDecorator<ControllerMetadata> =
    createClassDecorator<ControllerMetadata>('Controller', (args: ArgsIterator) => {
        args.next<ControllerMetadata>({
            isMetadata: (arg) => isClassMetadata(arg, ['routePrefix']),
            match: (arg) => isString(arg),
            setMetadata: (metadata, arg) => {
                metadata.routePrefix = arg;
            }
        });
    }) as IControllerDecorator<ControllerMetadata>;
 
export const Aspect: IClassDecorator<ClassMetadata> = createClassDecorator<ClassMetadata>('Aspect', null, (metadata) => {
    metadata.singleton = true;
    return metadata;
});
 
 
// 2. add decorator action
 let lifeScope = container.get(LifeScopeToken);
 let factory = new AopActionFactory();
 lifeScope.addAction(factory.create(AopActions.registAspect), DecoratorType.Class, IocState.design);
 
 
// 3. register decorator
lifeScope.registerDecorator(Aspect, AopActions.registAspect);
 

Container Interface

see more interface. all document is typescript .d.ts.

Documentation is available on the @ts-ioc/core docs site.

License

MIT © Houjun

Install

npm i @ts-ioc/core

DownloadsWeekly Downloads

1

Version

4.0.5

License

MIT

Unpacked Size

4.39 MB

Total Files

590

Last publish

Collaborators

  • avatar