FRE-594: Implement revision tracking and version history system
Add complete revision tracking system for scripts with: - Database schema for revisions and revision_changes tables - Diff engine with color-coded change types (addition/deletion/modification) - tRPC router with 14 endpoints (create/list/compare/rollback/branch/merge) - SolidJS components: RevisionTimeline, DiffViewer, RevisionReview - Unit tests for diff engine and router Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
77
src/db/schema/revisions.ts
Normal file
77
src/db/schema/revisions.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { sqliteTable, text, integer, index } from "drizzle-orm/sqlite-core";
|
||||
import { scripts } from "./scripts";
|
||||
import { users } from "./users";
|
||||
|
||||
export const revisions = sqliteTable(
|
||||
"revisions",
|
||||
{
|
||||
id: integer("id").primaryKey({ autoIncrement: true }),
|
||||
scriptId: integer("script_id")
|
||||
.notNull()
|
||||
.references(() => scripts.id),
|
||||
versionNumber: integer("version_number").notNull(),
|
||||
branchName: text("branch_name").notNull().default("main"),
|
||||
parentRevisionId: integer("parent_revision_id"),
|
||||
title: text("title").notNull(),
|
||||
summary: text("summary"),
|
||||
content: text("content").notNull(),
|
||||
authorId: integer("author_id")
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
status: text("status", {
|
||||
enum: ["draft", "pending_review", "accepted", "rejected"],
|
||||
})
|
||||
.notNull()
|
||||
.default("draft"),
|
||||
reviewedById: integer("reviewed_by_id").references(() => users.id),
|
||||
reviewedAt: integer("reviewed_at", { mode: "timestamp" }),
|
||||
createdAt: integer("created_at", { mode: "timestamp" })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
},
|
||||
(table) => ({
|
||||
scriptVersionIdx: index("revisions_script_version_idx").on(
|
||||
table.scriptId,
|
||||
table.versionNumber
|
||||
),
|
||||
scriptBranchIdx: index("revisions_script_branch_idx").on(
|
||||
table.scriptId,
|
||||
table.branchName
|
||||
),
|
||||
authorIdx: index("revisions_author_idx").on(table.authorId),
|
||||
})
|
||||
);
|
||||
|
||||
export const revisionChanges = sqliteTable(
|
||||
"revision_changes",
|
||||
{
|
||||
id: integer("id").primaryKey({ autoIncrement: true }),
|
||||
revisionId: integer("revision_id")
|
||||
.notNull()
|
||||
.references(() => revisions.id),
|
||||
changeType: text("change_type", {
|
||||
enum: ["addition", "deletion", "modification"],
|
||||
}).notNull(),
|
||||
elementType: text("element_type"),
|
||||
oldContent: text("old_content"),
|
||||
newContent: text("new_content"),
|
||||
sceneNumber: integer("scene_number"),
|
||||
lineNumber: integer("line_number"),
|
||||
pageNumber: integer("page_number"),
|
||||
createdAt: integer("created_at", { mode: "timestamp" })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
},
|
||||
(table) => ({
|
||||
revisionIdx: index("revision_changes_revision_idx").on(table.revisionId),
|
||||
changeTypeIdx: index("revision_changes_type_idx").on(table.changeType),
|
||||
})
|
||||
);
|
||||
|
||||
export type Revision = typeof revisions.$inferSelect;
|
||||
export type NewRevision = typeof revisions.$inferInsert;
|
||||
export type RevisionChange = typeof revisionChanges.$inferSelect;
|
||||
export type NewRevisionChange = typeof revisionChanges.$inferInsert;
|
||||
Reference in New Issue
Block a user