Save and load notes in Zeichen using an external API.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

71 Zeilen
2.4 KiB

  1. import { Deserializer, Serializer } from '../../core/src/storage'
  2. const CREATED = 201
  3. const NO_CONTENT = 204
  4. const NOT_FOUND = 404
  5. const GONE = 410
  6. export default class RemoteStorage<U, T> {
  7. constructor(
  8. private readonly baseUrl: string,
  9. private readonly getItemId = item => item['id'],
  10. private readonly serializers: Map<string, Serializer> = new Map([
  11. ['*/*', JSON.stringify],
  12. ['application/json', JSON.stringify],
  13. ['text/json', JSON.stringify],
  14. ]),
  15. private readonly deserializers: Map<string, Deserializer> = new Map([
  16. ['*/*', JSON.parse],
  17. ['application/json', JSON.parse],
  18. ['text/json', JSON.parse],
  19. ]),
  20. ) {}
  21. async getCollection(collectionId: string) {
  22. const response = await window.fetch([this.baseUrl, collectionId].join('/'))
  23. const contentType = response.headers.get('content-type')
  24. const { [contentType]: deserializer = this.deserializers.get('*/*'), } = Object.fromEntries(this.deserializers.entries())
  25. const payload = await response.text()
  26. return deserializer(payload)
  27. }
  28. async setItem(collectionId: string, item: U, contentType = 'application/json') {
  29. const { [contentType]: serializer = this.serializers.get('application/json'), } = Object.fromEntries(this.serializers.entries())
  30. const response = await window.fetch([this.baseUrl, collectionId, this.getItemId(item)].join('/'), {
  31. method: 'put',
  32. body: serializer(item),
  33. })
  34. // resource is created
  35. if (response.status === CREATED) {
  36. return
  37. }
  38. if (100 <= response.status && response.status <= 399) {
  39. console.warn(`Expected response is ${CREATED}, got ${response.status}.`)
  40. return
  41. }
  42. throw new Error(response.statusText)
  43. }
  44. async removeItem(collectionId: string, item: U) {
  45. const response = await window.fetch([this.baseUrl, collectionId, this.getItemId(item)].join('/'), {
  46. method: 'delete',
  47. })
  48. // resource is deleted
  49. if (response.status === NO_CONTENT) {
  50. return true
  51. }
  52. // resource is already deleted
  53. if (response.status === NOT_FOUND || response.status === GONE) {
  54. return false
  55. }
  56. if (100 <= response.status && response.status <= 399) {
  57. console.warn(`Expected response is ${NO_CONTENT}, got ${response.status}.`)
  58. // assume there's a change in the collection
  59. return true
  60. }
  61. throw new Error(response.statusText)
  62. }
  63. // TODO do removeCollection for account closing?
  64. }