Add featureFlag gateDecorator for sync-metadata (#2956)

* Add featureFlag gateDecorator for sync-metadata

* remove gate exampels

* gate messaging objects

* gate messaging recipient object

* add missing gate
This commit is contained in:
Weiko
2023-12-12 17:34:59 +01:00
committed by GitHub
parent 6977fd4ce2
commit f126bd95d6
15 changed files with 201 additions and 77 deletions
@@ -9,109 +9,156 @@ export class MetadataParser {
metadata: typeof BaseObjectMetadata,
workspaceId: string,
dataSourceId: string,
) {
workspaceFeatureFlagsMap: Record<string, boolean>,
): ObjectMetadataEntity | undefined {
const objectMetadata = Reflect.getMetadata('objectMetadata', metadata);
const fieldMetadata = Reflect.getMetadata('fieldMetadata', metadata);
if (objectMetadata) {
const fields = Object.values(fieldMetadata);
return {
...objectMetadata,
workspaceId,
dataSourceId,
fields: fields.map((field: FieldMetadataEntity) => ({
...field,
workspaceId,
isSystem: objectMetadata.isSystem || field.isSystem,
defaultValue: field.defaultValue || null,
options: field.options || null,
})),
};
if (!objectMetadata) {
throw new Error(
`Object metadata decorator not found, can\'t parse ${metadata.name}`,
);
}
return undefined;
if (isGatedAndNotEnabled(objectMetadata, workspaceFeatureFlagsMap)) {
return undefined;
}
const fields = Object.values(fieldMetadata).filter(
(field) => !isGatedAndNotEnabled(field, workspaceFeatureFlagsMap),
);
return {
...objectMetadata,
workspaceId,
dataSourceId,
fields: fields.map((field: FieldMetadataEntity) => ({
...field,
workspaceId,
isSystem: objectMetadata.isSystem || field.isSystem,
defaultValue: field.defaultValue || null,
options: field.options || null,
})),
};
}
static parseAllMetadata(
metadataCollection: (typeof BaseObjectMetadata)[],
workspaceId: string,
dataSourceId: string,
) {
return metadataCollection.map((metadata) =>
MetadataParser.parseMetadata(metadata, workspaceId, dataSourceId),
);
workspaceFeatureFlagsMap: Record<string, boolean>,
): ObjectMetadataEntity[] {
return metadataCollection
.map((metadata) =>
MetadataParser.parseMetadata(
metadata,
workspaceId,
dataSourceId,
workspaceFeatureFlagsMap,
),
)
.filter(
(metadata): metadata is ObjectMetadataEntity => metadata !== undefined,
);
}
static parseRelationMetadata(
metadata: typeof BaseObjectMetadata,
workspaceId: string,
objectMetadataFromDB: Record<string, ObjectMetadataEntity>,
workspaceFeatureFlagsMap: Record<string, boolean>,
) {
const objectMetadata = Reflect.getMetadata('objectMetadata', metadata);
const relationMetadata = Reflect.getMetadata('relationMetadata', metadata);
if (!relationMetadata) return [];
return relationMetadata.map((relation) => {
const fromObjectMetadata =
objectMetadataFromDB[relation.fromObjectNameSingular];
assert(
fromObjectMetadata,
`Object ${relation.fromObjectNameSingular} not found in DB
for relation defined in class ${objectMetadata.nameSingular}`,
if (!objectMetadata) {
throw new Error(
`Object metadata decorator not found, can\'t parse ${metadata.name}`,
);
}
const toObjectMetadata =
objectMetadataFromDB[relation.toObjectNameSingular];
if (isGatedAndNotEnabled(objectMetadata, workspaceFeatureFlagsMap)) {
return [];
}
assert(
toObjectMetadata,
`Object ${relation.toObjectNameSingular} not found in DB
for relation defined in class ${objectMetadata.nameSingular}`,
);
return relationMetadata
.filter(
(relation) => !isGatedAndNotEnabled(relation, workspaceFeatureFlagsMap),
)
.map((relation) => {
const fromObjectMetadata =
objectMetadataFromDB[relation.fromObjectNameSingular];
const fromFieldMetadata =
fromObjectMetadata?.fields[relation.fromFieldMetadataName];
assert(
fromObjectMetadata,
`Object ${relation.fromObjectNameSingular} not found in DB
for fromRelation defined in class ${objectMetadata.nameSingular}`,
);
assert(
fromFieldMetadata,
`Field ${relation.fromFieldMetadataName} not found in object ${relation.fromObjectNameSingular}
for relation defined in class ${objectMetadata.nameSingular}`,
);
const toObjectMetadata =
objectMetadataFromDB[relation.toObjectNameSingular];
const toFieldMetadata =
toObjectMetadata?.fields[relation.toFieldMetadataName];
assert(
toObjectMetadata,
`Object ${relation.toObjectNameSingular} not found in DB
for toRelation defined in class ${objectMetadata.nameSingular}`,
);
assert(
toFieldMetadata,
`Field ${relation.toFieldMetadataName} not found in object ${relation.toObjectNameSingular}
for relation defined in class ${objectMetadata.nameSingular}`,
);
const fromFieldMetadata =
fromObjectMetadata?.fields[relation.fromFieldMetadataName];
return {
relationType: relation.type,
fromObjectMetadataId: fromObjectMetadata?.id,
toObjectMetadataId: toObjectMetadata?.id,
fromFieldMetadataId: fromFieldMetadata?.id,
toFieldMetadataId: toFieldMetadata?.id,
workspaceId,
};
});
assert(
fromFieldMetadata,
`Field ${relation.fromFieldMetadataName} not found in object ${relation.fromObjectNameSingular}
for fromRelation defined in class ${objectMetadata.nameSingular}`,
);
const toFieldMetadata =
toObjectMetadata?.fields[relation.toFieldMetadataName];
assert(
toFieldMetadata,
`Field ${relation.toFieldMetadataName} not found in object ${relation.toObjectNameSingular}
for toRelation defined in class ${objectMetadata.nameSingular}`,
);
return {
relationType: relation.type,
fromObjectMetadataId: fromObjectMetadata?.id,
toObjectMetadataId: toObjectMetadata?.id,
fromFieldMetadataId: fromFieldMetadata?.id,
toFieldMetadataId: toFieldMetadata?.id,
workspaceId,
};
});
}
static parseAllRelations(
metadataCollection: (typeof BaseObjectMetadata)[],
workspaceId: string,
objectMetadataFromDB: Record<string, ObjectMetadataEntity>,
workspaceFeatureFlagsMap: Record<string, boolean>,
) {
return metadataCollection.flatMap((metadata) =>
MetadataParser.parseRelationMetadata(
metadata,
workspaceId,
objectMetadataFromDB,
workspaceFeatureFlagsMap,
),
);
}
}
function isGatedAndNotEnabled(
metadata,
workspaceFeatureFlagsMap: Record<string, boolean>,
): boolean {
const featureFlagValue =
metadata.gate?.featureFlag &&
workspaceFeatureFlagsMap[metadata.gate.featureFlag];
return metadata.gate?.featureFlag !== undefined && !featureFlagValue;
}