diff --git a/lib/ops/thread-activity-store-ops.js b/lib/ops/thread-activity-store-ops.js new file mode 100644 index 000000000..66f89fc1e --- /dev/null +++ b/lib/ops/thread-activity-store-ops.js @@ -0,0 +1,133 @@ +// @flow + +import { type BaseStoreOpsHandlers } from './base-ops.js'; +import type { + ThreadActivityStore, + ThreadActivityStoreEntry, +} from '../types/thread-activity-types.js'; + +// client types +export type ReplaceThreadActivityEntryOperation = { + +type: 'replace_thread_activity_entry', + +payload: { + +id: string, + +threadActivityStoreEntry: ThreadActivityStoreEntry, + }, +}; + +export type RemoveThreadActivityEntriesOperation = { + +type: 'remove_thread_activity_entries', + +payload: { +ids: $ReadOnlyArray }, +}; + +export type RemoveAllThreadActivityEntriesOperation = { + +type: 'remove_all_thread_activity_entries', +}; + +export type ThreadActivityStoreOperation = + | ReplaceThreadActivityEntryOperation + | RemoveThreadActivityEntriesOperation + | RemoveAllThreadActivityEntriesOperation; + +// SQLite types +export type ClientDBThreadActivityEntry = { + +id: string, + +threadActivityStoreEntry: string, +}; + +export type ClientDBReplaceThreadActivityEntryOperation = { + +type: 'replace_thread_activity_entry', + +payload: ClientDBThreadActivityEntry, +}; + +export type ClientDBThreadActivityStoreOperation = + | ClientDBReplaceThreadActivityEntryOperation + | RemoveThreadActivityEntriesOperation + | RemoveAllThreadActivityEntriesOperation; + +function convertThreadActivityEntryToClientDBThreadActivityEntry({ + id, + threadActivityStoreEntry, +}: { + +id: string, + +threadActivityStoreEntry: ThreadActivityStoreEntry, +}): ClientDBThreadActivityEntry { + return { + id, + threadActivityStoreEntry: JSON.stringify(threadActivityStoreEntry), + }; +} + +const threadActivityStoreOpsHandlers: BaseStoreOpsHandlers< + ThreadActivityStore, + ThreadActivityStoreOperation, + ClientDBThreadActivityStoreOperation, + ThreadActivityStore, + ClientDBThreadActivityEntry, +> = { + processStoreOperations( + threadActivityStore: ThreadActivityStore, + ops: $ReadOnlyArray, + ): ThreadActivityStore { + if (ops.length === 0) { + return threadActivityStore; + } + + let processedThreadActivityStore = threadActivityStore; + + for (const operation: ThreadActivityStoreOperation of ops) { + if (operation.type === 'replace_thread_activity_entry') { + const { id, threadActivityStoreEntry } = operation.payload; + processedThreadActivityStore = { + ...processedThreadActivityStore, + [id]: threadActivityStoreEntry, + }; + } else if (operation.type === 'remove_thread_activity_entries') { + for (const id of operation.payload.ids) { + const { [id]: _, ...rest } = processedThreadActivityStore; + processedThreadActivityStore = rest; + } + } else if (operation.type === 'remove_all_thread_activity_entries') { + processedThreadActivityStore = {}; + } + } + return processedThreadActivityStore; + }, + convertOpsToClientDBOps( + ops: $ReadOnlyArray, + ): $ReadOnlyArray { + return ops.map(threadActivityStoreOperation => { + if ( + threadActivityStoreOperation.type === + 'remove_all_thread_activity_entries' || + threadActivityStoreOperation.type === 'remove_thread_activity_entries' + ) { + return threadActivityStoreOperation; + } + + const { id, threadActivityStoreEntry } = + threadActivityStoreOperation.payload; + + return { + type: 'replace_thread_activity_entry', + payload: convertThreadActivityEntryToClientDBThreadActivityEntry({ + id, + threadActivityStoreEntry, + }), + }; + }); + }, + + translateClientDBData( + data: $ReadOnlyArray, + ): ThreadActivityStore { + return Object.fromEntries( + data.map((dbThreadActivityEntry: ClientDBThreadActivityEntry) => [ + dbThreadActivityEntry.id, + JSON.parse(dbThreadActivityEntry.threadActivityStoreEntry), + ]), + ); + }, +}; + +export { threadActivityStoreOpsHandlers };