Files
documents_manager/src/stores/nodesStore.ts
T
Sebastian ccb781f933 refactor: front end
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
2026-03-28 12:47:21 -04:00

342 lines
9.9 KiB
TypeScript

/**
* Nodes Store (thin wrapper over collections/entities stores)
*/
import { computed, ref, readonly } from 'vue'
import { defineStore } from 'pinia'
import type {
SourceSelector,
ListFilter,
ListSort,
ListRange,
CollectionMutableProperties,
DocumentInterface,
} from '../types'
import { CollectionObject, EntityObject } from '../models'
import { useCollectionsStore } from './collectionsStore'
import { useEntitiesStore } from './entitiesStore'
export const ROOT_ID = '00000000-0000-0000-0000-000000000000'
type NodeRecord = CollectionObject | EntityObject
export const useNodesStore = defineStore('documentsNodesStore', () => {
const collectionsStore = useCollectionsStore()
const entitiesStore = useEntitiesStore()
const error = ref<string | null>(null)
const transceiving = computed(() => collectionsStore.transceiving || entitiesStore.transceiving)
const nodeList = computed<NodeRecord[]>(() => {
return [...collectionsStore.collections, ...entitiesStore.entities]
})
const collectionList = computed<CollectionObject[]>(() => collectionsStore.collections)
const entityList = computed<EntityObject[]>(() => entitiesStore.entities)
function toId(value: string | number | null | undefined): string | null {
if (value === null || value === undefined || value === '') {
return null
}
return String(value)
}
function getServiceNodes(providerId: string, serviceId: string | number): NodeRecord[] {
return [
...collectionsStore.collectionsForService(providerId, serviceId),
...entitiesStore.entitiesForService(providerId, serviceId),
]
}
function getNode(providerId: string, serviceId: string | number, nodeId: string | number): NodeRecord | undefined {
const targetId = String(nodeId)
return getServiceNodes(providerId, serviceId)
.find((node) => String(node.identifier) === targetId)
}
function isRoot(nodeId: string | number | null | undefined): boolean {
const normalized = toId(nodeId)
return normalized === null || normalized === ROOT_ID
}
function getChildren(providerId: string, serviceId: string | number, parentId: string | number | null): NodeRecord[] {
const serviceNodes = getServiceNodes(providerId, serviceId)
if (isRoot(parentId)) {
return serviceNodes.filter((node) => {
const parent = toId(node.collection)
return parent === null || parent === ROOT_ID
})
}
const targetParent = String(parentId)
return serviceNodes.filter((node) => toId(node.collection) === targetParent)
}
function getChildCollections(providerId: string, serviceId: string | number, parentId: string | number | null): CollectionObject[] {
return getChildren(providerId, serviceId, parentId)
.filter((node): node is CollectionObject => node instanceof CollectionObject)
}
function getChildEntities(providerId: string, serviceId: string | number, parentId: string | number | null): EntityObject[] {
return getChildren(providerId, serviceId, parentId)
.filter((node): node is EntityObject => node instanceof EntityObject)
}
function getPath(providerId: string, serviceId: string | number, nodeId: string | number): NodeRecord[] {
const path: NodeRecord[] = []
let current = getNode(providerId, serviceId, nodeId)
while (current) {
path.unshift(current)
const parentId = toId(current.collection)
if (parentId === null || parentId === ROOT_ID) {
break
}
current = getNode(providerId, serviceId, parentId)
}
return path
}
async function fetchCollections(
providerId: string,
serviceId: string | number,
collectionId: string | number | null,
filter?: ListFilter,
sort?: ListSort,
): Promise<CollectionObject[]> {
error.value = null
try {
const sources: SourceSelector = {
[providerId]: {
[String(serviceId)]: collectionId === null
? true
: { [String(collectionId)]: true },
},
}
await collectionsStore.list(sources, filter, sort)
return collectionsStore.collectionsForService(providerId, serviceId)
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to fetch collections'
throw e
}
}
async function fetchEntities(
providerId: string,
serviceId: string | number,
collectionId: string | number | null,
filter?: ListFilter,
sort?: ListSort,
range?: ListRange,
): Promise<EntityObject[]> {
error.value = null
try {
const sources: SourceSelector = {
[providerId]: {
[String(serviceId)]: collectionId === null
? true
: { [String(collectionId)]: true },
},
}
await entitiesStore.list(sources, filter, sort, range)
return entitiesStore.entitiesForCollection(providerId, serviceId, collectionId)
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to fetch entities'
throw e
}
}
async function fetchNodes(
providerId: string,
serviceId: string | number,
parentId: string | number | null = ROOT_ID,
filter?: ListFilter,
sort?: ListSort,
range?: ListRange,
): Promise<NodeRecord[]> {
error.value = null
try {
await Promise.all([
fetchCollections(providerId, serviceId, parentId, filter, sort),
fetchEntities(providerId, serviceId, parentId, filter, sort, range),
])
return getChildren(providerId, serviceId, parentId)
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to fetch nodes'
throw e
}
}
async function createCollection(
providerId: string,
serviceId: string | number,
parentCollectionId: string | number | null,
properties: CollectionMutableProperties,
): Promise<CollectionObject> {
error.value = null
try {
return await collectionsStore.create(providerId, serviceId, parentCollectionId, properties)
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to create collection'
throw e
}
}
async function updateCollection(
providerId: string,
serviceId: string | number,
identifier: string | number,
properties: CollectionMutableProperties,
): Promise<CollectionObject> {
error.value = null
try {
return await collectionsStore.update(providerId, serviceId, identifier, properties)
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to update collection'
throw e
}
}
async function deleteCollection(
providerId: string,
serviceId: string | number,
identifier: string | number,
): Promise<boolean> {
error.value = null
try {
const response = await collectionsStore.delete(providerId, serviceId, identifier)
return response.success
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to delete collection'
throw e
}
}
async function createEntity(
providerId: string,
serviceId: string | number,
collectionId: string | number,
properties: DocumentInterface,
options?: Record<string, unknown>,
): Promise<EntityObject> {
error.value = null
try {
return await entitiesStore.create(providerId, serviceId, collectionId, properties, options)
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to create entity'
throw e
}
}
async function updateEntity(
providerId: string,
serviceId: string | number,
collectionId: string | number,
identifier: string | number,
properties: DocumentInterface,
): Promise<EntityObject> {
error.value = null
try {
return await entitiesStore.update(providerId, serviceId, collectionId, identifier, properties)
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to update entity'
throw e
}
}
async function deleteEntity(
providerId: string,
serviceId: string | number,
collectionId: string | number,
identifier: string | number,
): Promise<boolean> {
error.value = null
try {
const response = await entitiesStore.delete(providerId, serviceId, collectionId, identifier)
return response.success
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to delete entity'
throw e
}
}
async function readEntity(
providerId: string,
serviceId: string | number,
collectionId: string | number,
identifier: string | number,
): Promise<string | null> {
error.value = null
try {
return await entitiesStore.read(providerId, serviceId, collectionId, identifier)
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to read entity'
throw e
}
}
async function writeEntity(
providerId: string,
serviceId: string | number,
collectionId: string | number,
identifier: string | number,
content: string,
): Promise<number> {
error.value = null
try {
return await entitiesStore.write(providerId, serviceId, collectionId, identifier, content)
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to write entity'
throw e
}
}
function clearServiceNodes(providerId: string, serviceId: string | number): void {
collectionsStore.clearService(providerId, serviceId)
entitiesStore.clearService(providerId, serviceId)
}
function clearNodes(): void {
collectionsStore.clearAll()
entitiesStore.clearAll()
}
return {
transceiving: readonly(transceiving),
error: readonly(error),
ROOT_ID,
nodeList,
collectionList,
entityList,
getNode,
getServiceNodes,
getChildren,
getChildCollections,
getChildEntities,
getPath,
isRoot,
fetchNodes,
fetchCollections,
fetchEntities,
createCollection,
updateCollection,
deleteCollection,
createEntity,
updateEntity,
deleteEntity,
readEntity,
writeEntity,
clearServiceNodes,
clearNodes,
}
})