import { sql } from 'drizzle-orm' import { check, integer, sqliteTable, text, unique, type AnySQLiteColumn, type SQLiteColumnBuilderBase, } from 'drizzle-orm/sqlite-core' import tableNames from '../tableNames.json' import { crdtColumnNames } from '.' // Helper function to add common CRDT columns ( haexTimestamp) export const withCrdtColumns = < T extends Record, >( columns: T, ) => ({ ...columns, haexTimestamp: text(crdtColumnNames.haexTimestamp), }) export const haexSettings = sqliteTable( tableNames.haex.settings.name, withCrdtColumns({ id: text() .primaryKey() .$defaultFn(() => crypto.randomUUID()), key: text(), type: text(), value: text(), }), (table) => [unique().on(table.key, table.type, table.value)], ) export type InsertHaexSettings = typeof haexSettings.$inferInsert export type SelectHaexSettings = typeof haexSettings.$inferSelect export const haexExtensions = sqliteTable( tableNames.haex.extensions.name, withCrdtColumns({ id: text() .primaryKey() .$defaultFn(() => crypto.randomUUID()), public_key: text().notNull(), name: text().notNull(), version: text().notNull(), author: text(), description: text(), entry: text().default('index.html'), homepage: text(), enabled: integer({ mode: 'boolean' }).default(true), icon: text(), signature: text().notNull(), single_instance: integer({ mode: 'boolean' }).default(false), }), (table) => [ // UNIQUE constraint: Pro Developer (public_key) kann nur eine Extension mit diesem Namen existieren unique().on(table.public_key, table.name), ], ) export type InsertHaexExtensions = typeof haexExtensions.$inferInsert export type SelectHaexExtensions = typeof haexExtensions.$inferSelect export const haexExtensionPermissions = sqliteTable( tableNames.haex.extension_permissions.name, withCrdtColumns({ id: text() .primaryKey() .$defaultFn(() => crypto.randomUUID()), extensionId: text(tableNames.haex.extension_permissions.columns.extensionId) .notNull() .references((): AnySQLiteColumn => haexExtensions.id, { onDelete: 'cascade', }), resourceType: text('resource_type', { enum: ['fs', 'http', 'db', 'shell'], }), action: text({ enum: ['read', 'write'] }), target: text(), constraints: text({ mode: 'json' }), status: text({ enum: ['ask', 'granted', 'denied'] }) .notNull() .default('denied'), createdAt: text('created_at').default(sql`(CURRENT_TIMESTAMP)`), updateAt: integer('updated_at', { mode: 'timestamp' }).$onUpdate( () => new Date(), ), }), (table) => [ unique().on( table.extensionId, table.resourceType, table.action, table.target, ), ], ) export type InserthaexExtensionPermissions = typeof haexExtensionPermissions.$inferInsert export type SelecthaexExtensionPermissions = typeof haexExtensionPermissions.$inferSelect export const haexNotifications = sqliteTable( tableNames.haex.notifications.name, withCrdtColumns({ id: text().primaryKey(), alt: text(), date: text(), icon: text(), image: text(), read: integer({ mode: 'boolean' }), source: text(), text: text(), title: text(), type: text({ enum: ['error', 'success', 'warning', 'info', 'log'], }).notNull(), }), ) export type InsertHaexNotifications = typeof haexNotifications.$inferInsert export type SelectHaexNotifications = typeof haexNotifications.$inferSelect export const haexWorkspaces = sqliteTable( tableNames.haex.workspaces.name, withCrdtColumns({ id: text(tableNames.haex.workspaces.columns.id) .primaryKey() .$defaultFn(() => crypto.randomUUID()), deviceId: text(tableNames.haex.workspaces.columns.deviceId).notNull(), name: text(tableNames.haex.workspaces.columns.name).notNull(), position: integer(tableNames.haex.workspaces.columns.position) .notNull() .default(0), }), (table) => [unique().on(table.position)], ) export type InsertHaexWorkspaces = typeof haexWorkspaces.$inferInsert export type SelectHaexWorkspaces = typeof haexWorkspaces.$inferSelect export const haexDesktopItems = sqliteTable( tableNames.haex.desktop_items.name, withCrdtColumns({ id: text(tableNames.haex.desktop_items.columns.id) .primaryKey() .$defaultFn(() => crypto.randomUUID()), workspaceId: text(tableNames.haex.desktop_items.columns.workspaceId) .notNull() .references(() => haexWorkspaces.id, { onDelete: 'cascade' }), itemType: text(tableNames.haex.desktop_items.columns.itemType, { enum: ['system', 'extension', 'file', 'folder'], }).notNull(), // Für Extensions (wenn itemType = 'extension') extensionId: text( tableNames.haex.desktop_items.columns.extensionId, ).references((): AnySQLiteColumn => haexExtensions.id, { onDelete: 'cascade', }), // Für System Windows (wenn itemType = 'system') systemWindowId: text(tableNames.haex.desktop_items.columns.systemWindowId), positionX: integer(tableNames.haex.desktop_items.columns.positionX) .notNull() .default(0), positionY: integer(tableNames.haex.desktop_items.columns.positionY) .notNull() .default(0), }), (table) => [ check( 'item_reference', sql`(${table.itemType} = 'extension' AND ${table.extensionId} IS NOT NULL AND ${table.systemWindowId} IS NULL) OR (${table.itemType} = 'system' AND ${table.systemWindowId} IS NOT NULL AND ${table.extensionId} IS NULL) OR (${table.itemType} = 'file' AND ${table.systemWindowId} IS NOT NULL AND ${table.extensionId} IS NULL) OR (${table.itemType} = 'folder' AND ${table.systemWindowId} IS NOT NULL AND ${table.extensionId} IS NULL)`, ), ], ) export type InsertHaexDesktopItems = typeof haexDesktopItems.$inferInsert export type SelectHaexDesktopItems = typeof haexDesktopItems.$inferSelect