mirror of
https://github.com/haexhub/haex-hub.git
synced 2025-12-17 06:30:50 +01:00
362 lines
9.8 KiB
TypeScript
362 lines
9.8 KiB
TypeScript
import { eq, isNull } from 'drizzle-orm'
|
|
import {
|
|
haexPasswordsGroupItems,
|
|
haexPasswordsItemDetails,
|
|
haexPasswordsItemHistory,
|
|
haexPasswordsItemKeyValues,
|
|
type InsertHaexPasswordsItemDetails,
|
|
type InserthaexPasswordsItemKeyValues,
|
|
type SelectHaexPasswordsGroupItems,
|
|
type SelectHaexPasswordsGroups,
|
|
type SelectHaexPasswordsItemDetails,
|
|
type SelectHaexPasswordsItemKeyValues,
|
|
} from '~~/src-tauri/database/schemas/vault'
|
|
|
|
export const usePasswordItemStore = defineStore('passwordItemStore', () => {
|
|
const currentItemId = computed({
|
|
get: () =>
|
|
getSingleRouteParam(useRouter().currentRoute.value.params.itemId),
|
|
set: (entryId) => {
|
|
console.log('set entryId', entryId)
|
|
useRouter().currentRoute.value.params.entryId = entryId ?? ''
|
|
},
|
|
})
|
|
|
|
const currentItem = computedAsync(() => readAsync(currentItemId.value))
|
|
|
|
const items = ref<
|
|
{
|
|
haex_passwords_item_details: SelectHaexPasswordsItemDetails
|
|
haex_passwords_group_items: SelectHaexPasswordsGroupItems
|
|
}[]
|
|
>([])
|
|
|
|
const syncItemsAsync = async () => {
|
|
const { currentVault } = useVaultStore()
|
|
|
|
items.value = await currentVault.drizzle
|
|
.select()
|
|
.from(haexPasswordsItemDetails)
|
|
.innerJoin(
|
|
haexPasswordsGroupItems,
|
|
eq(haexPasswordsItemDetails.id, haexPasswordsGroupItems.itemId),
|
|
)
|
|
}
|
|
|
|
return {
|
|
currentItemId,
|
|
currentItem,
|
|
addAsync,
|
|
addKeyValueAsync,
|
|
addKeyValuesAsync,
|
|
deleteAsync,
|
|
deleteKeyValueAsync,
|
|
items,
|
|
readByGroupIdAsync,
|
|
readAsync,
|
|
readKeyValuesAsync,
|
|
syncItemsAsync,
|
|
updateAsync,
|
|
}
|
|
})
|
|
|
|
const addAsync = async (
|
|
details: SelectHaexPasswordsItemDetails,
|
|
keyValues: SelectHaexPasswordsItemKeyValues[],
|
|
group?: SelectHaexPasswordsGroups | null,
|
|
) => {
|
|
const { currentVault } = useVaultStore()
|
|
console.log('addItem', details, group)
|
|
|
|
const newDetails: InsertHaexPasswordsItemDetails = {
|
|
id: crypto.randomUUID(),
|
|
icon: details.icon || group?.icon || null,
|
|
note: details.note,
|
|
password: details.password,
|
|
tags: details.tags,
|
|
title: details.title,
|
|
url: details.url,
|
|
username: details.username,
|
|
}
|
|
|
|
const newKeyValues: InserthaexPasswordsItemKeyValues[] = keyValues.map(
|
|
(keyValue) => ({
|
|
id: crypto.randomUUID(),
|
|
itemId: newDetails.id,
|
|
key: keyValue.key,
|
|
value: keyValue.value,
|
|
}),
|
|
)
|
|
|
|
try {
|
|
await currentVault?.drizzle.transaction(async (tx) => {
|
|
await tx.insert(haexPasswordsItemDetails).values(newDetails)
|
|
|
|
await tx
|
|
.insert(haexPasswordsGroupItems)
|
|
.values({ itemId: newDetails.id, groupId: group?.id ?? null })
|
|
|
|
if (newKeyValues.length)
|
|
await tx.insert(haexPasswordsItemKeyValues).values(newKeyValues)
|
|
})
|
|
} catch (error) {
|
|
console.error('ERROR addItem', error)
|
|
}
|
|
|
|
return newDetails.id
|
|
}
|
|
|
|
const addKeyValueAsync = async (
|
|
item?: InserthaexPasswordsItemKeyValues | null,
|
|
itemId?: string,
|
|
) => {
|
|
const newKeyValue: InserthaexPasswordsItemKeyValues = {
|
|
id: crypto.randomUUID(),
|
|
itemId: item?.itemId || itemId,
|
|
key: item?.key,
|
|
value: item?.value,
|
|
}
|
|
try {
|
|
const { currentVault } = useVaultStore()
|
|
return await currentVault?.drizzle
|
|
.insert(haexPasswordsItemKeyValues)
|
|
.values(newKeyValue)
|
|
} catch (error) {
|
|
console.error('ERROR addItem', error)
|
|
}
|
|
}
|
|
|
|
const addKeyValuesAsync = async (
|
|
items: InserthaexPasswordsItemKeyValues[],
|
|
itemId?: string,
|
|
) => {
|
|
const { currentVault } = useVaultStore()
|
|
console.log('addKeyValues', items, itemId)
|
|
|
|
const newKeyValues: InserthaexPasswordsItemKeyValues[] = items?.map(
|
|
(item) => ({
|
|
id: crypto.randomUUID(),
|
|
itemId: item.itemId || itemId,
|
|
key: item.key,
|
|
value: item.value,
|
|
}),
|
|
)
|
|
|
|
try {
|
|
return await currentVault?.drizzle
|
|
.insert(haexPasswordsItemKeyValues)
|
|
.values(newKeyValues)
|
|
} catch (error) {
|
|
console.error('ERROR addItem', error)
|
|
}
|
|
}
|
|
|
|
const readByGroupIdAsync = async (groupId?: string | null) => {
|
|
try {
|
|
const { currentVault } = useVaultStore()
|
|
|
|
console.log('get entries by groupId', groupId || null)
|
|
|
|
if (groupId) {
|
|
const entries = await currentVault.drizzle
|
|
.select()
|
|
.from(haexPasswordsGroupItems)
|
|
.innerJoin(
|
|
haexPasswordsItemDetails,
|
|
eq(haexPasswordsItemDetails.id, haexPasswordsGroupItems.itemId),
|
|
)
|
|
.where(eq(haexPasswordsGroupItems.groupId, groupId))
|
|
|
|
console.log('found entries by groupId', entries)
|
|
return entries.map((entry) => entry.haex_passwords_item_details)
|
|
} else {
|
|
const entries = await currentVault.drizzle
|
|
.select()
|
|
.from(haexPasswordsGroupItems)
|
|
.innerJoin(
|
|
haexPasswordsItemDetails,
|
|
eq(haexPasswordsItemDetails.id, haexPasswordsGroupItems.itemId),
|
|
)
|
|
.where(isNull(haexPasswordsGroupItems.groupId))
|
|
|
|
console.log('found entries', entries)
|
|
return entries.map((entry) => entry.haex_passwords_item_details)
|
|
}
|
|
} catch (error) {
|
|
console.error(error)
|
|
return []
|
|
}
|
|
}
|
|
|
|
const readAsync = async (itemId: string | null) => {
|
|
if (!itemId) return null
|
|
|
|
try {
|
|
const { currentVault } = useVaultStore()
|
|
|
|
const details =
|
|
await currentVault.drizzle.query.haexPasswordsItemDetails.findFirst({
|
|
where: eq(haexPasswordsItemDetails.id, itemId),
|
|
})
|
|
|
|
console.log('readAsync details', details)
|
|
|
|
if (!details) return null
|
|
|
|
const history = (await usePasswordHistoryStore().getAsync(itemId)) ?? []
|
|
const keyValues = (await readKeyValuesAsync(itemId)) ?? []
|
|
|
|
console.log('found item by id', { details, history, keyValues })
|
|
return { details, history, keyValues }
|
|
} catch (error) {
|
|
console.error(error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
const readKeyValuesAsync = async (itemId: string | null) => {
|
|
if (!itemId) return null
|
|
const { currentVault } = useVaultStore()
|
|
|
|
const keyValues =
|
|
await currentVault.drizzle.query.haexPasswordsItemKeyValues.findMany({
|
|
where: eq(haexPasswordsGroupItems.itemId, itemId),
|
|
})
|
|
return keyValues
|
|
}
|
|
|
|
const updateAsync = async ({
|
|
details,
|
|
keyValues,
|
|
keyValuesAdd,
|
|
keyValuesDelete,
|
|
groupId,
|
|
}: {
|
|
details: SelectHaexPasswordsItemDetails
|
|
keyValues: SelectHaexPasswordsItemKeyValues[]
|
|
keyValuesAdd: SelectHaexPasswordsItemKeyValues[]
|
|
keyValuesDelete: SelectHaexPasswordsItemKeyValues[]
|
|
groupId: string | null
|
|
}) => {
|
|
const { currentVault } = useVaultStore()
|
|
|
|
if (!details.id) return
|
|
|
|
const newDetails: InsertHaexPasswordsItemDetails = {
|
|
id: details.id,
|
|
icon: details.icon,
|
|
note: details.note,
|
|
password: details.password,
|
|
tags: details.tags,
|
|
title: details.title,
|
|
url: details.url,
|
|
username: details.username,
|
|
}
|
|
|
|
const newKeyValues: InserthaexPasswordsItemKeyValues[] = keyValues
|
|
.map((keyValue) => ({
|
|
id: keyValue.id,
|
|
itemId: newDetails.id,
|
|
key: keyValue.key,
|
|
value: keyValue.value,
|
|
}))
|
|
.filter((keyValue) => keyValue.id)
|
|
|
|
const newKeyValuesAdd: InserthaexPasswordsItemKeyValues[] = keyValuesAdd.map(
|
|
(keyValue) => ({
|
|
id: keyValue.id || crypto.randomUUID(),
|
|
itemId: newDetails.id,
|
|
key: keyValue.key,
|
|
value: keyValue.value,
|
|
}),
|
|
)
|
|
|
|
console.log('update item', newDetails, newKeyValues, newKeyValuesAdd, groupId)
|
|
|
|
return await currentVault?.drizzle.transaction(async (tx) => {
|
|
await tx
|
|
.update(haexPasswordsItemDetails)
|
|
.set(newDetails)
|
|
.where(eq(haexPasswordsItemDetails.id, newDetails.id))
|
|
|
|
await tx
|
|
.update(haexPasswordsGroupItems)
|
|
.set({ itemId: newDetails.id, groupId })
|
|
.where(eq(haexPasswordsGroupItems.itemId, newDetails.id))
|
|
|
|
const promises = newKeyValues.map((keyValue) =>
|
|
tx
|
|
.update(haexPasswordsItemKeyValues)
|
|
.set(keyValue)
|
|
.where(eq(haexPasswordsItemKeyValues.id, keyValue.id)),
|
|
)
|
|
|
|
await Promise.all(promises)
|
|
|
|
if (newKeyValuesAdd.length)
|
|
await tx.insert(haexPasswordsItemKeyValues).values(newKeyValuesAdd)
|
|
|
|
const promisesDelete = keyValuesDelete.map((keyValue) =>
|
|
tx
|
|
.delete(haexPasswordsItemKeyValues)
|
|
.where(eq(haexPasswordsItemKeyValues.id, keyValue.id)),
|
|
)
|
|
await Promise.all(promisesDelete)
|
|
|
|
return newDetails.id
|
|
})
|
|
}
|
|
|
|
const deleteAsync = async (itemId: string, final: boolean = false) => {
|
|
const { currentVault } = useVaultStore()
|
|
const { createTrashIfNotExistsAsync, trashId } = usePasswordGroupStore()
|
|
|
|
console.log('deleteAsync', itemId, final)
|
|
if (final)
|
|
await currentVault?.drizzle.transaction(async (tx) => {
|
|
await tx
|
|
.delete(haexPasswordsItemKeyValues)
|
|
.where(eq(haexPasswordsItemKeyValues.itemId, itemId))
|
|
await tx
|
|
.delete(haexPasswordsItemHistory)
|
|
.where(eq(haexPasswordsItemHistory.itemId, itemId))
|
|
await tx
|
|
.delete(haexPasswordsGroupItems)
|
|
.where(eq(haexPasswordsGroupItems.itemId, itemId))
|
|
await tx
|
|
.delete(haexPasswordsItemDetails)
|
|
.where(eq(haexPasswordsItemDetails.id, itemId))
|
|
})
|
|
else {
|
|
if (await createTrashIfNotExistsAsync())
|
|
await currentVault.drizzle
|
|
.update(haexPasswordsGroupItems)
|
|
.set({ groupId: trashId })
|
|
.where(eq(haexPasswordsGroupItems.itemId, itemId))
|
|
}
|
|
}
|
|
|
|
const deleteKeyValueAsync = async (id: string) => {
|
|
console.log('deleteKeyValueAsync', id)
|
|
const { currentVault } = useVaultStore()
|
|
return await currentVault.drizzle
|
|
.delete(haexPasswordsItemKeyValues)
|
|
.where(eq(haexPasswordsItemKeyValues.id, id))
|
|
}
|
|
|
|
const areItemsEqual = (
|
|
groupA: unknown | unknown[] | null,
|
|
groupB: unknown | unknown[] | null,
|
|
) => {
|
|
if (groupA === null && groupB === null) return true
|
|
|
|
if (Array.isArray(groupA) && Array.isArray(groupB)) {
|
|
console.log('compare object arrays', groupA, groupB)
|
|
if (groupA.length === groupB.length) return true
|
|
|
|
return groupA.some((group, index) => {
|
|
return areObjectsEqual(group, groupA[index])
|
|
})
|
|
}
|
|
return areObjectsEqual(groupA, groupB)
|
|
} |