Remove sort_order columns from db schema and related functions
This commit is contained in:
154
src/lib/db.ts
154
src/lib/db.ts
@@ -7,7 +7,6 @@ export type Text = {
|
|||||||
updated_at: number;
|
updated_at: number;
|
||||||
last_saved_version_id: string | null;
|
last_saved_version_id: string | null;
|
||||||
folder_id: string | null;
|
folder_id: string | null;
|
||||||
sort_order: number | null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Folder = {
|
export type Folder = {
|
||||||
@@ -16,7 +15,6 @@ export type Folder = {
|
|||||||
parent_id: string | null;
|
parent_id: string | null;
|
||||||
created_at: number;
|
created_at: number;
|
||||||
updated_at: number;
|
updated_at: number;
|
||||||
sort_order: number | null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TextVersion = {
|
export type TextVersion = {
|
||||||
@@ -43,7 +41,6 @@ const MIGRATIONS = [
|
|||||||
parent_id TEXT,
|
parent_id TEXT,
|
||||||
created_at INTEGER NOT NULL,
|
created_at INTEGER NOT NULL,
|
||||||
updated_at INTEGER NOT NULL,
|
updated_at INTEGER NOT NULL,
|
||||||
sort_order INTEGER,
|
|
||||||
FOREIGN KEY(parent_id) REFERENCES folders(id)
|
FOREIGN KEY(parent_id) REFERENCES folders(id)
|
||||||
);`,
|
);`,
|
||||||
`CREATE TABLE IF NOT EXISTS prompts(
|
`CREATE TABLE IF NOT EXISTS prompts(
|
||||||
@@ -51,7 +48,8 @@ const MIGRATIONS = [
|
|||||||
title TEXT NOT NULL,
|
title TEXT NOT NULL,
|
||||||
created_at INTEGER NOT NULL,
|
created_at INTEGER NOT NULL,
|
||||||
updated_at INTEGER NOT NULL,
|
updated_at INTEGER NOT NULL,
|
||||||
last_saved_version_id TEXT
|
last_saved_version_id TEXT,
|
||||||
|
folder_id TEXT REFERENCES folders(id) ON DELETE SET NULL
|
||||||
);`,
|
);`,
|
||||||
`CREATE TABLE IF NOT EXISTS prompt_versions(
|
`CREATE TABLE IF NOT EXISTS prompt_versions(
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
@@ -82,8 +80,8 @@ async function migrate(db: Database) {
|
|||||||
await db.execute(statement);
|
await db.execute(statement);
|
||||||
}
|
}
|
||||||
await ensureColumn(db, "prompts", "folder_id", "TEXT REFERENCES folders(id) ON DELETE SET NULL");
|
await ensureColumn(db, "prompts", "folder_id", "TEXT REFERENCES folders(id) ON DELETE SET NULL");
|
||||||
await ensureColumn(db, "prompts", "sort_order", "INTEGER");
|
|
||||||
await db.execute("CREATE INDEX IF NOT EXISTS idx_prompts_folder ON prompts(folder_id);");
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_prompts_folder ON prompts(folder_id);");
|
||||||
|
await dropSortOrderColumns(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ensureColumn(
|
async function ensureColumn(
|
||||||
@@ -99,6 +97,75 @@ async function ensureColumn(
|
|||||||
await db.execute(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
await db.execute(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function hasColumn(db: Database, table: string, column: string) {
|
||||||
|
const columns = await db.select<{ name: string }[]>(
|
||||||
|
`PRAGMA table_info(${table})`
|
||||||
|
);
|
||||||
|
return columns.some((col) => col.name === column);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function dropSortOrderColumns(db: Database) {
|
||||||
|
const promptsHasSort = await hasColumn(db, "prompts", "sort_order");
|
||||||
|
const foldersHasSort = await hasColumn(db, "folders", "sort_order");
|
||||||
|
if (!promptsHasSort && !foldersHasSort) return;
|
||||||
|
|
||||||
|
await db.execute("PRAGMA foreign_keys = OFF");
|
||||||
|
await db.execute("BEGIN TRANSACTION");
|
||||||
|
try {
|
||||||
|
if (foldersHasSort) {
|
||||||
|
await db.execute("DROP TABLE IF EXISTS folders_new");
|
||||||
|
await db.execute(`
|
||||||
|
CREATE TABLE folders_new(
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
parent_id TEXT,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(parent_id) REFERENCES folders(id)
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
await db.execute(`
|
||||||
|
INSERT INTO folders_new(id, name, parent_id, created_at, updated_at)
|
||||||
|
SELECT id, name, parent_id, created_at, updated_at FROM folders
|
||||||
|
`);
|
||||||
|
await db.execute("DROP TABLE folders");
|
||||||
|
await db.execute("ALTER TABLE folders_new RENAME TO folders");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (promptsHasSort) {
|
||||||
|
await db.execute("DROP TABLE IF EXISTS prompts_new");
|
||||||
|
await db.execute(`
|
||||||
|
CREATE TABLE prompts_new(
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
last_saved_version_id TEXT,
|
||||||
|
folder_id TEXT REFERENCES folders(id) ON DELETE SET NULL
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
await db.execute(`
|
||||||
|
INSERT INTO prompts_new(id, title, created_at, updated_at, last_saved_version_id, folder_id)
|
||||||
|
SELECT id, title, created_at, updated_at, last_saved_version_id, folder_id FROM prompts
|
||||||
|
`);
|
||||||
|
await db.execute("DROP TABLE prompts");
|
||||||
|
await db.execute("ALTER TABLE prompts_new RENAME TO prompts");
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.execute("COMMIT");
|
||||||
|
} catch (error) {
|
||||||
|
await db.execute("ROLLBACK");
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
await db.execute("PRAGMA foreign_keys = ON");
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_prompts_updated ON prompts(updated_at DESC);");
|
||||||
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_prompts_folder ON prompts(folder_id);");
|
||||||
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_folders_parent ON folders(parent_id);");
|
||||||
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_folders_updated ON folders(updated_at DESC);");
|
||||||
|
}
|
||||||
|
|
||||||
export async function getDb(): Promise<Database> {
|
export async function getDb(): Promise<Database> {
|
||||||
if (!dbPromise) {
|
if (!dbPromise) {
|
||||||
dbPromise = (async () => {
|
dbPromise = (async () => {
|
||||||
@@ -118,10 +185,7 @@ export async function listTexts(): Promise<Text[]> {
|
|||||||
const db = await getDb();
|
const db = await getDb();
|
||||||
const rows = await db.select<Text[]>(
|
const rows = await db.select<Text[]>(
|
||||||
`SELECT * FROM prompts
|
`SELECT * FROM prompts
|
||||||
ORDER BY
|
ORDER BY updated_at DESC`
|
||||||
CASE WHEN sort_order IS NULL THEN 1 ELSE 0 END,
|
|
||||||
sort_order ASC,
|
|
||||||
updated_at DESC`
|
|
||||||
);
|
);
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
@@ -139,10 +203,7 @@ export async function searchTexts(term: string): Promise<Text[]> {
|
|||||||
WHERE v.prompt_id = p.id
|
WHERE v.prompt_id = p.id
|
||||||
AND LOWER(v.body) LIKE $1
|
AND LOWER(v.body) LIKE $1
|
||||||
)
|
)
|
||||||
ORDER BY
|
ORDER BY p.updated_at DESC`,
|
||||||
CASE WHEN p.sort_order IS NULL THEN 1 ELSE 0 END,
|
|
||||||
p.sort_order ASC,
|
|
||||||
p.updated_at DESC`,
|
|
||||||
[normalized]
|
[normalized]
|
||||||
);
|
);
|
||||||
return rows;
|
return rows;
|
||||||
@@ -190,8 +251,7 @@ export async function getDraft(promptId: string): Promise<TextDraft | null> {
|
|||||||
export async function createText(
|
export async function createText(
|
||||||
title: string,
|
title: string,
|
||||||
body: string,
|
body: string,
|
||||||
folderId: string | null = null,
|
folderId: string | null = null
|
||||||
sortOrder: number | null = null
|
|
||||||
): Promise<{ textId: string; versionId: string; createdAt: number }> {
|
): Promise<{ textId: string; versionId: string; createdAt: number }> {
|
||||||
const db = await getDb();
|
const db = await getDb();
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
@@ -199,8 +259,8 @@ export async function createText(
|
|||||||
const versionId = crypto.randomUUID();
|
const versionId = crypto.randomUUID();
|
||||||
|
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"INSERT INTO prompts(id, title, created_at, updated_at, last_saved_version_id, folder_id, sort_order) VALUES($1, $2, $3, $4, $5, $6, $7)",
|
"INSERT INTO prompts(id, title, created_at, updated_at, last_saved_version_id, folder_id) VALUES($1, $2, $3, $4, $5, $6)",
|
||||||
[textId, title, now, now, versionId, folderId, sortOrder]
|
[textId, title, now, now, versionId, folderId]
|
||||||
);
|
);
|
||||||
|
|
||||||
await db.execute(
|
await db.execute(
|
||||||
@@ -217,24 +277,20 @@ export async function listFolders(): Promise<Folder[]> {
|
|||||||
const db = await getDb();
|
const db = await getDb();
|
||||||
return db.select<Folder[]>(
|
return db.select<Folder[]>(
|
||||||
`SELECT * FROM folders
|
`SELECT * FROM folders
|
||||||
ORDER BY
|
ORDER BY updated_at DESC`
|
||||||
CASE WHEN sort_order IS NULL THEN 1 ELSE 0 END,
|
|
||||||
sort_order ASC,
|
|
||||||
updated_at DESC`
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createFolder(
|
export async function createFolder(
|
||||||
name: string,
|
name: string,
|
||||||
parentId: string | null = null,
|
parentId: string | null = null
|
||||||
sortOrder: number | null = null
|
|
||||||
): Promise<{ folderId: string; createdAt: number }> {
|
): Promise<{ folderId: string; createdAt: number }> {
|
||||||
const db = await getDb();
|
const db = await getDb();
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const folderId = crypto.randomUUID();
|
const folderId = crypto.randomUUID();
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"INSERT INTO folders(id, name, parent_id, created_at, updated_at, sort_order) VALUES($1, $2, $3, $4, $5, $6)",
|
"INSERT INTO folders(id, name, parent_id, created_at, updated_at) VALUES($1, $2, $3, $4, $5)",
|
||||||
[folderId, name, parentId, now, now, sortOrder]
|
[folderId, name, parentId, now, now]
|
||||||
);
|
);
|
||||||
return { folderId, createdAt: now };
|
return { folderId, createdAt: now };
|
||||||
}
|
}
|
||||||
@@ -250,34 +306,16 @@ export async function updateFolderName(folderId: string, name: string) {
|
|||||||
|
|
||||||
export async function moveFolder(
|
export async function moveFolder(
|
||||||
folderId: string,
|
folderId: string,
|
||||||
parentId: string | null,
|
parentId: string | null
|
||||||
sortOrder: number | null = null
|
|
||||||
) {
|
) {
|
||||||
const db = await getDb();
|
const db = await getDb();
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"UPDATE folders SET parent_id = $1, sort_order = $2, updated_at = $3 WHERE id = $4",
|
"UPDATE folders SET parent_id = $1, updated_at = $2 WHERE id = $3",
|
||||||
[parentId, sortOrder, now, folderId]
|
[parentId, now, folderId]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setFolderOrder(folderIds: string[]) {
|
|
||||||
const db = await getDb();
|
|
||||||
await db.execute("BEGIN TRANSACTION");
|
|
||||||
try {
|
|
||||||
for (let i = 0; i < folderIds.length; i += 1) {
|
|
||||||
await db.execute("UPDATE folders SET sort_order = $1 WHERE id = $2", [
|
|
||||||
i,
|
|
||||||
folderIds[i]
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
await db.execute("COMMIT");
|
|
||||||
} catch (error) {
|
|
||||||
await db.execute("ROLLBACK");
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function deleteFolder(folderId: string) {
|
export async function deleteFolder(folderId: string) {
|
||||||
const db = await getDb();
|
const db = await getDb();
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
@@ -300,33 +338,15 @@ export async function deleteFolder(folderId: string) {
|
|||||||
|
|
||||||
export async function moveTextToFolder(
|
export async function moveTextToFolder(
|
||||||
textId: string,
|
textId: string,
|
||||||
folderId: string | null,
|
folderId: string | null
|
||||||
sortOrder: number | null = null
|
|
||||||
) {
|
) {
|
||||||
const db = await getDb();
|
const db = await getDb();
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"UPDATE prompts SET folder_id = $1, sort_order = $2, updated_at = $3 WHERE id = $4",
|
"UPDATE prompts SET folder_id = $1, updated_at = $2 WHERE id = $3",
|
||||||
[folderId, sortOrder, now, textId]
|
[folderId, now, textId]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setTextOrder(textIds: string[]) {
|
|
||||||
const db = await getDb();
|
|
||||||
await db.execute("BEGIN TRANSACTION");
|
|
||||||
try {
|
|
||||||
for (let i = 0; i < textIds.length; i += 1) {
|
|
||||||
await db.execute("UPDATE prompts SET sort_order = $1 WHERE id = $2", [
|
|
||||||
i,
|
|
||||||
textIds[i]
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
await db.execute("COMMIT");
|
|
||||||
} catch (error) {
|
|
||||||
await db.execute("ROLLBACK");
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export async function saveManualVersion(
|
export async function saveManualVersion(
|
||||||
promptId: string,
|
promptId: string,
|
||||||
title: string,
|
title: string,
|
||||||
|
|||||||
Reference in New Issue
Block a user