/** * Collections Store */ import { ref, computed, readonly } from 'vue' import { defineStore } from 'pinia' import { type ServiceIdentifier, type CollectionIdentifier, type ListFilter, type ListSort, } from '../types' import { collectionService } from '../services' import { CollectionObject, CollectionPropertiesObject } from '../models/collection' export const useCollectionsStore = defineStore('chronoCollectionsStore', () => { // State const _collections = ref>({}) const transceiving = ref(false) /** * Get count of collections in store */ const count = computed(() => Object.keys(_collections.value).length) /** * Check if any collections are present in store */ const has = computed(() => count.value > 0) /** * Get all collections present in store */ const collections = computed(() => Object.values(_collections.value)) /** * Get all collections present in store grouped by service */ const collectionsByService = computed(() => { const groups: Record = {} Object.values(_collections.value).forEach((collection) => { const serviceKey = `${collection.provider}:${collection.service}` const serviceCollections = (groups[serviceKey] ??= []) serviceCollections.push(collection) }) return groups }) /** * Get a specific collection from store, with optional retrieval */ function collection(target: CollectionIdentifier, retrieve: boolean = false): CollectionObject | null { if (retrieve === true && !_collections.value[target]) { console.debug(`[Chrono Manager][Store] - Force fetching collection "${target}"`) fetch([target]) } return _collections.value[target] || null } /** * Get all collections for a specific service */ function collectionsForService(provider: string, service: string | number, retrieve: boolean = false): CollectionObject[] { const serviceIdentifier = `${provider}:${service}` as ServiceIdentifier const serviceCollections = Object.values(_collections.value) .filter(collection => `${collection.provider}:${collection.service}` === serviceIdentifier) if (retrieve === true && serviceCollections.length === 0) { console.debug(`[Chrono Manager][Store] - Force fetching collections for service "${serviceIdentifier}"`) list([serviceIdentifier]) } return serviceCollections } /** * Retrieve all or specific collections, optionally filtered by service/collection identifiers */ async function list(sources?: ServiceIdentifier[] | CollectionIdentifier[], filter?: ListFilter, sort?: ListSort): Promise> { transceiving.value = true try { const response = await collectionService.list({ sources, filter, sort }) const collections: Record = {} Object.entries(response).forEach(([_providerId, providerServices]) => { Object.entries(providerServices).forEach(([_serviceId, serviceCollections]) => { Object.entries(serviceCollections).forEach(([_collectionId, collectionObj]) => { collections[collectionObj.identifier] = collectionObj }) }) }) _collections.value = { ..._collections.value, ...collections } console.debug('[Chrono Manager][Store] - Successfully retrieved', Object.keys(collections).length, 'collections') return collections } catch (error: any) { console.error('[Chrono Manager][Store] - Failed to retrieve collections:', error) throw error } finally { transceiving.value = false } } /** * Retrieve specific collections by their identifiers */ async function fetch(targets: CollectionIdentifier[]): Promise> { transceiving.value = true try { const response = await collectionService.fetch({ targets }) Object.values(response).forEach(collectionObj => { _collections.value[collectionObj.identifier] = collectionObj }) console.debug('[Chrono Manager][Store] - Successfully fetched collections:', Object.keys(response).join(', ')) return response } catch (error: any) { console.error('[Chrono Manager][Store] - Failed to fetch collections:', error) throw error } finally { transceiving.value = false } } /** * Retrieve collection availability status for the given collection identifiers */ async function extant(targets: CollectionIdentifier[]): Promise>>> { transceiving.value = true try { const response = await collectionService.extant({ targets }) console.debug('[Chrono Manager][Store] - Successfully checked', targets ? targets.length : 0, 'collections') return response } catch (error: any) { console.error('[Chrono Manager][Store] - Failed to check collections:', error) throw error } finally { transceiving.value = false } } /** * Create a new collection with given provider, service, and properties */ async function create(provider: string, service: string | number, properties: CollectionPropertiesObject): Promise { transceiving.value = true try { const response = await collectionService.create({ provider, service, properties: properties.toJson(), }) _collections.value[response.identifier] = response console.debug('[Chrono Manager][Store] - Successfully created collection:', response.identifier) return response } catch (error: any) { console.error('[Chrono Manager][Store] - Failed to create collection:', error) throw error } finally { transceiving.value = false } } /** * Update an existing collection with given target and properties */ async function update(target: CollectionIdentifier, properties: CollectionPropertiesObject): Promise { transceiving.value = true try { const response = await collectionService.update({ target, properties: properties.toJson(), }) _collections.value[response.identifier] = response console.debug('[Chrono Manager][Store] - Successfully updated collection:', response.identifier) return response } catch (error: any) { console.error('[Chrono Manager][Store] - Failed to update collection:', error) throw error } finally { transceiving.value = false } } /** * Delete a collection by identifier. */ async function remove(target: CollectionIdentifier, force?: boolean): Promise { transceiving.value = true try { const response = await collectionService.delete({ target, options: { force } }) if (response !== true && !(response instanceof CollectionObject)) { console.warn('[Chrono Manager][Store] - Delete failed. Received unexpected response from delete operation:', response) return false } delete _collections.value[target] if (response instanceof CollectionObject) { _collections.value[response.identifier] = response console.debug('[Chrono Manager][Store] - Successfully moved collection', target, '->', response.identifier) return response } console.debug('[Chrono Manager][Store] - Successfully deleted collection:', target) return response } catch (error: any) { console.error('[Chrono Manager][Store] - Failed to delete collection:', error) throw error } finally { transceiving.value = false } } return { transceiving: readonly(transceiving), count, has, collections, collectionsByService, collectionsForService, collection, list, fetch, extant, create, update, delete: remove, } })