Add a dedicated GQL server for metadata available on /meta (#1820)

This commit is contained in:
Weiko
2023-10-03 10:17:13 +02:00
committed by GitHub
parent 37475f7c1b
commit 1e91c985df
56 changed files with 105 additions and 44 deletions

View File

@ -0,0 +1,33 @@
import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
} from 'typeorm';
export type TenantMigrationColumnChange = {
name: string;
type: string;
change: 'create' | 'alter';
};
export type TenantMigrationTableChange = {
name: string;
change: 'create' | 'alter';
columns?: TenantMigrationColumnChange[];
};
@Entity('tenant_migrations')
export class TenantMigration {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ nullable: true, type: 'jsonb' })
migrations: TenantMigrationTableChange[];
@Column({ nullable: true, name: 'applied_at' })
appliedAt: Date;
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
}

View File

@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { DataSourceModule } from 'src/metadata/data-source/data-source.module';
import { TenantMigrationService } from './tenant-migration.service';
@Module({
imports: [DataSourceModule],
exports: [TenantMigrationService],
providers: [TenantMigrationService],
})
export class TenantMigrationModule {}

View File

@ -0,0 +1,27 @@
import { Test, TestingModule } from '@nestjs/testing';
import { DataSourceService } from 'src/metadata/data-source/data-source.service';
import { TenantMigrationService } from './tenant-migration.service';
describe('TenantMigrationService', () => {
let service: TenantMigrationService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
TenantMigrationService,
{
provide: DataSourceService,
useValue: {},
},
],
}).compile();
service = module.get<TenantMigrationService>(TenantMigrationService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -0,0 +1,92 @@
import { Injectable } from '@nestjs/common';
import { IsNull } from 'typeorm';
import { DataSourceService } from 'src/metadata/data-source/data-source.service';
import {
TenantMigration,
TenantMigrationTableChange,
} from './tenant-migration.entity';
@Injectable()
export class TenantMigrationService {
constructor(private readonly dataSourceService: DataSourceService) {}
/**
* Get all pending migrations for a given workspaceId
*
* @param workspaceId: string
* @returns Promise<TenantMigration[]>
*/
public async getPendingMigrations(
workspaceId: string,
): Promise<TenantMigration[]> {
const workspaceDataSource =
await this.dataSourceService.connectToWorkspaceDataSource(workspaceId);
if (!workspaceDataSource) {
throw new Error('Workspace data source not found');
}
const tenantMigrationRepository =
workspaceDataSource.getRepository(TenantMigration);
return tenantMigrationRepository.find({
order: { createdAt: 'ASC' },
where: { appliedAt: IsNull() },
});
}
/**
* Set appliedAt as current date for a given migration.
* Should be called once the migration has been applied
*
* @param workspaceId: string
* @param migration: TenantMigration
*/
public async setAppliedAtForMigration(
workspaceId: string,
migration: TenantMigration,
) {
const workspaceDataSource =
await this.dataSourceService.connectToWorkspaceDataSource(workspaceId);
if (!workspaceDataSource) {
throw new Error('Workspace data source not found');
}
const tenantMigrationRepository =
workspaceDataSource.getRepository(TenantMigration);
await tenantMigrationRepository.save({
id: migration.id,
appliedAt: new Date(),
});
}
/**
* Create a new pending migration for a given workspaceId and expected changes
*
* @param workspaceId
* @param migrations
*/
public async createMigration(
workspaceId: string,
migrations: TenantMigrationTableChange[],
) {
const workspaceDataSource =
await this.dataSourceService.connectToWorkspaceDataSource(workspaceId);
if (!workspaceDataSource) {
throw new Error('Workspace data source not found');
}
const tenantMigrationRepository =
workspaceDataSource.getRepository(TenantMigration);
await tenantMigrationRepository.save({
migrations,
});
}
}