import Storage, { Collection, OutOfSyncError } from '../core/storage' import Engine from './Engine' export default class LocalStorage implements Storage { private readonly engine: Engine> constructor( private readonly ownerId: string, private readonly storageId: string, private readonly getItemId = item => item['id'], ) { this.engine = new Engine>(window.localStorage) } private getMeta() { const oldMeta = this.engine.getCollection(this.storageId) if (oldMeta === null) { throw new OutOfSyncError() } return oldMeta } private existenceCheck(newItem: T) { return oldItem => this.getItemId(oldItem) === this.getItemId(newItem) } async queryItems() { return this.getMeta().items } async saveItem(newItem: T) { const oldMeta = this.getMeta() const isExistingItem = oldMeta.items.some(this.existenceCheck(newItem)) const newMeta: Collection = { items: isExistingItem ? oldMeta.items.map(oldItem => this.existenceCheck(newItem)(oldItem) ? newItem : oldItem) : [...oldMeta.items, newItem], lastModifiedBy: this.ownerId, lastModifiedAt: new Date(), } this.engine.replaceCollection(this.storageId, newMeta) } async deleteItem(newItem: T) { const oldMeta = this.getMeta() const newItems = oldMeta.items.filter(oldItem => !this.existenceCheck(newItem)(oldItem)) const newMeta: Collection = { items: newItems, lastModifiedBy: this.ownerId, lastModifiedAt: new Date(), } this.engine.replaceCollection(this.storageId, newMeta) return oldMeta.items.length !== newItems.length } }