feat : add profile page
This commit is contained in:
@@ -1,65 +0,0 @@
|
||||
import { readFile } from "fs/promises";
|
||||
import postgres from "postgres";
|
||||
|
||||
const migrationTag = "0011_unique_submission_user";
|
||||
const migrationPath = "drizzle/0011_unique_submission_user.sql";
|
||||
|
||||
const databaseUrl = process.env.DATABASE_URL;
|
||||
if (!databaseUrl) {
|
||||
throw new Error("DATABASE_URL is not set");
|
||||
}
|
||||
|
||||
const sql = postgres(databaseUrl, { max: 1 });
|
||||
|
||||
try {
|
||||
const duplicates = await sql<{ form_id: string; user_discord_id: string; count: string }[]>`
|
||||
select form_id, user_discord_id, count(*)::text as count
|
||||
from form.submission
|
||||
where user_discord_id is not null
|
||||
group by form_id, user_discord_id
|
||||
having count(*) > 1
|
||||
limit 20
|
||||
`;
|
||||
|
||||
if (duplicates.length > 0) {
|
||||
console.error("Duplicate submissions would violate the unique index:");
|
||||
for (const duplicate of duplicates) {
|
||||
console.error(
|
||||
`form_id=${duplicate.form_id} user_discord_id=${duplicate.user_discord_id} count=${duplicate.count}`
|
||||
);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await sql`
|
||||
create unique index if not exists "submission_form_user_discord_id_unique"
|
||||
on "form"."submission" using btree ("form_id", "user_discord_id")
|
||||
`;
|
||||
|
||||
const migrationTable = await sql<{ exists: boolean }[]>`
|
||||
select to_regclass('drizzle.__drizzle_migrations') is not null as exists
|
||||
`;
|
||||
|
||||
if (migrationTable[0]?.exists) {
|
||||
const existing = await sql<{ count: string }[]>`
|
||||
select count(*)::text as count
|
||||
from drizzle.__drizzle_migrations
|
||||
where hash = ${migrationTag}
|
||||
`;
|
||||
|
||||
if (existing[0]?.count === "0") {
|
||||
const migrationSql = await readFile(migrationPath, "utf8");
|
||||
await sql`
|
||||
insert into drizzle.__drizzle_migrations (hash, created_at)
|
||||
values (${migrationTag}, ${Date.now()})
|
||||
`;
|
||||
console.log(`Applied ${migrationTag}: ${migrationSql.trim()}`);
|
||||
} else {
|
||||
console.log(`${migrationTag} was already recorded.`);
|
||||
}
|
||||
} else {
|
||||
console.log("Applied index. Drizzle migration table was not found, so no migration row was recorded.");
|
||||
}
|
||||
} finally {
|
||||
await sql.end();
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
import postgres from "postgres";
|
||||
|
||||
const databaseUrl = process.env.DATABASE_URL;
|
||||
if (!databaseUrl) {
|
||||
throw new Error("DATABASE_URL is not set");
|
||||
}
|
||||
|
||||
const expectedMigrations = [
|
||||
{
|
||||
hash: "418d5afb86b4866e697a0abfc992b913da1533e8df41cc0b618a9e23cbb70ba5",
|
||||
createdAt: 1782731728406,
|
||||
},
|
||||
{
|
||||
hash: "5e060f0fdac0296f4953f707182eb1c872f69d44e9ef89ba75c69fbc9c895851",
|
||||
createdAt: 1782731936083,
|
||||
},
|
||||
{
|
||||
hash: "b3d35909be61ab7fbffc6c36916d6444833385db517a302abe28cfea2b0ef544",
|
||||
createdAt: 1782731954122,
|
||||
},
|
||||
{
|
||||
hash: "1ad2b86e381f0d8ef17839a952c30f0ea6f0452367d1dcd19aa11a65d8eeecbd",
|
||||
createdAt: 1783089081925,
|
||||
},
|
||||
{
|
||||
hash: "f2c279f21375de159981c439e622e4ddcd8415384f7ca7287c3f1598bcb42fc4",
|
||||
createdAt: 1783613113217,
|
||||
},
|
||||
{
|
||||
hash: "38e26a4313f207b04bb1646f6a303c0f216ad687062d16100e4ca01db5fa74c2",
|
||||
createdAt: 1785152117830,
|
||||
},
|
||||
{
|
||||
hash: "8a65ae9a4fe4c7933d0d40182dab6da9654c8cb0f1275a8ebb43e1e0f8719256",
|
||||
createdAt: 1785169071234,
|
||||
},
|
||||
] as const;
|
||||
|
||||
const sql = postgres(databaseUrl, { max: 1 });
|
||||
|
||||
try {
|
||||
const [schemaState] = await sql<{
|
||||
form_tables: number;
|
||||
allowed_roles: boolean;
|
||||
denied_roles: boolean;
|
||||
cdn_table: boolean;
|
||||
image_cdn_id: boolean;
|
||||
allow_multiple_submissions: boolean;
|
||||
image_answer_mode: boolean;
|
||||
submitted_at_index: boolean;
|
||||
answer_image_fk: boolean;
|
||||
unique_submission_index: boolean;
|
||||
legacy_public_tables: boolean;
|
||||
}[]>`
|
||||
select
|
||||
(
|
||||
select count(*)::integer
|
||||
from information_schema.tables
|
||||
where table_schema = 'form'
|
||||
and table_name in ('answer', 'form', 'question', 'submission')
|
||||
) as form_tables,
|
||||
exists (
|
||||
select 1 from information_schema.columns
|
||||
where table_schema = 'form'
|
||||
and table_name = 'form'
|
||||
and column_name = 'allowed_roles'
|
||||
) as allowed_roles,
|
||||
exists (
|
||||
select 1 from information_schema.columns
|
||||
where table_schema = 'form'
|
||||
and table_name = 'form'
|
||||
and column_name = 'denied_roles'
|
||||
) as denied_roles,
|
||||
to_regclass('form.cdn') is not null as cdn_table,
|
||||
exists (
|
||||
select 1 from information_schema.columns
|
||||
where table_schema = 'form'
|
||||
and table_name = 'answer'
|
||||
and column_name = 'image_cdn_id'
|
||||
) as image_cdn_id,
|
||||
exists (
|
||||
select 1 from information_schema.columns
|
||||
where table_schema = 'form'
|
||||
and table_name = 'form'
|
||||
and column_name = 'allow_multiple_submissions'
|
||||
) as allow_multiple_submissions,
|
||||
exists (
|
||||
select 1 from information_schema.columns
|
||||
where table_schema = 'form'
|
||||
and table_name = 'question'
|
||||
and column_name = 'image_answer_mode'
|
||||
) as image_answer_mode,
|
||||
to_regclass('form.submission_form_submitted_at_id_idx') is not null
|
||||
as submitted_at_index,
|
||||
exists (
|
||||
select 1
|
||||
from information_schema.table_constraints
|
||||
where constraint_schema = 'form'
|
||||
and table_name = 'answer'
|
||||
and constraint_name = 'answer_image_cdn_id_cdn_id_fk'
|
||||
) as answer_image_fk,
|
||||
to_regclass('form.submission_form_user_discord_id_unique') is not null
|
||||
as unique_submission_index,
|
||||
exists (
|
||||
select 1
|
||||
from information_schema.tables
|
||||
where table_schema = 'public'
|
||||
and table_name in ('answer', 'form', 'question', 'submission')
|
||||
) as legacy_public_tables
|
||||
`;
|
||||
|
||||
const matchesExpectedSchema =
|
||||
schemaState?.form_tables === 4 &&
|
||||
schemaState.allowed_roles &&
|
||||
schemaState.denied_roles &&
|
||||
schemaState.cdn_table &&
|
||||
schemaState.image_cdn_id &&
|
||||
schemaState.allow_multiple_submissions &&
|
||||
schemaState.image_answer_mode &&
|
||||
schemaState.submitted_at_index &&
|
||||
schemaState.answer_image_fk &&
|
||||
!schemaState.unique_submission_index &&
|
||||
!schemaState.legacy_public_tables;
|
||||
|
||||
if (!matchesExpectedSchema) {
|
||||
throw new Error(
|
||||
"The database does not match the expected schema through migration 0013. Refusing to change the migration ledger."
|
||||
);
|
||||
}
|
||||
|
||||
await sql.begin(async (transaction) => {
|
||||
await transaction`lock table drizzle.__drizzle_migrations in exclusive mode`;
|
||||
|
||||
for (const migration of expectedMigrations) {
|
||||
await transaction`
|
||||
insert into drizzle.__drizzle_migrations (hash, created_at)
|
||||
select ${migration.hash}, ${migration.createdAt}
|
||||
where not exists (
|
||||
select 1
|
||||
from drizzle.__drizzle_migrations
|
||||
where hash = ${migration.hash}
|
||||
)
|
||||
`;
|
||||
await transaction`
|
||||
update drizzle.__drizzle_migrations
|
||||
set created_at = ${migration.createdAt}
|
||||
where hash = ${migration.hash}
|
||||
`;
|
||||
}
|
||||
});
|
||||
|
||||
console.log("Reconciled the Drizzle migration ledger through 0013.");
|
||||
} finally {
|
||||
await sql.end();
|
||||
}
|
||||
Reference in New Issue
Block a user