mirror of
https://github.com/chartdb/chartdb.git
synced 2026-05-02 23:59:46 -05:00
256 lines
7.1 KiB
TypeScript
256 lines
7.1 KiB
TypeScript
import type { DBCustomType } from './domain';
|
|
import type { Area } from './domain/area';
|
|
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());
|
|
});
|
|
|
|
diagram.areas?.forEach((area) => {
|
|
idsMap.set(area.id, generateId());
|
|
});
|
|
|
|
diagram.customTypes?.forEach((customType) => {
|
|
idsMap.set(customType.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): string | null => {
|
|
const newId = idsMap.get(id);
|
|
if (!newId) {
|
|
return null;
|
|
}
|
|
return newId;
|
|
};
|
|
|
|
const tableId = getNewId(table.id);
|
|
if (!tableId) {
|
|
throw new Error('Table id not found');
|
|
}
|
|
|
|
const newTable: DBTable = { ...table, id: tableId };
|
|
newTable.fields = table.fields
|
|
.map((field): DBField | null => {
|
|
const id = getNewId(field.id);
|
|
|
|
if (!id) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
...field,
|
|
id,
|
|
};
|
|
})
|
|
.filter((field): field is DBField => field !== null);
|
|
newTable.indexes = table.indexes
|
|
.map((index): DBIndex | null => {
|
|
const id = getNewId(index.id);
|
|
|
|
if (!id) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
...index,
|
|
fieldIds: index.fieldIds
|
|
.map((id) => getNewId(id))
|
|
.filter((fieldId): fieldId is string => fieldId !== null),
|
|
id,
|
|
};
|
|
})
|
|
.filter((index): index is DBIndex => index !== null);
|
|
|
|
return newTable;
|
|
};
|
|
|
|
export const cloneDiagram = (
|
|
diagram: Diagram,
|
|
options: {
|
|
generateId: () => string;
|
|
} = {
|
|
generateId: defaultGenerateId,
|
|
}
|
|
): { diagram: Diagram; idsMap: Map<string, string> } => {
|
|
const { generateId } = options;
|
|
const diagramId = generateId();
|
|
|
|
const idsMap = generateIdsMapFromDiagram(diagram, generateId);
|
|
|
|
const getNewId = (id: string): string | null => {
|
|
const newId = idsMap.get(id);
|
|
if (!newId) {
|
|
return null;
|
|
}
|
|
return newId;
|
|
};
|
|
|
|
const tables: DBTable[] =
|
|
diagram.tables?.map((table) =>
|
|
cloneTable(table, { generateId, idsMap })
|
|
) ?? [];
|
|
|
|
const relationships: DBRelationship[] =
|
|
diagram.relationships
|
|
?.map((relationship): DBRelationship | null => {
|
|
const id = getNewId(relationship.id);
|
|
const sourceTableId = getNewId(relationship.sourceTableId);
|
|
const targetTableId = getNewId(relationship.targetTableId);
|
|
const sourceFieldId = getNewId(relationship.sourceFieldId);
|
|
const targetFieldId = getNewId(relationship.targetFieldId);
|
|
|
|
if (
|
|
!id ||
|
|
!sourceTableId ||
|
|
!targetTableId ||
|
|
!sourceFieldId ||
|
|
!targetFieldId
|
|
) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
...relationship,
|
|
id,
|
|
sourceTableId,
|
|
targetTableId,
|
|
sourceFieldId,
|
|
targetFieldId,
|
|
};
|
|
})
|
|
.filter(
|
|
(relationship): relationship is DBRelationship =>
|
|
relationship !== null
|
|
) ?? [];
|
|
|
|
const dependencies: DBDependency[] =
|
|
diagram.dependencies
|
|
?.map((dependency): DBDependency | null => {
|
|
const id = getNewId(dependency.id);
|
|
const dependentTableId = getNewId(dependency.dependentTableId);
|
|
const tableId = getNewId(dependency.tableId);
|
|
|
|
if (!id || !dependentTableId || !tableId) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
...dependency,
|
|
id,
|
|
dependentTableId,
|
|
tableId,
|
|
};
|
|
})
|
|
.filter(
|
|
(dependency): dependency is DBDependency => dependency !== null
|
|
) ?? [];
|
|
|
|
const areas: Area[] =
|
|
diagram.areas
|
|
?.map((area) => {
|
|
const id = getNewId(area.id);
|
|
if (!id) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
...area,
|
|
id,
|
|
} satisfies Area;
|
|
})
|
|
.filter((area): area is Area => area !== null) ?? [];
|
|
|
|
const customTypes: DBCustomType[] =
|
|
diagram.customTypes
|
|
?.map((customType) => {
|
|
const id = getNewId(customType.id);
|
|
if (!id) {
|
|
return null;
|
|
}
|
|
return {
|
|
...customType,
|
|
id,
|
|
} satisfies DBCustomType;
|
|
})
|
|
.filter(
|
|
(customType): customType is DBCustomType => customType !== null
|
|
) ?? [];
|
|
|
|
return {
|
|
diagram: {
|
|
...diagram,
|
|
id: diagramId,
|
|
dependencies,
|
|
relationships,
|
|
tables,
|
|
areas,
|
|
customTypes,
|
|
createdAt: diagram.createdAt
|
|
? new Date(diagram.createdAt)
|
|
: new Date(),
|
|
updatedAt: diagram.updatedAt
|
|
? new Date(diagram.updatedAt)
|
|
: new Date(),
|
|
},
|
|
idsMap,
|
|
};
|
|
};
|