export clone (diagram & table) logic (#401)

This commit is contained in:
Guy Ben-Aharon
2024-11-14 15:11:21 +02:00
committed by GitHub
parent 9f8500fc7e
commit 9698821828
4 changed files with 156 additions and 98 deletions

149
src/lib/clone.ts Normal file
View File

@@ -0,0 +1,149 @@
import type { DBDependency } from './domain/db-dependency';
import type { DBField } from './domain/db-field';
import type { DBIndex } from './domain/db-index';
import type { DBRelationship } from './domain/db-relationship';
import type { DBTable } from './domain/db-table';
import type { Diagram } from './domain/diagram';
import { generateId as defaultGenerateId } from './utils';
const generateIdsMapFromTable = (
table: DBTable,
generateId: () => string = defaultGenerateId
): Map<string, string> => {
const idsMap = new Map<string, string>();
idsMap.set(table.id, generateId());
table.fields.forEach((field) => {
idsMap.set(field.id, generateId());
});
table.indexes.forEach((index) => {
idsMap.set(index.id, generateId());
});
return idsMap;
};
const generateIdsMapFromDiagram = (
diagram: Diagram,
generateId: () => string = defaultGenerateId
): Map<string, string> => {
let idsMap = new Map<string, string>();
diagram.tables?.forEach((table) => {
const tableIdsMap = generateIdsMapFromTable(table, generateId);
idsMap = new Map([...idsMap, ...tableIdsMap]);
});
diagram.relationships?.forEach((relationship) => {
idsMap.set(relationship.id, generateId());
});
diagram.dependencies?.forEach((dependency) => {
idsMap.set(dependency.id, generateId());
});
return idsMap;
};
export const cloneTable = (
table: DBTable,
options: {
generateId: () => string;
idsMap: Map<string, string>;
} = {
generateId: defaultGenerateId,
idsMap: new Map<string, string>(),
}
): DBTable => {
const { generateId } = options;
const idsMap = new Map([
...generateIdsMapFromTable(table, generateId),
...options.idsMap,
]);
const getNewId = (id: string) => {
const newId = idsMap.get(id);
if (!newId) {
throw new Error(`Id not found for ${id}`);
}
return newId;
};
const newTable: DBTable = { ...table, id: getNewId(table.id) };
newTable.fields = table.fields.map(
(field): DBField => ({
...field,
id: getNewId(field.id),
})
);
newTable.indexes = table.indexes.map(
(index): DBIndex => ({
...index,
fieldIds: index.fieldIds.map((id) => getNewId(id)),
id: getNewId(index.id),
})
);
return newTable;
};
export const cloneDiagram = (
diagram: Diagram,
options: {
generateId: () => string;
} = {
generateId: defaultGenerateId,
}
): Diagram => {
const { generateId } = options;
const diagramId = generateId();
const idsMap = generateIdsMapFromDiagram(diagram, generateId);
const getNewId = (id: string) => {
const newId = idsMap.get(id);
if (!newId) {
throw new Error(`Id not found for ${id}`);
}
return newId;
};
const tables: DBTable[] =
diagram.tables?.map((table) =>
cloneTable(table, { generateId, idsMap })
) ?? [];
const relationships: DBRelationship[] =
diagram.relationships?.map(
(relationship): DBRelationship => ({
...relationship,
id: getNewId(relationship.id),
sourceTableId: getNewId(relationship.sourceTableId),
targetTableId: getNewId(relationship.targetTableId),
sourceFieldId: getNewId(relationship.sourceFieldId),
targetFieldId: getNewId(relationship.targetFieldId),
})
) ?? [];
const dependencies: DBDependency[] =
diagram.dependencies?.map(
(dependency): DBDependency => ({
...dependency,
id: getNewId(dependency.id),
dependentTableId: getNewId(dependency.dependentTableId),
tableId: getNewId(dependency.tableId),
})
) ?? [];
return {
...diagram,
id: diagramId,
dependencies,
relationships,
tables,
createdAt: new Date(),
updatedAt: new Date(),
};
};

View File

@@ -1,5 +1,6 @@
import { cloneDiagram } from './clone';
import { diagramSchema, type Diagram } from './domain/diagram';
import { cloneDiagram, generateDiagramId, generateId } from './utils';
import { generateDiagramId } from './utils';
export const runningIdGenerator = (): (() => string) => {
let id = 0;
@@ -7,10 +8,10 @@ export const runningIdGenerator = (): (() => string) => {
};
const cloneDiagramWithRunningIds = (diagram: Diagram) =>
cloneDiagram(diagram, runningIdGenerator());
cloneDiagram(diagram, { generateId: runningIdGenerator() });
const cloneDiagramWithIds = (diagram: Diagram): Diagram => ({
...cloneDiagram(diagram, generateId),
...cloneDiagram(diagram),
id: generateDiagramId(),
});

View File

@@ -1,12 +1,6 @@
import { type ClassValue, clsx } from 'clsx';
import { customAlphabet } from 'nanoid';
import { twMerge } from 'tailwind-merge';
import type { Diagram } from './domain/diagram';
import type { DBTable } from './domain/db-table';
import type { DBField } from './domain/db-field';
import type { DBIndex } from './domain/db-index';
import type { DBRelationship } from './domain/db-relationship';
import type { DBDependency } from './domain/db-dependency';
const randomId = customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', 25);
const UUID_KEY = 'uuid';
@@ -95,93 +89,6 @@ export const waitFor = async (ms: number): Promise<void> => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
export const cloneDiagram = (
diagram: Diagram,
generateId: () => string
): Diagram => {
const diagramId = generateId();
const idsMap = new Map<string, string>();
diagram.tables?.forEach((table) => {
idsMap.set(table.id, generateId());
table.fields.forEach((field) => {
idsMap.set(field.id, generateId());
});
table.indexes.forEach((index) => {
idsMap.set(index.id, generateId());
});
});
diagram.relationships?.forEach((relationship) => {
idsMap.set(relationship.id, generateId());
});
diagram.dependencies?.forEach((dependency) => {
idsMap.set(dependency.id, generateId());
});
const getNewId = (id: string) => {
const newId = idsMap.get(id);
if (!newId) {
throw new Error(`Id not found for ${id}`);
}
return newId;
};
const tables: DBTable[] =
diagram.tables?.map((table) => {
const newTable: DBTable = { ...table, id: getNewId(table.id) };
newTable.fields = table.fields.map(
(field): DBField => ({
...field,
id: getNewId(field.id),
})
);
newTable.indexes = table.indexes.map(
(index): DBIndex => ({
...index,
fieldIds: index.fieldIds.map((id) => getNewId(id)),
id: getNewId(index.id),
})
);
return newTable;
}) ?? [];
const relationships: DBRelationship[] =
diagram.relationships?.map(
(relationship): DBRelationship => ({
...relationship,
id: getNewId(relationship.id),
sourceTableId: getNewId(relationship.sourceTableId),
targetTableId: getNewId(relationship.targetTableId),
sourceFieldId: getNewId(relationship.sourceFieldId),
targetFieldId: getNewId(relationship.targetFieldId),
})
) ?? [];
const dependencies: DBDependency[] =
diagram.dependencies?.map(
(dependency): DBDependency => ({
...dependency,
id: getNewId(dependency.id),
dependentTableId: getNewId(dependency.dependentTableId),
tableId: getNewId(dependency.tableId),
})
) ?? [];
return {
...diagram,
id: diagramId,
dependencies,
relationships,
tables,
createdAt: new Date(),
updatedAt: new Date(),
};
};
export const sha256 = async (message: string): Promise<string> => {
const msgBuffer = new TextEncoder().encode(message);

View File

@@ -1,11 +1,12 @@
import type { Diagram } from '@/lib/domain/diagram';
import type { Template } from './templates-data';
import { cloneDiagram, generateId, removeDups } from '@/lib/utils';
import { removeDups } from '@/lib/utils';
import { cloneDiagram } from '@/lib/clone';
export const convertTemplateToNewDiagram = (template: Template): Diagram => {
const diagramId = template.diagram.id;
const clonedDiagram = cloneDiagram(template.diagram, generateId);
const clonedDiagram = cloneDiagram(template.diagram);
return {
...template.diagram,