Resolve manifest via the mystic reference only

Drop the hardcoded MANIFEST_TX_ID fallback from the app, the deploy script
and the metadata prerender. The mystic reference now points at the manifest
that includes arweave-for-ao, so the UI picks up new ships without a code
change.
This commit is contained in:
fn
2026-09-03 16:50:16 +01:00
parent e57f80bad5
commit 3618d0aa2d
4 changed files with 16 additions and 59 deletions

View File

@@ -223,12 +223,6 @@ async function createUploader(uploadMode, arweave, jwk) {
}; };
} }
async function resolveBlogManifestTxId() {
const source = await fs.readFile(sourceConfigPath, "utf8");
const match = source.match(/MANIFEST_TX_ID\s*=\s*"([^"]+)"/);
return match?.[1] || "";
}
async function resolveBlogManifestReferenceName() { async function resolveBlogManifestReferenceName() {
const source = await fs.readFile(sourceConfigPath, "utf8"); const source = await fs.readFile(sourceConfigPath, "utf8");
const match = source.match(/MANIFEST_REFERENCE_NAME\s*=\s*"([^"]+)"/); const match = source.match(/MANIFEST_REFERENCE_NAME\s*=\s*"([^"]+)"/);
@@ -344,8 +338,7 @@ async function fetchPostSlugs(gateway, blogManifestTxId) {
async function resolvePostSlugs(gateway) { async function resolvePostSlugs(gateway) {
const candidates = [ const candidates = [
await getLatestManifestFromReference(gateway), await getLatestManifestFromReference(gateway),
await getLatestManifestFromAo(), await getLatestManifestFromAo()
await resolveBlogManifestTxId()
].filter(Boolean); ].filter(Boolean);
for (const blogManifestTxId of candidates) { for (const blogManifestTxId of candidates) {

View File

@@ -12,8 +12,7 @@ const DEFAULTS = {
BLOG_SITE_URL: "https://hyperzine.xyz", BLOG_SITE_URL: "https://hyperzine.xyz",
BLOG_DEFAULT_DESCRIPTION: "hyperzine", BLOG_DEFAULT_DESCRIPTION: "hyperzine",
ARWEAVE_GATEWAY: "https://arweave.net", ARWEAVE_GATEWAY: "https://arweave.net",
MANIFEST_REFERENCE_NAME: "", MANIFEST_REFERENCE_NAME: ""
MANIFEST_TX_ID: ""
}; };
const asObject = (value) => (typeof value === "object" && value !== null ? value : null); const asObject = (value) => (typeof value === "object" && value !== null ? value : null);
@@ -54,8 +53,7 @@ const parseConfig = async () => {
BLOG_SITE_URL: pick("BLOG_SITE_URL"), BLOG_SITE_URL: pick("BLOG_SITE_URL"),
BLOG_DEFAULT_DESCRIPTION: pick("BLOG_DEFAULT_DESCRIPTION"), BLOG_DEFAULT_DESCRIPTION: pick("BLOG_DEFAULT_DESCRIPTION"),
ARWEAVE_GATEWAY: pick("ARWEAVE_GATEWAY"), ARWEAVE_GATEWAY: pick("ARWEAVE_GATEWAY"),
MANIFEST_REFERENCE_NAME: pick("MANIFEST_REFERENCE_NAME"), MANIFEST_REFERENCE_NAME: pick("MANIFEST_REFERENCE_NAME")
MANIFEST_TX_ID: pick("MANIFEST_TX_ID")
}; };
}; };
@@ -121,10 +119,10 @@ const parseManifest = (input) => {
}); });
}; };
const fetchManifestPosts = async (manifestTxId) => { const fetchManifestPosts = async (config, manifestTxId) => {
if (!manifestTxId) return []; if (!manifestTxId) return [];
const url = `https://arweave.net/${manifestTxId}`; const gateway = (config.ARWEAVE_GATEWAY || DEFAULTS.ARWEAVE_GATEWAY).replace(/\/+$/, "");
const response = await fetch(url, { cache: "no-store" }); const response = await fetch(`${gateway}/${manifestTxId}`, { cache: "no-store" });
if (!response.ok) throw new Error(`Manifest fetch failed (${response.status})`); if (!response.ok) throw new Error(`Manifest fetch failed (${response.status})`);
const payload = await response.json(); const payload = await response.json();
const posts = parseManifest(payload); const posts = parseManifest(payload);
@@ -132,36 +130,17 @@ const fetchManifestPosts = async (manifestTxId) => {
}; };
const resolveManifestTxId = async (config) => { const resolveManifestTxId = async (config) => {
if (config.MANIFEST_REFERENCE_NAME) { if (!config.MANIFEST_REFERENCE_NAME) return "";
try {
const names = new ReferenceClient({ gateway: config.ARWEAVE_GATEWAY || DEFAULTS.ARWEAVE_GATEWAY }); const names = new ReferenceClient({ gateway: config.ARWEAVE_GATEWAY || DEFAULTS.ARWEAVE_GATEWAY });
const value = await names.resolveName(config.MANIFEST_REFERENCE_NAME); const value = await names.resolveName(config.MANIFEST_REFERENCE_NAME);
if (typeof value === "string" && value.length > 0) return value; if (typeof value === "string" && value.length > 0) return value;
throw new Error(`Reference ${config.MANIFEST_REFERENCE_NAME} did not resolve to a manifest id`); throw new Error(`Reference ${config.MANIFEST_REFERENCE_NAME} did not resolve to a manifest id`);
} catch (error) {
console.warn(
`[prerender-meta] Falling back to configured manifest; reference ${config.MANIFEST_REFERENCE_NAME} failed: ${error.message}`
);
}
}
return config.MANIFEST_TX_ID;
}; };
const fetchCurrentManifestPosts = async (config) => { const fetchCurrentManifestPosts = async (config) => {
const manifestTxId = await resolveManifestTxId(config); const manifestTxId = await resolveManifestTxId(config);
if (!manifestTxId) return []; if (!manifestTxId) return [];
return (await fetchManifestPosts(config, manifestTxId)).posts;
try {
return (await fetchManifestPosts(manifestTxId)).posts;
} catch (error) {
if (!config.MANIFEST_REFERENCE_NAME || manifestTxId === config.MANIFEST_TX_ID) throw error;
console.warn(
`[prerender-meta] Falling back to configured manifest; reference manifest ${manifestTxId} failed: ${error.message}`
);
}
return config.MANIFEST_TX_ID ? (await fetchManifestPosts(config.MANIFEST_TX_ID)).posts : [];
}; };
const buildMetaTags = ({ const buildMetaTags = ({

View File

@@ -5,7 +5,6 @@ export const BLOG_DEFAULT_DESCRIPTION =
"A blog about cyberspace decentralization"; "A blog about cyberspace decentralization";
export const BLOG_TWITTER_HANDLE = ""; export const BLOG_TWITTER_HANDLE = "";
export const MANIFEST_REFERENCE_NAME = "mystic"; export const MANIFEST_REFERENCE_NAME = "mystic";
export const MANIFEST_TX_ID = "SShELKFa2EsiB-OJbeoNOjAIxgah9OmRhxYXBF_M9wA";
export const ARWEAVE_GATEWAY = "https://arweave.net"; export const ARWEAVE_GATEWAY = "https://arweave.net";
export const AO_URL = "https://push-1.forward.computer"; export const AO_URL = "https://push-1.forward.computer";

View File

@@ -2,7 +2,7 @@ import DOMPurify from "dompurify";
import { marked, type Tokens } from "marked"; import { marked, type Tokens } from "marked";
import { parse as parseYaml } from "yaml"; import { parse as parseYaml } from "yaml";
import { ReferenceClient } from "@permaweb/references"; import { ReferenceClient } from "@permaweb/references";
import { ARWEAVE_GATEWAY, MANIFEST_REFERENCE_NAME, MANIFEST_TX_ID } from "./config"; import { ARWEAVE_GATEWAY, MANIFEST_REFERENCE_NAME } from "./config";
import { parseManifest, type Frontmatter, type ManifestPost } from "./types"; import { parseManifest, type Frontmatter, type ManifestPost } from "./types";
const formatDate = (date: string): string => const formatDate = (date: string): string =>
@@ -106,26 +106,12 @@ const resolveReferenceManifestTxId = async (): Promise<string> => {
}; };
const loadReferenceManifest = async () => { const loadReferenceManifest = async () => {
if (!MANIFEST_REFERENCE_NAME) return null; if (!MANIFEST_REFERENCE_NAME) throw new Error("No manifest reference configured");
return fetchManifest(await resolveReferenceManifestTxId());
try {
return await fetchManifest(await resolveReferenceManifestTxId());
} catch (error) {
console.warn(
`Could not load manifest reference ${MANIFEST_REFERENCE_NAME}; trying configured manifest`,
error
);
return null;
}
};
const loadConfiguredManifest = async () => {
if (!MANIFEST_TX_ID) throw new Error("No manifest reference or fallback manifest configured");
return fetchManifest(MANIFEST_TX_ID);
}; };
const loadCurrentManifest = async () => { const loadCurrentManifest = async () => {
return (await loadReferenceManifest()) ?? (await loadConfiguredManifest()); return loadReferenceManifest();
}; };
export const resolveManifestTxId = async (): Promise<string> => { export const resolveManifestTxId = async (): Promise<string> => {