Fix production build crash by resolving circular import dependency

Moved database schemas from src-tauri/database/schemas/ to src/database/schemas/
to fix bundling issues and resolved circular import dependency that caused
"Cannot access uninitialized variable" error in production builds.

Key changes:
- Moved crdtColumnNames definition into haex.ts to break circular dependency
- Restored .$defaultFn(() => crypto.randomUUID()) calls
- Kept AnySQLiteColumn type annotations
- Removed obsolete TDZ fix script (no longer needed)
- Updated all import paths across stores and configuration files
This commit is contained in:
2025-11-02 00:57:03 +01:00
parent 3ed8d6bc05
commit 6a7f58a513
26 changed files with 352 additions and 1324 deletions

View File

@ -1,8 +1,8 @@
import { writeFileSync, mkdirSync } from 'node:fs'
import { join, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
import tablesNames from './tableNames.json'
import { schema } from './index'
import tablesNames from '../../src/database/tableNames.json'
import { schema } from '../../src/database/index'
import { getTableColumns } from 'drizzle-orm'
import type { AnySQLiteColumn, SQLiteTable } from 'drizzle-orm/sqlite-core'

View File

@ -1,21 +0,0 @@
import { drizzle } from 'drizzle-orm/sqlite-proxy' // Adapter für Query Building ohne direkte Verbindung
import * as schema from './schemas' // Importiere alles aus deiner Schema-Datei
export * as schema from './schemas'
// sqlite-proxy benötigt eine (dummy) Ausführungsfunktion als Argument.
// Diese wird in unserem Tauri-Workflow nie aufgerufen, da wir nur .toSQL() verwenden.
// Sie muss aber vorhanden sein, um drizzle() aufrufen zu können.
const dummyExecutor = async (
sql: string,
params: unknown[],
method: 'all' | 'run' | 'get' | 'values',
) => {
console.warn(
`Frontend Drizzle Executor wurde aufgerufen (Methode: ${method}). Das sollte im Tauri-Invoke-Workflow nicht passieren!`,
)
// Wir geben leere Ergebnisse zurück, um die Typen zufriedenzustellen, falls es doch aufgerufen wird.
return { rows: [] } // Für 'run' (z.B. bei INSERT/UPDATE)
}
// Erstelle die Drizzle-Instanz für den SQLite-Dialekt
// Übergib den dummyExecutor und das importierte Schema
export const db = drizzle(dummyExecutor, { schema })

View File

@ -1,104 +0,0 @@
CREATE TABLE `haex_crdt_configs` (
`key` text PRIMARY KEY NOT NULL,
`value` text
);
--> statement-breakpoint
CREATE TABLE `haex_crdt_logs` (
`id` text PRIMARY KEY NOT NULL,
`haex_timestamp` text,
`table_name` text,
`row_pks` text,
`op_type` text,
`column_name` text,
`new_value` text,
`old_value` text
);
--> statement-breakpoint
CREATE INDEX `idx_haex_timestamp` ON `haex_crdt_logs` (`haex_timestamp`);--> statement-breakpoint
CREATE INDEX `idx_table_row` ON `haex_crdt_logs` (`table_name`,`row_pks`);--> statement-breakpoint
CREATE TABLE `haex_crdt_snapshots` (
`snapshot_id` text PRIMARY KEY NOT NULL,
`created` text,
`epoch_hlc` text,
`location_url` text,
`file_size_bytes` integer
);
--> statement-breakpoint
CREATE TABLE `haex_desktop_items` (
`id` text PRIMARY KEY NOT NULL,
`workspace_id` text NOT NULL,
`item_type` text NOT NULL,
`extension_id` text,
`system_window_id` text,
`position_x` integer DEFAULT 0 NOT NULL,
`position_y` integer DEFAULT 0 NOT NULL,
`haex_timestamp` text,
FOREIGN KEY (`workspace_id`) REFERENCES `haex_workspaces`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`extension_id`) REFERENCES `haex_extensions`(`id`) ON UPDATE no action ON DELETE cascade,
CONSTRAINT "item_reference" CHECK(("haex_desktop_items"."item_type" = 'extension' AND "haex_desktop_items"."extension_id" IS NOT NULL AND "haex_desktop_items"."system_window_id" IS NULL) OR ("haex_desktop_items"."item_type" = 'system' AND "haex_desktop_items"."system_window_id" IS NOT NULL AND "haex_desktop_items"."extension_id" IS NULL) OR ("haex_desktop_items"."item_type" = 'file' AND "haex_desktop_items"."system_window_id" IS NOT NULL AND "haex_desktop_items"."extension_id" IS NULL) OR ("haex_desktop_items"."item_type" = 'folder' AND "haex_desktop_items"."system_window_id" IS NOT NULL AND "haex_desktop_items"."extension_id" IS NULL))
);
--> statement-breakpoint
CREATE TABLE `haex_extension_permissions` (
`id` text PRIMARY KEY NOT NULL,
`extension_id` text NOT NULL,
`resource_type` text,
`action` text,
`target` text,
`constraints` text,
`status` text DEFAULT 'denied' NOT NULL,
`created_at` text DEFAULT (CURRENT_TIMESTAMP),
`updated_at` integer,
`haex_timestamp` text,
FOREIGN KEY (`extension_id`) REFERENCES `haex_extensions`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `haex_extension_permissions_extension_id_resource_type_action_target_unique` ON `haex_extension_permissions` (`extension_id`,`resource_type`,`action`,`target`);--> statement-breakpoint
CREATE TABLE `haex_extensions` (
`id` text PRIMARY KEY NOT NULL,
`public_key` text NOT NULL,
`name` text NOT NULL,
`version` text NOT NULL,
`author` text,
`description` text,
`entry` text DEFAULT 'index.html',
`homepage` text,
`enabled` integer DEFAULT true,
`icon` text,
`signature` text NOT NULL,
`single_instance` integer DEFAULT false,
`haex_timestamp` text
);
--> statement-breakpoint
CREATE UNIQUE INDEX `haex_extensions_public_key_name_unique` ON `haex_extensions` (`public_key`,`name`);--> statement-breakpoint
CREATE TABLE `haex_notifications` (
`id` text PRIMARY KEY NOT NULL,
`alt` text,
`date` text,
`icon` text,
`image` text,
`read` integer,
`source` text,
`text` text,
`title` text,
`type` text NOT NULL,
`haex_timestamp` text
);
--> statement-breakpoint
CREATE TABLE `haex_settings` (
`id` text PRIMARY KEY NOT NULL,
`key` text,
`type` text,
`value` text,
`haex_timestamp` text
);
--> statement-breakpoint
CREATE UNIQUE INDEX `haex_settings_key_type_value_unique` ON `haex_settings` (`key`,`type`,`value`);--> statement-breakpoint
CREATE TABLE `haex_workspaces` (
`id` text PRIMARY KEY NOT NULL,
`device_id` text NOT NULL,
`name` text NOT NULL,
`position` integer DEFAULT 0 NOT NULL,
`haex_timestamp` text
);
--> statement-breakpoint
CREATE UNIQUE INDEX `haex_workspaces_position_unique` ON `haex_workspaces` (`position`);

View File

@ -1,685 +0,0 @@
{
"version": "6",
"dialect": "sqlite",
"id": "8dc25226-70f9-4d2e-89d4-f3a6b2bdf58d",
"prevId": "00000000-0000-0000-0000-000000000000",
"tables": {
"haex_crdt_configs": {
"name": "haex_crdt_configs",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_crdt_logs": {
"name": "haex_crdt_logs",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"table_name": {
"name": "table_name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"row_pks": {
"name": "row_pks",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"op_type": {
"name": "op_type",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"column_name": {
"name": "column_name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"new_value": {
"name": "new_value",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"old_value": {
"name": "old_value",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"idx_haex_timestamp": {
"name": "idx_haex_timestamp",
"columns": [
"haex_timestamp"
],
"isUnique": false
},
"idx_table_row": {
"name": "idx_table_row",
"columns": [
"table_name",
"row_pks"
],
"isUnique": false
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_crdt_snapshots": {
"name": "haex_crdt_snapshots",
"columns": {
"snapshot_id": {
"name": "snapshot_id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"created": {
"name": "created",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"epoch_hlc": {
"name": "epoch_hlc",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"location_url": {
"name": "location_url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"file_size_bytes": {
"name": "file_size_bytes",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_desktop_items": {
"name": "haex_desktop_items",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"workspace_id": {
"name": "workspace_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"item_type": {
"name": "item_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"extension_id": {
"name": "extension_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"system_window_id": {
"name": "system_window_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"position_x": {
"name": "position_x",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 0
},
"position_y": {
"name": "position_y",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 0
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"haex_desktop_items_workspace_id_haex_workspaces_id_fk": {
"name": "haex_desktop_items_workspace_id_haex_workspaces_id_fk",
"tableFrom": "haex_desktop_items",
"tableTo": "haex_workspaces",
"columnsFrom": [
"workspace_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"haex_desktop_items_extension_id_haex_extensions_id_fk": {
"name": "haex_desktop_items_extension_id_haex_extensions_id_fk",
"tableFrom": "haex_desktop_items",
"tableTo": "haex_extensions",
"columnsFrom": [
"extension_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {
"item_reference": {
"name": "item_reference",
"value": "(\"haex_desktop_items\".\"item_type\" = 'extension' AND \"haex_desktop_items\".\"extension_id\" IS NOT NULL AND \"haex_desktop_items\".\"system_window_id\" IS NULL) OR (\"haex_desktop_items\".\"item_type\" = 'system' AND \"haex_desktop_items\".\"system_window_id\" IS NOT NULL AND \"haex_desktop_items\".\"extension_id\" IS NULL) OR (\"haex_desktop_items\".\"item_type\" = 'file' AND \"haex_desktop_items\".\"system_window_id\" IS NOT NULL AND \"haex_desktop_items\".\"extension_id\" IS NULL) OR (\"haex_desktop_items\".\"item_type\" = 'folder' AND \"haex_desktop_items\".\"system_window_id\" IS NOT NULL AND \"haex_desktop_items\".\"extension_id\" IS NULL)"
}
}
},
"haex_extension_permissions": {
"name": "haex_extension_permissions",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"extension_id": {
"name": "extension_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"resource_type": {
"name": "resource_type",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"action": {
"name": "action",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"target": {
"name": "target",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"constraints": {
"name": "constraints",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'denied'"
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"haex_extension_permissions_extension_id_resource_type_action_target_unique": {
"name": "haex_extension_permissions_extension_id_resource_type_action_target_unique",
"columns": [
"extension_id",
"resource_type",
"action",
"target"
],
"isUnique": true
}
},
"foreignKeys": {
"haex_extension_permissions_extension_id_haex_extensions_id_fk": {
"name": "haex_extension_permissions_extension_id_haex_extensions_id_fk",
"tableFrom": "haex_extension_permissions",
"tableTo": "haex_extensions",
"columnsFrom": [
"extension_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_extensions": {
"name": "haex_extensions",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"public_key": {
"name": "public_key",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"version": {
"name": "version",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"author": {
"name": "author",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"entry": {
"name": "entry",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "'index.html'"
},
"homepage": {
"name": "homepage",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"enabled": {
"name": "enabled",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": true
},
"icon": {
"name": "icon",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"signature": {
"name": "signature",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"single_instance": {
"name": "single_instance",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": false
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"haex_extensions_public_key_name_unique": {
"name": "haex_extensions_public_key_name_unique",
"columns": [
"public_key",
"name"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_notifications": {
"name": "haex_notifications",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"alt": {
"name": "alt",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"date": {
"name": "date",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"icon": {
"name": "icon",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"read": {
"name": "read",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"source": {
"name": "source",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"text": {
"name": "text",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_settings": {
"name": "haex_settings",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"key": {
"name": "key",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"haex_settings_key_type_value_unique": {
"name": "haex_settings_key_type_value_unique",
"columns": [
"key",
"type",
"value"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_workspaces": {
"name": "haex_workspaces",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"device_id": {
"name": "device_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"position": {
"name": "position",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 0
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"haex_workspaces_position_unique": {
"name": "haex_workspaces_position_unique",
"columns": [
"position"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@ -1,13 +0,0 @@
{
"version": "7",
"dialect": "sqlite",
"entries": [
{
"idx": 0,
"version": "6",
"when": 1761821821609,
"tag": "0000_dashing_night_nurse",
"breakpoints": true
}
]
}

View File

@ -1,52 +0,0 @@
import { integer, sqliteTable, text, index } from 'drizzle-orm/sqlite-core'
import tableNames from '../tableNames.json'
export const haexCrdtLogs = sqliteTable(
tableNames.haex.crdt.logs.name,
{
id: text()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
haexTimestamp: text(tableNames.haex.crdt.logs.columns.haexTimestamp),
tableName: text(tableNames.haex.crdt.logs.columns.tableName),
rowPks: text(tableNames.haex.crdt.logs.columns.rowPks, { mode: 'json' }),
opType: text(tableNames.haex.crdt.logs.columns.opType, {
enum: ['INSERT', 'UPDATE', 'DELETE'],
}),
columnName: text(tableNames.haex.crdt.logs.columns.columnName),
newValue: text(tableNames.haex.crdt.logs.columns.newValue, {
mode: 'json',
}),
oldValue: text(tableNames.haex.crdt.logs.columns.oldValue, {
mode: 'json',
}),
},
(table) => [
index('idx_haex_timestamp').on(table.haexTimestamp),
index('idx_table_row').on(table.tableName, table.rowPks),
],
)
export type InsertHaexCrdtLogs = typeof haexCrdtLogs.$inferInsert
export type SelectHaexCrdtLogs = typeof haexCrdtLogs.$inferSelect
export const haexCrdtSnapshots = sqliteTable(
tableNames.haex.crdt.snapshots.name,
{
snapshotId: text(tableNames.haex.crdt.snapshots.columns.snapshotId)
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
created: text(),
epochHlc: text(tableNames.haex.crdt.snapshots.columns.epochHlc),
locationUrl: text(tableNames.haex.crdt.snapshots.columns.locationUrl),
fileSizeBytes: integer(
tableNames.haex.crdt.snapshots.columns.fileSizeBytes,
),
},
)
export const haexCrdtConfigs = sqliteTable(tableNames.haex.crdt.configs.name, {
key: text()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
value: text(),
})

View File

@ -1,176 +0,0 @@
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<string, SQLiteColumnBuilderBase>,
>(
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

View File

@ -1,5 +0,0 @@
export const crdtColumnNames = {
haexTimestamp: 'haex_timestamp',
}
export * from './crdt'
export * from './haex'

View File

@ -1,126 +0,0 @@
{
"haex": {
"settings": {
"name": "haex_settings",
"columns": {
"id": "id",
"key": "key",
"type": "type",
"value": "value",
"haexTimestamp": "haex_timestamp"
}
},
"extensions": {
"name": "haex_extensions",
"columns": {
"id": "id",
"author": "author",
"description": "description",
"entry": "entry",
"homepage": "homepage",
"enabled": "enabled",
"icon": "icon",
"name": "name",
"public_key": "public_key",
"signature": "signature",
"url": "url",
"version": "version",
"haexTimestamp": "haex_timestamp"
}
},
"extension_permissions": {
"name": "haex_extension_permissions",
"columns": {
"id": "id",
"extensionId": "extension_id",
"resourceType": "resource_type",
"action": "action",
"target": "target",
"constraints": "constraints",
"status": "status",
"createdAt": "created_at",
"updateAt": "updated_at",
"haexTimestamp": "haex_timestamp"
}
},
"notifications": {
"name": "haex_notifications",
"columns": {
"id": "id",
"alt": "alt",
"date": "date",
"icon": "icon",
"image": "image",
"read": "read",
"source": "source",
"text": "text",
"title": "title",
"type": "type",
"haexTimestamp": "haex_timestamp"
}
},
"workspaces": {
"name": "haex_workspaces",
"columns": {
"id": "id",
"deviceId": "device_id",
"name": "name",
"position": "position",
"createdAt": "created_at",
"haexTimestamp": "haex_timestamp"
}
},
"desktop_items": {
"name": "haex_desktop_items",
"columns": {
"id": "id",
"workspaceId": "workspace_id",
"itemType": "item_type",
"extensionId": "extension_id",
"systemWindowId": "system_window_id",
"positionX": "position_x",
"positionY": "position_y",
"haexTimestamp": "haex_timestamp"
}
},
"crdt": {
"logs": {
"name": "haex_crdt_logs",
"columns": {
"id": "id",
"haexTimestamp": "haex_timestamp",
"tableName": "table_name",
"rowPks": "row_pks",
"opType": "op_type",
"columnName": "column_name",
"newValue": "new_value",
"oldValue": "old_value"
}
},
"snapshots": {
"name": "haex_crdt_snapshots",
"columns": {
"snapshotId": "snapshot_id",
"created": "created",
"epochHlc": "epoch_hlc",
"locationUrl": "location_url",
"fileSizeBytes": "file_size_bytes"
}
},
"configs": {
"name": "haex_crdt_configs",
"columns": {
"key": "key",
"value": "value"
}
}
}
}
}