Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { type Todo } from "./todo_item.ts"; ← from todo.item ^1.0.0 · built alongside by fune
/** Manual order: order ascending, ties by position in the array (a stable sort). */
function inManualOrder(todos: readonly Todo[], which: string): Todo[] {
const seen = new Set<string>();
for (const todo of todos) {
if (seen.has(todo.id)) throw new Error(`duplicate id "${todo.id}" in the ${which} list`);
seen.add(todo.id);
}
return [...todos].sort((a, b) => a.order - b.order);
}
/**
* Merge by id. A todo in both lists is taken from `incoming` (the newer
* copy: todo.item keeps no edit time to compare), in the place the current
* one had, because that is where the person put it. Todos only in `incoming`
* follow, in their own manual order. Todos only in `current` stay. The
* result is in manual order, renumbered 0 to n-1.
*/
export function mergeTodos(current: readonly Todo[], incoming: readonly Todo[]): readonly Todo[] {
const mine = inManualOrder(current, "current");
const theirs = inManualOrder(incoming, "incoming");
const byId = new Map(theirs.map((todo) => [todo.id, todo]));
const kept = new Set(mine.map((todo) => todo.id));
const merged = [...mine.map((todo) => byId.get(todo.id) ?? todo), ...theirs.filter((todo) => !kept.has(todo.id))];
return merged.map((todo, order) => ({ ...todo, order }));
}