Object metadata API create one using workspace migration v2 (#13420)
# Introduction In this PR we create basic transpilation methods and utils to handle input to flat, entity to flat, object maps to flat. In order to transpile everything into a common validation that will be implemented in another PR ## FieldMetadataEntity typing Added `never | null` to fields that should never be in order to ease general abstracted method to pass null, as anw it's what is in the database ## Todo - ~~Create a feature flag~~ - Integration test for object creation through metadata api + pg col introspection and snapshoting
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
import { FlatIndexFieldMetadata } from 'src/engine/workspace-manager/workspace-migration-v2/types/flat-index-field-metadata';
|
||||
|
||||
type FlatIndexFieldMetadataOverrides = Required<
|
||||
Pick<
|
||||
FlatIndexFieldMetadata,
|
||||
'fieldMetadataId' | 'indexMetadataId' | 'uniqueIdentifier'
|
||||
>
|
||||
> &
|
||||
Partial<FlatIndexFieldMetadata>;
|
||||
export const getFlatIndexFieldMetadataMock = (
|
||||
overrides: FlatIndexFieldMetadataOverrides,
|
||||
): FlatIndexFieldMetadata => {
|
||||
const createdAt = faker.date.anytime();
|
||||
|
||||
return {
|
||||
createdAt,
|
||||
id: faker.string.uuid(),
|
||||
order: faker.number.int(),
|
||||
updatedAt: createdAt,
|
||||
...overrides,
|
||||
};
|
||||
};
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
import { FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
|
||||
|
||||
type FlatIndexMetadataOverrides = Required<
|
||||
Pick<FlatIndexMetadata, 'uniqueIdentifier' | 'objectMetadataId'>
|
||||
> &
|
||||
Partial<FlatIndexMetadata>;
|
||||
export const getFlatIndexMetadataMock = (
|
||||
overrides: FlatIndexMetadataOverrides,
|
||||
): FlatIndexMetadata => {
|
||||
const createdAt = faker.date.anytime();
|
||||
|
||||
return {
|
||||
flatIndexFieldMetadatas: [],
|
||||
createdAt,
|
||||
id: faker.string.uuid(),
|
||||
indexType: IndexType.BTREE,
|
||||
indexWhereClause: undefined,
|
||||
isCustom: false,
|
||||
isUnique: false,
|
||||
name: 'defaultFlatIndexMetadataName',
|
||||
updatedAt: createdAt,
|
||||
workspaceId: faker.string.uuid(),
|
||||
...overrides,
|
||||
};
|
||||
};
|
||||
|
||||
export const getStandardFlatIndexMetadataMock = (
|
||||
overrides: Omit<FlatIndexMetadataOverrides, 'isCustom'>,
|
||||
) => {
|
||||
return getFlatIndexMetadataMock({
|
||||
isCustom: false,
|
||||
...overrides,
|
||||
});
|
||||
};
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { IndexFieldMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-field-metadata.entity';
|
||||
import { ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type';
|
||||
import { MetadataEntitiesRelationTarget } from 'src/engine/workspace-manager/workspace-migration-v2/types/metadata-entities-relation-targets.type';
|
||||
|
||||
type IndexFieldMetadataEntityRelationProperties =
|
||||
ExtractRecordTypeOrmRelationProperties<
|
||||
IndexFieldMetadataEntity,
|
||||
MetadataEntitiesRelationTarget
|
||||
>;
|
||||
|
||||
export type FlatIndexFieldMetadata = Partial<
|
||||
Omit<IndexFieldMetadataEntity, IndexFieldMetadataEntityRelationProperties>
|
||||
> & {
|
||||
uniqueIdentifier: string;
|
||||
};
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||
import { ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type';
|
||||
import { FlatIndexFieldMetadata } from 'src/engine/workspace-manager/workspace-migration-v2/types/flat-index-field-metadata';
|
||||
import { MetadataEntitiesRelationTarget } from 'src/engine/workspace-manager/workspace-migration-v2/types/metadata-entities-relation-targets.type';
|
||||
|
||||
type IndexMetadataRelationProperties = ExtractRecordTypeOrmRelationProperties<
|
||||
IndexMetadataEntity,
|
||||
MetadataEntitiesRelationTarget
|
||||
>;
|
||||
|
||||
export type FlatIndexMetadata = Partial<
|
||||
Omit<IndexMetadataEntity, IndexMetadataRelationProperties>
|
||||
> & {
|
||||
flatIndexFieldMetadatas: FlatIndexFieldMetadata[];
|
||||
uniqueIdentifier: string;
|
||||
};
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
import diff from 'microdiff';
|
||||
import { FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util';
|
||||
|
||||
const flatIndexMetadataPropertiesToCompare = [
|
||||
'flatIndexFieldMetadatas', // Comparing this as whole ? should iterate on each keys ? => TBD should only map over cols as before ?
|
||||
'indexType',
|
||||
'indexWhereClause',
|
||||
'isUnique',
|
||||
'name',
|
||||
] as const satisfies (keyof FlatIndexMetadata)[];
|
||||
|
||||
type FlatIndexMetadataPropertiesToCompare =
|
||||
(typeof flatIndexMetadataPropertiesToCompare)[number];
|
||||
|
||||
// Should also handle indexFieldMetadata comparison ?
|
||||
/**
|
||||
* This comparator handles update on colliding uniqueIdentifier flatIndexMetadata
|
||||
*/
|
||||
export const compareTwoFlatIndexMetadata = ({
|
||||
from,
|
||||
to,
|
||||
}: FromTo<FlatIndexMetadata>) => {
|
||||
const transformOptions = {
|
||||
shouldIgnoreProperty: (property: string) =>
|
||||
!flatIndexMetadataPropertiesToCompare.includes(
|
||||
property as FlatIndexMetadataPropertiesToCompare,
|
||||
),
|
||||
};
|
||||
|
||||
const fromCompare = transformMetadataForComparison(from, transformOptions);
|
||||
const toCompare = transformMetadataForComparison(to, transformOptions);
|
||||
|
||||
const flatIndexeDifferences = diff(fromCompare, toCompare);
|
||||
|
||||
return flatIndexeDifferences.flatMap<{ property: string } & FromTo<unknown>>(
|
||||
(difference) => {
|
||||
switch (difference.type) {
|
||||
case 'CHANGE': {
|
||||
const { oldValue, path, value } = difference;
|
||||
|
||||
const property = path[0];
|
||||
|
||||
if (typeof property === 'number') {
|
||||
return [];
|
||||
}
|
||||
|
||||
return {
|
||||
from: oldValue,
|
||||
property,
|
||||
to: value,
|
||||
};
|
||||
}
|
||||
case 'CREATE':
|
||||
case 'REMOVE':
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user