UNPKG

@deskthing/cli

Version:
250 lines (217 loc) โ€ข 7.85 kB
import { join, resolve } from "path"; import zl from "zip-lib"; import { readdir, stat, cp, rm, mkdir } from "fs/promises"; import { loadConfigs } from "./config"; import { build as buildEsbuild } from "esbuild"; import { build as buildVite } from "vite"; import viteLegacyPlugin from "@vitejs/plugin-legacy" import { exec } from "child_process" async function buildServer() { await buildEsbuild({ entryPoints: ["server/index.ts"], bundle: true, platform: "node", outfile: "dist/server/index.js", target: "ESNext", format: "esm", external: ['node:*', 'fs', 'path', 'child_process'], resolveExtensions: [".ts", ".js"], sourcemap: true, banner: { js: ` // ESM shims for Node.js built-in modules import { createRequire as DeskThingCreateRequire } from 'module'; import { fileURLToPath as DeskThingFileURLToPath } from 'url'; import { dirname as DeskThingDirname } from 'node:path'; const require = DeskThingCreateRequire(import.meta.url); const __filename = DeskThingFileURLToPath(import.meta.url); const __dirname = DeskThingDirname(__filename); `} }); } async function buildWorkers() { try { await stat("server/workers") } catch (e) { console.warn("\x1b[35mUnable to find workers file\x1b[0m"); console.warn("\x1b[90m(Can be ignored if you do not have workers)\x1b[0m"); return } try { const workersDir = "server/workers"; const files = await readdir(workersDir); const tsFiles = files .filter(file => file.endsWith('.ts')) .map(file => join(workersDir, file)); // Only proceed if there are TypeScript files to build if (tsFiles.length === 0) { console.warn("\x1b[35mNo TypeScript files found in workers directory\x1b[0m"); return; } await buildEsbuild({ entryPoints: tsFiles, bundle: true, platform: "node", outdir: "dist/server/workers", target: "ESNext", format: "esm", resolveExtensions: [".ts", ".js"], sourcemap: true, banner: { js: ` // ESM shims for Node.js built-in modules import { createRequire as DeskThingCreateRequire } from 'module'; import { fileURLToPath as DeskThingFileURLToPath } from 'url'; import { dirname as DeskThingDirname } from 'node:path'; const require = DeskThingCreateRequire(import.meta.url); const __filename = DeskThingFileURLToPath(import.meta.url); const __dirname = DeskThingDirname(__filename); ` } }); } catch (error) { console.error("\x1b[31mError building workers:\x1b[0m", error); } } const buildPostinstall = async () => { try { await stat("postinstall") } catch (e) { console.warn("\x1b[35mUnable to find postinstall file\x1b[0m"); console.warn("\x1b[90m(Can be ignored if you do not have a postinstall script)\x1b[0m"); return } try { await buildEsbuild({ entryPoints: ["postinstall/index.ts"], bundle: true, platform: "node", target: "ESNext", format: "esm", resolveExtensions: [".ts", ".js"], sourcemap: false, outfile: "dist/postinstall.mjs", // ensure that it is a module minify: true, }); } catch (error) { console.error("\x1b[31mError building postinstall:\x1b[0m", error); } } async function buildClient() { await buildVite({ configFile: "vite.config.ts", base: "./", plugins: [viteLegacyPlugin({ targets: ["Chrome 69"] })], build: { outDir: "dist/client", rollupOptions: { output: { assetFileNames: "[name]-[hash][extname]", chunkFileNames: "[name]-[hash].js", entryFileNames: "[name]-[hash].js", }, }, }, }); } async function copyDeskThing() { const deskthingPath = resolve("deskthing"); const publicPath = resolve("public"); const distFile = resolve("dist"); const manifestFile = join(deskthingPath, "manifest.json"); const oldmanifestFile = join(publicPath, "manifest.json"); if (await stat(manifestFile).catch(() => false)) { await cp(deskthingPath, join(distFile), { recursive: true }); } else if (await stat(oldmanifestFile).catch(() => false)) { console.log( "Using old manifest.json. Please move this to /deskthing or run `deskthing update`" ); await cp(publicPath, join(distFile), { recursive: true }); } else { throw new Error("No manifest.json found in either /deskthing or /public"); } } async function addFilesToArchive( archive: zl.Zip, folderPath: string, baseFolder = "" ) { const exists = await stat(folderPath).catch(() => false); if (!exists) return; const files = await readdir(folderPath); for (const file of files) { const filePath = join(folderPath, file); const stats = await stat(filePath); if (stats.isDirectory()) { await addFilesToArchive(archive, filePath, join(baseFolder, file)); } else { await archive.addFile(filePath, join(baseFolder, file)); } } } export async function createPackage() { const { packageJson, manifestJson } = loadConfigs(); const packageName = packageJson.name; const version = manifestJson.version || packageJson.version; const distPath = resolve("dist"); const outputFile = join(distPath, `${packageName}-v${version}.zip`); console.log("\x1b[36m%s\x1b[0m", "Zipping to " + outputFile); const archive = new zl.Zip(); console.log("\x1b[33m%s\x1b[0m", "๐Ÿ“ฆ Adding files to archive..."); await addFilesToArchive(archive, distPath); console.log("\x1b[33m%s\x1b[0m", "๐Ÿ“ Writing archive to file..."); await archive.archive(outputFile); console.log("\x1b[32m%s\x1b[0m", "โœ… Archive written successfully!"); } async function clean() { const distPath = resolve("dist"); try { await mkdir(distPath, { recursive: true }); const files = await readdir(distPath); for (const file of files) { const filePath = join(distPath, file); await rm(filePath, { recursive: true, force: true }); } } catch (error) { await mkdir(distPath, { recursive: true }); } } async function ensureNpmBuilt() { const nodeModulesPath = resolve("node_modules"); const nodeModulesExists = await stat(nodeModulesPath).catch(() => false); if (!nodeModulesExists) { console.log("\x1b[33m%s\x1b[0m", "๐Ÿ“ฆ Running npm install..."); await new Promise((resolve, reject) => { exec('npm install', (error, stdout, stderr) => { if (error) { reject(error); return; } resolve(stdout); }); }); } else { console.log("\x1b[32m%s\x1b[0m", "โœ… NPM is already built!"); } } export async function buildAll() { // Clear all of the files in the dist folder that relate to the build console.log("\x1b[33m%s\x1b[0m", "๐Ÿงน Clearing dist folder..."); await clean(); console.log("\x1b[33m%s\x1b[0m", "๐Ÿ“ฆ Ensuring NPM has been built..."); await ensureNpmBuilt(); console.log("\x1b[33m%s\x1b[0m", "๐Ÿ—๏ธ Building Client..."); await buildClient(); console.log("\x1b[33m%s\x1b[0m", "๐Ÿ—๏ธ Building Server..."); await buildServer(); console.log("\x1b[33m%s\x1b[0m", "๐Ÿ—๏ธ Building Workers..."); await buildWorkers(); console.log("\x1b[33m%s\x1b[0m", "๐Ÿ—๏ธ Building Postinstall Script..."); await buildPostinstall(); console.log("\x1b[33m%s\x1b[0m", "๐Ÿ—๏ธ Copying Manifest..."); await copyDeskThing(); console.log("\x1b[33m%s\x1b[0m", "๐Ÿ“ฆ Creating package..."); await createPackage(); console.log("\x1b[32m%s\x1b[0m", "โœ… Build completed successfully!"); }