feat: ship prebuilt plugin bundle for remote dsh install

Remote github installs only get packages/dsh-plugin; without bundle the
host tried pnpm build and hung. Pack web+server into bundle/ and start
from it so other machines can run after dsh plugin add.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-12 10:45:08 +08:00
parent d95f033d1f
commit b23959400d
13 changed files with 28325 additions and 41 deletions

View file

@ -0,0 +1,71 @@
/**
* Pack prebuilt web UI + server into packages/dsh-plugin/bundle
* so `dsh plugin add github:…#path:packages/dsh-plugin` works without monorepo.
*/
import { execSync } from "node:child_process";
import {
cpSync,
existsSync,
mkdirSync,
rmSync,
writeFileSync,
} from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import * as esbuild from "esbuild";
const pluginRoot = dirname(dirname(fileURLToPath(import.meta.url)));
const repoRoot = join(pluginRoot, "../..");
const bundleRoot = join(pluginRoot, "bundle");
const webOut = join(bundleRoot, "web");
const serverOut = join(bundleRoot, "server.mjs");
function run(cmd, cwd = repoRoot) {
console.log(`[pack] ${cmd}`);
execSync(cmd, { cwd, stdio: "inherit", env: process.env, windowsHide: true });
}
// 1) Build workspace libs + web
run("pnpm --filter @mind-map/shared build");
run("pnpm --filter @mind-map/graph-core build");
run("pnpm --filter @mind-map/graph-store build");
run("pnpm --filter @mind-map/layout-engine build");
// dream-skin ships TS+JSON; esbuild resolves it without a separate tsc emit
run("pnpm --filter @mind-map/web build");
const webDist = join(repoRoot, "apps/web/dist");
if (!existsSync(join(webDist, "index.html"))) {
throw new Error("apps/web/dist/index.html missing after build");
}
// 2) Fresh bundle dir
rmSync(bundleRoot, { recursive: true, force: true });
mkdirSync(webOut, { recursive: true });
cpSync(webDist, webOut, { recursive: true });
// 3) Bundle server (workspace + npm deps inlined; node builtins stay external)
console.log("[pack] esbuild apps/server → bundle/server.mjs");
await esbuild.build({
entryPoints: [join(repoRoot, "apps/server/src/index.ts")],
bundle: true,
platform: "node",
format: "esm",
outfile: serverOut,
packages: "bundle",
banner: {
js: "import { createRequire as __mmCr } from 'node:module'; const require = __mmCr(import.meta.url);",
},
logLevel: "info",
});
if (!existsSync(serverOut)) {
throw new Error("bundle/server.mjs was not produced");
}
writeFileSync(
join(bundleRoot, "README.txt"),
"Prebuilt assets for remote dsh plugin install. Regenerated by: node packages/dsh-plugin/scripts/pack-bundle.mjs\n",
"utf8",
);
console.log("[pack] OK →", bundleRoot);