@rmdes/indiekit-endpoint-rss 1.2.1 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +3 -0
- package/lib/publisher.js +25 -2
- package/lib/sync.js +1 -0
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -20,6 +20,9 @@ const defaults = {
|
|
|
20
20
|
retentionDays: 30,
|
|
21
21
|
minItemsPerFeed: 10,
|
|
22
22
|
maxPostsPerCycle: 10,
|
|
23
|
+
// Eleventy's watcher settles a new file in stabilityThreshold (2s) + watch
|
|
24
|
+
// throttle (3s); posting faster than that loses builds.
|
|
25
|
+
postIntervalMs: 5000,
|
|
23
26
|
};
|
|
24
27
|
|
|
25
28
|
export default class RssEndpoint {
|
package/lib/publisher.js
CHANGED
|
@@ -4,6 +4,14 @@ import { buildJf2 } from "./jf2-builder.js";
|
|
|
4
4
|
|
|
5
5
|
const TOKEN_TTL = "5m";
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Pause between posts
|
|
9
|
+
* @param {number} ms - Milliseconds
|
|
10
|
+
* @returns {Promise<void>} Resolves after the delay
|
|
11
|
+
*/
|
|
12
|
+
const sleep = (ms) =>
|
|
13
|
+
ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
|
|
14
|
+
|
|
7
15
|
/**
|
|
8
16
|
* Mint a short-lived token for background publishing.
|
|
9
17
|
*
|
|
@@ -18,7 +26,10 @@ export function mintToken(me) {
|
|
|
18
26
|
throw new Error("Cannot publish: SECRET is not configured");
|
|
19
27
|
}
|
|
20
28
|
|
|
21
|
-
|
|
29
|
+
// Both scopes: an item that already has a post is updated, not created, and
|
|
30
|
+
// checkScope treats them as distinct actions — a create-only token gets a
|
|
31
|
+
// 403 insufficient_scope on every republish.
|
|
32
|
+
return jwt.sign({ me, scope: "create update" }, process.env.SECRET, {
|
|
22
33
|
expiresIn: TOKEN_TTL,
|
|
23
34
|
});
|
|
24
35
|
}
|
|
@@ -160,8 +171,10 @@ export function pendingQuery(feed) {
|
|
|
160
171
|
* @param {string} options.micropubEndpoint - Micropub endpoint URL
|
|
161
172
|
* @param {string} options.me - Publication URL
|
|
162
173
|
* @param {number} options.maxPostsPerCycle - Cap per cycle
|
|
174
|
+
* @param {number} [options.postIntervalMs] - Pause between posts
|
|
163
175
|
* @param {Function} [options.postImpl] - Post implementation, for tests
|
|
164
176
|
* @param {Function} [options.mintImpl] - Token minter, for tests
|
|
177
|
+
* @param {Function} [options.sleepImpl] - Sleep implementation, for tests
|
|
165
178
|
* @returns {Promise<object>} Counts for this feed
|
|
166
179
|
*/
|
|
167
180
|
export async function publishPending(feed, itemsCollection, options) {
|
|
@@ -175,6 +188,8 @@ export async function publishPending(feed, itemsCollection, options) {
|
|
|
175
188
|
maxPostsPerCycle,
|
|
176
189
|
postImpl = postToMicropub,
|
|
177
190
|
mintImpl = mintToken,
|
|
191
|
+
postIntervalMs = 0,
|
|
192
|
+
sleepImpl = sleep,
|
|
178
193
|
} = options;
|
|
179
194
|
|
|
180
195
|
const query = pendingQuery(feed);
|
|
@@ -196,7 +211,7 @@ export async function publishPending(feed, itemsCollection, options) {
|
|
|
196
211
|
// postData.create replaceOne's on the same URL, so it overwrites rather
|
|
197
212
|
// than duplicates. Add a q=source reconciliation if a feed ever produces
|
|
198
213
|
// non-deterministic slugs.
|
|
199
|
-
for (const item of items) {
|
|
214
|
+
for (const [index, item] of items.entries()) {
|
|
200
215
|
try {
|
|
201
216
|
// Minted per item, not once for the batch: signing is a cheap HMAC, and
|
|
202
217
|
// a single batch token can expire mid-cycle on a slow endpoint. The
|
|
@@ -240,6 +255,14 @@ export async function publishPending(feed, itemsCollection, options) {
|
|
|
240
255
|
|
|
241
256
|
console.error(`[RSS] Publish failed for ${item.guid}: ${error.message}`);
|
|
242
257
|
}
|
|
258
|
+
|
|
259
|
+
// Space the posts out. Each one writes a markdown file, and Eleventy's
|
|
260
|
+
// watcher needs chokidar's stabilityThreshold (2s) plus its own watch
|
|
261
|
+
// throttle (3s) to absorb one before the next lands. A burst arriving
|
|
262
|
+
// faster makes it log "Wrote 0 files" and leave the posts unbuilt.
|
|
263
|
+
if (index < items.length - 1) {
|
|
264
|
+
await sleepImpl(postIntervalMs);
|
|
265
|
+
}
|
|
243
266
|
}
|
|
244
267
|
|
|
245
268
|
console.log(
|
package/lib/sync.js
CHANGED
|
@@ -154,6 +154,7 @@ export async function runSync(dbOrIndiekit, options, publishContext) {
|
|
|
154
154
|
const result = await publishPending(feed, itemsCollection, {
|
|
155
155
|
...publishContext,
|
|
156
156
|
maxPostsPerCycle: options.maxPostsPerCycle || 10,
|
|
157
|
+
postIntervalMs: options.postIntervalMs ?? 5000,
|
|
157
158
|
});
|
|
158
159
|
itemsPublished += result.published;
|
|
159
160
|
} catch (error) {
|
package/package.json
CHANGED