feat: syndication webhook on incremental builds
Add an eleventy.after hook that triggers syndication immediately after incremental rebuilds, cutting latency from ~2 min (poller) to ~5 sec. Uses built-in crypto for HS256 JWT — no new dependencies. Confab-Link: http://localhost:8080/sessions/d116ad5b-ef8a-424e-9ebe-76c06bef1df6
This commit is contained in:
+36
-1
@@ -9,7 +9,7 @@ import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
|
|||||||
import { minify } from "html-minifier-terser";
|
import { minify } from "html-minifier-terser";
|
||||||
import registerUnfurlShortcode, { getCachedCard, prefetchUrl } from "./lib/unfurl-shortcode.js";
|
import registerUnfurlShortcode, { getCachedCard, prefetchUrl } from "./lib/unfurl-shortcode.js";
|
||||||
import matter from "gray-matter";
|
import matter from "gray-matter";
|
||||||
import { createHash } from "crypto";
|
import { createHash, createHmac } from "crypto";
|
||||||
import { execFileSync } from "child_process";
|
import { execFileSync } from "child_process";
|
||||||
import { readFileSync, readdirSync, existsSync, mkdirSync, writeFileSync, copyFileSync } from "fs";
|
import { readFileSync, readdirSync, existsSync, mkdirSync, writeFileSync, copyFileSync } from "fs";
|
||||||
import { resolve, dirname } from "path";
|
import { resolve, dirname } from "path";
|
||||||
@@ -1096,6 +1096,41 @@ export default function (eleventyConfig) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Syndication webhook — trigger after incremental rebuilds (new posts are now live)
|
||||||
|
// Cuts syndication latency from ~2 min (poller) to ~5 sec (immediate trigger)
|
||||||
|
if (incremental) {
|
||||||
|
const syndicateUrl = process.env.SYNDICATE_WEBHOOK_URL;
|
||||||
|
if (syndicateUrl) {
|
||||||
|
try {
|
||||||
|
const secretFile = process.env.SYNDICATE_SECRET_FILE || "/app/data/config/.secret";
|
||||||
|
const secret = readFileSync(secretFile, "utf-8").trim();
|
||||||
|
|
||||||
|
// Build a minimal HS256 JWT using built-in crypto (no jsonwebtoken dependency)
|
||||||
|
const header = Buffer.from(JSON.stringify({ alg: "HS256", typ: "JWT" })).toString("base64url");
|
||||||
|
const now = Math.floor(Date.now() / 1000);
|
||||||
|
const payload = Buffer.from(JSON.stringify({
|
||||||
|
me: siteUrl,
|
||||||
|
scope: "update",
|
||||||
|
iat: now,
|
||||||
|
exp: now + 300, // 5 minutes
|
||||||
|
})).toString("base64url");
|
||||||
|
const signature = createHmac("sha256", secret)
|
||||||
|
.update(`${header}.${payload}`)
|
||||||
|
.digest("base64url");
|
||||||
|
const token = `${header}.${payload}.${signature}`;
|
||||||
|
|
||||||
|
const res = await fetch(`${syndicateUrl}?token=${token}`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
signal: AbortSignal.timeout(30000),
|
||||||
|
});
|
||||||
|
console.log(`[syndicate-hook] Triggered syndication: ${res.status}`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`[syndicate-hook] Failed:`, err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WebSub hub notification — skip on incremental rebuilds
|
// WebSub hub notification — skip on incremental rebuilds
|
||||||
if (incremental) return;
|
if (incremental) return;
|
||||||
const hubUrl = "https://websubhub.com/hub";
|
const hubUrl = "https://websubhub.com/hub";
|
||||||
|
|||||||
Reference in New Issue
Block a user