@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

    Install

    npm i @ts-ioc/core

    DownloadsWeekly Downloads

    87

    Version

    4.0.5

    License

    MIT

    Unpacked Size

    4.39 MB

    Total Files

    590

    Last publish

    Collaborators

    • houjun