aboutsummaryrefslogtreecommitdiffstats
path: root/packages/db/schema.ts
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2026-02-04 09:44:18 +0000
committerGitHub <noreply@github.com>2026-02-04 09:44:18 +0000
commit3c838ddb26c1e86d3f201ce71f13c834be705f69 (patch)
tree892fe4f8cd2ca01d6e4cd34f677fc16aa2fd63f6 /packages/db/schema.ts
parent3fcccb858ee3ef22fe9ce479af4ce458ac9a0fe1 (diff)
downloadkarakeep-3c838ddb26c1e86d3f201ce71f13c834be705f69.tar.zst
feat: Import workflow v3 (#2378)
* feat: import workflow v3 * batch stage * revert migration * cleanups * pr comments * move to models * add allowed workers * e2e tests * import list ids * add missing indicies * merge test * more fixes * add resume/pause to UI * fix ui states * fix tests * simplify progress tracking * remove backpressure * fix list imports * fix race on claiming bookmarks * remove the codex file
Diffstat (limited to 'packages/db/schema.ts')
-rw-r--r--packages/db/schema.ts68
1 files changed, 67 insertions, 1 deletions
diff --git a/packages/db/schema.ts b/packages/db/schema.ts
index 8ed91e28..217456c4 100644
--- a/packages/db/schema.ts
+++ b/packages/db/schema.ts
@@ -833,10 +833,19 @@ export const importSessions = sqliteTable(
rootListId: text("rootListId").references(() => bookmarkLists.id, {
onDelete: "set null",
}),
+ status: text("status", {
+ enum: ["staging", "pending", "running", "paused", "completed", "failed"],
+ })
+ .notNull()
+ .default("staging"),
+ lastProcessedAt: integer("lastProcessedAt", { mode: "timestamp" }),
createdAt: createdAtField(),
modifiedAt: modifiedAtField(),
},
- (is) => [index("importSessions_userId_idx").on(is.userId)],
+ (is) => [
+ index("importSessions_userId_idx").on(is.userId),
+ index("importSessions_status_idx").on(is.status),
+ ],
);
export const importSessionBookmarks = sqliteTable(
@@ -861,6 +870,63 @@ export const importSessionBookmarks = sqliteTable(
],
);
+export const importStagingBookmarks = sqliteTable(
+ "importStagingBookmarks",
+ {
+ id: text("id")
+ .notNull()
+ .primaryKey()
+ .$defaultFn(() => createId()),
+ importSessionId: text("importSessionId")
+ .notNull()
+ .references(() => importSessions.id, { onDelete: "cascade" }),
+
+ // Bookmark data to create
+ type: text("type", { enum: ["link", "text", "asset"] }).notNull(),
+ url: text("url"),
+ title: text("title"),
+ content: text("content"),
+ note: text("note"),
+ tags: text("tags", { mode: "json" }).$type<string[]>(),
+ listIds: text("listIds", { mode: "json" }).$type<string[]>(),
+ sourceAddedAt: integer("sourceAddedAt", { mode: "timestamp" }),
+
+ // Processing state
+ status: text("status", {
+ enum: ["pending", "processing", "completed", "failed"],
+ })
+ .notNull()
+ .default("pending"),
+ processingStartedAt: integer("processingStartedAt", {
+ mode: "timestamp",
+ }),
+
+ // Result (for observability)
+ result: text("result", {
+ enum: ["accepted", "rejected", "skipped_duplicate"],
+ }),
+ resultReason: text("resultReason"),
+ resultBookmarkId: text("resultBookmarkId").references(() => bookmarks.id, {
+ onDelete: "set null",
+ }),
+
+ createdAt: createdAtField(),
+ completedAt: integer("completedAt", { mode: "timestamp" }),
+ },
+ (isb) => [
+ index("importStaging_session_status_idx").on(
+ isb.importSessionId,
+ isb.status,
+ ),
+ index("importStaging_completedAt_idx").on(isb.completedAt),
+ index("importStaging_status_idx").on(isb.status),
+ index("importStaging_status_processingStartedAt_idx").on(
+ isb.status,
+ isb.processingStartedAt,
+ ),
+ ],
+);
+
// Relations
export const userRelations = relations(users, ({ many, one }) => ({