wahs.wah.su/src/build.tsx

271 lines
7.6 KiB
TypeScript

import { Log } from "./utils";
import { renderToString } from "react-dom/server";
import Base from "./templates/base";
import fs from "fs";
import exec from "child_process";
const environment: "prod" | "dev" =
(process.env.ENVIRONMENT as "prod" | "dev") || "prod";
const log = new Log();
if (environment == "dev") {
log.warn("Running in a dev mode!");
}
if (!fs.existsSync("out")) fs.mkdirSync("out");
// List Objects from S3 bucket
import { S3Client, ListObjectsV2Command } from "@aws-sdk/client-s3";
import IndexPage from "./templates";
import type { ReactNode } from "react";
import ImagesPage from "./templates/images";
import VideosPage from "./templates/videos";
import ImagePage from "./templates/viewImage";
import FavoritesPage from "./templates/favorites";
const S3 = new S3Client({
region: "auto",
endpoint: `${process.env.ENDPOINT}`,
credentials: {
accessKeyId: `${process.env.ACCESS_KEY_ID}`,
secretAccessKey: `${process.env.SECRET_ACCESS_KEY}`,
},
});
let images: string[] = [];
let videos: string[] = [];
let config = {
endpoint: process.env.ENDPOINT,
bucket: process.env.BUCKET,
prefix: process.env.PREFIX,
};
async function listAllObjects(bucketName: string, prefix: string) {
let isTruncated: boolean = true;
let continuationToken: string = "";
while (isTruncated) {
const params = {
Bucket: bucketName,
Prefix: prefix,
ContinuationToken: continuationToken,
};
const response = await S3.send(new ListObjectsV2Command(params));
if (response && response.Contents) {
response.Contents.forEach((item) => {
if (item.Key != undefined) {
const ext = item.Key.split(".")[item.Key.split(".").length - 1];
const obj = item.Key.split("/")[item.Key.split("/").length - 1];
if (["png", "jpg", "jpeg"].includes(ext.toLowerCase())) {
images.push(obj);
} else if (["mp4"].includes(ext.toLowerCase())) {
videos.push(obj);
}
}
});
isTruncated = response.IsTruncated as boolean;
continuationToken = response.NextContinuationToken as string;
}
}
}
if (!fs.existsSync(".cache")) fs.mkdirSync(".cache");
if (!fs.existsSync(".cache/objects.json")) {
log.info("Listing all objects in S3 bucket . . .");
await listAllObjects(
process.env.BUCKET as string,
process.env.PREFIX as string
);
fs.writeFileSync(
".cache/objects.json",
JSON.stringify({ config, images, videos })
);
log.info(
`Total: ${images.length + videos.length} | ${images.length} Images | ${
videos.length
} Videos`
);
} else {
log.info("Using S3 Bucket cache . . .");
const _cacheFile = fs.readFileSync(".cache/objects.json", {
encoding: "utf-8",
});
config = JSON.parse(_cacheFile)["config"];
images = JSON.parse(_cacheFile)["images"];
videos = JSON.parse(_cacheFile)["videos"];
log.info(
`Total: ${images.length + videos.length} | ${images.length} Images | ${
videos.length
} Videos`
);
}
if (!fs.existsSync("out/data")) fs.mkdirSync("out/data");
if (!fs.existsSync("out/data/config.json")) {
fs.writeFileSync("out/data/config.json", JSON.stringify(config));
}
if (!fs.existsSync("out/data/images.json")) {
fs.writeFileSync("out/data/images.json", JSON.stringify(images));
}
if (!fs.existsSync("out/data/videos.json")) {
fs.writeFileSync("out/data/videos.json", JSON.stringify(videos));
}
function generateHTMLFile(
title: string,
path: string,
description: string,
script: string[],
Element: ReactNode,
output: string
) {
const _script = [environment == "dev" ? "/static/dev/hotreload.js" : ""];
script.forEach((item) => _script.push(item));
if (!fs.existsSync(`out${path}`)) fs.mkdirSync(`out${path}`);
let html = renderToString(
<Base
title={title}
environment={environment}
path={path}
head={{
description: description,
image: "https://s3.tebi.io/wahs.wah.su/red_panda/1928. bqiKzsaDPlw.jpg",
url: process.env.WEB_URL as string,
preload: [
`${
environment == "prod" ? process.env.WEB_URL : ""
}/data/config.json`,
`${
environment == "prod" ? process.env.WEB_URL : ""
}/data/images.json`,
`${
environment == "prod" ? process.env.WEB_URL : ""
}/data/videos.json`,
],
dns: [process.env.ENDPOINT as string, "https://wsrv.nl"],
script: _script,
}}
>
{Element}
</Base>
);
fs.writeFileSync(output, `<!DOCTYPE html>${html}`);
console.log(`Generated: ${output}`);
}
fs.cpSync("src/static", "out/static", { recursive: true });
if (environment == "dev") {
fs.cpSync("src/static_dev", "out/static/dev", { recursive: true });
} else {
log.info("Minifying resources...");
exec.exec(
"bun run tailwindcss -i src/input.css -o out/static/tailwind.min.css --build --minify",
(error, stdout, stderr) => {
if (error) {
log.error(error.message);
return;
}
if (stderr) {
log.error(stderr);
return;
}
log.info(stdout);
}
);
const transpiler = new Bun.Transpiler({
loader: "js",
target: "browser",
minifyWhitespace: true,
});
const files = fs.readdirSync("src/static");
const minify = files.filter((file) => file.endsWith(".js"));
minify.forEach((file) => {
const ext = file.split(".")[file.split(".").length - 1];
const name = file.split(".")[0];
const orFile = fs.readFileSync(`src/static/${file}`, {
encoding: "utf-8",
});
const minFile = transpiler.transformSync(orFile);
fs.writeFileSync(`out/static/${name}.min.${ext}`, minFile);
});
}
generateHTMLFile(
"Wah-Collection",
"/",
`Home page of Wah-Collection by @radiquum | ${images.length} Images | ${
videos.length
} Videos | ${images.length + videos.length} Total`,
[
environment == "dev" ? "/static/Placeholders.js" : "/static/Placeholders.min.js",
environment == "dev" ? "/static/utils.js" : "/static/utils.min.js",
environment == "dev"
? "/static/populateIndex.js"
: "/static/populateIndex.min.js",
],
<IndexPage />,
"out/index.html"
);
generateHTMLFile(
"Wah-Collection/Images",
"/images/",
`Image page of Wah-Collection | ${images.length} Images`,
[
environment == "dev" ? "/static/Placeholders.js" : "/static/Placeholders.min.js",
environment == "dev" ? "/static/utils.js" : "/static/utils.min.js",
environment == "dev"
? "/static/populateImages.js"
: "/static/populateImages.min.js",
],
<ImagesPage />,
"out/images/index.html"
);
generateHTMLFile(
"Wah-Collection/Image",
"/image/",
`View the full image on the WAH-Collection`,
[
environment == "dev" ? "/static/imagePageUtils.js" : "/static/imagePageUtils.min.js",
],
<ImagePage />,
"out/image/index.html"
);
generateHTMLFile(
"Wah-Collection/Videos",
"/videos/",
`Video page of Wah-Collection | ${videos.length} Videos`,
[
environment == "dev" ? "/static/Placeholders.js" : "/static/Placeholders.min.js",
environment == "dev" ? "/static/utils.js" : "/static/utils.min.js",
environment == "dev"
? "/static/populateVideos.js"
: "/static/populateVideos.min.js",
],
<VideosPage />,
"out/videos/index.html"
);
generateHTMLFile(
"Wah-Collection/Favorites",
"/favorites/",
`Your favorites of Wah-Collection`,
[
environment == "dev" ? "/static/Placeholders.js" : "/static/Placeholders.min.js",
environment == "dev" ? "/static/utils.js" : "/static/utils.min.js",
environment == "dev"
? "/static/populateFavorites.js"
: "/static/populateFavorites.min.js",
],
<FavoritesPage />,
"out/favorites/index.html"
);