TierList migration finished

This commit is contained in:
Dreamgineer
2025-10-17 16:12:17 -04:00 Unverified
parent fc97ebc35f
commit 38f8de1387
26 changed files with 763 additions and 901 deletions
+87 -52
View File
@@ -1,6 +1,7 @@
"use server";
import { and, eq, inArray, not, or, sql } from "drizzle-orm";
import { getTableConfig, type PgDatabase } from "drizzle-orm/pg-core";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { apiAuthCheck } from "./auth";
@@ -8,10 +9,15 @@ import { uidRegex } from "./const";
import { db } from "./db";
import {
artifactSettings,
cdn,
characters,
settings,
submissions,
tierlistBadges,
tierlistColumns,
tierlistStates,
tierlistTiers,
tierlistTypes,
tierlistVersions,
} from "./db/schema";
import { sse } from "./utils";
@@ -181,10 +187,13 @@ export async function tlPlacements(
) {
if (!(await apiAuthCheck())) throw "Unauthorized";
// biome-ignore lint/correctness/noUnusedVariables: immutable property removal
const { untiered, ...placementObj } = placements;
await db
.update(tierlistVersions)
.set({
placements,
placements: placementObj,
})
.where(eq(tierlistVersions.id, list));
@@ -192,58 +201,84 @@ export async function tlPlacements(
sse.publish(placements, { topic: `tl-${list}`, event: "update_placements" });
}
/*export async function reorder(
table: PgTable & { id: PgColumn; order: PgColumn },
target: string | { id: string; order: number },
data: Partial<{ id: string; order: number }>,
) {
return await db.transaction(async (tx) => {
const [item] =
typeof target === "string"
? ((await tx.select().from(table).where(eq(table.id, target))) as {
id: string;
order: number;
}[])
: [target];
if (!item) throw new Error("Item not found");
const newOrder = data.order;
if (newOrder != null && newOrder !== item.order) {
// Moving up
if (newOrder < item.order) {
await tx
.update(table)
.set({ order: sql`${table.order} + 1` })
.where(
and(
eq(table.list, item.list),
gte(table.order, newOrder),
lt(table.order, item.order),
),
);
}
// Moving down
else {
await tx
.update(tierlistStates)
.set({ order: sql`${tierlistStates.order} - 1` })
.where(
and(
eq(tierlistStates.list, item.list),
lte(tierlistStates.order, newOrder),
gt(tierlistStates.order, item.order),
),
);
export async function cdnDelete(ids: string[], force = false) {
if (force) await db.delete(cdn).where(inArray(cdn.id, ids));
else
for (const id of ids) {
const refs = await cdnReferences(id);
if (refs.length) {
revalidatePath("/cdn/admin");
return { id, refs };
}
await db.delete(cdn).where(eq(cdn.id, id));
}
revalidatePath("/cdn/admin");
}
// Finally, move the item itself
await tx
.update(tierlistStates)
.set(data)
.where(eq(tierlistStates.id, item.id));
export async function cdnReferences(
id: string,
// biome-ignore lint/suspicious/noExplicitAny: type parameters
tx: PgDatabase<any, any, any> = db,
) {
const tables = [
[characters, "image"],
[tierlistTypes, "image"],
[tierlistTiers, "image"],
[tierlistColumns, "image"],
[tierlistBadges, "image"],
[tierlistVersions, "image", "disclaimer"],
] as const;
const promises: Promise<{
table: string;
cols: string[];
}>[] = [];
for (const [table, ...cols] of tables)
promises.push(
tx
.select({ id: table.id })
.from(table)
.where(
and(
...cols.map((c) =>
eq(table[c as keyof typeof table._.columns], id),
),
),
)
.then((r) => {
const config = getTableConfig(table);
return {
table: config.schema
? `${config.schema}.${config.name}`
: config.name,
cols: r.map((c) => c.id),
};
}),
);
return Promise.all(promises).then((l) =>
l
.filter((t) => t.cols.length)
.flatMap((t) => t.cols.map((c) => `${t.table}#${c}`)),
);
}
return { ...item, ...data };
});
}*/
export async function cdnify(
data: Blob | File,
// biome-ignore lint/suspicious/noExplicitAny: type parameters
config: { tx?: PgDatabase<any, any, any>; name?: string } = {},
) {
const { tx = db, name } = config;
const [{ id }] = await tx
.insert(cdn)
.values({
name: name || data instanceof File ? (data as File).name : null,
data: Buffer.from(await data.arrayBuffer()),
size: `${data.size}`,
type: data.type,
})
.returning({ id: cdn.id });
try {
revalidatePath("/admin/cdn");
} catch {}
return id;
}