import { bigint, boolean, check, index, integer, jsonb, text, timestamp, unique } from 'drizzle-orm/pg-core'; import { sql } from 'drizzle-orm'; import { metaSchema } from './schemas'; // Registry of GUI-visible tables. Runtime lists live in schema `lists` (one real // table per list, created through meta.create_list()); that schema is excluded // from drizzle-kit via schemaFilter. Structure truth is pg_catalog; these rows are // presentation. See src/lib/server/lists.ts for the list engine. const ts = (name: string) => timestamp(name, { withTimezone: true }); export const metaTables = metaSchema.table( 'tables', { id: integer('id').primaryKey().generatedByDefaultAsIdentity(), schemaName: text('schema_name').notNull(), tableName: text('table_name').notNull(), slug: text('slug').notNull().unique('tables_slug_key'), displayName: text('display_name').notNull(), description: text('description'), icon: text('icon'), pictureUrl: text('picture_url'), kind: text('kind', { enum: ['list', 'core', 'ref'] }).notNull(), editable: boolean('editable').notNull().default(true), hasDone: boolean('has_done').notNull().default(false), defaultSort: text('default_sort'), sortOrder: integer('sort_order').notNull().default(0), archivedAt: ts('archived_at'), createdAt: ts('created_at').notNull().defaultNow(), updatedAt: ts('updated_at').notNull().defaultNow() }, (t) => [ unique('tables_schema_name_table_name_key').on(t.schemaName, t.tableName), check('tables_slug_check', sql`slug ~ '^[a-z0-9][a-z0-9-]{0,62}$'`), check('tables_kind_check', sql`kind IN ('list','core','ref')`) ] ); export const uiTypes = [ 'text', 'longtext', 'url', 'image', 'number', 'cents', 'date', 'datetime', 'bool', 'select', 'multiselect', 'fk', 'json' ] as const; export type UiType = (typeof uiTypes)[number]; export const metaColumns = metaSchema.table( 'columns', { id: integer('id').primaryKey().generatedByDefaultAsIdentity(), tableId: integer('table_id') .notNull() .references(() => metaTables.id, { onDelete: 'cascade' }), columnName: text('column_name').notNull(), label: text('label'), uiType: text('ui_type', { enum: uiTypes }).notNull(), options: jsonb('options').$type<{ values?: string[] }>().notNull().default({}), position: integer('position').notNull().default(0), hidden: boolean('hidden').notNull().default(false), helpText: text('help_text'), createdAt: ts('created_at').notNull().defaultNow(), updatedAt: ts('updated_at').notNull().defaultNow() }, (t) => [ unique('columns_table_id_column_name_key').on(t.tableId, t.columnName), index('columns_table_id_index').on(t.tableId), check( 'columns_ui_type_check', sql`ui_type IN ('text','longtext','url','image','number','cents','date','datetime','bool','select','multiselect','fk','json')` ) ] ); /** Audit trail of every write made through the database browser (/lists/db). */ export const metaEditLog = metaSchema.table( 'edit_log', { id: bigint('id', { mode: 'number' }).primaryKey().generatedAlwaysAsIdentity(), at: ts('at').notNull().defaultNow(), userId: text('user_id'), userEmail: text('user_email'), schemaName: text('schema_name').notNull(), tableName: text('table_name').notNull(), action: text('action').notNull(), pk: jsonb('pk'), before: jsonb('before'), after: jsonb('after') }, (t) => [ index('edit_log_table_at_index').on(t.schemaName, t.tableName, t.at), check( 'edit_log_action_check', sql`action IN ('insert','update','delete','import','add_column')` ) ] ); export type MetaTable = typeof metaTables.$inferSelect; export type MetaColumn = typeof metaColumns.$inferSelect;