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."