#!/usr/bin/env node "use strict"; const fs = require("fs/promises"); const path = require("path"); const { spawnSync } = require("child_process"); const REPO_ROOT = path.resolve(__dirname, "..", ".."); const RUST_ROOT = path.join(REPO_ROOT, "rust"); const CRATE_ROOT = path.join(RUST_ROOT, "crates", "tree-shell-runtime-wasm"); const GENERATED_ROOT = path.join(CRATE_ROOT, "generated"); const TOOLCHAIN = "1.89.0-x86_64-unknown-linux-gnu"; const TARGET = "wasm32-unknown-unknown"; const OUT_NAME = "mnote-tree-shell-runtime"; const MANIFEST_PATH = path.join(CRATE_ROOT, "Cargo.toml"); const WASM_PATH = path.join( RUST_ROOT, "target", TARGET, "debug", "tree_shell_runtime_wasm.wasm", ); const ENTRY_PATH = path.join(GENERATED_ROOT, `${OUT_NAME}.js`); const OUTPUT_WASM_PATH = path.join(GENERATED_ROOT, `${OUT_NAME}_bg.wasm`); const GITIGNORE_PATH = path.join(GENERATED_ROOT, ".gitignore"); function run(command, args, options = {}) { const result = spawnSync(command, args, { cwd: options.cwd ?? REPO_ROOT, env: process.env, encoding: "utf8", stdio: "pipe", }); if (result.status === 0) { return result; } const stdout = (result.stdout || "").trim(); const stderr = (result.stderr || "").trim(); const details = [stdout, stderr].filter(Boolean).join("\n"); throw new Error( [`命令失败:${command} ${args.join(" ")}`, details].filter(Boolean).join("\n"), ); } async function ensureGeneratedDir() { await fs.rm(GENERATED_ROOT, { recursive: true, force: true }); await fs.mkdir(GENERATED_ROOT, { recursive: true }); await fs.writeFile(GITIGNORE_PATH, "*\n!.gitignore\n", "utf8"); } async function verifyOutput() { const entrySource = await fs.readFile(ENTRY_PATH, "utf8"); await fs.access(OUTPUT_WASM_PATH); if (!entrySource.includes("export function reduceTreeShellRuntime")) { throw new Error("tree shell runtime js glue 缺少 reduceTreeShellRuntime 导出"); } } async function buildTreeShellRuntime() { // 说明:tree shell iframe 主链直接加载固定 wasm/js 产物,因此在 Next 启动前先生成正式 artifact。 run("rustup", ["target", "add", TARGET, "--toolchain", TOOLCHAIN], { cwd: RUST_ROOT }); run( "cargo", [ `+${TOOLCHAIN}`, "build", "--manifest-path", MANIFEST_PATH, "--package", "tree-shell-runtime-wasm", "--lib", "--target", TARGET, "--locked", ], { cwd: RUST_ROOT }, ); await ensureGeneratedDir(); run( "wasm-bindgen", [ WASM_PATH, "--target", "web", "--out-dir", GENERATED_ROOT, "--out-name", OUT_NAME, ], { cwd: RUST_ROOT }, ); await verifyOutput(); return { generatedRoot: GENERATED_ROOT, entryPath: ENTRY_PATH, wasmPath: OUTPUT_WASM_PATH, }; } module.exports = { buildTreeShellRuntime, GENERATED_ROOT, OUT_NAME, }; if (require.main === module) { buildTreeShellRuntime() .then(({ generatedRoot }) => { process.stdout.write(`tree shell runtime 已生成:${generatedRoot}\n`); }) .catch((error) => { process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`); process.exit(1); }); }