Let a super admin read the database from the app

A new super admin settings page, /admin/settings/database, lists every
table with its record count and size, and one page of the open table's
records newest key first. Values are cut inside SQL (400 characters, with
a flag saying so) and a record opens whole in a modal, so a table of long
texts reads without shipping it all. A search matches every column's
text, word by word or as a phrase, which is the one thing that also works
on a virtual table. Nothing in it writes: the catalog, the records and
the single record are all reads, GET only.
This commit is contained in:
2026-10-23 06:03:42 +01:00
parent 9b26c169d6
commit 41bb4aaac2
48 changed files with 2573 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
import { z } from "zod";
import { AppData } from "@/src/data/app-data";
/**
* The table a database browser request asks for, by its own name.
*/
const TableField = z
.string()
.min(1, "Pick a table")
.max(120, "That isn't a table name");
/**
* `GET api/admin/database/records`: one page of one table's records.
*/
export const DatabaseRecordsRequestSchema = z.object({
table: TableField.optional(),
page: z.coerce.number().int().positive().default(1),
search: z.string().max(200).optional(),
mode: z.enum(["every_word", "phrase"]).default("every_word"),
});
export type DatabaseRecordsRequest = z.infer<typeof DatabaseRecordsRequestSchema>;
/**
* `GET api/admin/database/record`: one record, by its key.
*/
export const DatabaseRecordRequestSchema = z.object({
table: TableField,
key: z
.string()
.min(1, "Pick a record")
.max(AppData.DatabaseBrowserCellMaxChars, "That isn't a record key"),
});
export type DatabaseRecordRequest = z.infer<typeof DatabaseRecordRequestSchema>;