mirror of
https://github.com/chartdb/chartdb.git
synced 2025-10-23 07:11:56 +00:00
export clone (diagram & table) logic (#401)
This commit is contained in:
149
src/lib/clone.ts
Normal file
149
src/lib/clone.ts
Normal 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(),
|
||||
};
|
||||
};
|
@@ -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(),
|
||||
});
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user