Monorepo containing core modules of Zeichen.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Storage.ts 1.6 KiB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import Storage, { Collection, OutOfSyncError } from '../core/storage'
  2. import Engine from './Engine'
  3. export default class LocalStorage<T> implements Storage<T> {
  4. private readonly engine: Engine<Collection<T>>
  5. constructor(
  6. private readonly ownerId: string,
  7. private readonly storageId: string,
  8. private readonly getItemId = item => item['id'],
  9. ) {
  10. this.engine = new Engine<Collection<T>>(window.localStorage)
  11. }
  12. private getMeta() {
  13. const oldMeta = this.engine.getCollection(this.storageId)
  14. if (oldMeta === null) {
  15. throw new OutOfSyncError()
  16. }
  17. return oldMeta
  18. }
  19. private existenceCheck(newItem: T) {
  20. return oldItem => this.getItemId(oldItem) === this.getItemId(newItem)
  21. }
  22. async queryItems() {
  23. return this.getMeta().items
  24. }
  25. async saveItem(newItem: T) {
  26. const oldMeta = this.getMeta()
  27. const isExistingItem = oldMeta.items.some(this.existenceCheck(newItem))
  28. const newMeta: Collection<T> = {
  29. items: isExistingItem
  30. ? oldMeta.items.map(oldItem => this.existenceCheck(newItem)(oldItem) ? newItem : oldItem)
  31. : [...oldMeta.items, newItem],
  32. lastModifiedBy: this.ownerId,
  33. lastModifiedAt: new Date(),
  34. }
  35. this.engine.replaceCollection(this.storageId, newMeta)
  36. }
  37. async deleteItem(newItem: T) {
  38. const oldMeta = this.getMeta()
  39. const newItems = oldMeta.items.filter(oldItem => !this.existenceCheck(newItem)(oldItem))
  40. const newMeta: Collection<T> = {
  41. items: newItems,
  42. lastModifiedBy: this.ownerId,
  43. lastModifiedAt: new Date(),
  44. }
  45. this.engine.replaceCollection(this.storageId, newMeta)
  46. return oldMeta.items.length !== newItems.length
  47. }
  48. }