fix: nested relations not working and relations not prefixed (#2782)

* fix: nested relations n+n

* fix: prefix custom relations

* fix: only apply targetColumnMap when it's a custom object

* fix: force workspaceId to be provided

* fix: toIsCustom -> isToCustom

* fix: remove console.log
This commit is contained in:
Jérémy M
2023-12-01 15:26:48 +01:00
committed by GitHub
parent 6e6f0af26e
commit 474db1e142
28 changed files with 226 additions and 131 deletions

View File

@ -7,7 +7,7 @@ import {
import { InjectRepository } from '@nestjs/typeorm';
import { v4 as uuidV4 } from 'uuid';
import { Repository } from 'typeorm';
import { FindOneOptions, Repository } from 'typeorm';
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
import { WorkspaceMigrationRunnerService } from 'src/workspace/workspace-migration-runner/workspace-migration-runner.service';
@ -47,8 +47,12 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
): Promise<FieldMetadataEntity> {
const objectMetadata =
await this.objectMetadataService.findOneWithinWorkspace(
record.objectMetadataId,
record.workspaceId,
{
where: {
id: record.objectMetadataId,
},
},
);
if (!objectMetadata) {
@ -156,8 +160,12 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
const objectMetadata =
await this.objectMetadataService.findOneWithinWorkspace(
existingFieldMetadata?.objectMetadataId,
record.workspaceId,
{
where: {
id: existingFieldMetadata?.objectMetadataId,
},
},
);
if (!objectMetadata) {
@ -200,11 +208,15 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
}
public async findOneWithinWorkspace(
fieldMetadataId: string,
workspaceId: string,
options: FindOneOptions<FieldMetadataEntity>,
) {
return this.fieldMetadataRepository.findOne({
where: { id: fieldMetadataId, workspaceId },
...options,
where: {
...options.where,
workspaceId,
},
});
}

View File

@ -27,10 +27,11 @@ export class BeforeDeleteOneField implements BeforeDeleteOneHook<any> {
}
const fieldMetadata =
await this.fieldMetadataService.findOneWithinWorkspace(
instance.id.toString(),
workspaceId,
);
await this.fieldMetadataService.findOneWithinWorkspace(workspaceId, {
where: {
id: instance.id.toString(),
},
});
if (!fieldMetadata) {
throw new BadRequestException('Field does not exist');

View File

@ -31,10 +31,11 @@ export class BeforeUpdateOneField<T extends UpdateFieldInput>
}
const fieldMetadata =
await this.fieldMetadataService.findOneWithinWorkspace(
instance.id.toString(),
workspaceId,
);
await this.fieldMetadataService.findOneWithinWorkspace(workspaceId, {
where: {
id: instance.id.toString(),
},
});
if (!fieldMetadata) {
throw new BadRequestException('Field does not exist');

View File

@ -16,6 +16,7 @@ export interface FieldMetadataInterface<
defaultValue?: FieldMetadataDefaultValue<T>;
options?: FieldMetadataOptions<T>;
objectMetadataId: string;
workspaceId?: string;
description?: string;
isNullable?: boolean;
fromRelationMetadata?: RelationMetadataEntity;

View File

@ -3,6 +3,7 @@ import { BadRequestException } from '@nestjs/common';
import { FieldMetadataTargetColumnMap } from 'src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface';
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity';
import { createCustomColumnName } from 'src/metadata/utils/create-custom-column-name.util';
/**
* Generate a target column map for a given type, this is used to map the field to the correct column(s) in the database.
@ -16,7 +17,9 @@ export function generateTargetColumnMap(
isCustomField: boolean,
fieldName: string,
): FieldMetadataTargetColumnMap {
const columnName = isCustomField ? `_${fieldName}` : fieldName;
const columnName = isCustomField
? createCustomColumnName(fieldName)
: fieldName;
switch (type) {
case FieldMetadataType.UUID:

View File

@ -26,10 +26,11 @@ export class BeforeDeleteOneObject implements BeforeDeleteOneHook<any> {
}
const objectMetadata =
await this.objectMetadataService.findOneWithinWorkspace(
instance.id.toString(),
workspaceId,
);
await this.objectMetadataService.findOneWithinWorkspace(workspaceId, {
where: {
id: instance.id.toString(),
},
});
if (!objectMetadata) {
throw new BadRequestException('Object does not exist');

View File

@ -39,10 +39,11 @@ export class BeforeUpdateOneObject<T extends UpdateObjectInput>
}
const objectMetadata =
await this.objectMetadataService.findOneWithinWorkspace(
instance.id.toString(),
workspaceId,
);
await this.objectMetadataService.findOneWithinWorkspace(workspaceId, {
where: {
id: instance.id.toString(),
},
});
if (!objectMetadata) {
throw new BadRequestException('Object does not exist');

View File

@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Equal, In, Repository } from 'typeorm';
import { FindManyOptions, FindOneOptions, Repository } from 'typeorm';
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
import { WorkspaceMigrationService } from 'src/metadata/workspace-migration/workspace-migration.service';
@ -21,6 +21,7 @@ import {
RelationMetadataEntity,
RelationMetadataType,
} from 'src/metadata/relation-metadata/relation-metadata.entity';
import { createCustomColumnName } from 'src/metadata/utils/create-custom-column-name.util';
import { ObjectMetadataEntity } from './object-metadata.entity';
@ -63,7 +64,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
const createdObjectMetadata = await super.createOne({
...record,
dataSourceId: lastDataSourceMetadata.id,
targetTableName: `_${record.nameSingular}`,
targetTableName: createCustomColumnName(record.nameSingular),
isActive: true,
isCustom: true,
isSystem: false,
@ -298,39 +299,39 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
return createdObjectMetadata;
}
public async getObjectMetadataFromWorkspaceId(workspaceId: string) {
return this.objectMetadataRepository.find({
where: { workspaceId },
public async findOneWithinWorkspace(
workspaceId: string,
options: FindOneOptions<ObjectMetadataEntity>,
): Promise<ObjectMetadataEntity | null> {
return this.objectMetadataRepository.findOne({
...options,
where: {
...options.where,
workspaceId,
},
relations: [
'fields',
'fields.fromRelationMetadata',
'fields.fromRelationMetadata.fromObjectMetadata',
'fields.fromRelationMetadata.toObjectMetadata',
'fields.fromRelationMetadata.toObjectMetadata.fields',
'fields.toRelationMetadata',
'fields.toRelationMetadata.fromObjectMetadata',
'fields.toRelationMetadata.fromObjectMetadata.fields',
'fields.toRelationMetadata.toObjectMetadata',
],
});
}
public async findOneWithinWorkspace(
objectMetadataId: string,
workspaceId: string,
) {
return this.objectMetadataRepository.findOne({
where: { id: objectMetadataId, workspaceId },
});
}
public async findManyWithinWorkspace(
objectMetadataIds: string[],
workspaceId: string,
options?: FindManyOptions<ObjectMetadataEntity>,
) {
return this.objectMetadataRepository.findBy({
id: In(objectMetadataIds),
workspaceId: Equal(workspaceId),
return this.objectMetadataRepository.find({
...options,
where: {
...options?.where,
workspaceId,
},
relations: [
'fields',
'fields.fromRelationMetadata',
'fields.toRelationMetadata',
],
});
}

View File

@ -26,10 +26,11 @@ export class BeforeDeleteOneRelation implements BeforeDeleteOneHook<any> {
}
const relationMetadata =
await this.relationMetadataService.findOneWithinWorkspace(
instance.id.toString(),
workspaceId,
);
await this.relationMetadataService.findOneWithinWorkspace(workspaceId, {
where: {
id: instance.id.toString(),
},
});
if (!relationMetadata) {
throw new BadRequestException('Relation does not exist');

View File

@ -6,7 +6,7 @@ import {
import { InjectRepository } from '@nestjs/typeorm';
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
import { Repository } from 'typeorm';
import { FindOneOptions, In, Repository } from 'typeorm';
import camelCase from 'lodash.camelcase';
import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service';
@ -16,6 +16,8 @@ import { WorkspaceMigrationRunnerService } from 'src/workspace/workspace-migrati
import { WorkspaceMigrationService } from 'src/metadata/workspace-migration/workspace-migration.service';
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity';
import { WorkspaceMigrationColumnActionType } from 'src/metadata/workspace-migration/workspace-migration.entity';
import { ObjectMetadataEntity } from 'src/metadata/object-metadata/object-metadata.entity';
import { createCustomColumnName } from 'src/metadata/utils/create-custom-column-name.util';
import {
RelationMetadataEntity,
@ -85,14 +87,18 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
const objectMetadataEntries =
await this.objectMetadataService.findManyWithinWorkspace(
[record.fromObjectMetadataId, record.toObjectMetadataId],
record.workspaceId,
{
where: {
id: In([record.fromObjectMetadataId, record.toObjectMetadataId]),
},
},
);
const objectMetadataMap = objectMetadataEntries.reduce((acc, curr) => {
acc[curr.id] = curr;
return acc;
}, {});
}, {} as { [key: string]: ObjectMetadataEntity });
if (
objectMetadataMap[record.fromObjectMetadataId] === undefined ||
@ -103,7 +109,11 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
);
}
const foreignKeyColumnName = `${camelCase(record.toName)}Id`;
const baseColumnName = `${camelCase(record.toName)}Id`;
const isToCustom = objectMetadataMap[record.toObjectMetadataId].isCustom;
const foreignKeyColumnName = isToCustom
? createCustomColumnName(baseColumnName)
: baseColumnName;
const createdFields = await this.fieldMetadataService.createMany([
// FROM
@ -126,7 +136,11 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
description: record.toDescription,
icon: record.toIcon,
isCustom: true,
targetColumnMap: {},
targetColumnMap: isToCustom
? {
value: createCustomColumnName(record.toName),
}
: {},
isActive: true,
type: FieldMetadataType.RELATION,
objectMetadataId: record.toObjectMetadataId,
@ -134,12 +148,14 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
},
// FOREIGN KEY
{
name: foreignKeyColumnName,
name: baseColumnName,
label: `${record.toLabel} Foreign Key`,
description: undefined,
description: `${record.toDescription} Foreign Key`,
icon: undefined,
isCustom: true,
targetColumnMap: {},
targetColumnMap: {
value: foreignKeyColumnName,
},
isActive: true,
// Should not be visible on the front side
isSystem: true,
@ -203,11 +219,15 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
}
public async findOneWithinWorkspace(
relationMetadataId: string,
workspaceId: string,
options: FindOneOptions<RelationMetadataEntity>,
) {
return this.relationMetadataRepository.findOne({
where: { id: relationMetadataId, workspaceId },
...options,
where: {
...options.where,
workspaceId,
},
relations: ['fromFieldMetadata', 'toFieldMetadata'],
});
}

View File

@ -0,0 +1,3 @@
export const createCustomColumnName = (name: string) => {
return `_${name}`;
};