Refactor tenant ORM integration (#1650)

* Refactor tenant ORM integration

* fix tests
This commit is contained in:
Weiko
2023-09-19 17:58:28 +02:00
committed by GitHub
parent 07684c4f08
commit ec90c77ec1
38 changed files with 747 additions and 531 deletions

View File

@ -0,0 +1,7 @@
export const baseColumns = {
id: {
primary: true,
type: 'uuid',
generated: 'uuid',
},
} as const;

View File

@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { ObjectMetadataModule } from 'src/tenant/metadata/object-metadata/object-metadata.module';
import { EntitySchemaGeneratorService } from './entity-schema-generator.service';
@Module({
imports: [ObjectMetadataModule],
providers: [EntitySchemaGeneratorService],
exports: [EntitySchemaGeneratorService],
})
export class EntitySchemaGeneratorModule {}

View File

@ -0,0 +1,29 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ObjectMetadataService } from 'src/tenant/metadata/object-metadata/object-metadata.service';
import { EntitySchemaGeneratorService } from './entity-schema-generator.service';
describe('EntitySchemaGeneratorService', () => {
let service: EntitySchemaGeneratorService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
EntitySchemaGeneratorService,
{
provide: ObjectMetadataService,
useValue: {},
},
],
}).compile();
service = module.get<EntitySchemaGeneratorService>(
EntitySchemaGeneratorService,
);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -0,0 +1,43 @@
import { Injectable } from '@nestjs/common';
import { EntitySchema } from 'typeorm';
import { ObjectMetadataService } from 'src/tenant/metadata/object-metadata/object-metadata.service';
import { baseColumns } from './base.entity';
import {
convertFieldTypeToPostgresType,
sanitizeColumnName,
} from './entity-schema-generator.util';
@Injectable()
export class EntitySchemaGeneratorService {
constructor(private readonly objectMetadataService: ObjectMetadataService) {}
async getTypeORMEntitiesByDataSourceId(dataSourceId: string) {
const objectMetadata =
await this.objectMetadataService.getObjectMetadataFromDataSourceId(
dataSourceId,
);
const entities = objectMetadata.map((object) => {
return new EntitySchema({
name: object.name,
columns: {
...baseColumns,
...object.fields.reduce((columns, field) => {
return {
...columns,
[sanitizeColumnName(field.name)]: {
type: convertFieldTypeToPostgresType(field.type),
nullable: true,
},
};
}, {}),
},
});
});
return entities;
}
}

View File

@ -0,0 +1,46 @@
/**
* Converts a UUID to a base 36 string.
* This is used to generate the schema name since hyphens from workspace uuid are not allowed in postgres schema names.
*
* @param uuid
* @returns
*/
export const uuidToBase36 = (uuid: string): string => {
const hexString = uuid.replace(/-/g, '');
const base10Number = BigInt('0x' + hexString);
const base36String = base10Number.toString(36);
return base36String;
};
/**
* Sanitizes a column name by replacing all non-alphanumeric characters with an underscore.
* Note: Probablay not the best way to do this, leaving it here as a placeholder for now.
*
* @param columnName
* @returns string
*/
export const sanitizeColumnName = (columnName: string): string =>
columnName.replace(/[^a-zA-Z0-9]/g, '_');
/**
* Converts a field type to a postgres type. Field types are defined in the UI.
*
* @param fieldType
* @returns string
*/
export const convertFieldTypeToPostgresType = (fieldType: string): string => {
switch (fieldType) {
case 'text':
return 'text';
case 'url':
return 'text';
case 'number':
return 'numeric';
case 'boolean':
return 'boolean';
case 'date':
return 'timestamp';
default:
return 'text';
}
};