Hi,
our API is built in such a way that all requests require to have a X-Tenant-Id header set, so we know how to instantiate repositories. All our repositories are set up in such a way:
@Injectable({ scope: Scope.REQUEST })
export class BaseRepository<T extends BaseTable> {
protected tableClass: { new (...args: any[]): T };
protected _repository: Repository<T>;
public constructor(
@Inject(DATA_SOURCE)
protected readonly dataSource: DataSource,
@Inject(TENANT_ID)
public readonly tenantId: string,
) {}
public get repository() {
if (!this._repository) {
this._repository = this.dataSource.getRepository(this.tableClass);
}
return this._repository;
}
public async findById(id: string) {
return this.repository.findOne({
where: {
id,
tenantId: this.tenantId,
},
});
}
}
We then have a provider that provides this TENANT_ID value using the following logic:
const tenantIdProvider = {
provide: TENANT_ID,
scope: Scope.REQUEST,
durable: true,
useFactory: (request: Request | { tenantId: string }) => {
return 'tenantId' in request
? request.tenantId
: (request.headers['x-tenant-id'] as string);
},
inject: [REQUEST],
};
This works great with HTTP methods, because we provide is a header.
Now we want to implement a module that listens to Redis events (example, or some other external source), and we want to provide the tenantId via other means, such as via the payload of a message.
How do we properly initialise whatever module we're using to provide this tenant ID via other means?
It feels like we need to be able to (optionally) inject another type of context, instead of the HTTP context, but I wouldn't know where to start.