Skip to content

Commit bdbd504

Browse files
committed
add schema code validate
1 parent 51b3026 commit bdbd504

File tree

7 files changed

+97
-51
lines changed

7 files changed

+97
-51
lines changed

backend/src/build-system/handlers/backend/requirements-document/prompt.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ export const generateBackendOverviewPrompt = (
77
framework: string,
88
packages: Record<string, string>,
99
): string => {
10+
const defaultDependencies = {
11+
sqlite3: '^5',
12+
express: '^4',
13+
};
1014
return `Role: You are a Senior Backend Architect specializing in backend systems. Generate the System Overview and API Endpoints specifications based on the following inputs.
1115
1216
Task: Generate a Backend Overview Document following these guidelines:
@@ -15,10 +19,7 @@ Project Name: ${projectName}
1519
### Technology Stack
1620
- Language: ${language}
1721
- Framework: ${framework}
18-
- Key Packages:
19-
${Object.entries(packages)
20-
.map(([pkg, version]) => ` - ${pkg}@${version}`)
21-
.join('\n')}
22+
- Key Packages: ${JSON.stringify(defaultDependencies)}
2223
2324
### Instructions and Rules:
2425
1. Design a clear system architecture based on the technology stack and requirements

backend/src/build-system/handlers/database/schemas/prompt.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ Here is dbAnalysis content:
8686
${dbAnalysis}
8787
</GENERATE>
8888
89-
Rules for generation:
89+
Rules for schema generation:
9090
1. Use ${databaseType}-specific data types and features.
9191
2. Ensure all schema operations are idempotent. For example:
9292
- Use "CREATE TABLE IF NOT EXISTS" for table creation.
@@ -96,6 +96,15 @@ Rules for generation:
9696
4. Use standardized naming conventions.
9797
5. Generate schema in the correct creation order for dependencies.
9898
99+
Rules for mock data generation:
100+
1. After creating each table, add INSERT statements with 5-10 rows of realistic sample data.
101+
2. Mock data should relate to the purpose of the appliaction.
102+
3. Ensure referential integrity in the mock data (foreign keys reference valid primary keys).
103+
4. Use realistic values appropriate for each column type and purpose.
104+
5. For timestamp fields, use recent dates.
105+
6. Include a variety of data scenarios to demonstrate different use cases.
106+
7. Image Assets: If mock requires any images, you can use placeholder image URLs from https://picsum.photos/<width>/<height>. Note that the width and height values (e.g., 500/300) are adjustable as needed.
107+
99108
Example output:
100109
<GENERATE>
101110
CREATE TABLE IF NOT EXISTS users (
@@ -111,6 +120,12 @@ CREATE TABLE IF NOT EXISTS users (
111120
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
112121
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
113122
123+
-- Mock data for users
124+
INSERT INTO users (email, username, password_hash, subscription_type) VALUES
125+
('[email protected]', 'user1', 'hash1', 'premium'),
126+
('[email protected]', 'user2', 'hash2', 'free'),
127+
('[email protected]', 'user3', 'hash3', 'premium'),
128+
114129
CREATE TABLE IF NOT EXISTS playlists (
115130
id SERIAL PRIMARY KEY,
116131
title VARCHAR(255) NOT NULL,

backend/src/build-system/handlers/database/schemas/schemas.ts

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ import {
88
isSupportedDatabaseType,
99
} from '../../../utils/database-utils';
1010
import { prompts } from './prompt';
11-
import { saveGeneratedCode } from 'src/build-system/utils/files';
12-
import * as path from 'path';
1311
import { formatResponse } from 'src/build-system/utils/strings';
1412
import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper';
1513
import { FileWriteError, ModelUnavailableError } from 'src/build-system/errors';
1614
import { DBRequirementHandler } from '../requirements-document';
1715
import { BuildNode, BuildNodeRequire } from 'src/build-system/hanlder-manager';
16+
import { CodeValidator } from 'src/build-system/handlers/frontend-code-generate/CodeValidator';
17+
import { saveGeneratedCode } from 'src/build-system/utils/files';
18+
import * as path from 'path';
1819

1920
@BuildNode()
2021
@BuildNodeRequire([DBRequirementHandler])
@@ -30,6 +31,7 @@ export class DBSchemaHandler implements BuildHandler {
3031
context.getGlobalContext('databaseType') || 'PostgreSQL';
3132
const dbRequirements = context.getNodeData(DBRequirementHandler);
3233
const uuid = context.getGlobalContext('projectUUID');
34+
const backendPath = context.getGlobalContext('backendPath');
3335

3436
// 2. Validate database type
3537
if (!isSupportedDatabaseType(databaseType)) {
@@ -82,7 +84,7 @@ export class DBSchemaHandler implements BuildHandler {
8284
databaseType,
8385
fileExtension,
8486
);
85-
let schemaContent: string;
87+
let schemaContent = '';
8688
try {
8789
const schemaResponse = await chatSyncWithClocker(
8890
context,
@@ -101,49 +103,67 @@ export class DBSchemaHandler implements BuildHandler {
101103
}
102104

103105
// Step 3: Validate generated schema
104-
this.logger.debug('Validating generated schema...');
105-
const validationPrompt = prompts.validateDatabaseSchema(
106-
schemaContent,
107-
databaseType,
108-
);
109-
try {
110-
const validationResponse = await chatSyncWithClocker(
111-
context,
112-
{
113-
model: 'gpt-4o-mini',
114-
messages: [
115-
{ content: validationPrompt, role: 'system' },
116-
{
117-
role: 'user',
118-
content:
119-
'help me fix my schema code if there is any failed validation, generate full validated version schemas for me, with <GENERATE></GENERATE> xml tag',
120-
},
121-
],
122-
},
123-
'validateDatabaseSchema',
124-
DBSchemaHandler.name,
125-
);
126-
schemaContent = formatResponse(validationResponse);
127-
} catch (error) {
128-
throw new ModelUnavailableError(
129-
`Model unavailable during validation: ${error}`,
106+
const maxFixAttempts = 2;
107+
const schemaValidator = new CodeValidator(backendPath, 'sqlite3');
108+
for (let attempt = 1; attempt <= maxFixAttempts; attempt++) {
109+
this.logger.debug('Validating generated schema...');
110+
111+
// Write schema to file
112+
const schemaFileName = `schema.${fileExtension}`;
113+
114+
try {
115+
await saveGeneratedCode(
116+
path.join(uuid, 'backend', schemaFileName),
117+
schemaContent,
118+
);
119+
this.logger.log(
120+
`Schema file (${schemaFileName}) written successfully.`,
121+
);
122+
} catch (error) {
123+
throw new FileWriteError(
124+
`Failed to write schema file: ${error.message}`,
125+
);
126+
}
127+
128+
const validationResult = await schemaValidator.validate();
129+
130+
if (validationResult.success) {
131+
this.logger.log(
132+
`Sqlite3 Schema build succeeded on attempt #${attempt}.`,
133+
);
134+
break; // done, move on
135+
}
136+
this.logger.warn(
137+
`Build failed on attempt #${attempt} for file Sqlite3 Schema.`,
130138
);
131-
}
132139

133-
// Write schema to file
134-
const schemaFileName = `schema.${fileExtension}`;
135-
try {
136-
saveGeneratedCode(
137-
path.join(uuid, 'backend', schemaFileName),
140+
const validationPrompt = prompts.validateDatabaseSchema(
138141
schemaContent,
142+
databaseType,
139143
);
140-
this.logger.log(
141-
`Schema file (${schemaFileName}) written successfully.`,
142-
);
143-
} catch (error) {
144-
throw new FileWriteError(
145-
`Failed to write schema file: ${error.message}`,
146-
);
144+
try {
145+
const validationResponse = await chatSyncWithClocker(
146+
context,
147+
{
148+
model: 'o3-mini-high',
149+
messages: [
150+
{ content: validationPrompt, role: 'system' },
151+
{
152+
role: 'user',
153+
content: `This is the error ${validationResult.error}
154+
Help me fix my schema code if there is any failed validation, generate full validated version schemas for me, with <GENERATE></GENERATE> xml tag`,
155+
},
156+
],
157+
},
158+
'validateDatabaseSchema',
159+
DBSchemaHandler.name,
160+
);
161+
schemaContent = formatResponse(validationResponse);
162+
} catch (error) {
163+
throw new ModelUnavailableError(
164+
`Model unavailable during validation: ${error}`,
165+
);
166+
}
147167
}
148168

149169
return {

backend/src/build-system/handlers/frontend-code-generate/CodeReview.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,7 @@ export class CodeQueueProcessor {
196196
let fixResponse = await chatSyncWithClocker(
197197
this.context,
198198
{
199-
// model: 'o3-mini-high',
200-
model: 'gpt-4o-mini',
199+
model: 'o3-mini-high',
201200
messages: [
202201
{ role: 'system', content: fixPrompt },
203202
{
@@ -277,7 +276,6 @@ export class CodeQueueProcessor {
277276
this.context,
278277
{
279278
model: 'o3-mini-high',
280-
// model: 'gpt-4o-mini',
281279
messages: [
282280
{ role: 'system', content: fixPrompt },
283281
{

backend/src/build-system/handlers/frontend-code-generate/CodeValidator.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,17 @@ export class CodeValidator {
4242
cwd: this.projectPath,
4343
shell: true,
4444
});
45-
} else {
45+
} else if (this.projectPart === 'backend') {
4646
npmProcess = spawn('npm', ['run', 'check'], {
4747
cwd: this.projectPath,
4848
shell: true,
4949
});
50+
} else if (this.projectPart === 'sqlite3') {
51+
// Run SQLite in-memory check on the schema file
52+
npmProcess = spawn('sqlite3', [':memory:', '".read schema.sql"'], {
53+
cwd: this.projectPath,
54+
shell: true,
55+
});
5056
}
5157

5258
this.logger.log('Running npm build command in', this.projectPath);

backend/src/build-system/handlers/frontend-code-generate/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ interface FileInfos {
3333
*/
3434
@BuildNode()
3535
@BuildNodeRequire([
36+
UXSMSHandler,
37+
UXDMDHandler,
3638
BackendRequirementHandler,
3739
FileStructureAndArchitectureHandler,
3840
])

backend/src/build-system/handlers/frontend-code-generate/prompt.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ ${theme}
2626
10. Mock the response if the API returns an empty or undefined value, and you don't need to explicitly show that it is mock data.
2727
11. Write EVERY CODE DETAIL, DON'T LEAVE TODO.
2828
12. Image Assets: If your implementation requires any images except some button logo, you can use placeholder image URLs from https://picsum.photos/<width>/<height>. Note that the width and height values (e.g., 500/300) are adjustable as needed.
29+
13. API Documentation:
30+
If user provided, read carfully details in Api Document remeber to use correct request format then use the api.
31+
Use the correct method (GET, POST, PUT, DELETE) and endpoint. Do not use Options.
32+
The backend address is "localhost:3000".
2933
3034
## Library:
3135
"react-router": "^6",

0 commit comments

Comments
 (0)