app: lists on meta tables, schema-qualified SQL, typed columns

- lists read/write real lists.* tables via meta.tables/meta.columns and the
  SECURITY DEFINER meta functions; typed extra columns in the item forms
- old numeric list URLs 308-redirect to the slug
- include_recurring is boolean, osu accuracy/pp/rate numeric
- raw SQL qualified with the new schemas
This commit is contained in:
2026-10-23 22:03:42 +00:00
parent 64fb8df262
commit 4cfe6bad6c
25 changed files with 529 additions and 218 deletions

View File

@@ -3,9 +3,10 @@ import postgres from 'postgres';
// Read-only fingerprints: lets a deployment verify saved progress without logging it.
if (!process.env.DB_URL) throw new Error('DB_URL is required');
const client = postgres(process.env.DB_URL, { max: 1 });
// All saved progress lives in schema `games` since the schema reorg.
const tables = [
'user_entries',
'user_games',
'catch_em_all_entries',
'catch_em_all_games',
'catch_em_all_settings',
'pokemon_journeys',
'pokemon_catches',
@@ -20,11 +21,11 @@ const tables = [
try {
const result: Record<string, unknown> = {};
for (const table of tables) {
const [exists] = await client`select to_regclass(${'public.' + table}) is not null as present`;
const [exists] = await client`select to_regclass(${'games.' + table}) is not null as present`;
if (!exists.present) continue;
const [row] = await client.unsafe(`select count(*)::int as rows,
md5(coalesce(string_agg(record, E'\\n' order by record), '')) as fingerprint
from (select row_to_json(t)::text as record from "${table}" t) s`);
from (select row_to_json(t)::text as record from games."${table}" t) s`);
result[table] = row;
}
console.log(JSON.stringify(result, null, 2));