Pinia Persistent Storage via AT Protocol for Open Web Desktop
1import { resolveActorServiceEndpoint, useAgent } from "#imports"
2
3export function parseAtprotoStoreKey(
4 key: string,
5): { collection: string; rkey: string } | null {
6 if (!key.startsWith('owd/')) return null
7
8 const parts = key.split('/')
9
10 if (parts[1] === 'application') {
11 const last = parts[parts.length - 1]
12 if (last === 'windows' || last === 'meta') {
13 const nome = parts.slice(2, -1).join('/')
14 return {
15 collection: `org.owdproject.application.${last}`,
16 rkey: nome,
17 }
18 }
19 }
20
21 // owd/desktop
22 if (parts[1] === 'desktop') {
23 const rkey = parts[2] ?? 'self'
24 return {
25 collection: 'org.owdproject.desktop',
26 rkey,
27 }
28 }
29
30 return null
31}
32
33export function listAtprotoApplicationStateRecords(
34 agent: any,
35 repo: string,
36 collection: string,
37) {
38 return agent.com.atproto.repo
39 .listRecords({
40 repo,
41 collection,
42 })
43 .then((response: any) => response.data)
44 .then((data: any) => data.records)
45 .catch(() => [])
46}
47
48export function getAtprotoApplicationState(
49 agent: any,
50 repo: string,
51 collection: string,
52 rkey: string,
53) {
54 return agent.com.atproto.repo.getRecord({
55 repo,
56 collection,
57 rkey,
58 })
59}
60
61export function putAtprotoApplicationState(
62 agent: any,
63 repo: string,
64 collection: string,
65 rkey: string,
66 record: any,
67) {
68 return agent.com.atproto.repo.putRecord({
69 repo,
70 collection,
71 rkey,
72 record,
73 })
74}
75
76/**
77 * Load actor desktop
78 *
79 * @param actorDid
80 */
81export async function loadActorDesktopStateMap(actorDid: string) {
82 const actorServiceEndpoint = await resolveActorServiceEndpoint(actorDid)
83 const actorAgent = useAgent(actorServiceEndpoint)
84
85 const [
86 atprotoActorDesktopRecord,
87 atprotoApplicationWindowsList,
88 atprotoApplicationMetaList,
89 ] = await Promise.allSettled([
90 getAtprotoApplicationState(
91 actorAgent,
92 actorDid,
93 'org.owdproject.desktop',
94 'self',
95 ),
96 listAtprotoApplicationStateRecords(
97 actorAgent,
98 actorDid,
99 'org.owdproject.application.windows',
100 ),
101 listAtprotoApplicationStateRecords(
102 actorAgent,
103 actorDid,
104 'org.owdproject.application.meta',
105 ),
106 ])
107
108 const stateMap: Record<string, any> = {}
109
110 // desktop state
111 if (
112 atprotoActorDesktopRecord.status === 'fulfilled' &&
113 atprotoActorDesktopRecord.value?.data
114 ) {
115 stateMap['owd/desktop'] = atprotoActorDesktopRecord.value.data.value
116 }
117
118 // windows state
119 if (atprotoApplicationWindowsList.status === 'fulfilled') {
120 for (const record of atprotoApplicationWindowsList.value) {
121 const appId = record.uri.split('/').pop()
122 stateMap[`owd/application/${appId}/windows`] = {
123 windows: record.value.windows,
124 }
125 }
126 }
127
128 // meta state
129 if (atprotoApplicationMetaList.status === 'fulfilled') {
130 for (const record of atprotoApplicationMetaList.value) {
131 const appId = record.uri.split('/').pop()
132 stateMap[`owd/application/${appId}/meta`] = {
133 ...record.value,
134 }
135 }
136 }
137
138 return stateMap
139}