@paroicms/site-generator-plugin
Version:
ParoiCMS Site Generator Plugin
127 lines (126 loc) • 5.28 kB
JavaScript
import { generateSlug } from "@paroicms/public-anywhere-lib";
import { createSimpleTranslator } from "@paroicms/public-server-lib";
import { randomUUID } from "node:crypto";
import { mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { loadStep, readStepSchema } from "../../db/db-read.queries.js";
import { insertStep, saveGeneratedSiteStep, } from "../../db/db-write.queries.js";
import { fillSiteWithFakeContent } from "../fake-content-generator/create-database-with-fake-content.js";
import { safeCallStep } from "../lib/session-utils.js";
import { createTheme } from "./theme-creator.js";
export async function generateSite(ctx, input) {
const { service, logger, sitesDir, packConf: { packName }, } = ctx;
const { fromStepNumber, withSampleData } = input;
const stepHandle = await insertStep(ctx, {
kind: "generateSite",
status: "pending",
currentActivity: "generatingSite",
});
const { l10n, siteSchema, localizedValues } = await readStepSchema(ctx, fromStepNumber);
const siteId = randomUUID();
logger.info(`Generating site: ${siteId}…`);
const siteDir = join(sitesDir, siteId);
await mkdir(siteDir);
await writeFile(join(siteDir, "site-schema.json"), JSON.stringify(siteSchema, null, 2), "utf-8");
for (const [language, l10nData] of Object.entries(l10n)) {
await writeFile(join(siteDir, `site-schema.l10n.${language}.json`), JSON.stringify(l10nData, null, 2), "utf-8");
}
await writeFile(join(siteDir, "package.json"), JSON.stringify(getPackageJsonContent({
siteTitle: localizedValues.siteTitle.en ??
Object.values(localizedValues.siteTitle)[0] ??
"new-website",
}), null, 2), "utf-8");
await writeFile(join(siteDir, "postcss.config.js"), `export default {
plugins: {
"postcss-import": {},
"postcss-nested": {},
cssnano: {
preset: "default",
},
},
};
`, "utf-8");
await createTheme(ctx, siteDir, siteSchema);
const regSite = await service.getServerConnector().registerNewSite({
packName,
siteDir,
domain: siteId,
version: "0.0.0",
});
const siteConnector = service.getUnsafeSiteConnector({ fqdn: regSite.fqdn });
const account = {
kind: "local",
email: `${siteId}@yopmail.com`,
name: "Admin",
password: Math.random().toString(36).substring(2, 6), // 4 random lowercase characters,
roles: ["admin"],
};
await siteConnector.createAccount(account, { asContactEmail: true });
const { siteUrl } = regSite;
const values = {
status: withSampleData ? "pending" : "completed",
siteId,
siteUrl,
localizedValues,
loginEmail: account.email,
loginPassword: account.password,
};
await saveGeneratedSiteStep(ctx, stepHandle, values);
if (withSampleData) {
const { siteSchema: loadedSiteSchema, homeRoutingCluster } = await siteConnector.loadSiteSchemaAndIds();
const schemaI18n = createSimpleTranslator({
labels: loadedSiteSchema.l10n,
logger: ctx.logger,
});
const generateCtx = {
...ctx,
siteConnector,
fqdn: regSite.fqdn,
siteSchema: loadedSiteSchema,
schemaI18n,
homeRoutingCluster,
};
safeCallStep(ctx, stepHandle, () => fillSiteWithFakeContent(generateCtx, stepHandle, { homeRoutingCluster, localizedValues }));
}
return await loadStep(ctx, stepHandle.stepNumber);
}
function getPackageJsonContent(options) {
return {
name: generateSlug(options.siteTitle),
version: "0.0.0",
private: true,
type: "module",
scripts: {
start: "paroicms | npm run _pino-pretty",
"start:dev": "nodemon --watch './site-schema*.json' --watch ./config.json",
clear: "rimraf theme/assets/bundle.css",
build: "postcss theme/assets/css/index.css -o theme/assets/bundle.css",
dev: "concurrently -n 'node,css' -c 'yellow.bold,magenta.bold' 'npm run start:dev' 'npm run css:watch'",
"css:watch": "postcss theme/assets/css/index.css -o theme/assets/bundle.css --watch",
"_pino-pretty": "pino-pretty -U false -x 'stats:25' -X 'stats:grey' -t 'yyyy-mm-dd HH:MM:ss.l' -i 'hostname,pid,fqdn'",
},
dependencies: {
"@paroicms/contact-form-plugin": "*",
"@paroicms/content-loading-plugin": "*",
"@paroicms/internal-link-plugin": "*",
"@paroicms/list-field-plugin": "*",
"@paroicms/mcp-plugin": "*",
"@paroicms/public-menu-plugin": "*",
"@paroicms/tiptap-editor-plugin": "*",
"@paroicms/platform-video-plugin": "*",
"@paroicms/server": "*",
"@paroicms/zoom-plugin": "*",
},
devDependencies: {
concurrently: "~9.1.2",
cssnano: "~7.1.2",
nodemon: "~3.1.9",
"pino-pretty": "~13.0.0",
postcss: "~8.5.6",
"postcss-cli": "~11.0.1",
"postcss-import": "~16.1.1",
"postcss-nested": "~7.0.2",
rimraf: "~6.0.1",
},
};
}