From 7d3d1ca229dbcd5ba39d0bdf7daf39a2fdd8cb59 Mon Sep 17 00:00:00 2001 From: msowho Date: Mon, 18 Jul 2022 01:34:22 +0500 Subject: [PATCH] ESBuild integration --- package.json | 2 ++ src/cobalt.js | 57 ++++++++++++++++++++++++++++++++++++++- src/modules/builder.js | 29 ++++++++++++++++++++ src/modules/pageRender.js | 5 ++-- 4 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 src/modules/builder.js diff --git a/package.json b/package.json index b9c52126..2dcecc75 100644 --- a/package.json +++ b/package.json @@ -24,10 +24,12 @@ "dependencies": { "cors": "^2.8.5", "dotenv": "^16.0.1", + "esbuild": "^0.14.49", "express": "^4.17.1", "express-rate-limit": "^6.3.0", "ffmpeg-static": "^5.0.0", "got": "^12.1.0", + "mime-types": "^2.1.35", "node-cache": "^5.1.2", "url-pattern": "^1.0.3", "xml-js": "^1.6.11", diff --git a/src/cobalt.js b/src/cobalt.js index ae10d381..41df6f7c 100644 --- a/src/cobalt.js +++ b/src/cobalt.js @@ -13,6 +13,10 @@ import { apiJSON } from "./modules/sub/utils.js"; import loc from "./modules/sub/i18n.js"; import { Bright, Cyan } from "./modules/sub/consoleText.js"; import stream from "./modules/stream/stream.js"; +import { UUID } from "./modules/sub/crypto.js"; +import { buildJS, buildCSS } from "./modules/builder.js"; +import { lookup } from "mime-types"; +import { Readable } from "stream"; const commitHash = shortCommit(); const app = express(); @@ -109,18 +113,69 @@ if (fs.existsSync('./.env')) { "hash": commitHash, "type": "default", "lang": req.header('Accept-Language') ? req.header('Accept-Language').slice(0, 2) : "en", - "useragent": req.header('user-agent') ? req.header('user-agent') : genericUserAgent + "useragent": req.header('user-agent') ? req.header('user-agent') : genericUserAgent, + "distUUID": req.app.get('currentDistUUID'), })) } }); app.get("/favicon.ico", async (req, res) => { res.redirect('/icons/favicon.ico'); }); + + app.head("/dist/:uuid/:file", (req, res) => { + let { uuid, file } = req.params, + dist = req.app.get(`dist~${uuid}`); + + if (!dist || !dist.files.hasOwnProperty(file)) { + res.sendStatus(404); + } + + res.setHeader('Content-Type', lookup(file)); + res.setHeader('Content-Length', dist.files[file].length); + + res.status(204); + res.end(); + res.sendStatus(500); + }); + app.get("/dist/:uuid/:file", (req, res) => { + let { uuid, file } = req.params, + dist = req.app.get(`dist~${uuid}`); + + if (!dist || !dist.files.hasOwnProperty(file)) { + res.sendStatus(404); + } + + res.setHeader('Content-Type', lookup(file)); + + const readableStream = Readable.from(dist.files[file]); + readableStream.pipe(res); + }); + app.get("/*", async (req, res) => { res.redirect('/') }); app.listen(process.env.port, () => { console.log(`\n${Bright(`${appName} (${version})`)}\n\nURL: ${Cyan(`${process.env.selfURL}`)}\nPort: ${process.env.port}\nCurrent commit: ${Bright(`${commitHash}`)}\nStart time: ${Bright(Math.floor(new Date().getTime()))}\n`) + + // Building JS and CSS with builder module + Promise.all([ + buildJS(), + buildCSS() + ]).then(([js, css]) => { + let currentDistUUID = UUID(), + // TODO: Move deep copy to utils + currentDist = { + uuid: currentDistUUID, + files: JSON.parse(JSON.stringify(css.fontData)) + }; + + currentDist.files[`bundle.${commitHash}.js`] = js; + currentDist.files[`bundle.${commitHash}.css`] = css.code; + + // e is real 2401 + app.set('currentDistUUID', currentDistUUID); + app.set(`dist~${currentDistUUID}`, currentDist); + }); }); } else { console.log('Required config files are missing. Please run "npm run setup" first.') diff --git a/src/modules/builder.js b/src/modules/builder.js new file mode 100644 index 00000000..1877d190 --- /dev/null +++ b/src/modules/builder.js @@ -0,0 +1,29 @@ +import { readFile, readdir } from "fs/promises"; + +import * as esbuild from "esbuild"; + +export async function buildJS () { + let originalJS = await readFile('./src/static/cobalt.js', { encoding: 'utf-8' }), + transformedJS = await esbuild.transform(originalJS, { minify: true }); + + return transformedJS.code +} + +// TODO: Make it work with new fonts +export async function buildCSS () { + let mainCSS = await readFile('./src/static/cobalt.css', { encoding: 'utf-8' }), + fontCSS = await readFile('./src/static/fonts/notosansmono/notosansmono.css', { encoding: 'utf-8' }), + fontFiles = (await readdir('./src/static/fonts/notosansmono/')).filter((f) => f.endsWith('.woff2')), + transformedCSS = await esbuild.transform(fontCSS + mainCSS, { minify: true, loader: 'css' }); + + const fontData = {} + for (let index in fontFiles) { + const filename = fontFiles[index] + fontData[filename] = await readFile(`./src/static/fonts/notosansmono/${filename}`, { encoding: 'utf-8' }) + } + + return { + code: transformedCSS.code, + fontData: fontData + } +} diff --git a/src/modules/pageRender.js b/src/modules/pageRender.js index 158f785d..3a69921e 100644 --- a/src/modules/pageRender.js +++ b/src/modules/pageRender.js @@ -47,8 +47,7 @@ export default function(obj) { - - + @@ -194,7 +193,7 @@ export default function(obj) { - + `; } catch (err) { return `${loc('en', 'apiError', 'noRender', obj.hash)}`;