|
|
@@ -0,0 +1,55 @@ |
|
|
|
import Storage, { Collection, OutOfSyncError } from '../../core/src/storage' |
|
|
|
import Engine from './Engine' |
|
|
|
|
|
|
|
export default class LocalStorage<T> implements Storage<T> { |
|
|
|
private readonly engine: Engine<Collection<T>> |
|
|
|
|
|
|
|
constructor( |
|
|
|
private readonly ownerId: string, |
|
|
|
private readonly storageId: string, |
|
|
|
private readonly getItemId = item => item['id'], |
|
|
|
) { |
|
|
|
this.engine = new Engine<Collection<T>>(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<T> = { |
|
|
|
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<T> = { |
|
|
|
items: newItems, |
|
|
|
lastModifiedBy: this.ownerId, |
|
|
|
lastModifiedAt: new Date(), |
|
|
|
} |
|
|
|
this.engine.replaceCollection(this.storageId, newMeta) |
|
|
|
return oldMeta.items.length !== newItems.length |
|
|
|
} |
|
|
|
} |