Pinia Persistent Storage via AT Protocol for Open Web Desktop
1import { createPersistedStatePlugin } from 'pinia-plugin-persistedstate-2'
2import { deepEqual } from '@owdproject/core/runtime/utils/utilCommon'
3import { defineNuxtPlugin, useRuntimeConfig } from 'nuxt/app'
4import { toRaw } from 'vue'
5import { usePinia, useRouter, useAtproto, useAgent } from '#imports'
6
7import localforage from 'localforage/src/localforage.js'
8import {
9 putAtprotoApplicationState,
10 parseAtprotoStoreKey,
11 loadActorDesktopStateMap
12} from './utils/utilAtprotoApplicationStates'
13
14export default defineNuxtPlugin({
15 name: 'owd-plugin-atproto-persistence',
16 dependsOn: ['owd-plugin-atproto'],
17 async setup() {
18 const pinia = usePinia()
19 const atproto = useAtproto()
20 const runtimeConfig = useRuntimeConfig()
21 const router = useRouter()
22
23 let states = {}
24 let actorDid = undefined
25
26 if (router.currentRoute.value.params.did) {
27 actorDid = router.currentRoute.value.params.did
28 } else {
29 if (
30 runtimeConfig.public.atprotoPersistence &&
31 runtimeConfig.public.atprotoPersistence.loadOwnerDesktopOnMounted
32 ) {
33 actorDid = runtimeConfig.public.atprotoDesktop.owner.did
34 }
35 }
36
37 if (actorDid) {
38 states = await loadActorDesktopStateMap(runtimeConfig.public.atprotoDesktop.owner.did)
39 }
40
41 pinia.use(
42 createPersistedStatePlugin({
43 persist: false,
44 storage: {
45 getItem: async (piniaKey) => {
46
47 if (states.hasOwnProperty(piniaKey)) {
48 return JSON.stringify(states[piniaKey])
49 }
50
51 return localforage.getItem(piniaKey)
52 },
53 setItem: async (piniaKey, piniaValue) => {
54 const previousPiniaValue = await localforage.getItem(piniaKey)
55 await localforage.setItem(piniaKey, piniaValue)
56
57 const atprotoTargetRecord = parseAtprotoStoreKey(piniaKey)
58
59 if (!atprotoTargetRecord || !atproto.isLogged()) {
60 return piniaValue
61 }
62
63 const { collection, rkey } = atprotoTargetRecord
64
65 if (deepEqual(toRaw(piniaValue), toRaw(previousPiniaValue))) {
66 return piniaValue
67 }
68
69 const agent = useAgent('private')
70
71 return putAtprotoApplicationState(
72 agent,
73 agent.assertDid,
74 collection,
75 rkey,
76 JSON.parse(piniaValue),
77 )
78 },
79 removeItem: async (key) => {
80 await localforage.removeItem(key)
81 },
82 },
83 }),
84 )
85 },
86})