All checks were successful
Deploy production / deploy (push) Successful in 2m33s
118 lines
3.6 KiB
TypeScript
118 lines
3.6 KiB
TypeScript
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;
|