UNPKG

@paroicms/site-generator-plugin

Version:

ParoiCMS Site Generator Plugin

102 lines (101 loc) 4.63 kB
import { pathExists } from "@paroicms/internal-server-lib"; import { messageOf } from "@paroicms/public-anywhere-lib"; import { ApiError, escapeHtml, makeStylesheetLinkAsyncTag, } from "@paroicms/public-server-lib"; import { join } from "node:path"; import { executeCommand } from "./commands/execute-command.js"; import { packageDir, pluginVersion } from "./context.js"; import { formatGeneratorCommand, GeneratorPluginConfigurationAT } from "./data-format.js"; import { createOrOpenSiteGeneratorConnection } from "./db/db-init.js"; import { initializeImageNames } from "./generator/lib/images-lib.js"; import { createRawContext } from "./lib/create-raw-context.js"; import { startSiteRemover } from "./lib/site-remover.js"; await initializeImageNames(); const plugin = { version: pluginVersion, async siteInit(service) { const { cn, logNextQuery } = await createOrOpenSiteGeneratorConnection({ sqliteFile: join(service.registeredSite.dataDir, "site-generator.sqlite"), canCreate: true, logger: service.logger, }); const pluginConf = GeneratorPluginConfigurationAT.assert(service.configuration); if (!!pluginConf.googleRecaptchaSecretKey !== !!pluginConf.googleRecaptchaSiteKey) { throw new Error("[Site Generator] Invalid Google reCAPTCHA configuration"); } if (!pluginConf.googleRecaptchaSiteKey) { service.logger.warn("[Site Generator] Google reCAPTCHA keys are not set. The site generator will not be protected."); } let debugDir = pluginConf.debugDir; if (debugDir) { if (!(await pathExists(debugDir))) { service.logger.warn(`[generator] Debug directory (debugDir) doesn't exist: ${debugDir}`); debugDir = undefined; } } let rawContext; service.registerHook("initialized", ({ service }) => { rawContext = createRawContext(service, { cn, logNextQuery, pluginConf, debugDir, }); startSiteRemover(rawContext); }); service.setPublicAssetsDirectory(join(packageDir, "frontend", "dist")); service.registerOutLiquidTagFunction("siteGeneratorApp", (service) => { service.setRenderState("siteGeneratorApp", true); return `<div id="site-generator-app"></div>`; }, { raw: true }); service.registerHeadTags(({ state }) => { if (!state.get("siteGeneratorApp")) return; return [ makeStylesheetLinkAsyncTag(`${service.pluginAssetsUrl}/frontend.css`), `<script type="module" src="${escapeHtml(`${service.pluginAssetsUrl}/frontend.mjs`)}" class="js-script-site-generator" data-google-recaptcha-site-key="${escapeHtml(pluginConf.googleRecaptchaSiteKey ?? "")}" async></script>`, ]; }); service.setPublicApiHandler(async (service, httpContext, relativePath) => { if (!rawContext) throw new Error("should be initialized"); const ctx = rawContext; const { req, res } = httpContext; if (relativePath !== "") { res.status(404).send({ status: 404 }); return; } let command; try { command = formatGeneratorCommand(req.body); } catch (error) { service.logger.error("Invalid command:", error); res.status(400).send({ status: 400, message: messageOf(error) }); return; } try { const result = await executeCommand(ctx, command); const buf = Buffer.from(JSON.stringify(result), "utf-8"); res.status(200); res.append("Content-Type", "application/json"); res.append("Content-Length", buf.byteLength.toString()); res.send(buf); } catch (error) { service.logger.error("Error executing command:", error); if (error instanceof ApiError) { const response = { success: false, userMessage: error.message, }; res.status(error.status).send(response); } else { const response = { success: false }; res.status(500).send(response); } } }); }, }; export default plugin;