111 lines
2.6 KiB
TypeScript
111 lines
2.6 KiB
TypeScript
import { sign } from "jsonwebtoken";
|
|
import { file } from "bun";
|
|
|
|
const getAdminApiKey = async () => {
|
|
const keyPath = process.env.GHOST_ADMIN_API_KEY_PATH;
|
|
if (!keyPath) {
|
|
throw new Error(
|
|
"Environment variable GHOST_ADMIN_API_KEY_PATH is not set.",
|
|
);
|
|
}
|
|
|
|
const keyFile = file(keyPath);
|
|
if (!(await keyFile.exists())) {
|
|
throw new Error(`Key file not found at path: ${keyPath}`);
|
|
}
|
|
|
|
return await keyFile.text();
|
|
};
|
|
|
|
const getEndpoint = () => {
|
|
const endpoint = process.env.GHOST_URL;
|
|
if (!endpoint) {
|
|
throw new Error("Environment variable GHOST_URL is not set.");
|
|
}
|
|
|
|
return endpoint;
|
|
};
|
|
|
|
const createJwt = (key: string) => {
|
|
const [id, secret] = key.split(":");
|
|
if (!id || !secret) {
|
|
throw new Error("Invalid API key format. Expected format: {id}:{secret}");
|
|
}
|
|
|
|
return sign({}, Buffer.from(secret, "hex"), {
|
|
keyid: id,
|
|
algorithm: "HS256",
|
|
expiresIn: "5m",
|
|
audience: `/admin/`,
|
|
});
|
|
};
|
|
|
|
const upload = async (
|
|
slug: string,
|
|
path: string,
|
|
type: string | undefined,
|
|
): Promise<any> => {
|
|
const endpoint = getEndpoint();
|
|
const fullEndpoint = `${endpoint}${slug}`;
|
|
|
|
const key = await getAdminApiKey();
|
|
const token = createJwt(key);
|
|
|
|
const f = Bun.file(path, { type });
|
|
const formData = new FormData();
|
|
formData.append("file", f);
|
|
|
|
const response = await fetch(fullEndpoint, {
|
|
method: "POST",
|
|
headers: {
|
|
Authorization: `Ghost ${token}`,
|
|
},
|
|
body: formData,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(
|
|
`Failed to upload to ${fullEndpoint}: ${response.status} ${response.statusText}`,
|
|
);
|
|
}
|
|
|
|
return await response.json();
|
|
};
|
|
|
|
export const uploadImage = async (imagePath: string): Promise<string> => {
|
|
const slug = `/ghost/api/admin/images/upload`;
|
|
return (await upload(slug, imagePath, "image/jpeg")).images[0].url;
|
|
};
|
|
|
|
export const uploadFile = async (filePath: string): Promise<string> => {
|
|
const slug = `/ghost/api/admin/files/upload`;
|
|
return (await upload(slug, filePath, undefined)).files[0].url;
|
|
};
|
|
|
|
export const uploadPost = async (post: any): Promise<string> => {
|
|
const endpoint = getEndpoint();
|
|
const fullEndpoint = `${endpoint}/ghost/api/admin/posts`;
|
|
|
|
const key = await getAdminApiKey();
|
|
const token = createJwt(key);
|
|
|
|
const response = await fetch(fullEndpoint, {
|
|
method: "POST",
|
|
headers: {
|
|
Authorization: `Ghost ${token}`,
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
posts: [post],
|
|
}),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(
|
|
`Failed to upload to ${fullEndpoint}: ${response.status} ${response.statusText}`,
|
|
);
|
|
}
|
|
|
|
return (await response.json()).posts[0].url;
|
|
};
|