feat(id): brand ProjectID through Drizzle and Zod schemas (#16948)

This commit is contained in:
Kit Langton
2026-03-11 16:44:26 -04:00
committed by GitHub
parent c37f7b9d99
commit dbc00aa8e0
15 changed files with 77 additions and 44 deletions

View File

@@ -8,6 +8,7 @@ import { readFileSync, readdirSync } from "fs"
import { JsonMigration } from "../../src/storage/json-migration"
import { Global } from "../../src/global"
import { ProjectTable } from "../../src/project/project.sql"
import { ProjectID } from "../../src/project/schema"
import { SessionTable, MessageTable, PartTable, TodoTable, PermissionTable } from "../../src/session/session.sql"
import { SessionShareTable } from "../../src/share/share.sql"
@@ -123,7 +124,7 @@ describe("JSON to SQLite migration", () => {
const db = drizzle({ client: sqlite })
const projects = db.select().from(ProjectTable).all()
expect(projects.length).toBe(1)
expect(projects[0].id).toBe("proj_test123abc")
expect(projects[0].id).toBe(ProjectID.make("proj_test123abc"))
expect(projects[0].worktree).toBe("/test/path")
expect(projects[0].name).toBe("Test Project")
expect(projects[0].sandboxes).toEqual(["/test/sandbox"])
@@ -148,7 +149,7 @@ describe("JSON to SQLite migration", () => {
const db = drizzle({ client: sqlite })
const projects = db.select().from(ProjectTable).all()
expect(projects.length).toBe(1)
expect(projects[0].id).toBe("proj_filename") // Uses filename, not JSON id
expect(projects[0].id).toBe(ProjectID.make("proj_filename")) // Uses filename, not JSON id
})
test("migrates project with commands", async () => {
@@ -169,7 +170,7 @@ describe("JSON to SQLite migration", () => {
const db = drizzle({ client: sqlite })
const projects = db.select().from(ProjectTable).all()
expect(projects.length).toBe(1)
expect(projects[0].id).toBe("proj_with_commands")
expect(projects[0].id).toBe(ProjectID.make("proj_with_commands"))
expect(projects[0].commands).toEqual({ start: "npm run dev" })
})
@@ -190,7 +191,7 @@ describe("JSON to SQLite migration", () => {
const db = drizzle({ client: sqlite })
const projects = db.select().from(ProjectTable).all()
expect(projects.length).toBe(1)
expect(projects[0].id).toBe("proj_no_commands")
expect(projects[0].id).toBe(ProjectID.make("proj_no_commands"))
expect(projects[0].commands).toBeNull()
})
@@ -220,7 +221,7 @@ describe("JSON to SQLite migration", () => {
const sessions = db.select().from(SessionTable).all()
expect(sessions.length).toBe(1)
expect(sessions[0].id).toBe("ses_test456def")
expect(sessions[0].project_id).toBe("proj_test123abc")
expect(sessions[0].project_id).toBe(ProjectID.make("proj_test123abc"))
expect(sessions[0].slug).toBe("test-session")
expect(sessions[0].title).toBe("Test Session Title")
expect(sessions[0].summary_additions).toBe(10)
@@ -426,7 +427,7 @@ describe("JSON to SQLite migration", () => {
const sessions = db.select().from(SessionTable).all()
expect(sessions.length).toBe(1)
expect(sessions[0].id).toBe("ses_migrated")
expect(sessions[0].project_id).toBe(gitBasedProjectID) // Uses directory, not stale JSON
expect(sessions[0].project_id).toBe(ProjectID.make(gitBasedProjectID)) // Uses directory, not stale JSON
})
test("uses filename for session id when JSON has different value", async () => {
@@ -458,7 +459,7 @@ describe("JSON to SQLite migration", () => {
const sessions = db.select().from(SessionTable).all()
expect(sessions.length).toBe(1)
expect(sessions[0].id).toBe("ses_from_filename") // Uses filename, not JSON id
expect(sessions[0].project_id).toBe("proj_test123abc")
expect(sessions[0].project_id).toBe(ProjectID.make("proj_test123abc"))
})
test("is idempotent (running twice doesn't duplicate)", async () => {
@@ -643,7 +644,7 @@ describe("JSON to SQLite migration", () => {
const db = drizzle({ client: sqlite })
const projects = db.select().from(ProjectTable).all()
expect(projects.length).toBe(1)
expect(projects[0].id).toBe("proj_test123abc")
expect(projects[0].id).toBe(ProjectID.make("proj_test123abc"))
})
test("skips invalid todo entries while preserving source positions", async () => {