Skip to content
Romain Lenzotti edited this page Jun 25, 2020 · 46 revisions

How to create a new Ts.ED package

  • Fork the project + yarn install
  • Create a new directory named my-package in packages directory.
  • Copy package.json from typeorm and change the name field by @tsed/my-package change also the description, keywords, etc... Add contributors field with your name
  • Add your required dependencies in the new package and run yarn install on root
  • Copy tsconfig.compile.json from typeorm
  • Copy Readme and change usage and installation description
  • Add src directory
  • In src add index.ts and create a module file. Example: for typeorm, it's TypeORMModule.ts
  • Export all required class, decorators, service, etc... in the index.js

Note: Decorators can be generated with the cli. Just run the cli inside your packages/my-package.

Module example

import {PlatformApplication, OnDestroy, OnInit} from "@tsed/common";
import {Module, Inject, Constant} from "@tsed/di";
import {MyService} from "./services/MyService";

@Module({
  imports: [MyService] // prebuild MyService. Use this field to build services before the module.
})
export class MyModule implements OnInit, OnDestroy {
  @Inject()
  app: PlatformApplication;
  
  @Constant("myConfig", {})
  settings: any;

  @Inject()
  myService: MyService;

  async $onInit(): Promise<any> {
    console.log("Init")
  }

  $onDestroy(): Promise<any> | void {
     console.log("Destroy");
  }
}

How to create a new Type of provider

It might be useful to create a new kind of provider to declare some class with a specify provider type. By using this type you can querying in the registry all provider which match with the expected type!

Create a new directory registries in your Ts.ED package and copy this example (here is an example from passport package):

/**
 *
 * @type {Registry<Provider<any>, IProvider<any>>}
 */
import {GlobalProviders, Provider, TypedProvidersRegistry} from "@tsed/common";

export const PROVIDER_TYPE_PROTOCOL = "protocol";
/**
 *
 * @type {Registry<Provider<any>, IProvider<any>>}
 */
// tslint:disable-next-line: variable-name
export const ProtocolRegistry: TypedProvidersRegistry = GlobalProviders.createRegistry(PROVIDER_TYPE_PROTOCOL, Provider, {
  injectable: true // tell DI that all classes registered in this registry can be injected to another class
});
/**
 * Add a new service in the `ProviderRegistry`. This service will be built when `InjectorService` will be loaded.
 *
 * #### Example
 *
 * ```typescript
 * import {registerSocketService, InjectorService} from "@tsed/common";
 *
 * export default class MyFooService {
 *     constructor(){}
 *     getFoo() {
 *         return "test";
 *     }
 * }
 *
 * registerProtocol({provide: MyFooService});
 * // or
 * registerProtocol(MyFooService);
 *
 * const injector = new InjectorService();
 * injector.load();
 *
 * const myFooService = injector.get<MyFooService>(MyFooService);
 * myFooService.getFoo(); // test
 * ```
 *
 * @param provider Provider configuration.
 */
export const registerProtocol = GlobalProviders.createRegisterFn(PROVIDER_TYPE_PROTOCOL);

Now the registerProtocol is available and can be used anywere.

The next step is to declare a new class decorator (tsed g decorator):

import {registerProtocol} from "../registries/ProtocolRegistry";

export interface ProtocolOptions<T> {
  name: string;
  strategy: any;
  settings: T;
}
export class Protocol<T = any>(options: ProtocolOptions<T>): ClassDecorator {
  return (target: any) => {
     registerProtocol(target);
     Store.from(target).set("protocol", options); // save options
  }
}

Now in our module we can get all classes which use the @Protocol decorator:

import {nameOf} from "@tsed/core";
import {OnDestroy, OnInit} from "@tsed/common";
import {Module, InjectorService, Inject} from "@tsed/di";
import {PROVIDER_TYPE_PROTOCOL} from "./registries";

@Module({
  imports: []
})
export class PassportModule implements OnInit, OnDestroy {
  @Inject()
  injector: InjectorService;

  async $onInit(): Promise<any> {
    console.log("Init")
    
    this.getProcotols().forEach((provider) => {
       console.log("Class name:", nameOf(provider.instance));  
       console.log("Class options:", provider.store.get("protocol"));
    });  
    
  }

  $onDestroy(): Promise<any> | void {
     console.log("Destroy");
  }
   
  private getProtocols() {
     return Array.from(this.injector.getProviders(PROVIDER_TYPE_PROTOCOL))
  }
}

You can look the passport package codes to see more detail

Clone this wiki locally