a tool for shared writing and social publishing
1import { createClient } from "@supabase/supabase-js";
2import { Database } from "supabase/database.types";
3import * as fs from "fs";
4import * as path from "path";
5
6const DID = "did:plc:x2xmijn2egk5g67u3cwkddzy";
7
8// Backup database connection
9const BACKUP_DB_URL = "https://bjhtnewlvuekinenkoga.supabase.co";
10const BACKUP_SERVICE_ROLE_KEY = process.env.BACKUP_SUPABASE_SERVICE_ROLE_KEY;
11
12if (!BACKUP_SERVICE_ROLE_KEY) {
13 console.error("Error: BACKUP_SUPABASE_SERVICE_ROLE_KEY environment variable is required");
14 process.exit(1);
15}
16
17const supabase = createClient<Database>(BACKUP_DB_URL, BACKUP_SERVICE_ROLE_KEY);
18
19async function main() {
20 console.log("=== Extracting Backup Data ===");
21 console.log(`DID: ${DID}`);
22 console.log(`Backup DB: ${BACKUP_DB_URL}`);
23 console.log("");
24
25 // 1. Publications (site.standard only)
26 console.log("Fetching publications...");
27 const { data: publications, error: pubError } = await supabase
28 .from("publications")
29 .select("*")
30 .like("uri", `at://${DID}/site.standard.publication/%`);
31
32 if (pubError) throw new Error(`Failed to fetch publications: ${pubError.message}`);
33 console.log(` Found ${publications?.length ?? 0} publications`);
34
35 // 2. Documents (site.standard only)
36 console.log("Fetching documents...");
37 const { data: documents, error: docError } = await supabase
38 .from("documents")
39 .select("*")
40 .like("uri", `at://${DID}/site.standard.document/%`);
41
42 if (docError) throw new Error(`Failed to fetch documents: ${docError.message}`);
43 console.log(` Found ${documents?.length ?? 0} documents`);
44
45 // 3. Documents in Publications (for site.standard publications)
46 console.log("Fetching documents_in_publications...");
47 const { data: documentsInPublications, error: dipError } = await supabase
48 .from("documents_in_publications")
49 .select("*")
50 .like("publication", `at://${DID}/site.standard.publication/%`);
51
52 if (dipError) throw new Error(`Failed to fetch documents_in_publications: ${dipError.message}`);
53 console.log(` Found ${documentsInPublications?.length ?? 0} documents_in_publications`);
54
55 // 4. Publication Subscriptions (OTHER users subscribed to user's publications)
56 console.log("Fetching publication_subscriptions...");
57 const { data: publicationSubscriptions, error: subError } = await supabase
58 .from("publication_subscriptions")
59 .select("*")
60 .like("publication", `at://${DID}/site.standard.publication/%`);
61
62 if (subError) throw new Error(`Failed to fetch publication_subscriptions: ${subError.message}`);
63 console.log(` Found ${publicationSubscriptions?.length ?? 0} publication_subscriptions`);
64
65 // 5. Recommends on user's documents (OTHER users' recommends)
66 console.log("Fetching recommends_on_documents...");
67 const { data: recommendsOnDocuments, error: recError } = await supabase
68 .from("recommends_on_documents")
69 .select("*")
70 .like("document", `at://${DID}/site.standard.document/%`);
71
72 if (recError) throw new Error(`Failed to fetch recommends_on_documents: ${recError.message}`);
73 console.log(` Found ${recommendsOnDocuments?.length ?? 0} recommends_on_documents`);
74
75 // 6. Comments on user's site.standard documents
76 console.log("Fetching comments_on_documents...");
77 const { data: comments, error: commentError } = await supabase
78 .from("comments_on_documents")
79 .select("*")
80 .like("document", `at://${DID}/site.standard.document/%`);
81
82 if (commentError) throw new Error(`Failed to fetch comments_on_documents: ${commentError.message}`);
83 console.log(` Found ${comments?.length ?? 0} comments_on_documents`);
84
85 // 7. Document mentions in bsky
86 console.log("Fetching document_mentions_in_bsky...");
87 const { data: documentMentions, error: mentionError } = await supabase
88 .from("document_mentions_in_bsky")
89 .select("*")
90 .like("document", `at://${DID}/site.standard.document/%`);
91
92 if (mentionError) throw new Error(`Failed to fetch document_mentions_in_bsky: ${mentionError.message}`);
93 console.log(` Found ${documentMentions?.length ?? 0} document_mentions_in_bsky`);
94
95 // 8. Leaflets in publications (site.standard only)
96 console.log("Fetching leaflets_in_publications...");
97 const { data: leafletsInPublications, error: lipError } = await supabase
98 .from("leaflets_in_publications")
99 .select("*")
100 .like("publication", `at://${DID}/site.standard.publication/%`);
101
102 if (lipError) throw new Error(`Failed to fetch leaflets_in_publications: ${lipError.message}`);
103 console.log(` Found ${leafletsInPublications?.length ?? 0} leaflets_in_publications`);
104
105 // 9. Leaflets to documents (site.standard only)
106 console.log("Fetching leaflets_to_documents...");
107 const { data: leafletsToDocuments, error: ltdError } = await supabase
108 .from("leaflets_to_documents")
109 .select("*")
110 .like("document", `at://${DID}/site.standard.document/%`);
111
112 if (ltdError) throw new Error(`Failed to fetch leaflets_to_documents: ${ltdError.message}`);
113 console.log(` Found ${leafletsToDocuments?.length ?? 0} leaflets_to_documents`);
114
115 // 10. Publication domains
116 console.log("Fetching publication_domains...");
117 const { data: publicationDomains, error: pdError } = await supabase
118 .from("publication_domains")
119 .select("*")
120 .like("publication", `at://${DID}/site.standard.publication/%`);
121
122 if (pdError) throw new Error(`Failed to fetch publication_domains: ${pdError.message}`);
123 console.log(` Found ${publicationDomains?.length ?? 0} publication_domains`);
124
125 // Build output object
126 const output = {
127 did: DID,
128 publications: (publications ?? []).map((p) => ({
129 uri: p.uri,
130 identity_did: p.identity_did,
131 name: p.name,
132 record: p.record,
133 indexed_at: p.indexed_at,
134 })),
135 documents: (documents ?? []).map((d) => ({
136 uri: d.uri,
137 data: d.data,
138 indexed_at: d.indexed_at,
139 })),
140 documentsInPublications: (documentsInPublications ?? []).map((dip) => ({
141 publication: dip.publication,
142 document: dip.document,
143 indexed_at: dip.indexed_at,
144 })),
145 publicationSubscriptions: (publicationSubscriptions ?? []).map((sub) => ({
146 publication: sub.publication,
147 identity: sub.identity,
148 created_at: sub.created_at,
149 record: sub.record,
150 uri: sub.uri,
151 })),
152 recommendsOnDocuments: (recommendsOnDocuments ?? []).map((rec) => ({
153 uri: rec.uri,
154 record: rec.record,
155 document: rec.document,
156 recommender_did: rec.recommender_did,
157 indexed_at: rec.indexed_at,
158 })),
159 comments: (comments ?? []).map((c) => ({
160 uri: c.uri,
161 document: c.document,
162 record: c.record,
163 profile: c.profile,
164 indexed_at: c.indexed_at,
165 })),
166 documentMentions: (documentMentions ?? []).map((m) => ({
167 uri: m.uri,
168 document: m.document,
169 link: m.link,
170 indexed_at: m.indexed_at,
171 })),
172 leafletsInPublications: (leafletsInPublications ?? []).map((lip) => ({
173 publication: lip.publication,
174 leaflet: lip.leaflet,
175 doc: lip.doc,
176 archived: lip.archived,
177 title: lip.title,
178 description: lip.description,
179 cover_image: lip.cover_image,
180 tags: lip.tags,
181 })),
182 leafletsToDocuments: (leafletsToDocuments ?? []).map((ltd) => ({
183 leaflet: ltd.leaflet,
184 document: ltd.document,
185 title: ltd.title,
186 description: ltd.description,
187 created_at: ltd.created_at,
188 })),
189 publicationDomains: (publicationDomains ?? []).map((pd) => ({
190 publication: pd.publication,
191 domain: pd.domain,
192 identity: pd.identity,
193 created_at: pd.created_at,
194 })),
195 };
196
197 // Write to file
198 const outputPath = path.join(__dirname, "backup-data", "user-restore-data.json");
199 fs.writeFileSync(outputPath, JSON.stringify(output, null, 2));
200
201 console.log("");
202 console.log("=== Extraction Complete ===");
203 console.log(`Output written to: ${outputPath}`);
204 console.log("");
205 console.log("Summary:");
206 console.log(` Publications: ${output.publications.length}`);
207 console.log(` Documents: ${output.documents.length}`);
208 console.log(` Documents in Publications: ${output.documentsInPublications.length}`);
209 console.log(` Publication Subscriptions: ${output.publicationSubscriptions.length}`);
210 console.log(` Recommends on Documents: ${output.recommendsOnDocuments.length}`);
211 console.log(` Comments: ${output.comments.length}`);
212 console.log(` Document Mentions: ${output.documentMentions.length}`);
213 console.log(` Leaflets in Publications: ${output.leafletsInPublications.length}`);
214 console.log(` Leaflets to Documents: ${output.leafletsToDocuments.length}`);
215 console.log(` Publication Domains: ${output.publicationDomains.length}`);
216}
217
218main().catch(console.error);