Markdown -> Semble importer
1import type {Agent} from "@atproto/api";
2import type {RepoRecordGroups} from "./diff";
3import type {AtprotoDraftRecords, MockStrongRef} from "./record-builder";
4
5export async function createSembleRecords(
6 agent: Agent,
7 repo: string,
8 drafts: AtprotoDraftRecords,
9 existing?: RepoRecordGroups
10): Promise<{created: number; failures: Array<{rkey: string; error: string}>}> {
11 const failures: Array<{rkey: string; error: string}> = [];
12 let created = 0;
13
14 const collectionRefs = new Map<string, MockStrongRef>();
15 if (existing) {
16 for (const entry of existing.collections) {
17 const name = extractCollectionName(entry.value);
18 if (!name || !entry.cid) continue;
19 collectionRefs.set(name, {uri: entry.uri, cid: entry.cid});
20 }
21 }
22
23 const cardRefs = new Map<string, MockStrongRef>();
24
25 for (const envelope of drafts.collections) {
26 try {
27 const response = await agent.com.atproto.repo.createRecord({
28 repo,
29 collection: envelope.collection,
30 rkey: envelope.rkey,
31 record: envelope.record
32 });
33 if (envelope.recordId && response.data.cid) {
34 collectionRefs.set(envelope.recordId, {uri: response.data.uri, cid: response.data.cid});
35 }
36 created += 1;
37 } catch (error) {
38 failures.push({
39 rkey: envelope.rkey,
40 error: error instanceof Error ? error.message : String(error)
41 });
42 }
43 }
44
45 for (const envelope of drafts.cards) {
46 try {
47 const response = await agent.com.atproto.repo.createRecord({
48 repo,
49 collection: envelope.collection,
50 rkey: envelope.rkey,
51 record: envelope.record
52 });
53 if (envelope.recordId && response.data.cid) {
54 cardRefs.set(envelope.recordId, {uri: response.data.uri, cid: response.data.cid});
55 }
56 created += 1;
57 } catch (error) {
58 failures.push({
59 rkey: envelope.rkey,
60 error: error instanceof Error ? error.message : String(error)
61 });
62 }
63 }
64
65 for (const envelope of drafts.notes) {
66 const cardRef = envelope.cardId ? cardRefs.get(envelope.cardId) : undefined;
67 if (!cardRef) {
68 failures.push({rkey: envelope.rkey, error: "Missing parent card ref for note."});
69 continue;
70 }
71
72 try {
73 const record = {...envelope.record, parentCard: cardRef};
74 await agent.com.atproto.repo.createRecord({
75 repo,
76 collection: envelope.collection,
77 rkey: envelope.rkey,
78 record
79 });
80 created += 1;
81 } catch (error) {
82 failures.push({
83 rkey: envelope.rkey,
84 error: error instanceof Error ? error.message : String(error)
85 });
86 }
87 }
88
89 for (const envelope of drafts.collectionLinks) {
90 const collectionRef = envelope.collectionName ? collectionRefs.get(envelope.collectionName) : undefined;
91 const cardRef = envelope.cardId ? cardRefs.get(envelope.cardId) : undefined;
92 if (!collectionRef || !cardRef) {
93 failures.push({rkey: envelope.rkey, error: "Missing collection or card ref for link."});
94 continue;
95 }
96
97 try {
98 const record = {...envelope.record, collection: collectionRef, card: cardRef};
99 await agent.com.atproto.repo.createRecord({
100 repo,
101 collection: envelope.collection,
102 rkey: envelope.rkey,
103 record
104 });
105 created += 1;
106 } catch (error) {
107 failures.push({
108 rkey: envelope.rkey,
109 error: error instanceof Error ? error.message : String(error)
110 });
111 }
112 }
113
114 return {created, failures};
115}
116
117function extractCollectionName(value: unknown): string | undefined {
118 if (!value || typeof value !== "object") return undefined;
119 const record = value as {name?: unknown};
120 return typeof record.name === "string" ? record.name : undefined;
121}