codeflash-internal/js/cf-webapp/scripts/postinstall-wasm.mjs
Kevin Turcios 48b5e2b46d
fix: make tree-sitter WASM build failure non-fatal when cache exists (#2602)
## Summary
- If the WASM build fails (e.g. GitHub CDN outage for tree-sitter-cli or
wasi-sdk) but a cached `.wasm` file already exists, warn instead of
crashing `pnpm install`
- Only hard-fail when no cached WASM exists at all

This prevents transient CDN outages from blocking deploys when the WASM
artifacts are already cached.

## Test plan
- [ ] CI passes on this PR (validates the postinstall script doesn't
crash)
- [ ] Verify deploy workflow can proceed when WASM cache hits
2026-04-13 11:43:07 -05:00

80 lines
2.8 KiB
JavaScript

#!/usr/bin/env node
/**
* Postinstall script that caches tree-sitter WASM artifacts in public/.
* Prisma client generation is handled by pnpm workspaces — no symlinks needed.
*
* Uses Node module resolution to find packages regardless of where pnpm
* stores them (isolated node_modules with symlinks to the store).
*/
import { existsSync, readFileSync, writeFileSync, copyFileSync } from "fs"
import { createRequire } from "module"
import { execSync } from "child_process"
import { dirname, resolve } from "path"
const require = createRequire(import.meta.url)
// Resolve package directory. Some packages (e.g. web-tree-sitter) don't
// export ./package.json, so fall back to resolving the main entry.
function pkgDir(name) {
try {
return dirname(require.resolve(`${name}/package.json`))
} catch {
return dirname(require.resolve(name))
}
}
// --- Tree-sitter WASM ---
const PUBLIC = resolve("public")
const WASM_FILE = resolve(PUBLIC, "tree-sitter-python.wasm")
const WEB_WASM = resolve(PUBLIC, "web-tree-sitter.wasm")
const VERSION_STAMP = resolve(PUBLIC, ".tree-sitter-python-version")
// Always copy web-tree-sitter.wasm (fast — just a file copy)
try {
const webTreeSitterSrc = resolve(pkgDir("web-tree-sitter"), "web-tree-sitter.wasm")
copyFileSync(webTreeSitterSrc, WEB_WASM)
console.log("[postinstall] Copied web-tree-sitter.wasm")
} catch {
console.warn("[postinstall] web-tree-sitter.wasm not found — skipping copy")
}
// Read the installed tree-sitter-python version
let installedVersion = "unknown"
let treeSitterPythonDir
try {
treeSitterPythonDir = pkgDir("tree-sitter-python")
const pkg = JSON.parse(readFileSync(resolve(treeSitterPythonDir, "package.json"), "utf8"))
installedVersion = pkg.version
} catch {
// Package not installed — will force build
}
// Check if we can skip the build
let cachedVersion = ""
try {
cachedVersion = readFileSync(VERSION_STAMP, "utf8").trim()
} catch {
// No stamp — first install
}
if (existsSync(WASM_FILE) && cachedVersion === installedVersion) {
console.log(`[postinstall] tree-sitter-python.wasm is up-to-date (v${installedVersion}) — skipping build`)
process.exit(0)
}
// Build tree-sitter-python WASM
console.log(`[postinstall] Building tree-sitter-python.wasm (v${installedVersion})...`)
try {
execSync(`npx tree-sitter build --wasm ${treeSitterPythonDir} -o ${WASM_FILE}`, {
stdio: "inherit",
})
writeFileSync(VERSION_STAMP, installedVersion)
console.log(`[postinstall] Built and cached tree-sitter-python.wasm (v${installedVersion})`)
} catch (err) {
if (existsSync(WASM_FILE)) {
console.warn("[postinstall] Failed to rebuild tree-sitter-python.wasm, using stale cached version:", err.message)
} else {
console.error("[postinstall] Failed to build tree-sitter-python.wasm and no cached version exists:", err.message)
process.exit(1)
}
}