cherry-picked 2c38b85

handles references mapping with new associations
This commit is contained in:
arpitnath 2024-04-07 00:31:21 +05:30
parent 770e207af1
commit 7d8c2b9719
2 changed files with 116 additions and 9 deletions

View file

@ -0,0 +1,53 @@
export function updateEntityReferences(node, resourceMapping: Record<string, string> = {}) {
if (typeof node === 'object') {
for (const key in node) {
let value = node[key];
if (typeof value === 'string' && value.includes('{{') && value.includes('}}')) {
const referenceExists = value;
if (referenceExists) {
const ref = value.replace('{{', '').replace('}}', '');
const entityName = ref.split('.')[1];
if (resourceMapping[entityName]) {
const newValue = value.replace(entityName, resourceMapping[entityName]);
node[key] = newValue;
}
}
} else if (typeof value === 'object') {
value = updateEntityReferences(value, resourceMapping);
}
}
}
return node;
}
export function findAllEntityReferences(node, allRefs): [] {
if (typeof node === 'object') {
for (const key in node) {
const value = node[key];
if (typeof value === 'string' && value.includes('{{') && value.includes('}}')) {
const referenceExists = value;
if (referenceExists) {
const ref = value.replace('{{', '').replace('}}', '');
const entityName = ref.split('.')[1];
allRefs.push(entityName);
}
} else if (typeof value === 'object') {
findAllEntityReferences(value, allRefs);
}
}
}
return allRefs;
}
export function isValidUUID(uuid) {
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
return uuidRegex.test(uuid);
}

View file

@ -32,7 +32,7 @@ import { Component } from 'src/entities/component.entity';
import { Layout } from 'src/entities/layout.entity';
import { EventHandler, Target } from 'src/entities/event_handler.entity';
import { v4 as uuid } from 'uuid';
import { findAllEntityReferences, isValidUUID, updateEntityReferences } from 'src/helpers/import_export.helpers';
interface AppResourceMappings {
defaultDataSourceIdMapping: Record<string, string>;
dataQueryMapping: Record<string, string>;
@ -237,21 +237,19 @@ export class AppImportExportService {
? true
: isTooljetVersionWithNormalizedAppDefinitionSchem(importedAppTooljetVersion);
const shouldUpdateForGridCompatibility = !cloning;
const importedApp = await this.createImportedAppForUser(this.entityManager, schemaUnifiedAppParams, user);
await this.setupImportedAppAssociations(
const resourceMapping = await this.setupImportedAppAssociations(
this.entityManager,
importedApp,
schemaUnifiedAppParams,
user,
externalResourceMappings,
isNormalizedAppDefinitionSchema,
shouldUpdateForGridCompatibility,
tooljetVersion
);
await this.createAdminGroupPermissions(this.entityManager, importedApp);
await this.updateEntityReferencesForImportedApp(this.entityManager, resourceMapping);
// NOTE: App slug updation callback doesn't work while wrapped in transaction
// hence updating slug explicitly
@ -262,6 +260,64 @@ export class AppImportExportService {
return importedApp;
}
async updateEntityReferencesForImportedApp(manager: EntityManager, resourceMapping: AppResourceMappings) {
const mappings = { ...resourceMapping.componentsMapping, ...resourceMapping.dataQueryMapping };
const newComponentIds = Object.values(resourceMapping.componentsMapping);
const newQueriesIds = Object.values(resourceMapping.dataQueryMapping);
if (newComponentIds.length > 0) {
const components = await manager
.createQueryBuilder(Component, 'components')
.where('components.id IN(:...componentIds)', { componentIds: newComponentIds })
.select([
'components.id',
'components.properties',
'components.styles',
'components.general',
'components.validation',
'components.generalStyles',
'components.displayPreferences',
])
.getMany();
const toUpdateComponents = components.filter((component) => {
const entityReferencesInComponentDefinitions = findAllEntityReferences(component, []).filter(
(entity) => entity && isValidUUID(entity)
);
if (entityReferencesInComponentDefinitions.length > 0) {
return updateEntityReferences(component, mappings);
}
});
if (!isEmpty(toUpdateComponents)) {
await manager.save(toUpdateComponents);
}
}
if (newQueriesIds.length > 0) {
const dataQueries = await manager
.createQueryBuilder(DataQuery, 'dataQueries')
.where('dataQueries.id IN(:...dataQueryIds)', { dataQueryIds: newQueriesIds })
.select(['dataQueries.id', 'dataQueries.options'])
.getMany();
const toUpdateDataQueries = dataQueries.filter((dataQuery) => {
const entityReferencesInQueryOptions = findAllEntityReferences(dataQuery, []).filter(
(entity) => entity && isValidUUID(entity)
);
if (entityReferencesInQueryOptions.length > 0) {
return updateEntityReferences(dataQuery, mappings);
}
});
if (!isEmpty(toUpdateDataQueries)) {
await manager.save(toUpdateDataQueries);
}
}
}
async createImportedAppForUser(manager: EntityManager, appParams: any, user: User): Promise<App> {
return await catchDbException(async () => {
const importedApp = manager.create(App, {
@ -328,7 +384,6 @@ export class AppImportExportService {
user: User,
externalResourceMappings: Record<string, unknown>,
isNormalizedAppDefinitionSchema: boolean,
shouldUpdateForGridCompatibility: boolean,
tooljetVersion: string
) {
// Old version without app version
@ -393,7 +448,6 @@ export class AppImportExportService {
importingPages,
importingComponents,
importingEvents,
shouldUpdateForGridCompatibility,
tooljetVersion
);
@ -599,7 +653,6 @@ export class AppImportExportService {
importingPages: Page[],
importingComponents: Component[],
importingEvents: EventHandler[],
shouldUpdateForGridCompatibility: boolean,
tooljetVersion: string
): Promise<AppResourceMappings> {
appResourceMappings = { ...appResourceMappings };
@ -1656,9 +1709,10 @@ export class AppImportExportService {
.createQueryBuilder(EventHandler, 'event')
.where('event.appVersionId = :versionId', { versionId })
.getMany();
const mappings = { ...oldDataQueryToNewMapping, ...oldComponentToNewComponentMapping } as Record<string, string>;
for (const event of allEvents) {
const eventDefinition = event.event;
const eventDefinition = updateEntityReferences(event.event, mappings);
if (eventDefinition?.actionId === 'run-query' && oldDataQueryToNewMapping[eventDefinition.queryId]) {
eventDefinition.queryId = oldDataQueryToNewMapping[eventDefinition.queryId];