/** * Entity management service */ import { transceivePost, transceiveStream } from './transceive'; import type { EntityListRequest, EntityListResponse, EntityFetchRequest, EntityFetchResponse, EntityExtantRequest, EntityExtantResponse, EntityCreateRequest, EntityCreateResponse, EntityUpdateRequest, EntityUpdateResponse, EntityDeleteRequest, EntityDeleteResponse, EntityDeltaRequest, EntityDeltaResponse, EntityTransmitRequest, EntityTransmitResponse, EntityInterface, EntityStreamRequest, EntityStreamResponse, } from '../types/entity'; import { useIntegrationStore } from '@KTXC/stores/integrationStore'; import { EntityObject } from '../models'; /** * Helper to create the right entity model class based on provider identifier * Uses provider-specific factory if available, otherwise returns base EntityObject */ function createEntityObject(data: EntityInterface): EntityObject { const integrationStore = useIntegrationStore(); const factoryItem = integrationStore.getItemById('mail_entity_factory', data.provider) as any; const factory = factoryItem?.factory; // Use provider factory if available, otherwise base class return factory ? factory(data) : new EntityObject().fromJson(data); } export const entityService = { /** * Retrieve list of entities, optionally filtered by source selector * * @param request - list request parameters * * @returns Promise with entity object list grouped by provider, service, collection, and entity identifier */ async list(request: EntityListRequest = {}): Promise>>>> { const response = await transceivePost('entity.list', request); // Convert nested response to EntityObject instances const providerList: Record>>> = {}; Object.entries(response).forEach(([providerId, providerServices]) => { const serviceList: Record>> = {}; Object.entries(providerServices).forEach(([serviceId, serviceCollections]) => { const collectionList: Record> = {}; Object.entries(serviceCollections).forEach(([collectionId, collectionEntities]) => { const entityList: Record = {}; Object.entries(collectionEntities).forEach(([entityId, entityData]) => { entityList[entityId] = createEntityObject(entityData); }); collectionList[collectionId] = entityList; }); serviceList[serviceId] = collectionList; }); providerList[providerId] = serviceList; }); return providerList; }, /** * Retrieve a specific entity by provider and identifier * * @param request - fetch request parameters * * @returns Promise with entity objects keyed by identifier */ async fetch(request: EntityFetchRequest): Promise> { const response = await transceivePost('entity.fetch', request); // Convert response to EntityObject instances const list: Record = {}; Object.entries(response).forEach(([identifier, entityData]) => { list[identifier] = createEntityObject(entityData); }); return list; }, /** * Retrieve entity availability status for a given source selector * * @param request - extant request parameters * * @returns Promise with entity availability status */ async extant(request: EntityExtantRequest): Promise { return await transceivePost('entity.extant', request); }, /** * Create a new entity * * @param request - create request parameters * * @returns Promise with created entity object */ async create(request: EntityCreateRequest): Promise { const response = await transceivePost('entity.create', request); return createEntityObject(response); }, /** * Update an existing entity * * @param request - update request parameters * * @returns Promise with updated entity object */ async update(request: EntityUpdateRequest): Promise { const response = await transceivePost('entity.update', request); return createEntityObject(response); }, /** * Delete an entity * * @param request - delete request parameters * * @returns Promise with deletion result */ async delete(request: EntityDeleteRequest): Promise { return await transceivePost('entity.delete', request); }, /** * Retrieve delta changes for entities * * @param request - delta request parameters * * @returns Promise with delta changes (created, modified, deleted) */ async delta(request: EntityDeltaRequest): Promise { return await transceivePost('entity.delta', request); }, /** * Send an entity * * @param request - transmit request parameters * * @returns Promise with transmission result */ async transmit(request: EntityTransmitRequest): Promise { return await transceivePost('entity.transmit', request); }, /** * Stream entities as NDJSON, invoking onEntity for each entity as it arrives. * * The server emits one entity per line so the caller receives entities * progressively rather than waiting for the full collection to load. * * @param request - stream request parameters (same shape as list) * @param onEntity - called synchronously for each entity as it is received * * @returns Promise resolving to { total } when the stream completes */ async stream( request: EntityStreamRequest, onEntity: (entity: EntityObject) => void ): Promise<{ total: number }> { return await transceiveStream( 'entity.stream', request, (entity) => { onEntity(createEntityObject(entity)); } ); }, }; export default entityService;