Files
haex-hub-mirror/src/stores/vault/index.ts
haex 6a7f58a513 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
2025-11-02 00:57:03 +01:00

189 lines
4.5 KiB
TypeScript

// src/stores/vault/index.ts
import { drizzle } from 'drizzle-orm/sqlite-proxy'
import { invoke } from '@tauri-apps/api/core'
import { schema } from '~/database'
import type {
AsyncRemoteCallback,
SqliteRemoteDatabase,
} from 'drizzle-orm/sqlite-proxy'
interface IVault {
name: string
drizzle: SqliteRemoteDatabase<typeof schema>
}
interface IOpenVaults {
[vaultId: string]: IVault
}
export const useVaultStore = defineStore('vaultStore', () => {
const {
public: { haexVault },
} = useRuntimeConfig()
const router = useRouter()
const currentVaultId = computed<string | undefined>({
get: () =>
getSingleRouteParam(router.currentRoute.value.params.vaultId),
set: (newVaultId) => {
router.currentRoute.value.params.vaultId = newVaultId ?? ''
},
})
const currentVaultName = ref(haexVault.defaultVaultName || 'HaexHub')
const openVaults = ref<IOpenVaults>({})
const currentVault = computed(
() => openVaults.value?.[currentVaultId.value ?? ''],
)
const openAsync = async ({
path = '',
password,
}: {
path: string
password: string
}) => {
try {
await invoke<string>('open_encrypted_database', {
vaultPath: path,
key: password,
})
const vaultId = await getVaultIdAsync(path)
const fileName = getFileName(path) ?? path
openVaults.value = {
...openVaults.value,
[vaultId]: {
name: fileName,
drizzle: drizzle<typeof schema>(drizzleCallback, {
schema: schema,
logger: false,
}),
},
}
return vaultId
} catch (error) {
console.error('Error openAsync ', error)
throw error
}
}
const createAsync = async ({
vaultName,
password,
}: {
vaultName: string
password: string
}) => {
const vaultPath = await invoke<string>('create_encrypted_database', {
vaultName,
key: password,
})
return await openAsync({ path: vaultPath, password })
}
const closeAsync = async () => {
if (!currentVaultId.value) return
delete openVaults.value?.[currentVaultId.value]
}
const existsVault = () => {
if (!currentVault.value?.drizzle) {
console.error('Kein Vault geöffnet')
return
}
}
return {
closeAsync,
createAsync,
currentVault,
currentVaultId,
currentVaultName,
existsVault,
openAsync,
openVaults,
}
})
const getVaultIdAsync = async (path: string) => {
const encoder = new TextEncoder()
const data = encoder.encode(path)
const hashBuffer = await crypto.subtle.digest('SHA-256', data)
const hashArray = Array.from(new Uint8Array(hashBuffer))
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
return hashHex
}
const isSelectQuery = (sql: string) => {
const selectRegex = /^\s*SELECT\b/i
return selectRegex.test(sql)
}
const hasReturning = (sql: string) => {
const returningRegex = /\bRETURNING\b/i
return returningRegex.test(sql)
}
const drizzleCallback = (async (
sql: string,
params: unknown[],
method: 'get' | 'run' | 'all' | 'values',
) => {
// Wir MÜSSEN 'any[]' verwenden, um Drizzle's Typ zu erfüllen.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let rows: any[] = []
try {
if (isSelectQuery(sql)) {
// SELECT statements
rows = await invoke<unknown[]>('sql_select_with_crdt', {
sql,
params,
}).catch((e) => {
console.error('SQL select Error:', e, sql, params)
return []
})
} else if (hasReturning(sql)) {
// INSERT/UPDATE/DELETE with RETURNING → use query
rows = await invoke<unknown[]>('sql_query_with_crdt', {
sql,
params,
}).catch((e) => {
console.error('SQL query with CRDT Error:', e, sql, params)
return []
})
} else {
// INSERT/UPDATE/DELETE without RETURNING → use execute
await invoke<unknown[]>('sql_execute_with_crdt', {
sql,
params,
}).catch((e) => {
console.error('SQL execute with CRDT Error:', e, sql, params, rows)
return []
})
}
} catch (error) {
console.error('Fehler im drizzleCallback invoke:', error, {
sql,
params,
method,
})
}
/* console.log('drizzleCallback', method, sql, params)
console.log('drizzleCallback rows', rows, rows.slice(0, 1)) */
if (method === 'get') {
return rows.length > 0 ? { rows: rows.at(0) } : { rows }
}
return { rows }
}) satisfies AsyncRemoteCallback