fix: paths p4
This commit is contained in:
@@ -228,8 +228,88 @@ async function resolveBlogManifestTxId() {
|
|||||||
return match?.[1] || "";
|
return match?.[1] || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function resolveAoConfig() {
|
||||||
|
const source = await fs.readFile(sourceConfigPath, "utf8");
|
||||||
|
const aoUrlMatch = source.match(/AO_URL\s*=\s*"([^"]+)"/);
|
||||||
|
const aoProcessIdMatch = source.match(/AO_PROCESS_ID\s*=\s*"([^"]+)"/);
|
||||||
|
return {
|
||||||
|
aoUrl: aoUrlMatch?.[1] || "",
|
||||||
|
aoProcessId: aoProcessIdMatch?.[1] || ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const asObject = (value) => (typeof value === "object" && value !== null ? value : null);
|
||||||
|
const asString = (value) => (typeof value === "string" && value.length > 0 ? value : null);
|
||||||
|
|
||||||
|
function findManifestIdInTags(tagsValue) {
|
||||||
|
const tags = Array.isArray(tagsValue) ? tagsValue : [];
|
||||||
|
for (const tag of tags) {
|
||||||
|
const tagObject = asObject(tag);
|
||||||
|
if (!tagObject) continue;
|
||||||
|
const name = asString(tagObject.name) ?? asString(tagObject.Name);
|
||||||
|
const value = asString(tagObject.value) ?? asString(tagObject.Value);
|
||||||
|
if (name === "LatestManifestId" && value) return value;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractManifestId(payload) {
|
||||||
|
const root = asObject(payload);
|
||||||
|
const results = asObject(root?.results);
|
||||||
|
if (!results) return "";
|
||||||
|
|
||||||
|
const outbox = asObject(results.outbox);
|
||||||
|
if (outbox) {
|
||||||
|
for (const message of Object.values(outbox)) {
|
||||||
|
const messageObject = asObject(message);
|
||||||
|
if (!messageObject) continue;
|
||||||
|
const direct = asString(messageObject.LatestManifestId);
|
||||||
|
if (direct) return direct;
|
||||||
|
const tagged = findManifestIdInTags(messageObject.Tags);
|
||||||
|
if (tagged) return tagged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const raw = asObject(results.raw);
|
||||||
|
const rawMessages = Array.isArray(raw?.Messages) ? raw.Messages : [];
|
||||||
|
for (const message of rawMessages) {
|
||||||
|
const messageObject = asObject(message);
|
||||||
|
if (!messageObject) continue;
|
||||||
|
const tagged = findManifestIdInTags(messageObject.Tags);
|
||||||
|
if (tagged) return tagged;
|
||||||
|
}
|
||||||
|
|
||||||
|
const json = asObject(results.json);
|
||||||
|
const body = json?.body;
|
||||||
|
const parsedBody = typeof body === "string" ? asObject(JSON.parse(body)) : asObject(body);
|
||||||
|
const jsonMessages = Array.isArray(parsedBody?.Messages) ? parsedBody.Messages : [];
|
||||||
|
for (const message of jsonMessages) {
|
||||||
|
const messageObject = asObject(message);
|
||||||
|
if (!messageObject) continue;
|
||||||
|
const tagged = findManifestIdInTags(messageObject.Tags);
|
||||||
|
if (tagged) return tagged;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getLatestManifestFromAo() {
|
||||||
|
const { aoUrl, aoProcessId } = await resolveAoConfig();
|
||||||
|
if (!aoUrl || !aoProcessId) return "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = `${aoUrl}/${aoProcessId}~process@1.0/compute?Action=Get&require-codec=application/json&accept-bundle=true`;
|
||||||
|
const response = await fetch(url, { cache: "no-store" });
|
||||||
|
if (!response.ok) return "";
|
||||||
|
const payload = await response.json();
|
||||||
|
return extractManifestId(payload);
|
||||||
|
} catch {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function resolvePostSlugs(gateway) {
|
async function resolvePostSlugs(gateway) {
|
||||||
const blogManifestTxId = await resolveBlogManifestTxId();
|
const blogManifestTxId = (await getLatestManifestFromAo()) || (await resolveBlogManifestTxId());
|
||||||
if (!blogManifestTxId) return [];
|
if (!blogManifestTxId) return [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
92
src/lib.ts
92
src/lib.ts
@@ -1,7 +1,7 @@
|
|||||||
import DOMPurify from "dompurify";
|
import DOMPurify from "dompurify";
|
||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
import { parse as parseYaml } from "yaml";
|
import { parse as parseYaml } from "yaml";
|
||||||
import { ARWEAVE_GATEWAY, MANIFEST_TX_ID } from "./config";
|
import { AO_PROCESS_ID, AO_URL, ARWEAVE_GATEWAY, MANIFEST_TX_ID } 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 =>
|
||||||
@@ -25,8 +25,96 @@ export const getReadableDate = (date?: string | null): string | null => {
|
|||||||
return formatDate(date);
|
return formatDate(date);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const MANIFEST_ID_CACHE_TTL_MS = 60_000;
|
||||||
|
let manifestIdCache: { expiresAt: number; manifestId: string } | null = null;
|
||||||
|
|
||||||
|
const asObject = (value: unknown): Record<string, unknown> | null =>
|
||||||
|
typeof value === "object" && value !== null ? (value as Record<string, unknown>) : null;
|
||||||
|
|
||||||
|
const asString = (value: unknown): string | null =>
|
||||||
|
typeof value === "string" && value.length > 0 ? value : null;
|
||||||
|
|
||||||
|
const findManifestIdInTags = (tagsValue: unknown): string | null => {
|
||||||
|
const tags = Array.isArray(tagsValue) ? tagsValue : [];
|
||||||
|
for (const tag of tags) {
|
||||||
|
const tagObject = asObject(tag);
|
||||||
|
if (!tagObject) continue;
|
||||||
|
const name = asString(tagObject.name) ?? asString(tagObject.Name);
|
||||||
|
const value = asString(tagObject.value) ?? asString(tagObject.Value);
|
||||||
|
if (name === "LatestManifestId" && value) return value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const extractManifestId = (payload: unknown): string | null => {
|
||||||
|
const root = asObject(payload);
|
||||||
|
const results = asObject(root?.results);
|
||||||
|
if (!results) return null;
|
||||||
|
|
||||||
|
const outbox = asObject(results.outbox);
|
||||||
|
if (outbox) {
|
||||||
|
for (const message of Object.values(outbox)) {
|
||||||
|
const messageObject = asObject(message);
|
||||||
|
if (!messageObject) continue;
|
||||||
|
const direct = asString(messageObject.LatestManifestId);
|
||||||
|
if (direct) return direct;
|
||||||
|
const tagged = findManifestIdInTags(messageObject.Tags);
|
||||||
|
if (tagged) return tagged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const raw = asObject(results.raw);
|
||||||
|
const rawMessages = Array.isArray(raw?.Messages) ? raw.Messages : [];
|
||||||
|
for (const message of rawMessages) {
|
||||||
|
const messageObject = asObject(message);
|
||||||
|
if (!messageObject) continue;
|
||||||
|
const tagged = findManifestIdInTags(messageObject.Tags);
|
||||||
|
if (tagged) return tagged;
|
||||||
|
}
|
||||||
|
|
||||||
|
const json = asObject(results.json);
|
||||||
|
const body = json?.body;
|
||||||
|
const parsedBody =
|
||||||
|
typeof body === "string" ? asObject(JSON.parse(body)) : asObject(body);
|
||||||
|
const jsonMessages = Array.isArray(parsedBody?.Messages) ? parsedBody.Messages : [];
|
||||||
|
for (const message of jsonMessages) {
|
||||||
|
const messageObject = asObject(message);
|
||||||
|
if (!messageObject) continue;
|
||||||
|
const tagged = findManifestIdInTags(messageObject.Tags);
|
||||||
|
if (tagged) return tagged;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getLatestManifestFromAo = async (): Promise<string | null> => {
|
||||||
|
try {
|
||||||
|
const now = Date.now();
|
||||||
|
if (manifestIdCache && manifestIdCache.expiresAt > now) {
|
||||||
|
return manifestIdCache.manifestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `${AO_URL}/${AO_PROCESS_ID}~process@1.0/compute?Action=Get&require-codec=application/json&accept-bundle=true`;
|
||||||
|
const response = await fetch(url, { cache: "no-store" });
|
||||||
|
if (!response.ok) return null;
|
||||||
|
|
||||||
|
const payload: unknown = await response.json();
|
||||||
|
const manifestId = extractManifestId(payload);
|
||||||
|
if (!manifestId) return null;
|
||||||
|
|
||||||
|
manifestIdCache = {
|
||||||
|
expiresAt: now + MANIFEST_ID_CACHE_TTL_MS,
|
||||||
|
manifestId
|
||||||
|
};
|
||||||
|
return manifestId;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const loadManifest = async (): Promise<ManifestPost[]> => {
|
export const loadManifest = async (): Promise<ManifestPost[]> => {
|
||||||
const response = await fetch(arweaveUrl(MANIFEST_TX_ID));
|
const manifestTxId = (await getLatestManifestFromAo()) ?? MANIFEST_TX_ID;
|
||||||
|
const response = await fetch(arweaveUrl(manifestTxId));
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Failed to load manifest (${response.status})`);
|
throw new Error(`Failed to load manifest (${response.status})`);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user