Add Tenant initialisation service (#2100)

* Add Tenant initialisation service

* few fixes

* fix constraint

* fix tests

* update metadata json with employees and address

* add V2

* remove metadata.gql
This commit is contained in:
Weiko
2023-10-18 18:01:52 +02:00
committed by GitHub
parent 1cd91e60fa
commit 7fbef6d60d
37 changed files with 513 additions and 177 deletions

View File

@ -0,0 +1,55 @@
{
"nameSingular": "companyV2",
"namePlural": "companiesV2",
"labelSingular": "Company",
"labelPlural": "Companies",
"targetTableName": "company",
"description": "A company",
"icon": "business",
"fields": [
{
"type": "text",
"name": "name",
"label": "Name",
"targetColumnMap": {
"value": "name"
},
"description": "Name of the company",
"icon": null,
"isNullable": false
},
{
"type": "text",
"name": "domainName",
"label": "Domain Name",
"targetColumnMap": {
"value": "domainName"
},
"description": "Domain name of the company",
"icon": "url",
"isNullable": true
},
{
"type": "text",
"name": "address",
"label": "Address",
"targetColumnMap": {
"value": "address"
},
"description": "Address of the company",
"icon": "location",
"isNullable": true
},
{
"type": "number",
"name": "employees",
"label": "Employees",
"targetColumnMap": {
"value": "employees"
},
"description": "Number of employees",
"icon": "people",
"isNullable": true
}
]
}

View File

@ -0,0 +1,5 @@
import companyObject from './companies.metadata.json';
export const standardObjectsMetadata = {
companyV2: companyObject,
};

View File

@ -0,0 +1,24 @@
import { Module } from '@nestjs/common';
import { DataSourceModule } from 'src/metadata/data-source/data-source.module';
import { MigrationRunnerModule } from 'src/metadata/migration-runner/migration-runner.module';
import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module';
import { FieldMetadataModule } from 'src/metadata/field-metadata/field-metadata.module';
import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module';
import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data-source-metadata.module';
import { TenantInitialisationService } from './tenant-initialisation.service';
@Module({
imports: [
DataSourceModule,
TenantMigrationModule,
MigrationRunnerModule,
ObjectMetadataModule,
FieldMetadataModule,
DataSourceMetadataModule,
],
exports: [TenantInitialisationService],
providers: [TenantInitialisationService],
})
export class TenantInitialisationModule {}

View File

@ -0,0 +1,93 @@
import { Injectable } from '@nestjs/common';
import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service';
import { MigrationRunnerService } from 'src/metadata/migration-runner/migration-runner.service';
import { DataSourceService } from 'src/metadata/data-source/data-source.service';
import { FieldMetadataService } from 'src/metadata/field-metadata/services/field-metadata.service';
import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service';
import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service';
import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity';
import { ObjectMetadata } from 'src/metadata/object-metadata/object-metadata.entity';
import { standardObjectsMetadata } from './standard-objects/standard-object-metadata';
@Injectable()
export class TenantInitialisationService {
constructor(
private readonly dataSourceService: DataSourceService,
private readonly tenantMigrationService: TenantMigrationService,
private readonly migrationRunnerService: MigrationRunnerService,
private readonly objectMetadataService: ObjectMetadataService,
private readonly fieldMetadataService: FieldMetadataService,
private readonly dataSourceMetadataService: DataSourceMetadataService,
) {}
/**
* Init a workspace by creating a new data source and running all migrations
* @param workspaceId
* @returns Promise<void>
*/
public async init(workspaceId: string): Promise<void> {
const schemaName = await this.dataSourceService.createWorkspaceSchema(
workspaceId,
);
const dataSourceMetadata =
await this.dataSourceMetadataService.createDataSourceMetadata(
workspaceId,
schemaName,
);
await this.tenantMigrationService.insertStandardMigrations(workspaceId);
// Todo: keep in mind that we don't handle concurrency issues such as migrations being created at the same time
// but it shouldn't be the role of this service to handle this kind of issues for now.
// To check later when we run this in a job.
await this.migrationRunnerService.executeMigrationFromPendingMigrations(
workspaceId,
);
await this.createObjectsAndFieldsMetadata(
dataSourceMetadata.id,
workspaceId,
);
}
/**
*
* Create all standard objects and fields metadata for a given workspace
*
* @param dataSourceMetadataId
* @param workspaceId
*/
private async createObjectsAndFieldsMetadata(
dataSourceMetadataId: string,
workspaceId: string,
) {
const createdObjectMetadata = await this.objectMetadataService.createMany(
Object.values(standardObjectsMetadata).map((objectMetadata) => ({
...objectMetadata,
dataSourceId: dataSourceMetadataId,
fields: [],
workspaceId,
isCustom: false,
isActive: true,
})),
);
await this.fieldMetadataService.createMany(
createdObjectMetadata.flatMap((objectMetadata: ObjectMetadata) =>
standardObjectsMetadata[objectMetadata.nameSingular].fields.map(
(field: FieldMetadata) => ({
...field,
objectId: objectMetadata.id,
dataSourceId: dataSourceMetadataId,
workspaceId,
isCustom: false,
isActive: true,
}),
),
),
);
}
}