From d711141c2d07d44d90ec072d3786cb97d16b2392 Mon Sep 17 00:00:00 2001 From: Rizky Date: Tue, 17 Oct 2023 07:18:57 +0700 Subject: [PATCH] adding site bundle export --- app/srv/api/site-bundle.ts | 31 ++++++++++ app/srv/api/site-export.ts | 112 +++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 app/srv/api/site-bundle.ts create mode 100644 app/srv/api/site-export.ts diff --git a/app/srv/api/site-bundle.ts b/app/srv/api/site-bundle.ts new file mode 100644 index 00000000..2402cb06 --- /dev/null +++ b/app/srv/api/site-bundle.ts @@ -0,0 +1,31 @@ +import { createHash } from "crypto"; +import { dir } from "dir"; +import { readAsync } from "fs-jetpack"; +import { apiContext } from "service-srv"; +const cache = { + md5: "", + content: null as any, +}; + +export const _ = { + url: "/site-bundle/:mode", + async api(mode: "md5" | "download") { + const { req, res } = apiContext(this); + + if (!cache.md5) { + const content = await readAsync(dir.path("srv/site.zip"), "buffer"); + + if (content) { + cache.md5 = createHash("md5").update(content).digest("hex"); + cache.content = content; + } + } + if (mode === "md5") { + res.setHeader("Content-Type", "text/plain"); + return cache.md5; + } + + res.setHeader("Content-Type", "application/zip"); + res.send(cache.content); + }, +}; diff --git a/app/srv/api/site-export.ts b/app/srv/api/site-export.ts new file mode 100644 index 00000000..c6f00299 --- /dev/null +++ b/app/srv/api/site-export.ts @@ -0,0 +1,112 @@ +import { apiContext } from "service-srv"; + +import { dir } from "dir"; +import fs from "fs"; +import { exists } from "fs-jetpack"; +import { gzipSync } from "zlib"; +import path from "path"; + +export const _ = { + url: "/site-export/:site_id", + async api(site_id: string) { + const { req, res } = apiContext(this); + const site = (await db.site.findFirst({ + where: { id: site_id }, + })) as any; + const pages = await db.page.findMany({ + where: { + id_site: site_id, + is_deleted: false, + name: { not: { startsWith: "layout:" } }, + }, + }); + + if (site) { + const layout = await db.page.findFirst({ + where: { + id_site: site.id, + name: { startsWith: "layout:" }, + is_default_layout: true, + is_deleted: false, + }, + select: { content_tree: true, id: true }, + }); + + const cgroups = await db.site_use_comp.findMany({ + where: { id_site: site.id }, + }); + + if (cgroups) { + site.cgroup_ids = []; + for (const id of cgroups.map((c) => c.use_id_site)) { + site.cgroup_ids.push(id); + } + } + + if (layout) { + const childs = (layout.content_tree as any).childs; + if (childs && childs.length > 0) { + (site as any).layout = childs[0]; + (site as any).layout_id = layout.id; + } + } + } + + const comps = await db.component.findMany({ + where: { + component_group: { + component_site: { + some: { + id_site: site_id, + }, + }, + }, + }, + }); + const npm = { + site: {} as Record, + pages: {} as Record>, + }; + npm.site = readDirectoryRecursively(dir.path(`../npm/site/${site_id}`)); + + for (const page of pages) { + if (exists(dir.path(`../npm/page/${page.id}`))) { + npm.pages[page.id] = readDirectoryRecursively( + dir.path(`../npm/page/${page.id}`) + ); + } + } + + const str = gzipSync(JSON.stringify({ site, pages, npm, comps })); + res.send(str); + }, +}; + +function readDirectoryRecursively( + dirPath: string, + baseDir?: string[] +): Record { + const result: Record = {}; + + const contents = fs.readdirSync(dirPath); + + for (const item of contents) { + const itemPath = path.join(dirPath, item); + const stats = fs.statSync(itemPath); + + if (stats.isFile()) { + const content = fs.readFileSync(itemPath, "utf-8"); + result[[...(baseDir || []), item].join("/")] = content; + } else if (stats.isDirectory()) { + if (item !== "node_modules") { + const subdirResult = readDirectoryRecursively(itemPath, [ + ...(baseDir || []), + item, + ]); + Object.assign(result, subdirResult); + } + } + } + + return result; +}