feat(core): engagements, lists and copies with history restore

Engagements store partial dates as value + precision and track field_sources;
lists (list/grouping/thread, grouping-only rating/review) keep dense item
order and snapshot items in history; copies store price in cents. All three
restore through restoreVersion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-30 19:35:15 +01:00
1 parent 13b81b1cd5
commit c7471f7761
7 files changed
+1209

No files matched your search

+9
View File
@@ -3,8 +3,11 @@ import type { Db } from "@sttracker/db/db";
import { newId, nowIso } from "@sttracker/db/ids";
import { fromJson, toJson } from "@sttracker/db/json";
import type { Database } from "@sttracker/db/schema";
import { restoreCopyFromHistory } from "./copies.ts";
import { restoreEngagementFromHistory } from "./engagements.ts";
import { restoreEntryFromHistory } from "./entries.ts";
import { NotFoundError } from "./errors.ts";
import { restoreListFromHistory } from "./lists.ts";
/** Who made a change. Plugin actors are `plugin:<pluginId>:<connectionId>`; API tokens are `token:<name>`. */
export type Actor = "user" | `plugin:${string}:${string}` | `token:${string}`;
@@ -108,6 +111,12 @@ export async function restoreVersion(db: Db, userId: string, historyId: string):
switch (h.entity as HistoryEntity) {
case "entry":
return restoreEntryFromHistory(tx, userId, h.entityId, h.before);
case "engagement":
return restoreEngagementFromHistory(tx, userId, h.entityId, h.before);
case "copy":
return restoreCopyFromHistory(tx, userId, h.entityId, h.before);
case "list":
return restoreListFromHistory(tx, userId, h.entityId, h.before);
default:
throw new NotFoundError("history");
}