let lastTimestamp = 0; let sameTimestampSequence = 0; export interface DedupeEntityIdsResult { items: T[]; changed: boolean; } export function createEntityId(prefix: string, timestamp = Date.now()): string { if (timestamp === lastTimestamp) { sameTimestampSequence += 1; } else { lastTimestamp = timestamp; sameTimestampSequence = 0; } return `${prefix}-${timestamp}-${sameTimestampSequence.toString(36)}`; } export function dedupeEntityIds( items: T[], prefix: string, timestamp = Date.now(), ): DedupeEntityIdsResult { const seen = new Set(); let changed = false; const deduped = items.map((item) => { if (item.id && !seen.has(item.id)) { seen.add(item.id); return item; } changed = true; let nextId = createEntityId(prefix, timestamp); while (seen.has(nextId)) { nextId = createEntityId(prefix, timestamp); } seen.add(nextId); return { ...item, id: nextId }; }); return { items: changed ? deduped : items, changed }; }