#!/usr/bin/env node const { spawnSync } = require("node:child_process"); const { existsSync, readdirSync, statSync } = require("node:fs"); const { join, resolve } = require("node:path"); const root = resolve(__dirname, ".."); const srcResources = join(root, "src", "resources"); const distResources = join(root, "dist", "resources"); const stampPath = join(distResources, ".sf-resource-build-stamp"); const copyResourcesScript = join(root, "scripts", "copy-resources.cjs"); function latestMtimeMs(path) { let latest = 0; const stack = [path]; while (stack.length > 0) { const current = stack.pop(); if (!current) continue; let entries; try { entries = readdirSync(current, { withFileTypes: true }); } catch { continue; } for (const entry of entries) { const entryPath = join(current, entry.name); let stat; try { stat = statSync(entryPath); } catch { continue; } latest = Math.max(latest, stat.mtimeMs); if (entry.isDirectory()) { stack.push(entryPath); } } } return latest; } function sourceInputsMtimeMs() { return Math.max( latestMtimeMs(srcResources), existsSync(copyResourcesScript) ? statSync(copyResourcesScript).mtimeMs : 0, existsSync(join(root, "tsconfig.resources.json")) ? statSync(join(root, "tsconfig.resources.json")).mtimeMs : 0, ); } function hasCompleteResourceBuild() { return ( existsSync(stampPath) && existsSync(join(distResources, "SF-WORKFLOW.md")) && existsSync(join(distResources, "agents")) && existsSync(join(distResources, "extensions")) ); } function shouldRebuild() { if (process.env.SF_DEV_CLI_SKIP_RESOURCE_BUILD === "1") return false; if (process.env.SF_SKIP_SOURCE_RESOURCE_BUILD === "1") return false; if (!hasCompleteResourceBuild()) return true; let stampMtime = 0; try { stampMtime = statSync(stampPath).mtimeMs; } catch { return true; } return sourceInputsMtimeMs() > stampMtime; } if (shouldRebuild()) { console.error( "[forge] Source resources changed; rebuilding dist/resources before launch...", ); const result = spawnSync(process.execPath, [copyResourcesScript], { cwd: root, stdio: "inherit", env: process.env, }); if (result.status !== 0) { process.exit(result.status ?? 1); } }