sc-postiz-poster/lib/postizClient.js
2026-06-24 20:22:55 -05:00

48 lines
2 KiB
JavaScript

// Single source of truth for talking to the Postiz public API. One factory,
// built from the plugin's saved { baseUrl, apiKey }. Self-hosted vs cloud is
// purely the baseUrl -- no other code in the plugin branches on deployment.
const { PATH_BASE, ENDPOINTS, AUTH_HEADER } = require("./constants");
const makePostizClient = (pluginCfg) => {
const baseUrl = String((pluginCfg && pluginCfg.baseUrl) || "").replace(/\/+$/, "");
const apiKey = String((pluginCfg && pluginCfg.apiKey) || "");
const request = async (method, endpoint, body) => {
// Guard the operator-set baseUrl before we ever send the sealed apiKey:
// reject unparseable / non-http(s) schemes (file:, gopher:, data:, ...).
// Private/self-hosted hosts are allowed by design (self-hosted Postiz).
let parsed;
try {
parsed = new URL(baseUrl);
} catch (e) {
throw new Error(`Postiz baseUrl is not a valid URL: ${baseUrl}`);
}
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
throw new Error(`Postiz baseUrl must use http or https: ${baseUrl}`);
}
const url = `${baseUrl}${PATH_BASE}${endpoint}`;
const headers = { [AUTH_HEADER]: apiKey };
const init = { method, headers };
if (body !== undefined) {
headers["Content-Type"] = "application/json";
init.body = JSON.stringify(body);
}
const res = await fetch(url, init);
if (!res.ok) {
const text = await res.text();
throw new Error(`Postiz ${method} ${endpoint} -> ${res.status} ${text}`);
}
return res.status === 204 ? null : res.json();
};
return {
createPost: (payload) => request("POST", ENDPOINTS.POSTS, payload),
listIntegrations: () => request("GET", ENDPOINTS.INTEGRATIONS),
uploadMedia: (payload) => request("POST", ENDPOINTS.UPLOAD, payload)
};
};
module.exports = { makePostizClient };