tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
28
pulls
pipelines
Merge branch 'main' into update/reader
awarm.space
1 month ago
558ecf78
e088ff46
+71
-51
7 changed files
expand all
collapse all
unified
split
actions
publishToPublication.ts
app
api
inngest
functions
sync_document_metadata.ts
lish
[did]
[publication]
generateFeed.ts
createPub
getPublicationURL.ts
updatePublication.ts
feeds
index.ts
supabase
migrations
20260211000000_indexed_default_false.sql
+1
actions/publishToPublication.ts
···
300
300
await supabaseServerClient.from("documents").upsert({
301
301
uri: result.uri,
302
302
data: record as unknown as Json,
303
303
+
indexed: true,
303
304
});
304
305
305
306
if (publication_uri) {
+15
-9
app/api/inngest/functions/sync_document_metadata.ts
···
21
21
const handle = doc?.alsoKnownAs
22
22
?.find((a) => a.startsWith("at://"))
23
23
?.replace("at://", "");
24
24
-
return { handle: handle ?? null, isBridgy: handle?.includes("brid.gy") ?? false };
24
24
+
if (!doc) return null;
25
25
+
const isBridgy = !!doc?.service?.find(
26
26
+
(s) =>
27
27
+
typeof s.serviceEndpoint === "string" &&
28
28
+
s.serviceEndpoint.includes("atproto.brid.gy"),
29
29
+
);
30
30
+
return { handle: handle ?? null, isBridgy, doc };
25
31
});
32
32
+
if (!handleResult) return { error: "No Handle" };
26
33
27
27
-
if (handleResult.isBridgy) {
28
28
-
await step.run("set-unindexed", async () => {
29
29
-
await supabaseServerClient
30
30
-
.from("documents")
31
31
-
.update({ indexed: false })
32
32
-
.eq("uri", document_uri);
33
33
-
});
34
34
-
}
34
34
+
await step.run("set-indexed", async () => {
35
35
+
return await supabaseServerClient
36
36
+
.from("documents")
37
37
+
.update({ indexed: !handleResult.isBridgy })
38
38
+
.eq("uri", document_uri)
39
39
+
.select();
40
40
+
});
35
41
36
42
if (!bsky_post_uri || handleResult.isBridgy) {
37
43
return { handle: handleResult.handle };
+45
-38
app/lish/[did]/[publication]/generateFeed.ts
···
53
53
},
54
54
});
55
55
56
56
-
await Promise.all(
57
57
-
publication.documents_in_publications.map(async (doc) => {
58
58
-
if (!doc.documents) return;
59
59
-
const record = normalizeDocumentRecord(
60
60
-
doc.documents?.data,
61
61
-
doc.documents?.uri,
62
62
-
);
63
63
-
const uri = new AtUri(doc.documents?.uri);
64
64
-
const rkey = uri.rkey;
65
65
-
if (!record) return;
56
56
+
let docs = publication.documents_in_publications.sort((a, b) => {
57
57
+
const dateA = a.documents?.sort_date
58
58
+
? new Date(a.documents.sort_date).getTime()
59
59
+
: 0;
60
60
+
const dateB = b.documents?.sort_date
61
61
+
? new Date(b.documents.sort_date).getTime()
62
62
+
: 0;
63
63
+
return dateB - dateA; // Sort in descending order (newest first)
64
64
+
});
65
65
+
for (const doc of docs) {
66
66
+
if (!doc.documents) continue;
67
67
+
const record = normalizeDocumentRecord(
68
68
+
doc.documents?.data,
69
69
+
doc.documents?.uri,
70
70
+
);
71
71
+
const uri = new AtUri(doc.documents?.uri);
72
72
+
const rkey = uri.rkey;
73
73
+
if (!record) continue;
66
74
67
67
-
let blocks: PubLeafletPagesLinearDocument.Block[] = [];
68
68
-
if (hasLeafletContent(record) && record.content.pages[0]) {
69
69
-
const firstPage = record.content.pages[0];
70
70
-
if (PubLeafletPagesLinearDocument.isMain(firstPage)) {
71
71
-
blocks = firstPage.blocks || [];
72
72
-
}
75
75
+
let blocks: PubLeafletPagesLinearDocument.Block[] = [];
76
76
+
if (hasLeafletContent(record) && record.content.pages[0]) {
77
77
+
const firstPage = record.content.pages[0];
78
78
+
if (PubLeafletPagesLinearDocument.isMain(firstPage)) {
79
79
+
blocks = firstPage.blocks || [];
73
80
}
74
74
-
const stream = await renderToReadableStream(
75
75
-
createElement(StaticPostContent, { blocks, did: uri.host }),
76
76
-
);
77
77
-
const reader = stream.getReader();
78
78
-
const chunks = [];
81
81
+
}
82
82
+
const stream = await renderToReadableStream(
83
83
+
createElement(StaticPostContent, { blocks, did: uri.host }),
84
84
+
);
85
85
+
const reader = stream.getReader();
86
86
+
const chunks = [];
79
87
80
80
-
let done, value;
81
81
-
while (!done) {
82
82
-
({ done, value } = await reader.read());
83
83
-
if (value) {
84
84
-
chunks.push(new TextDecoder().decode(value));
85
85
-
}
88
88
+
let done, value;
89
89
+
while (!done) {
90
90
+
({ done, value } = await reader.read());
91
91
+
if (value) {
92
92
+
chunks.push(new TextDecoder().decode(value));
86
93
}
94
94
+
}
87
95
88
88
-
const docUrl = getDocumentURL(record, doc.documents.uri, pubRecord);
89
89
-
feed.addItem({
90
90
-
title: record.title,
91
91
-
description: record.description,
92
92
-
date: record.publishedAt ? new Date(record.publishedAt) : new Date(),
93
93
-
id: docUrl,
94
94
-
link: docUrl,
95
95
-
content: chunks.join(""),
96
96
-
});
97
97
-
}),
98
98
-
);
96
96
+
const docUrl = getDocumentURL(record, doc.documents.uri, pubRecord);
97
97
+
feed.addItem({
98
98
+
title: record.title,
99
99
+
description: record.description,
100
100
+
date: record.publishedAt ? new Date(record.publishedAt) : new Date(),
101
101
+
id: docUrl,
102
102
+
link: docUrl,
103
103
+
content: chunks.join(""),
104
104
+
});
105
105
+
}
99
106
100
107
return feed;
101
108
}
+7
-3
app/lish/createPub/getPublicationURL.ts
···
58
58
docUri: string,
59
59
publication?: PublicationInput | NormalizedPublication | null,
60
60
): string {
61
61
-
const path = doc.path || "/" + new AtUri(docUri).rkey;
61
61
+
let path = doc.path || "/" + new AtUri(docUri).rkey;
62
62
+
if (path[0] !== "/") path = "/" + path;
62
63
const aturi = new AtUri(docUri);
63
64
64
65
const isNormalized =
65
66
!!publication &&
66
66
-
(publication as NormalizedPublication).$type === "site.standard.publication";
67
67
+
(publication as NormalizedPublication).$type ===
68
68
+
"site.standard.publication";
67
69
const normPub = isNormalized
68
70
? (publication as NormalizedPublication)
69
71
: publication
70
72
? normalizePublicationRecord((publication as PublicationInput).record)
71
73
: null;
72
72
-
const pubInput = isNormalized ? null : (publication as PublicationInput | null);
74
74
+
const pubInput = isNormalized
75
75
+
? null
76
76
+
: (publication as PublicationInput | null);
73
77
74
78
// Non-leaflet documents always use the full publication site URL
75
79
if (doc.content && !hasLeafletContent(doc) && normPub?.url) {
+1
-1
app/lish/createPub/updatePublication.ts
···
275
275
276
276
return buildRecord(normalizedPub, existingBasePath, publicationType, {
277
277
name,
278
278
-
description,
278
278
+
...(description !== undefined && { description }),
279
279
icon: iconBlob,
280
280
preferences,
281
281
});
+1
feeds/index.ts
···
115
115
);
116
116
}
117
117
query = query
118
118
+
.eq("indexed", true)
118
119
.or("data->postRef.not.is.null,data->bskyPostRef.not.is.null")
119
120
.order("sort_date", { ascending: false })
120
121
.order("uri", { ascending: false })
+1
supabase/migrations/20260211000000_indexed_default_false.sql
···
1
1
+
ALTER TABLE documents ALTER COLUMN indexed SET DEFAULT false;