Spaces:
Sleeping
Sleeping
File size: 5,400 Bytes
ec675f2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | #!/bin/bash
set -e
# 1. Move to the builder root
cd ~/website-builder
echo "π Working in: $(pwd)"
# 2. Create validator.ts if missing
if [ ! -f "lib/validator.ts" ]; then
echo "π Creating lib/validator.ts..."
cat > lib/validator.ts << 'VALIDATOR_EOF'
import { spawn } from "child_process";
import fs from "fs";
import path from "path";
export interface ValidationResult {
success: boolean;
installLog: string;
buildLog: string;
error?: string;
duration: number;
}
function runCommand(
cmd: string,
args: string[],
cwd: string,
timeout: number = 300000
): Promise<{ stdout: string; stderr: string; code: number | null }> {
return new Promise((resolve) => {
const child = spawn(cmd, args, { cwd, shell: true });
let stdout = "", stderr = "";
child.stdout.on("data", (d) => { stdout += d.toString(); });
child.stderr.on("data", (d) => { stderr += d.toString(); });
const timer = setTimeout(() => {
child.kill("SIGTERM");
resolve({ stdout, stderr: stderr + "\n[ERROR] Timed out", code: null });
}, timeout);
child.on("close", (code) => { clearTimeout(timer); resolve({ stdout, stderr, code }); });
child.on("error", (err) => { clearTimeout(timer); resolve({ stdout, stderr: stderr + "\n" + err.message, code: null }); });
});
}
export async function validateProject(
projectDir: string,
options: { installTimeout?: number; buildTimeout?: number } = {}
): Promise<ValidationResult> {
const start = Date.now();
const installTimeout = options.installTimeout || 300000;
const buildTimeout = options.buildTimeout || 300000;
if (!fs.existsSync(projectDir)) {
return { success: false, installLog: "", buildLog: "", error: `Directory not found: ${projectDir}`, duration: 0 };
}
const pkgPath = path.join(projectDir, "package.json");
if (!fs.existsSync(pkgPath)) {
return { success: false, installLog: "", buildLog: "", error: "No package.json", duration: 0 };
}
const installResult = await runCommand("npm", ["install", "--no-audit", "--no-fund", "--loglevel=error"], projectDir, installTimeout);
const installLog = installResult.stdout + "\n" + installResult.stderr;
if (installResult.code !== 0 && installResult.code !== null) {
return { success: false, installLog, buildLog: "", error: `npm install failed with code ${installResult.code}`, duration: Date.now() - start };
}
const buildResult = await runCommand("npm", ["run", "build"], projectDir, buildTimeout);
const buildLog = buildResult.stdout + "\n" + buildResult.stderr;
if (buildResult.code !== 0 && buildResult.code !== null) {
return { success: false, installLog, buildLog, error: `npm run build failed with code ${buildResult.code}`, duration: Date.now() - start };
}
return { success: true, installLog, buildLog, duration: Date.now() - start };
}
export async function validateAndSave(
projectDir: string,
options?: { installTimeout?: number; buildTimeout?: number }
): Promise<ValidationResult> {
const result = await validateProject(projectDir, options);
const reportPath = path.join(projectDir, ".validation.json");
fs.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
return result;
}
VALIDATOR_EOF
echo "β
validator.ts created"
else
echo "β
validator.ts already exists"
fi
# 3. Add import to server.ts if missing
if ! grep -q 'import { validateAndSave } from "./lib/validator"' server.ts; then
echo "π Adding import to server.ts..."
# Insert after the last import line
sed -i '/^import /a import { validateAndSave } from "./lib/validator";' server.ts
echo "β
Import added"
else
echo "β
Import already present"
fi
# 4. Add validation block if missing
if ! grep -q 'validateAndSave(projectDir)' server.ts; then
echo "π Adding validation block after writeProject..."
# Insert after writeProject(projectDir, files); line
sed -i '/writeProject(projectDir, files);/a \
// Validate the project (install + build)\n\
const validation = await validateAndSave(projectDir);\n\
if (!validation.success) {\n\
console.error(`[build] Validation failed:\\n${validation.error}`);\n\
}' server.ts
echo "β
Validation block added"
else
echo "β
Validation block already present"
fi
# 5. Restart the API
echo "π Restarting API..."
pm2 restart crawl-api
# 6. Wait a moment for the API to come up
sleep 2
# 7. Test a new generation
echo "π Testing a new generation..."
response=$(curl -s -X POST http://localhost:8092/build \
-H "Authorization: Bearer d3v-crawl-server-key-2026" \
-H "Content-Type: application/json" \
-d '{"prompt":"create a premium SaaS landing page for a cloud storage product with features and pricing pages","reference":"https://dropbox.com"}')
echo "$response" | python3 -c "import sys,json; d=json.load(sys.stdin); print('β
Project directory:', d['projectDir'])" 2>/dev/null || {
echo "β API returned an error. Checking logs..."
pm2 logs crawl-api --lines 20
}
# 8. Show validation report for the latest project
latest_project=$(ls -td ~/website-builder/generated_projects/*/ 2>/dev/null | head -1)
if [ -n "$latest_project" ] && [ -f "$latest_project/.validation.json" ]; then
echo "π Validation report for latest project:"
cat "$latest_project/.validation.json" | python3 -m json.tool
else
echo "β οΈ No validation report found (maybe generation failed)."
fi
echo "β
Done."
|