Files
bigcapital/packages/server/src/services/Tenancy/TenancyService.ts
2024-07-25 18:46:24 +02:00

138 lines
3.6 KiB
TypeScript

import { Container, Service, Inject } from 'typedi';
import TenantsManagerService from '@/services/Tenancy/TenantsManager';
import tenantModelsLoader from '@/loaders/tenantModels';
import tenantRepositoriesLoader from '@/loaders/tenantRepositories';
import tenantCacheLoader from '@/loaders/tenantCache';
import SmsClientLoader from '@/loaders/smsClient';
@Service()
export default class HasTenancyService {
@Inject()
tenantsManager: TenantsManagerService;
/**
* Retrieve the given tenant container.
* @param {number} tenantId
* @return {Container}
*/
tenantContainer(tenantId: number) {
return Container.of(`tenant-${tenantId}`);
}
/**
* Singleton tenant service.
* @param {number} tenantId - Tenant id.
* @param {string} key - Service key.
* @param {Function} callback
*/
singletonService(tenantId: number, key: string, callback: Function) {
const container = this.tenantContainer(tenantId);
const Logger = Container.get('logger');
const hasServiceInstnace = container.has(key);
if (!hasServiceInstnace) {
const serviceInstance = callback();
container.set(key, serviceInstance);
Logger.info(`[tenant_DI] ${key} injected to tenant container.`, {
tenantId,
key,
});
return serviceInstance;
} else {
return container.get(key);
}
}
/**
* Retrieve knex instance of the given tenant id.
* @param {number} tenantId
*/
knex(tenantId: number) {
return this.singletonService(tenantId, 'tenantManager', () => {
return this.tenantsManager.getKnexInstance(tenantId);
});
}
/**
* Retrieve models of the givne tenant id.
* @param {number} tenantId - The tenant id.
*/
models(tenantId: number) {
const knexInstance = this.knex(tenantId);
return this.singletonService(tenantId, 'models', () => {
return tenantModelsLoader(knexInstance);
});
}
/**
* Retrieve repositories of the given tenant id.
* @param {number} tenantId - Tenant id.
*/
repositories(tenantId: number) {
return this.singletonService(tenantId, 'repositories', () => {
const cache = this.cache(tenantId);
const knex = this.knex(tenantId);
const i18n = this.i18n(tenantId);
const repositories = tenantRepositoriesLoader(knex, cache, i18n);
Object.values(repositories).forEach((repository) => {
repository.setTenantId(tenantId);
});
return repositories;
});
}
/**
* Sets i18n locals function.
* @param {number} tenantId
* @param locals
*/
setI18nLocals(tenantId: number, locals: any) {
return this.singletonService(tenantId, 'i18n', () => {
return locals;
});
}
/**
* Retrieve i18n locales methods.
* @param {number} tenantId - Tenant id.
*/
i18n(tenantId: number) {
return this.singletonService(tenantId, 'i18n', () => {
throw new Error('I18n locals is not set yet.');
});
}
/**
* Retrieve tenant cache instance.
* @param {number} tenantId - Tenant id.
*/
cache(tenantId: number) {
return this.singletonService(tenantId, 'cache', () => {
return tenantCacheLoader(tenantId);
});
}
settings(tenantId: number) {
return this.singletonService(tenantId, 'settings', () => {
throw new Error('Settings is not injected yet.');
});
}
smsClient(tenantId: number) {
return this.singletonService(tenantId, 'smsClient', () => {
const settings = this.settings(tenantId);
const token = settings.get({
group: 'sms_integration',
key: 'easysms_token',
});
return SmsClientLoader(token);
});
}
}