@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>(token: Token<T>, ...providers: ProviderTypes[]): 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>(token: Token<T>, alias?: string, ...providers: ProviderTypes[]): T;

    /**
     * resolve token value in this container only.
     *
     * @template T
     * @param {Token<T>} token
     * @param {...ProviderTypes[]} providers
     * @returns {T}
     * @memberof IContainer
     */
    resolveValue<T>(token: Token<T>, ...providers: ProviderTypes[]): T;

    /**
     * get service or target reference service.
     *
     * @template T
     * @param {Token<T>} token servive token.
     * @param {...ProviderTypes[]} providers
     * @returns {T}
     * @memberof IContainer
     */
    getService<T>(token: Token<T>, ...providers: ProviderTypes[]): 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>(token: Token<T>, target: Token<any> | Token<any>[], ...providers: ProviderTypes[]): 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>(token: Token<T>, target: Token<any> | Token<any>[], toRefToken: RefTokenFac<T>, ...providers: ProviderTypes[]): 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>(token: Token<T>, target: Token<any> | Token<any>[], defaultToken: boolean | Token<T>, ...providers: ProviderTypes[]): 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>(token: Token<T>, target: Token<any> | Token<any>[], toRefToken: RefTokenFac<T>, defaultToken: boolean | Token<T>, ...providers: ProviderTypes[]): 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>(refToken: ReferenceToken<T>, target: Token<any> | Token<any>[], defaultToken?: Token<T>, ...providers: ProviderTypes[]): 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

Package Sidebar

Install

npm i @ts-ioc/core

Weekly Downloads

0

Version

4.0.5

License

MIT

Unpacked Size

4.39 MB

Total Files

590

Last publish

Collaborators

  • houjun