mycontext-cli 0.4.20 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -11
- package/dist/agents/implementations/BackendDevAgent.d.ts +39 -0
- package/dist/agents/implementations/BackendDevAgent.d.ts.map +1 -0
- package/dist/agents/implementations/BackendDevAgent.js +821 -0
- package/dist/agents/implementations/BackendDevAgent.js.map +1 -0
- package/dist/agents/implementations/CodeGenSubAgent.d.ts +1 -1
- package/dist/agents/implementations/CodeGenSubAgent.d.ts.map +1 -1
- package/dist/agents/implementations/CodeGenSubAgent.js +47 -22
- package/dist/agents/implementations/CodeGenSubAgent.js.map +1 -1
- package/dist/agents/implementations/DocsSubAgent.d.ts +7 -0
- package/dist/agents/implementations/DocsSubAgent.d.ts.map +1 -1
- package/dist/agents/implementations/DocsSubAgent.js +20 -11
- package/dist/agents/implementations/DocsSubAgent.js.map +1 -1
- package/dist/agents/implementations/EnhancementAgent.d.ts +1 -1
- package/dist/agents/implementations/EnhancementAgent.d.ts.map +1 -1
- package/dist/agents/implementations/EnhancementAgent.js +17 -12
- package/dist/agents/implementations/EnhancementAgent.js.map +1 -1
- package/dist/cli.js +210 -39
- package/dist/cli.js.map +1 -1
- package/dist/commands/analyze.d.ts +52 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +740 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/auth.d.ts +19 -26
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +187 -180
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/build-app.d.ts +33 -0
- package/dist/commands/build-app.d.ts.map +1 -0
- package/dist/commands/build-app.js +507 -0
- package/dist/commands/build-app.js.map +1 -0
- package/dist/commands/generate-components.d.ts +2 -0
- package/dist/commands/generate-components.d.ts.map +1 -1
- package/dist/commands/generate-components.js +96 -49
- package/dist/commands/generate-components.js.map +1 -1
- package/dist/commands/generate-todos.d.ts +25 -0
- package/dist/commands/generate-todos.d.ts.map +1 -0
- package/dist/commands/generate-todos.js +249 -0
- package/dist/commands/generate-todos.js.map +1 -0
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +251 -93
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +86 -7
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +10 -7
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/migrate.d.ts +29 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +485 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/model.d.ts +13 -16
- package/dist/commands/model.d.ts.map +1 -1
- package/dist/commands/model.js +89 -320
- package/dist/commands/model.js.map +1 -1
- package/dist/commands/playbooks.d.ts +33 -0
- package/dist/commands/playbooks.d.ts.map +1 -0
- package/dist/commands/playbooks.js +662 -0
- package/dist/commands/playbooks.js.map +1 -0
- package/dist/commands/pricing.d.ts +15 -0
- package/dist/commands/pricing.d.ts.map +1 -0
- package/dist/commands/pricing.js +129 -0
- package/dist/commands/pricing.js.map +1 -0
- package/dist/commands/promote.d.ts +22 -0
- package/dist/commands/promote.d.ts.map +1 -0
- package/dist/commands/promote.js +204 -0
- package/dist/commands/promote.js.map +1 -0
- package/dist/commands/setup.d.ts +5 -18
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +180 -340
- package/dist/commands/setup.js.map +1 -1
- package/dist/config/ai-providers.json +81 -40
- package/dist/config/api.d.ts +9 -0
- package/dist/config/api.d.ts.map +1 -0
- package/dist/config/api.js +25 -0
- package/dist/config/api.js.map +1 -0
- package/dist/config/api.ts +29 -0
- package/dist/config/pricing.json +55 -0
- package/dist/types/index.d.ts +7 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/apiKeyManager.d.ts.map +1 -1
- package/dist/utils/apiKeyManager.js +7 -0
- package/dist/utils/apiKeyManager.js.map +1 -1
- package/dist/utils/fileSystem.d.ts.map +1 -1
- package/dist/utils/fileSystem.js +3 -1
- package/dist/utils/fileSystem.js.map +1 -1
- package/dist/utils/geminiClient.d.ts +61 -0
- package/dist/utils/geminiClient.d.ts.map +1 -0
- package/dist/utils/geminiClient.js +173 -0
- package/dist/utils/geminiClient.js.map +1 -0
- package/dist/utils/hostedApiClient.d.ts +32 -0
- package/dist/utils/hostedApiClient.d.ts.map +1 -0
- package/dist/utils/hostedApiClient.js +231 -0
- package/dist/utils/hostedApiClient.js.map +1 -0
- package/dist/utils/hybridAIClient.d.ts +14 -3
- package/dist/utils/hybridAIClient.d.ts.map +1 -1
- package/dist/utils/hybridAIClient.js +190 -65
- package/dist/utils/hybridAIClient.js.map +1 -1
- package/dist/utils/qwenClient.d.ts +22 -0
- package/dist/utils/qwenClient.d.ts.map +1 -0
- package/dist/utils/qwenClient.js +185 -0
- package/dist/utils/qwenClient.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,821 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.BackendDevAgent = void 0;
|
|
40
|
+
const hybridAIClient_1 = require("../../utils/hybridAIClient");
|
|
41
|
+
const fileSystem_1 = require("../../utils/fileSystem");
|
|
42
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
+
const path_1 = __importDefault(require("path"));
|
|
44
|
+
const fs = __importStar(require("fs-extra"));
|
|
45
|
+
class BackendDevAgent {
|
|
46
|
+
constructor() {
|
|
47
|
+
this.name = "BackendDevAgent";
|
|
48
|
+
this.description = "Generates server actions, custom hooks, and backend integration code";
|
|
49
|
+
this.personality = "technical, systematic, backend-focused";
|
|
50
|
+
this.llmProvider = "hybrid";
|
|
51
|
+
this.expertise = ["backend", "server-actions", "hooks", "api-integration"];
|
|
52
|
+
this.aiClient = new hybridAIClient_1.HybridAIClient();
|
|
53
|
+
this.fs = new fileSystem_1.FileSystemManager();
|
|
54
|
+
}
|
|
55
|
+
async run(input) {
|
|
56
|
+
return this.execute(input);
|
|
57
|
+
}
|
|
58
|
+
async execute(options) {
|
|
59
|
+
const { projectPath, typesPath, componentsListPath, contextPath } = options;
|
|
60
|
+
console.log(chalk_1.default.blue("🔧 Backend Dev Agent: Creating server actions and hooks..."));
|
|
61
|
+
try {
|
|
62
|
+
// Step 1: Analyze types and context
|
|
63
|
+
const typesAnalysis = await this.analyzeTypes(typesPath || path_1.default.join(projectPath, ".mycontext", "02-types.ts"));
|
|
64
|
+
const componentsAnalysis = await this.analyzeComponents(componentsListPath ||
|
|
65
|
+
path_1.default.join(projectPath, ".mycontext", "04-component-list.json"));
|
|
66
|
+
const contextAnalysis = await this.analyzeContext(contextPath || path_1.default.join(projectPath, ".mycontext", "01-prd.md"));
|
|
67
|
+
// Step 2: Generate server actions
|
|
68
|
+
const serverActions = await this.generateServerActions(typesAnalysis, componentsAnalysis, contextAnalysis);
|
|
69
|
+
// Step 3: Generate custom hooks
|
|
70
|
+
const customHooks = await this.generateCustomHooks(serverActions, typesAnalysis);
|
|
71
|
+
// Step 4: Create server actions file
|
|
72
|
+
await this.createServerActionsFile(projectPath, serverActions);
|
|
73
|
+
// Step 5: Create custom hooks file
|
|
74
|
+
await this.createCustomHooksFile(projectPath, customHooks);
|
|
75
|
+
// Step 6: Create component-specific context files
|
|
76
|
+
await this.createComponentContextFiles(projectPath, componentsAnalysis, serverActions, customHooks);
|
|
77
|
+
// Step 7: Update components to use server actions and hooks
|
|
78
|
+
await this.updateComponentsWithBackend(projectPath, serverActions, customHooks, componentsAnalysis);
|
|
79
|
+
// Step 8: Create database schema (if needed)
|
|
80
|
+
await this.createDatabaseSchema(projectPath, typesAnalysis);
|
|
81
|
+
console.log(chalk_1.default.green("✅ Backend Dev Agent: Server actions and hooks created successfully!"));
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error(chalk_1.default.red("❌ Backend Dev Agent failed:"), error);
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async analyzeTypes(typesPath) {
|
|
89
|
+
if (!(await fs.pathExists(typesPath))) {
|
|
90
|
+
console.log(chalk_1.default.yellow("⚠️ Types file not found, using default analysis"));
|
|
91
|
+
return { entities: [], relationships: [] };
|
|
92
|
+
}
|
|
93
|
+
const typesContent = await fs.readFile(typesPath, "utf-8");
|
|
94
|
+
const prompt = `Analyze this TypeScript types file and extract:
|
|
95
|
+
1. Entity types (interfaces/types that represent data models)
|
|
96
|
+
2. Relationship types (how entities relate to each other)
|
|
97
|
+
3. Action types (functions that should have server actions)
|
|
98
|
+
4. State types (types used for component state)
|
|
99
|
+
|
|
100
|
+
Types file:
|
|
101
|
+
\`\`\`typescript
|
|
102
|
+
${typesContent}
|
|
103
|
+
\`\`\`
|
|
104
|
+
|
|
105
|
+
Return a JSON object with this structure:
|
|
106
|
+
{
|
|
107
|
+
"entities": [
|
|
108
|
+
{
|
|
109
|
+
"name": "User",
|
|
110
|
+
"properties": [{"name": "id", "type": "string"}, ...],
|
|
111
|
+
"relationships": ["posts", "comments"]
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
"actions": [
|
|
115
|
+
{
|
|
116
|
+
"name": "createUser",
|
|
117
|
+
"parameters": [{"name": "data", "type": "CreateUserInput"}],
|
|
118
|
+
"returnType": "User"
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
"stateTypes": [
|
|
122
|
+
{
|
|
123
|
+
"name": "UserState",
|
|
124
|
+
"properties": [{"name": "users", "type": "User[]"}, {"name": "loading", "type": "boolean"}]
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
}`;
|
|
128
|
+
try {
|
|
129
|
+
const response = await this.aiClient.generateText(prompt, {
|
|
130
|
+
temperature: 0.1,
|
|
131
|
+
maxTokens: 2000,
|
|
132
|
+
});
|
|
133
|
+
return JSON.parse(response.text || "{}");
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
console.log(chalk_1.default.yellow("⚠️ AI analysis failed, using fallback"));
|
|
137
|
+
return this.fallbackTypesAnalysis(typesContent);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
fallbackTypesAnalysis(typesContent) {
|
|
141
|
+
// Simple regex-based analysis as fallback
|
|
142
|
+
const entities = [];
|
|
143
|
+
const actions = [];
|
|
144
|
+
const stateTypes = [];
|
|
145
|
+
// Extract interface definitions
|
|
146
|
+
const interfaceRegex = /interface\s+(\w+)\s*\{([^}]+)\}/g;
|
|
147
|
+
let match;
|
|
148
|
+
while ((match = interfaceRegex.exec(typesContent)) !== null) {
|
|
149
|
+
const name = match[1];
|
|
150
|
+
const properties = match[2]
|
|
151
|
+
.split("\n")
|
|
152
|
+
.map((line) => line.trim())
|
|
153
|
+
.filter((line) => line && !line.startsWith("//"))
|
|
154
|
+
.map((line) => {
|
|
155
|
+
const [propName, propType] = line.split(":").map((s) => s.trim());
|
|
156
|
+
return {
|
|
157
|
+
name: propName,
|
|
158
|
+
type: propType?.replace(/[;,]/g, "") || "any",
|
|
159
|
+
};
|
|
160
|
+
})
|
|
161
|
+
.filter((prop) => prop.name && prop.type);
|
|
162
|
+
entities.push({ name, properties, relationships: [] });
|
|
163
|
+
}
|
|
164
|
+
return { entities, actions, stateTypes };
|
|
165
|
+
}
|
|
166
|
+
async analyzeComponents(componentsListPath) {
|
|
167
|
+
if (!(await fs.pathExists(componentsListPath))) {
|
|
168
|
+
return { components: [] };
|
|
169
|
+
}
|
|
170
|
+
const componentsList = JSON.parse(await fs.readFile(componentsListPath, "utf-8"));
|
|
171
|
+
return componentsList;
|
|
172
|
+
}
|
|
173
|
+
async analyzeContext(contextPath) {
|
|
174
|
+
if (!(await fs.pathExists(contextPath))) {
|
|
175
|
+
return { requirements: [] };
|
|
176
|
+
}
|
|
177
|
+
const contextContent = await fs.readFile(contextPath, "utf-8");
|
|
178
|
+
const prompt = `Analyze this PRD/context file and extract backend requirements:
|
|
179
|
+
1. Data operations needed (CRUD operations)
|
|
180
|
+
2. Business logic requirements
|
|
181
|
+
3. External API integrations
|
|
182
|
+
4. Authentication/authorization needs
|
|
183
|
+
5. Real-time features needed
|
|
184
|
+
|
|
185
|
+
Context:
|
|
186
|
+
\`\`\`
|
|
187
|
+
${contextContent}
|
|
188
|
+
\`\`\`
|
|
189
|
+
|
|
190
|
+
Return a JSON object with this structure:
|
|
191
|
+
{
|
|
192
|
+
"dataOperations": ["create", "read", "update", "delete"],
|
|
193
|
+
"businessLogic": ["validation", "computation", "transformation"],
|
|
194
|
+
"externalAPIs": [],
|
|
195
|
+
"authRequirements": ["user_management", "permissions"],
|
|
196
|
+
"realtimeFeatures": ["notifications", "live_updates"]
|
|
197
|
+
}`;
|
|
198
|
+
try {
|
|
199
|
+
const response = await this.aiClient.generateText(prompt, {
|
|
200
|
+
temperature: 0.1,
|
|
201
|
+
maxTokens: 1000,
|
|
202
|
+
});
|
|
203
|
+
return JSON.parse(response.text || "{}");
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
return {
|
|
207
|
+
dataOperations: ["create", "read", "update", "delete"],
|
|
208
|
+
businessLogic: [],
|
|
209
|
+
externalAPIs: [],
|
|
210
|
+
authRequirements: [],
|
|
211
|
+
realtimeFeatures: [],
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async generateServerActions(typesAnalysis, componentsAnalysis, contextAnalysis) {
|
|
216
|
+
const prompt = `Based on the analysis, generate Next.js server actions for this application.
|
|
217
|
+
|
|
218
|
+
Types Analysis:
|
|
219
|
+
${JSON.stringify(typesAnalysis, null, 2)}
|
|
220
|
+
|
|
221
|
+
Components Analysis:
|
|
222
|
+
${JSON.stringify(componentsAnalysis, null, 2)}
|
|
223
|
+
|
|
224
|
+
Context Analysis:
|
|
225
|
+
${JSON.stringify(contextAnalysis, null, 2)}
|
|
226
|
+
|
|
227
|
+
Generate server actions that:
|
|
228
|
+
1. Use Next.js 14 server actions (not API routes)
|
|
229
|
+
2. Include proper TypeScript types
|
|
230
|
+
3. Handle errors gracefully
|
|
231
|
+
4. Include validation
|
|
232
|
+
5. Are optimized for the specific entities and operations needed
|
|
233
|
+
|
|
234
|
+
Return a JSON array of server actions with this structure:
|
|
235
|
+
[
|
|
236
|
+
{
|
|
237
|
+
"name": "createTodo",
|
|
238
|
+
"description": "Create a new todo item",
|
|
239
|
+
"parameters": [
|
|
240
|
+
{"name": "title", "type": "string", "required": true, "description": "Todo title"},
|
|
241
|
+
{"name": "description", "type": "string", "required": false, "description": "Todo description"}
|
|
242
|
+
],
|
|
243
|
+
"returnType": "Todo",
|
|
244
|
+
"isAsync": true,
|
|
245
|
+
"implementation": "// Server action implementation",
|
|
246
|
+
"relatedComponents": ["TodoForm", "TodoList"]
|
|
247
|
+
}
|
|
248
|
+
]`;
|
|
249
|
+
try {
|
|
250
|
+
const response = await this.aiClient.generateText(prompt, {
|
|
251
|
+
temperature: 0.2,
|
|
252
|
+
maxTokens: 3000,
|
|
253
|
+
});
|
|
254
|
+
return JSON.parse(response.text || "[]");
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
console.log(chalk_1.default.yellow("⚠️ AI generation failed, using fallback server actions"));
|
|
258
|
+
return this.generateFallbackServerActions(typesAnalysis);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
generateFallbackServerActions(typesAnalysis) {
|
|
262
|
+
const actions = [];
|
|
263
|
+
// Generate basic CRUD actions for each entity
|
|
264
|
+
typesAnalysis.entities?.forEach((entity) => {
|
|
265
|
+
const entityName = entity.name.toLowerCase();
|
|
266
|
+
// Create action
|
|
267
|
+
actions.push({
|
|
268
|
+
name: `create${entity.name}`,
|
|
269
|
+
description: `Create a new ${entity.name}`,
|
|
270
|
+
parameters: entity.properties
|
|
271
|
+
.filter((prop) => prop.name !== "id" &&
|
|
272
|
+
prop.name !== "createdAt" &&
|
|
273
|
+
prop.name !== "updatedAt")
|
|
274
|
+
.map((prop) => ({
|
|
275
|
+
name: prop.name,
|
|
276
|
+
type: prop.type,
|
|
277
|
+
required: true,
|
|
278
|
+
description: `${prop.name} for ${entity.name}`,
|
|
279
|
+
})),
|
|
280
|
+
returnType: entity.name,
|
|
281
|
+
isAsync: true,
|
|
282
|
+
implementation: `// TODO: Implement create${entity.name} server action`,
|
|
283
|
+
relatedComponents: [],
|
|
284
|
+
});
|
|
285
|
+
// Read action
|
|
286
|
+
actions.push({
|
|
287
|
+
name: `get${entity.name}s`,
|
|
288
|
+
description: `Get all ${entity.name}s`,
|
|
289
|
+
parameters: [],
|
|
290
|
+
returnType: `${entity.name}[]`,
|
|
291
|
+
isAsync: true,
|
|
292
|
+
implementation: `// TODO: Implement get${entity.name}s server action`,
|
|
293
|
+
relatedComponents: [],
|
|
294
|
+
});
|
|
295
|
+
// Update action
|
|
296
|
+
actions.push({
|
|
297
|
+
name: `update${entity.name}`,
|
|
298
|
+
description: `Update a ${entity.name}`,
|
|
299
|
+
parameters: [
|
|
300
|
+
{
|
|
301
|
+
name: "id",
|
|
302
|
+
type: "string",
|
|
303
|
+
required: true,
|
|
304
|
+
description: `${entity.name} ID`,
|
|
305
|
+
},
|
|
306
|
+
...entity.properties
|
|
307
|
+
.filter((prop) => prop.name !== "id" && prop.name !== "createdAt")
|
|
308
|
+
.map((prop) => ({
|
|
309
|
+
name: prop.name,
|
|
310
|
+
type: prop.type,
|
|
311
|
+
required: false,
|
|
312
|
+
description: `${prop.name} for ${entity.name}`,
|
|
313
|
+
})),
|
|
314
|
+
],
|
|
315
|
+
returnType: entity.name,
|
|
316
|
+
isAsync: true,
|
|
317
|
+
implementation: `// TODO: Implement update${entity.name} server action`,
|
|
318
|
+
relatedComponents: [],
|
|
319
|
+
});
|
|
320
|
+
// Delete action
|
|
321
|
+
actions.push({
|
|
322
|
+
name: `delete${entity.name}`,
|
|
323
|
+
description: `Delete a ${entity.name}`,
|
|
324
|
+
parameters: [
|
|
325
|
+
{
|
|
326
|
+
name: "id",
|
|
327
|
+
type: "string",
|
|
328
|
+
required: true,
|
|
329
|
+
description: `${entity.name} ID`,
|
|
330
|
+
},
|
|
331
|
+
],
|
|
332
|
+
returnType: "void",
|
|
333
|
+
isAsync: true,
|
|
334
|
+
implementation: `// TODO: Implement delete${entity.name} server action`,
|
|
335
|
+
relatedComponents: [],
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
return actions;
|
|
339
|
+
}
|
|
340
|
+
async generateCustomHooks(serverActions, typesAnalysis) {
|
|
341
|
+
const prompt = `Generate React custom hooks that connect to the server actions.
|
|
342
|
+
|
|
343
|
+
Server Actions:
|
|
344
|
+
${JSON.stringify(serverActions, null, 2)}
|
|
345
|
+
|
|
346
|
+
Types Analysis:
|
|
347
|
+
${JSON.stringify(typesAnalysis, null, 2)}
|
|
348
|
+
|
|
349
|
+
Create hooks that:
|
|
350
|
+
1. Use React's useState and useEffect
|
|
351
|
+
2. Call server actions
|
|
352
|
+
3. Handle loading and error states
|
|
353
|
+
4. Provide optimistic updates where appropriate
|
|
354
|
+
5. Use proper TypeScript types
|
|
355
|
+
|
|
356
|
+
Return a JSON array of custom hooks:
|
|
357
|
+
[
|
|
358
|
+
{
|
|
359
|
+
"name": "useTodos",
|
|
360
|
+
"description": "Hook for managing todos",
|
|
361
|
+
"serverAction": "getTodos",
|
|
362
|
+
"stateType": "TodoState",
|
|
363
|
+
"implementation": "// Hook implementation",
|
|
364
|
+
"relatedComponents": ["TodoList", "TodoForm"]
|
|
365
|
+
}
|
|
366
|
+
]`;
|
|
367
|
+
try {
|
|
368
|
+
const response = await this.aiClient.generateText(prompt, {
|
|
369
|
+
temperature: 0.2,
|
|
370
|
+
maxTokens: 2000,
|
|
371
|
+
});
|
|
372
|
+
return JSON.parse(response.text || "[]");
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
return this.generateFallbackCustomHooks(serverActions);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
generateFallbackCustomHooks(serverActions) {
|
|
379
|
+
const hooks = [];
|
|
380
|
+
// Group server actions by entity
|
|
381
|
+
const entityActions = new Map();
|
|
382
|
+
serverActions.forEach((action) => {
|
|
383
|
+
const entityName = action.name
|
|
384
|
+
.replace(/^(create|get|update|delete)/, "")
|
|
385
|
+
.toLowerCase();
|
|
386
|
+
if (!entityActions.has(entityName)) {
|
|
387
|
+
entityActions.set(entityName, []);
|
|
388
|
+
}
|
|
389
|
+
entityActions.get(entityName).push(action);
|
|
390
|
+
});
|
|
391
|
+
// Generate hooks for each entity
|
|
392
|
+
entityActions.forEach((actions, entityName) => {
|
|
393
|
+
const capitalizedEntity = entityName.charAt(0).toUpperCase() + entityName.slice(1);
|
|
394
|
+
hooks.push({
|
|
395
|
+
name: `use${capitalizedEntity}s`,
|
|
396
|
+
description: `Hook for managing ${capitalizedEntity}s`,
|
|
397
|
+
serverAction: actions.find((a) => a.name.startsWith("get"))?.name || "",
|
|
398
|
+
stateType: `${capitalizedEntity}State`,
|
|
399
|
+
implementation: `// TODO: Implement use${capitalizedEntity}s hook`,
|
|
400
|
+
relatedComponents: [],
|
|
401
|
+
});
|
|
402
|
+
});
|
|
403
|
+
return hooks;
|
|
404
|
+
}
|
|
405
|
+
async createServerActionsFile(projectPath, serverActions) {
|
|
406
|
+
const actionsDir = path_1.default.join(projectPath, "src", "lib", "actions");
|
|
407
|
+
await fs.ensureDir(actionsDir);
|
|
408
|
+
let content = `"use server";
|
|
409
|
+
|
|
410
|
+
// Generated server actions
|
|
411
|
+
// This file contains all server actions for the application
|
|
412
|
+
|
|
413
|
+
`;
|
|
414
|
+
// Group actions by entity
|
|
415
|
+
const entityActions = new Map();
|
|
416
|
+
serverActions.forEach((action) => {
|
|
417
|
+
const entityName = action.name
|
|
418
|
+
.replace(/^(create|get|update|delete)/, "")
|
|
419
|
+
.toLowerCase();
|
|
420
|
+
if (!entityActions.has(entityName)) {
|
|
421
|
+
entityActions.set(entityName, []);
|
|
422
|
+
}
|
|
423
|
+
entityActions.get(entityName).push(action);
|
|
424
|
+
});
|
|
425
|
+
entityActions.forEach((actions, entityName) => {
|
|
426
|
+
const capitalizedEntity = entityName.charAt(0).toUpperCase() + entityName.slice(1);
|
|
427
|
+
content += `// ${capitalizedEntity} Actions\n`;
|
|
428
|
+
content += `// ========================\n\n`;
|
|
429
|
+
actions.forEach((action) => {
|
|
430
|
+
content += `export async function ${action.name}(\n`;
|
|
431
|
+
action.parameters.forEach((param, index) => {
|
|
432
|
+
content += ` ${param.name}: ${param.type}${param.required ? "" : "?"}`;
|
|
433
|
+
if (index < action.parameters.length - 1)
|
|
434
|
+
content += ",";
|
|
435
|
+
content += "\n";
|
|
436
|
+
});
|
|
437
|
+
content += `): Promise<${action.returnType}> {\n`;
|
|
438
|
+
content += ` // ${action.description}\n`;
|
|
439
|
+
content += ` try {\n`;
|
|
440
|
+
content += ` // TODO: Implement ${action.name}\n`;
|
|
441
|
+
content += ` // Add validation, database operations, etc.\n`;
|
|
442
|
+
content += ` \n`;
|
|
443
|
+
content += ` throw new Error("Not implemented yet");\n`;
|
|
444
|
+
content += ` } catch (error) {\n`;
|
|
445
|
+
content += ` console.error("Error in ${action.name}:", error);\n`;
|
|
446
|
+
content += ` throw new Error("Failed to ${action.name
|
|
447
|
+
.replace(/([A-Z])/g, " $1")
|
|
448
|
+
.toLowerCase()}");\n`;
|
|
449
|
+
content += ` }\n`;
|
|
450
|
+
content += `}\n\n`;
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
await fs.writeFile(path_1.default.join(actionsDir, "index.ts"), content);
|
|
454
|
+
console.log(chalk_1.default.green("✅ Server actions file created"));
|
|
455
|
+
}
|
|
456
|
+
async createComponentContextFiles(projectPath, componentsAnalysis, serverActions, customHooks) {
|
|
457
|
+
const { groups = {} } = componentsAnalysis;
|
|
458
|
+
for (const [groupName, components] of Object.entries(groups)) {
|
|
459
|
+
const groupDir = path_1.default.join(projectPath, "src", "components", groupName);
|
|
460
|
+
for (const component of components) {
|
|
461
|
+
const componentDir = path_1.default.join(groupDir, component.name);
|
|
462
|
+
const mycontextDir = path_1.default.join(componentDir, ".mycontext");
|
|
463
|
+
await fs.ensureDir(mycontextDir);
|
|
464
|
+
// Create component-specific server actions
|
|
465
|
+
const componentActions = serverActions.filter((action) => action.relatedComponents.includes(component.name));
|
|
466
|
+
if (componentActions.length > 0) {
|
|
467
|
+
const actionsContent = this.generateComponentActions(componentActions, component.name);
|
|
468
|
+
await fs.writeFile(path_1.default.join(mycontextDir, "actions.ts"), actionsContent);
|
|
469
|
+
}
|
|
470
|
+
// Create component-specific hooks
|
|
471
|
+
const componentHooks = customHooks.filter((hook) => hook.relatedComponents.includes(component.name));
|
|
472
|
+
if (componentHooks.length > 0) {
|
|
473
|
+
const hooksContent = this.generateComponentHooks(componentHooks, component.name);
|
|
474
|
+
await fs.writeFile(path_1.default.join(mycontextDir, "hooks.ts"), hooksContent);
|
|
475
|
+
}
|
|
476
|
+
// Create component context file
|
|
477
|
+
const contextContent = this.generateComponentContext(component, componentActions, componentHooks);
|
|
478
|
+
await fs.writeFile(path_1.default.join(mycontextDir, "context.ts"), contextContent);
|
|
479
|
+
// Create component README
|
|
480
|
+
const readmeContent = this.generateComponentReadme(component, componentActions, componentHooks);
|
|
481
|
+
await fs.writeFile(path_1.default.join(mycontextDir, "README.md"), readmeContent);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
console.log(chalk_1.default.green("✅ Component context files created"));
|
|
485
|
+
}
|
|
486
|
+
generateComponentActions(actions, componentName) {
|
|
487
|
+
let content = `"use server";
|
|
488
|
+
|
|
489
|
+
// Server actions for ${componentName}
|
|
490
|
+
// Generated by Backend Dev Agent
|
|
491
|
+
|
|
492
|
+
`;
|
|
493
|
+
actions.forEach((action) => {
|
|
494
|
+
content += `export async function ${action.name}(\n`;
|
|
495
|
+
action.parameters.forEach((param, index) => {
|
|
496
|
+
content += ` ${param.name}: ${param.type}${param.required ? "" : "?"}`;
|
|
497
|
+
if (index < action.parameters.length - 1)
|
|
498
|
+
content += ",";
|
|
499
|
+
content += "\n";
|
|
500
|
+
});
|
|
501
|
+
content += `): Promise<${action.returnType}> {\n`;
|
|
502
|
+
content += ` // ${action.description}\n`;
|
|
503
|
+
content += ` try {\n`;
|
|
504
|
+
content += ` // TODO: Implement ${action.name} for ${componentName}\n`;
|
|
505
|
+
content += ` // Add component-specific logic here\n`;
|
|
506
|
+
content += ` \n`;
|
|
507
|
+
content += ` throw new Error("Not implemented yet");\n`;
|
|
508
|
+
content += ` } catch (error) {\n`;
|
|
509
|
+
content += ` console.error("Error in ${action.name}:", error);\n`;
|
|
510
|
+
content += ` throw new Error("Failed to ${action.name
|
|
511
|
+
.replace(/([A-Z])/g, " $1")
|
|
512
|
+
.toLowerCase()}");\n`;
|
|
513
|
+
content += ` }\n`;
|
|
514
|
+
content += `}\n\n`;
|
|
515
|
+
});
|
|
516
|
+
return content;
|
|
517
|
+
}
|
|
518
|
+
generateComponentHooks(hooks, componentName) {
|
|
519
|
+
let content = `"use client";
|
|
520
|
+
|
|
521
|
+
// Custom hooks for ${componentName}
|
|
522
|
+
// Generated by Backend Dev Agent
|
|
523
|
+
|
|
524
|
+
import { useState, useEffect } from "react";
|
|
525
|
+
import * as actions from "./actions";
|
|
526
|
+
|
|
527
|
+
`;
|
|
528
|
+
hooks.forEach((hook) => {
|
|
529
|
+
content += `// ${hook.name}\n`;
|
|
530
|
+
content += `// ${hook.description}\n`;
|
|
531
|
+
content += `export function ${hook.name}() {\n`;
|
|
532
|
+
content += ` const [data, setData] = useState<${hook.stateType}>({\n`;
|
|
533
|
+
content += ` loading: false,\n`;
|
|
534
|
+
content += ` error: null,\n`;
|
|
535
|
+
content += ` // TODO: Add specific state properties for ${componentName}\n`;
|
|
536
|
+
content += ` });\n\n`;
|
|
537
|
+
content += ` // TODO: Implement ${hook.name} logic for ${componentName}\n`;
|
|
538
|
+
content += ` // - Call server actions from ./actions\n`;
|
|
539
|
+
content += ` // - Handle loading states\n`;
|
|
540
|
+
content += ` // - Handle errors\n`;
|
|
541
|
+
content += ` // - Provide optimistic updates\n\n`;
|
|
542
|
+
content += ` return data;\n`;
|
|
543
|
+
content += `}\n\n`;
|
|
544
|
+
});
|
|
545
|
+
return content;
|
|
546
|
+
}
|
|
547
|
+
generateComponentContext(component, actions, hooks) {
|
|
548
|
+
return `// Component context for ${component.name}
|
|
549
|
+
// This file defines the context and configuration for this component
|
|
550
|
+
|
|
551
|
+
export interface ${component.name}Context {
|
|
552
|
+
// Component-specific state
|
|
553
|
+
loading: boolean;
|
|
554
|
+
error: string | null;
|
|
555
|
+
|
|
556
|
+
// Component-specific data
|
|
557
|
+
data: any;
|
|
558
|
+
|
|
559
|
+
// Component-specific actions
|
|
560
|
+
actions: {
|
|
561
|
+
${actions
|
|
562
|
+
.map((action) => `${action.name}: () => Promise<${action.returnType}>`)
|
|
563
|
+
.join(";\n ")}
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
// Component-specific hooks
|
|
567
|
+
hooks: {
|
|
568
|
+
${hooks
|
|
569
|
+
.map((hook) => `${hook.name}: () => ${hook.stateType}`)
|
|
570
|
+
.join(";\n ")}
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export const ${component.name}Config = {
|
|
575
|
+
name: "${component.name}",
|
|
576
|
+
description: "${component.description}",
|
|
577
|
+
type: "${component.type}",
|
|
578
|
+
priority: "${component.priority}",
|
|
579
|
+
dependencies: ${JSON.stringify(component.dependencies || [], null, 2)},
|
|
580
|
+
tags: ${JSON.stringify(component.tags || [], null, 2)},
|
|
581
|
+
|
|
582
|
+
// Server actions available
|
|
583
|
+
serverActions: [
|
|
584
|
+
${actions.map((action) => `"${action.name}"`).join(",\n ")}
|
|
585
|
+
],
|
|
586
|
+
|
|
587
|
+
// Custom hooks available
|
|
588
|
+
customHooks: [
|
|
589
|
+
${hooks.map((hook) => `"${hook.name}"`).join(",\n ")}
|
|
590
|
+
],
|
|
591
|
+
|
|
592
|
+
// Component-specific configuration
|
|
593
|
+
config: {
|
|
594
|
+
// Add component-specific config here
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
`;
|
|
598
|
+
}
|
|
599
|
+
generateComponentReadme(component, actions, hooks) {
|
|
600
|
+
return `# ${component.name}
|
|
601
|
+
|
|
602
|
+
${component.description}
|
|
603
|
+
|
|
604
|
+
## Type
|
|
605
|
+
${component.type}
|
|
606
|
+
|
|
607
|
+
## Priority
|
|
608
|
+
${component.priority}
|
|
609
|
+
|
|
610
|
+
## Dependencies
|
|
611
|
+
${(component.dependencies || []).map((dep) => `- ${dep}`).join("\n")}
|
|
612
|
+
|
|
613
|
+
## Tags
|
|
614
|
+
${(component.tags || []).map((tag) => `- ${tag}`).join("\n")}
|
|
615
|
+
|
|
616
|
+
## Server Actions
|
|
617
|
+
|
|
618
|
+
This component has access to the following server actions:
|
|
619
|
+
|
|
620
|
+
${actions
|
|
621
|
+
.map((action) => `### ${action.name}
|
|
622
|
+
${action.description}
|
|
623
|
+
|
|
624
|
+
**Parameters:**
|
|
625
|
+
${action.parameters
|
|
626
|
+
.map((param) => `- \`${param.name}\`: ${param.type}${param.required ? " (required)" : " (optional)"} - ${param.description}`)
|
|
627
|
+
.join("\n")}
|
|
628
|
+
|
|
629
|
+
**Returns:** \`${action.returnType}\`
|
|
630
|
+
|
|
631
|
+
`)
|
|
632
|
+
.join("\n")}
|
|
633
|
+
|
|
634
|
+
## Custom Hooks
|
|
635
|
+
|
|
636
|
+
This component has access to the following custom hooks:
|
|
637
|
+
|
|
638
|
+
${hooks
|
|
639
|
+
.map((hook) => `### ${hook.name}
|
|
640
|
+
${hook.description}
|
|
641
|
+
|
|
642
|
+
**State Type:** \`${hook.stateType}\`
|
|
643
|
+
|
|
644
|
+
`)
|
|
645
|
+
.join("\n")}
|
|
646
|
+
|
|
647
|
+
## Usage
|
|
648
|
+
|
|
649
|
+
\`\`\`tsx
|
|
650
|
+
import { ${component.name} } from './${component.name}';
|
|
651
|
+
import { ${hooks
|
|
652
|
+
.map((hook) => hook.name)
|
|
653
|
+
.join(", ")} } from './.mycontext/hooks';
|
|
654
|
+
import { ${actions
|
|
655
|
+
.map((action) => action.name)
|
|
656
|
+
.join(", ")} } from './.mycontext/actions';
|
|
657
|
+
|
|
658
|
+
function MyComponent() {
|
|
659
|
+
const { data, loading, error } = ${hooks[0]?.name || "useData"}();
|
|
660
|
+
|
|
661
|
+
return (
|
|
662
|
+
<${component.name}
|
|
663
|
+
data={data}
|
|
664
|
+
loading={loading}
|
|
665
|
+
error={error}
|
|
666
|
+
/>
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
\`\`\`
|
|
670
|
+
|
|
671
|
+
## Development
|
|
672
|
+
|
|
673
|
+
To work with this component:
|
|
674
|
+
|
|
675
|
+
1. **Server Actions**: Edit \`.mycontext/actions.ts\` to implement the actual server logic
|
|
676
|
+
2. **Custom Hooks**: Edit \`.mycontext/hooks.ts\` to implement state management
|
|
677
|
+
3. **Context**: Edit \`.mycontext/context.ts\` to configure component behavior
|
|
678
|
+
4. **Component**: Edit the main component file to integrate with the context
|
|
679
|
+
|
|
680
|
+
## Moving to Production
|
|
681
|
+
|
|
682
|
+
When ready to move to production:
|
|
683
|
+
|
|
684
|
+
\`\`\`bash
|
|
685
|
+
# Move context files to parent directory
|
|
686
|
+
mycontext promote ${component.name}
|
|
687
|
+
|
|
688
|
+
# Or move all components in a group
|
|
689
|
+
mycontext promote-group ${component.group || "default"}
|
|
690
|
+
\`\`\`
|
|
691
|
+
|
|
692
|
+
This will:
|
|
693
|
+
- Move \`.mycontext/*\` files to the parent component directory
|
|
694
|
+
- Update import paths
|
|
695
|
+
- Add \`.mycontext/\` to \`.gitignore\`
|
|
696
|
+
- Clean up development files
|
|
697
|
+
`;
|
|
698
|
+
}
|
|
699
|
+
async createCustomHooksFile(projectPath, customHooks) {
|
|
700
|
+
const hooksDir = path_1.default.join(projectPath, "src", "lib", "hooks");
|
|
701
|
+
await fs.ensureDir(hooksDir);
|
|
702
|
+
let content = `"use client";
|
|
703
|
+
|
|
704
|
+
// Generated custom hooks
|
|
705
|
+
// This file contains all custom hooks for the application
|
|
706
|
+
|
|
707
|
+
import { useState, useEffect } from "react";
|
|
708
|
+
import * as actions from "../actions";
|
|
709
|
+
|
|
710
|
+
`;
|
|
711
|
+
customHooks.forEach((hook) => {
|
|
712
|
+
content += `// ${hook.name}\n`;
|
|
713
|
+
content += `// ${hook.description}\n`;
|
|
714
|
+
content += `export function ${hook.name}() {\n`;
|
|
715
|
+
content += ` const [data, setData] = useState<${hook.stateType}>({\n`;
|
|
716
|
+
content += ` loading: false,\n`;
|
|
717
|
+
content += ` error: null,\n`;
|
|
718
|
+
content += ` // TODO: Add specific state properties\n`;
|
|
719
|
+
content += ` });\n\n`;
|
|
720
|
+
content += ` // TODO: Implement ${hook.name} logic\n`;
|
|
721
|
+
content += ` // - Call server actions\n`;
|
|
722
|
+
content += ` // - Handle loading states\n`;
|
|
723
|
+
content += ` // - Handle errors\n`;
|
|
724
|
+
content += ` // - Provide optimistic updates\n\n`;
|
|
725
|
+
content += ` return data;\n`;
|
|
726
|
+
content += `}\n\n`;
|
|
727
|
+
});
|
|
728
|
+
await fs.writeFile(path_1.default.join(hooksDir, "index.ts"), content);
|
|
729
|
+
console.log(chalk_1.default.green("✅ Custom hooks file created"));
|
|
730
|
+
}
|
|
731
|
+
async updateComponentsWithBackend(projectPath, serverActions, customHooks, componentsAnalysis) {
|
|
732
|
+
// This would analyze existing components and update them to use server actions and hooks
|
|
733
|
+
// For now, we'll create a guide file
|
|
734
|
+
const guidePath = path_1.default.join(projectPath, "src", "lib", "BACKEND_INTEGRATION.md");
|
|
735
|
+
let content = `# Backend Integration Guide
|
|
736
|
+
|
|
737
|
+
This file explains how to integrate the generated server actions and hooks with your components.
|
|
738
|
+
|
|
739
|
+
## Server Actions
|
|
740
|
+
|
|
741
|
+
The following server actions are available in \`src/lib/actions/index.ts\`:
|
|
742
|
+
|
|
743
|
+
${serverActions
|
|
744
|
+
.map((action) => `- **${action.name}**: ${action.description}`)
|
|
745
|
+
.join("\n")}
|
|
746
|
+
|
|
747
|
+
## Custom Hooks
|
|
748
|
+
|
|
749
|
+
The following custom hooks are available in \`src/lib/hooks/index.ts\`:
|
|
750
|
+
|
|
751
|
+
${customHooks
|
|
752
|
+
.map((hook) => `- **${hook.name}**: ${hook.description}`)
|
|
753
|
+
.join("\n")}
|
|
754
|
+
|
|
755
|
+
## Integration Steps
|
|
756
|
+
|
|
757
|
+
1. Import server actions in your components:
|
|
758
|
+
\`\`\`typescript
|
|
759
|
+
import { createTodo, getTodos } from "@/lib/actions";
|
|
760
|
+
\`\`\`
|
|
761
|
+
|
|
762
|
+
2. Import custom hooks in your components:
|
|
763
|
+
\`\`\`typescript
|
|
764
|
+
import { useTodos } from "@/lib/hooks";
|
|
765
|
+
\`\`\`
|
|
766
|
+
|
|
767
|
+
3. Use hooks for state management:
|
|
768
|
+
\`\`\`typescript
|
|
769
|
+
function TodoList() {
|
|
770
|
+
const { data, loading, error } = useTodos();
|
|
771
|
+
// Component logic
|
|
772
|
+
}
|
|
773
|
+
\`\`\`
|
|
774
|
+
|
|
775
|
+
4. Call server actions directly:
|
|
776
|
+
\`\`\`typescript
|
|
777
|
+
async function handleSubmit(formData: FormData) {
|
|
778
|
+
const result = await createTodo({
|
|
779
|
+
title: formData.get("title") as string,
|
|
780
|
+
description: formData.get("description") as string,
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
\`\`\`
|
|
784
|
+
|
|
785
|
+
## Next Steps
|
|
786
|
+
|
|
787
|
+
1. Implement the actual server action logic (database operations, validation, etc.)
|
|
788
|
+
2. Implement the custom hook logic (state management, error handling, etc.)
|
|
789
|
+
3. Connect components to use these hooks and actions
|
|
790
|
+
4. Add proper error handling and loading states
|
|
791
|
+
5. Test the integration
|
|
792
|
+
|
|
793
|
+
`;
|
|
794
|
+
await fs.writeFile(guidePath, content);
|
|
795
|
+
console.log(chalk_1.default.green("✅ Backend integration guide created"));
|
|
796
|
+
}
|
|
797
|
+
async createDatabaseSchema(projectPath, typesAnalysis) {
|
|
798
|
+
const schemaDir = path_1.default.join(projectPath, "src", "lib", "db");
|
|
799
|
+
await fs.ensureDir(schemaDir);
|
|
800
|
+
let content = `// Database schema
|
|
801
|
+
// This file defines the database schema based on your types
|
|
802
|
+
|
|
803
|
+
`;
|
|
804
|
+
typesAnalysis.entities?.forEach((entity) => {
|
|
805
|
+
content += `// ${entity.name} table\n`;
|
|
806
|
+
content += `export const ${entity.name.toLowerCase()}Schema = {\n`;
|
|
807
|
+
content += ` // TODO: Define database schema for ${entity.name}\n`;
|
|
808
|
+
content += ` // Example for Prisma:\n`;
|
|
809
|
+
content += ` // model ${entity.name} {\n`;
|
|
810
|
+
entity.properties.forEach((prop) => {
|
|
811
|
+
content += ` // ${prop.name} ${prop.type}\n`;
|
|
812
|
+
});
|
|
813
|
+
content += ` // }\n`;
|
|
814
|
+
content += `};\n\n`;
|
|
815
|
+
});
|
|
816
|
+
await fs.writeFile(path_1.default.join(schemaDir, "schema.ts"), content);
|
|
817
|
+
console.log(chalk_1.default.green("✅ Database schema file created"));
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
exports.BackendDevAgent = BackendDevAgent;
|
|
821
|
+
//# sourceMappingURL=BackendDevAgent.js.map
|