Add onDeleteAction to RelationMetadata (#4100)
* Add onDeleteAction to relationMetadata * rename to SET NULL * fix migration * fix migration * fix after review
This commit is contained in:
@ -48,6 +48,28 @@ describe('WorkspaceRelationComparator', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should generate UPDATE action for changed relations', () => {
|
||||
const original = [
|
||||
createMockRelationMetadata({ onDeleteAction: 'CASCADE' }),
|
||||
];
|
||||
const standard = [
|
||||
createMockRelationMetadata({ onDeleteAction: 'SET_NULL' }),
|
||||
];
|
||||
|
||||
const result = comparator.compare(original, standard);
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
action: ComparatorAction.UPDATE,
|
||||
object: expect.objectContaining({
|
||||
fromObjectMetadataId: 'object-1',
|
||||
fromFieldMetadataId: 'field-1',
|
||||
onDeleteAction: 'SET_NULL',
|
||||
}),
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not generate any action for identical relations', () => {
|
||||
const relation = createMockRelationMetadata({});
|
||||
const original = [{ id: '1', ...relation }];
|
||||
|
||||
@ -11,6 +11,7 @@ import { RelationMetadataEntity } from 'src/metadata/relation-metadata/relation-
|
||||
import { transformMetadataForComparison } from 'src/workspace/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util';
|
||||
|
||||
const relationPropertiesToIgnore = ['createdAt', 'updatedAt'] as const;
|
||||
const relationPropertiesToUpdate = ['onDeleteAction'];
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceRelationComparator {
|
||||
@ -51,19 +52,54 @@ export class WorkspaceRelationComparator {
|
||||
);
|
||||
|
||||
for (const difference of relationMetadataDifference) {
|
||||
if (difference.type === 'CREATE') {
|
||||
results.push({
|
||||
action: ComparatorAction.CREATE,
|
||||
object: difference.value,
|
||||
});
|
||||
} else if (
|
||||
difference.type === 'REMOVE' &&
|
||||
difference.path[difference.path.length - 1] !== 'id'
|
||||
) {
|
||||
results.push({
|
||||
action: ComparatorAction.DELETE,
|
||||
object: difference.oldValue,
|
||||
});
|
||||
switch (difference.type) {
|
||||
case 'CREATE':
|
||||
results.push({
|
||||
action: ComparatorAction.CREATE,
|
||||
object: difference.value,
|
||||
});
|
||||
break;
|
||||
case 'REMOVE':
|
||||
if (difference.path[difference.path.length - 1] !== 'id') {
|
||||
results.push({
|
||||
action: ComparatorAction.DELETE,
|
||||
object: difference.oldValue,
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'CHANGE':
|
||||
const fieldName = difference.path[0];
|
||||
const property = difference.path[difference.path.length - 1];
|
||||
|
||||
if (!relationPropertiesToUpdate.includes(property as string)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const originalRelationMetadata =
|
||||
originalRelationMetadataMap[fieldName];
|
||||
|
||||
if (!originalRelationMetadata) {
|
||||
throw new Error(
|
||||
`Relation ${fieldName} not found in originalRelationMetadataMap`,
|
||||
);
|
||||
}
|
||||
|
||||
results.push({
|
||||
action: ComparatorAction.UPDATE,
|
||||
object: {
|
||||
id: originalRelationMetadata.id,
|
||||
fromObjectMetadataId:
|
||||
originalRelationMetadata.fromObjectMetadataId,
|
||||
fromFieldMetadataId: originalRelationMetadata.fromFieldMetadataId,
|
||||
toObjectMetadataId: originalRelationMetadata.toObjectMetadataId,
|
||||
toFieldMetadataId: originalRelationMetadata.toFieldMetadataId,
|
||||
workspaceId: originalRelationMetadata.workspaceId,
|
||||
...{
|
||||
[property]: difference.value,
|
||||
},
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
import 'reflect-metadata';
|
||||
|
||||
import { RelationMetadataDecoratorParams } from 'src/workspace/workspace-sync-metadata/interfaces/reflect-relation-metadata.interface';
|
||||
import {
|
||||
ReflectRelationMetadata,
|
||||
RelationMetadataDecoratorParams,
|
||||
} from 'src/workspace/workspace-sync-metadata/interfaces/reflect-relation-metadata.interface';
|
||||
|
||||
import { TypedReflect } from 'src/utils/typed-reflect';
|
||||
import { convertClassNameToObjectMetadataName } from 'src/workspace/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util';
|
||||
import { RelationOnDeleteAction } from 'src/metadata/relation-metadata/relation-metadata.entity';
|
||||
|
||||
export function RelationMetadata(
|
||||
params: RelationMetadataDecoratorParams,
|
||||
@ -29,8 +33,9 @@ export function RelationMetadata(
|
||||
toObjectNameSingular: params.objectName,
|
||||
fromFieldMetadataName: fieldKey,
|
||||
toFieldMetadataName: params.inverseSideFieldName ?? objectName,
|
||||
onDelete: params.onDelete ?? RelationOnDeleteAction.SET_NULL,
|
||||
gate,
|
||||
},
|
||||
} satisfies ReflectRelationMetadata,
|
||||
],
|
||||
target.constructor,
|
||||
);
|
||||
|
||||
@ -110,6 +110,7 @@ export class StandardRelationFactory {
|
||||
fromFieldMetadataId: fromFieldMetadata?.id,
|
||||
toFieldMetadataId: toFieldMetadata?.id,
|
||||
workspaceId: context.workspaceId,
|
||||
onDeleteAction: relationMetadata.onDelete,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@ -43,4 +43,5 @@ export type FieldComparatorResult =
|
||||
|
||||
export type RelationComparatorResult =
|
||||
| ComparatorCreateResult<Partial<RelationMetadataEntity>>
|
||||
| ComparatorDeleteResult<RelationMetadataEntity>;
|
||||
| ComparatorDeleteResult<RelationMetadataEntity>
|
||||
| ComparatorUpdateResult<Partial<RelationMetadataEntity>>;
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
import { ReflectRelationMetadata } from 'src/workspace/workspace-sync-metadata/interfaces/reflect-Relation-metadata.interface';
|
||||
|
||||
export type PartialRelationMetadata = ReflectRelationMetadata & {
|
||||
id: string;
|
||||
workspaceId: string;
|
||||
fromObjectMetadataId: string;
|
||||
toObjectMetadataId: string;
|
||||
fromFieldMetadataId: string;
|
||||
toFieldMetadataId: string;
|
||||
};
|
||||
@ -1,11 +1,15 @@
|
||||
import { GateDecoratorParams } from 'src/workspace/workspace-sync-metadata/interfaces/gate-decorator.interface';
|
||||
|
||||
import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-metadata.entity';
|
||||
import {
|
||||
RelationOnDeleteAction,
|
||||
RelationMetadataType,
|
||||
} from 'src/metadata/relation-metadata/relation-metadata.entity';
|
||||
|
||||
export interface RelationMetadataDecoratorParams {
|
||||
type: RelationMetadataType;
|
||||
objectName: string;
|
||||
inverseSideFieldName?: string;
|
||||
onDelete?: RelationOnDeleteAction;
|
||||
}
|
||||
|
||||
export interface ReflectRelationMetadata {
|
||||
@ -15,4 +19,5 @@ export interface ReflectRelationMetadata {
|
||||
fromFieldMetadataName: string;
|
||||
toFieldMetadataName: string;
|
||||
gate?: GateDecoratorParams;
|
||||
onDelete: RelationOnDeleteAction;
|
||||
}
|
||||
|
||||
@ -209,6 +209,7 @@ export class WorkspaceMetadataUpdaterService {
|
||||
storage: WorkspaceSyncStorage,
|
||||
): Promise<{
|
||||
createdRelationMetadataCollection: RelationMetadataEntity[];
|
||||
updatedRelationMetadataCollection: RelationMetadataEntity[];
|
||||
}> {
|
||||
const relationMetadataRepository = manager.getRepository(
|
||||
RelationMetadataEntity,
|
||||
@ -223,6 +224,15 @@ export class WorkspaceMetadataUpdaterService {
|
||||
storage.relationMetadataCreateCollection,
|
||||
);
|
||||
|
||||
/**
|
||||
* Update relation metadata
|
||||
*/
|
||||
|
||||
const updatedRelationMetadataCollection =
|
||||
await relationMetadataRepository.save(
|
||||
storage.relationMetadataUpdateCollection,
|
||||
);
|
||||
|
||||
/**
|
||||
* Delete relation metadata
|
||||
*/
|
||||
@ -250,6 +260,7 @@ export class WorkspaceMetadataUpdaterService {
|
||||
|
||||
return {
|
||||
createdRelationMetadataCollection,
|
||||
updatedRelationMetadataCollection,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,6 +84,8 @@ export class WorkspaceSyncRelationMetadataService {
|
||||
for (const relationComparatorResult of relationComparatorResults) {
|
||||
if (relationComparatorResult.action === ComparatorAction.CREATE) {
|
||||
storage.addCreateRelationMetadata(relationComparatorResult.object);
|
||||
} else if (relationComparatorResult.action === ComparatorAction.UPDATE) {
|
||||
storage.addUpdateRelationMetadata(relationComparatorResult.object);
|
||||
} else if (relationComparatorResult.action === ComparatorAction.DELETE) {
|
||||
storage.addDeleteRelationMetadata(relationComparatorResult.object);
|
||||
}
|
||||
@ -103,6 +105,16 @@ export class WorkspaceSyncRelationMetadataService {
|
||||
WorkspaceMigrationBuilderAction.CREATE,
|
||||
);
|
||||
|
||||
return createRelationWorkspaceMigrations;
|
||||
const updateRelationWorkspaceMigrations =
|
||||
await this.workspaceMigrationRelationFactory.create(
|
||||
originalObjectMetadataCollection,
|
||||
metadataRelationUpdaterResult.updatedRelationMetadataCollection,
|
||||
WorkspaceMigrationBuilderAction.UPDATE,
|
||||
);
|
||||
|
||||
return [
|
||||
...createRelationWorkspaceMigrations,
|
||||
...updateRelationWorkspaceMigrations,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { PartialObjectMetadata } from 'src/workspace/workspace-sync-metadata/interfaces/partial-object-metadata.interface';
|
||||
import { PartialFieldMetadata } from 'src/workspace/workspace-sync-metadata/interfaces/partial-field-metadata.interface';
|
||||
import { PartialRelationMetadata } from 'src/workspace/workspace-sync-metadata/interfaces/partial-relation-metadata.interface';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/metadata/object-metadata/object-metadata.entity';
|
||||
import { FieldMetadataEntity } from 'src/metadata/field-metadata/field-metadata.entity';
|
||||
@ -25,6 +26,8 @@ export class WorkspaceSyncStorage {
|
||||
[];
|
||||
private readonly _relationMetadataDeleteCollection: RelationMetadataEntity[] =
|
||||
[];
|
||||
private readonly _relationMetadataUpdateCollection: Partial<PartialRelationMetadata>[] =
|
||||
[];
|
||||
|
||||
constructor() {}
|
||||
|
||||
@ -56,6 +59,10 @@ export class WorkspaceSyncStorage {
|
||||
return this._relationMetadataCreateCollection;
|
||||
}
|
||||
|
||||
get relationMetadataUpdateCollection() {
|
||||
return this._relationMetadataUpdateCollection;
|
||||
}
|
||||
|
||||
get relationMetadataDeleteCollection() {
|
||||
return this._relationMetadataDeleteCollection;
|
||||
}
|
||||
@ -90,6 +97,10 @@ export class WorkspaceSyncStorage {
|
||||
this._relationMetadataCreateCollection.push(relation);
|
||||
}
|
||||
|
||||
addUpdateRelationMetadata(relation: Partial<PartialRelationMetadata>) {
|
||||
this._relationMetadataUpdateCollection.push(relation);
|
||||
}
|
||||
|
||||
addDeleteRelationMetadata(relation: RelationMetadataEntity) {
|
||||
this._relationMetadataDeleteCollection.push(relation);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user