feat(05-01): extend documents schema with 4 new columns + migration 0003

- Added SignatureFieldData interface export to schema.ts
- Added signatureFields (jsonb), textFillData (jsonb), assignedClientId (text), preparedFilePath (text) nullable columns to documents table
- Added jsonb import to drizzle-orm/pg-core imports
- Generated and applied migration 0003_cool_natasha_romanoff.sql

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chandler Copeland
2026-03-19 23:53:12 -06:00
parent a997ebda20
commit d67130da20
4 changed files with 314 additions and 1 deletions

View File

@@ -0,0 +1,4 @@
ALTER TABLE "documents" ADD COLUMN "signature_fields" jsonb;--> statement-breakpoint
ALTER TABLE "documents" ADD COLUMN "text_fill_data" jsonb;--> statement-breakpoint
ALTER TABLE "documents" ADD COLUMN "assigned_client_id" text;--> statement-breakpoint
ALTER TABLE "documents" ADD COLUMN "prepared_file_path" text;

View File

@@ -0,0 +1,289 @@
{
"id": "0f0c2e60-e89f-41d9-8a4f-cec2b4dfe938",
"prevId": "2b5e908a-37da-4cb2-b42e-066a7c727965",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.clients": {
"name": "clients",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.documents": {
"name": "documents",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"client_id": {
"name": "client_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "document_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'Draft'"
},
"sent_at": {
"name": "sent_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"form_template_id": {
"name": "form_template_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"file_path": {
"name": "file_path",
"type": "text",
"primaryKey": false,
"notNull": false
},
"signature_fields": {
"name": "signature_fields",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"text_fill_data": {
"name": "text_fill_data",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"assigned_client_id": {
"name": "assigned_client_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"prepared_file_path": {
"name": "prepared_file_path",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"documents_client_id_clients_id_fk": {
"name": "documents_client_id_clients_id_fk",
"tableFrom": "documents",
"tableTo": "clients",
"columnsFrom": [
"client_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"documents_form_template_id_form_templates_id_fk": {
"name": "documents_form_template_id_form_templates_id_fk",
"tableFrom": "documents",
"tableTo": "form_templates",
"columnsFrom": [
"form_template_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.form_templates": {
"name": "form_templates",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"filename": {
"name": "filename",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"form_templates_filename_unique": {
"name": "form_templates_filename_unique",
"nullsNotDistinct": false,
"columns": [
"filename"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"password_hash": {
"name": "password_hash",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"users_email_unique": {
"name": "users_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.document_status": {
"name": "document_status",
"schema": "public",
"values": [
"Draft",
"Sent",
"Viewed",
"Signed"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -22,6 +22,13 @@
"when": 1773977523128, "when": 1773977523128,
"tag": "0002_wealthy_zzzax", "tag": "0002_wealthy_zzzax",
"breakpoints": true "breakpoints": true
},
{
"idx": 3,
"version": "7",
"when": 1773985969484,
"tag": "0003_cool_natasha_romanoff",
"breakpoints": true
} }
] ]
} }

View File

@@ -1,6 +1,15 @@
import { pgEnum, pgTable, text, timestamp } from "drizzle-orm/pg-core"; import { jsonb, pgEnum, pgTable, text, timestamp } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm"; import { relations } from "drizzle-orm";
export interface SignatureFieldData {
id: string;
page: number; // 1-indexed
x: number; // PDF user space, bottom-left origin, points
y: number; // PDF user space, bottom-left origin, points
width: number; // PDF points (default: 144 — 2 inches)
height: number; // PDF points (default: 36 — 0.5 inches)
}
export const users = pgTable("users", { export const users = pgTable("users", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()), id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
email: text("email").notNull().unique(), email: text("email").notNull().unique(),
@@ -42,6 +51,10 @@ export const documents = pgTable("documents", {
createdAt: timestamp("created_at").defaultNow().notNull(), createdAt: timestamp("created_at").defaultNow().notNull(),
formTemplateId: text("form_template_id").references(() => formTemplates.id), formTemplateId: text("form_template_id").references(() => formTemplates.id),
filePath: text("file_path"), filePath: text("file_path"),
signatureFields: jsonb("signature_fields").$type<SignatureFieldData[]>(),
textFillData: jsonb("text_fill_data").$type<Record<string, string>>(),
assignedClientId: text("assigned_client_id"),
preparedFilePath: text("prepared_file_path"),
}); });
export const documentsRelations = relations(documents, ({ one }) => ({ export const documentsRelations = relations(documents, ({ one }) => ({