How can i setup multitenant in NESTJS

爷,独闯天下 提交于 2019-12-06 11:07:19

We also have a Mulit-Tenancy Setup for our NestJS Setup.
You could have a middleware that decides, depending on the request, which datasource to use. In our example we are using TypeORM which has a pretty good integration in NestJS. There are some useful functions within the TypeORM package.

Middleware

export class AppModule {
  constructor(private readonly connection: Connection) {
  }

  configure(consumer: MiddlewareConsumer): void {
    consumer
      .apply(async (req, res, next) => {
        try {
          getConnection(tenant);
          next();
        } catch (e) {
          const tenantRepository = this.connection.getRepository(tenant);
          const tenant = await tenantRepository.findOne({ name: tenant });
          if (tenant) {
            const createdConnection: Connection = await createConnection(options);
            if (createdConnection) {
              next();
            } else {
              throw new CustomNotFoundException(
                'Database Connection Error',
                'There is a Error with the Database!',
              );
            }
          }
        }
      }).forRoutes('*');
   }

This is an example of our middleware. TypeORM is managing the connections internally. So the first thing you would try is to load the connection for that specific tenant. If there is one, good otherwise just create one. The good thing here is, that once created the connection stays available in the TypeORM connection manager. This way you always have a connection in the routes.
In your routes you need a identification for your tenants. In our case it is just a string which is extracted from the url. Whatever value it is you can bind it to the request object inside your middleware. In your controller you extract that value again and pass it to your services. Then you have to load the repository for your tenant and your good to go.

Service Class

@Injectable()
export class SampleService {

  constructor() {}

  async getTenantRepository(tenant: string): Promise<Repository<Entity>> {
    try {
      const connection: Connection = await getConnection(tenant);
      return connection.getRepository(Property);
    } catch (e) {
      throw new CustomInternalServerError('Internal Server Error', 'Internal Server Error');
    }
  }

  async findOne(params: Dto, tenant: string) {

    const entityRepository: Repository<Entity> = await this.getTenantRepository(tenant);

    return await propertyRepository.findOne({ where: params });

  }

That's what a service looks like in our application.

Hopefully this will inspire you and get you going with your problem :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!