1
0
silverbullet/plugos/bin/plugos-bundle.ts

149 lines
3.7 KiB
TypeScript
Raw Normal View History

#!/usr/bin/env node
import esbuild from "esbuild";
2022-03-28 06:51:24 +00:00
import { readFile, unlink, watch, writeFile } from "fs/promises";
import path from "path";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
2022-03-21 14:21:34 +00:00
import { Manifest } from "../types";
2022-03-27 09:26:13 +00:00
import YAML from "yaml";
import { preloadModules } from "../../common/preload_modules";
async function compile(
filePath: string,
functionName: string,
debug: boolean,
meta = true
) {
2022-03-28 06:51:24 +00:00
let outFile = "_out.tmp";
let inFile = filePath;
if (functionName) {
// Generate a new file importing just this one function and exporting it
2022-03-28 06:51:24 +00:00
inFile = "_in.js";
await writeFile(
inFile,
2022-03-28 06:51:24 +00:00
`import {${functionName}} from "./${filePath}";export default ${functionName};`
);
}
// TODO: Figure out how to make source maps work correctly with eval() code
let result = await esbuild.build({
entryPoints: [inFile],
bundle: true,
format: "iife",
globalName: "mod",
2022-03-28 13:25:05 +00:00
platform: "browser",
sourcemap: false, //sourceMap ? "inline" : false,
minify: !debug,
outfile: outFile,
metafile: true,
external: preloadModules,
});
if (meta) {
let text = await esbuild.analyzeMetafile(result.metafile);
console.log("Bundle info for", functionName, text);
}
let jsCode = (await readFile(outFile)).toString();
await unlink(outFile);
if (inFile !== filePath) {
await unlink(inFile);
}
2022-03-28 13:25:05 +00:00
return `(() => { ${jsCode}
return mod;})()`;
}
2022-03-20 09:22:38 +00:00
async function bundle(manifestPath: string, sourceMaps: boolean) {
const rootPath = path.dirname(manifestPath);
2022-03-27 09:26:13 +00:00
const manifest = YAML.parse(
2022-03-21 14:21:34 +00:00
(await readFile(manifestPath)).toString()
) as Manifest<any>;
for (let [name, def] of Object.entries(manifest.functions)) {
2022-03-20 09:22:38 +00:00
let jsFunctionName = "default",
filePath = path.join(rootPath, def.path!);
if (filePath.indexOf(":") !== -1) {
[filePath, jsFunctionName] = filePath.split(":");
}
def.code = await compile(filePath, jsFunctionName, sourceMaps);
delete def.path;
}
return manifest;
}
2022-03-27 07:55:29 +00:00
async function buildManifest(
manifestPath: string,
distPath: string,
debug: boolean
) {
let generatedManifest = await bundle(manifestPath, debug);
2022-03-27 09:26:13 +00:00
const outFile =
manifestPath.substring(
0,
manifestPath.length - path.extname(manifestPath).length
) + ".json";
const outPath = path.join(distPath, path.basename(outFile));
2022-03-27 07:55:29 +00:00
console.log("Emitting bundle to", outPath);
await writeFile(outPath, JSON.stringify(generatedManifest, null, 2));
return { generatedManifest, outPath };
}
async function run() {
2022-03-27 07:55:29 +00:00
let args = yargs(hideBin(process.argv))
.option("debug", {
type: "boolean",
})
2022-03-27 07:55:29 +00:00
.option("watch", {
type: "boolean",
alias: "w",
})
.option("dist", {
type: "string",
default: ".",
})
.parse();
2022-03-27 07:55:29 +00:00
if (args._.length === 0) {
console.log(
2022-03-27 09:31:12 +00:00
"Usage: plugos-bundle [--debug] [--dist <path>] <manifest.plug.yaml> <manifest2.plug.yaml> ..."
2022-03-27 07:55:29 +00:00
);
process.exit(1);
}
2022-03-28 06:51:24 +00:00
async function buildAll() {
for (const plugManifestPath of args._) {
let manifestPath = plugManifestPath as string;
try {
2022-03-27 07:55:29 +00:00
await buildManifest(manifestPath, args.dist, !!args.debug);
2022-03-28 06:51:24 +00:00
} catch (e) {
console.error(`Error building ${manifestPath}:`, e);
}
}
}
await buildAll();
if (args.watch) {
console.log("Watching for changes...");
for await (const { eventType, filename } of watch(".", {
recursive: true,
})) {
if (
filename.endsWith(".plug.yaml") ||
filename.endsWith(".ts") ||
(filename.endsWith(".js") && !filename.endsWith("_in.js"))
) {
console.log("Change detected", eventType, filename);
await buildAll();
}
2022-03-27 07:55:29 +00:00
}
}
}
run().catch((e) => {
console.error(e);
process.exit(1);
});