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.
Files changed (106) hide show
  1. package/README.md +14 -11
  2. package/dist/agents/implementations/BackendDevAgent.d.ts +39 -0
  3. package/dist/agents/implementations/BackendDevAgent.d.ts.map +1 -0
  4. package/dist/agents/implementations/BackendDevAgent.js +821 -0
  5. package/dist/agents/implementations/BackendDevAgent.js.map +1 -0
  6. package/dist/agents/implementations/CodeGenSubAgent.d.ts +1 -1
  7. package/dist/agents/implementations/CodeGenSubAgent.d.ts.map +1 -1
  8. package/dist/agents/implementations/CodeGenSubAgent.js +47 -22
  9. package/dist/agents/implementations/CodeGenSubAgent.js.map +1 -1
  10. package/dist/agents/implementations/DocsSubAgent.d.ts +7 -0
  11. package/dist/agents/implementations/DocsSubAgent.d.ts.map +1 -1
  12. package/dist/agents/implementations/DocsSubAgent.js +20 -11
  13. package/dist/agents/implementations/DocsSubAgent.js.map +1 -1
  14. package/dist/agents/implementations/EnhancementAgent.d.ts +1 -1
  15. package/dist/agents/implementations/EnhancementAgent.d.ts.map +1 -1
  16. package/dist/agents/implementations/EnhancementAgent.js +17 -12
  17. package/dist/agents/implementations/EnhancementAgent.js.map +1 -1
  18. package/dist/cli.js +210 -39
  19. package/dist/cli.js.map +1 -1
  20. package/dist/commands/analyze.d.ts +52 -0
  21. package/dist/commands/analyze.d.ts.map +1 -0
  22. package/dist/commands/analyze.js +740 -0
  23. package/dist/commands/analyze.js.map +1 -0
  24. package/dist/commands/auth.d.ts +19 -26
  25. package/dist/commands/auth.d.ts.map +1 -1
  26. package/dist/commands/auth.js +187 -180
  27. package/dist/commands/auth.js.map +1 -1
  28. package/dist/commands/build-app.d.ts +33 -0
  29. package/dist/commands/build-app.d.ts.map +1 -0
  30. package/dist/commands/build-app.js +507 -0
  31. package/dist/commands/build-app.js.map +1 -0
  32. package/dist/commands/generate-components.d.ts +2 -0
  33. package/dist/commands/generate-components.d.ts.map +1 -1
  34. package/dist/commands/generate-components.js +96 -49
  35. package/dist/commands/generate-components.js.map +1 -1
  36. package/dist/commands/generate-todos.d.ts +25 -0
  37. package/dist/commands/generate-todos.d.ts.map +1 -0
  38. package/dist/commands/generate-todos.js +249 -0
  39. package/dist/commands/generate-todos.js.map +1 -0
  40. package/dist/commands/generate.d.ts +3 -0
  41. package/dist/commands/generate.d.ts.map +1 -1
  42. package/dist/commands/generate.js +251 -93
  43. package/dist/commands/generate.js.map +1 -1
  44. package/dist/commands/init.d.ts +5 -0
  45. package/dist/commands/init.d.ts.map +1 -1
  46. package/dist/commands/init.js +86 -7
  47. package/dist/commands/init.js.map +1 -1
  48. package/dist/commands/list.d.ts.map +1 -1
  49. package/dist/commands/list.js +10 -7
  50. package/dist/commands/list.js.map +1 -1
  51. package/dist/commands/migrate.d.ts +29 -0
  52. package/dist/commands/migrate.d.ts.map +1 -0
  53. package/dist/commands/migrate.js +485 -0
  54. package/dist/commands/migrate.js.map +1 -0
  55. package/dist/commands/model.d.ts +13 -16
  56. package/dist/commands/model.d.ts.map +1 -1
  57. package/dist/commands/model.js +89 -320
  58. package/dist/commands/model.js.map +1 -1
  59. package/dist/commands/playbooks.d.ts +33 -0
  60. package/dist/commands/playbooks.d.ts.map +1 -0
  61. package/dist/commands/playbooks.js +662 -0
  62. package/dist/commands/playbooks.js.map +1 -0
  63. package/dist/commands/pricing.d.ts +15 -0
  64. package/dist/commands/pricing.d.ts.map +1 -0
  65. package/dist/commands/pricing.js +129 -0
  66. package/dist/commands/pricing.js.map +1 -0
  67. package/dist/commands/promote.d.ts +22 -0
  68. package/dist/commands/promote.d.ts.map +1 -0
  69. package/dist/commands/promote.js +204 -0
  70. package/dist/commands/promote.js.map +1 -0
  71. package/dist/commands/setup.d.ts +5 -18
  72. package/dist/commands/setup.d.ts.map +1 -1
  73. package/dist/commands/setup.js +180 -340
  74. package/dist/commands/setup.js.map +1 -1
  75. package/dist/config/ai-providers.json +81 -40
  76. package/dist/config/api.d.ts +9 -0
  77. package/dist/config/api.d.ts.map +1 -0
  78. package/dist/config/api.js +25 -0
  79. package/dist/config/api.js.map +1 -0
  80. package/dist/config/api.ts +29 -0
  81. package/dist/config/pricing.json +55 -0
  82. package/dist/types/index.d.ts +7 -1
  83. package/dist/types/index.d.ts.map +1 -1
  84. package/dist/utils/apiKeyManager.d.ts.map +1 -1
  85. package/dist/utils/apiKeyManager.js +7 -0
  86. package/dist/utils/apiKeyManager.js.map +1 -1
  87. package/dist/utils/fileSystem.d.ts.map +1 -1
  88. package/dist/utils/fileSystem.js +3 -1
  89. package/dist/utils/fileSystem.js.map +1 -1
  90. package/dist/utils/geminiClient.d.ts +61 -0
  91. package/dist/utils/geminiClient.d.ts.map +1 -0
  92. package/dist/utils/geminiClient.js +173 -0
  93. package/dist/utils/geminiClient.js.map +1 -0
  94. package/dist/utils/hostedApiClient.d.ts +32 -0
  95. package/dist/utils/hostedApiClient.d.ts.map +1 -0
  96. package/dist/utils/hostedApiClient.js +231 -0
  97. package/dist/utils/hostedApiClient.js.map +1 -0
  98. package/dist/utils/hybridAIClient.d.ts +14 -3
  99. package/dist/utils/hybridAIClient.d.ts.map +1 -1
  100. package/dist/utils/hybridAIClient.js +190 -65
  101. package/dist/utils/hybridAIClient.js.map +1 -1
  102. package/dist/utils/qwenClient.d.ts +22 -0
  103. package/dist/utils/qwenClient.d.ts.map +1 -0
  104. package/dist/utils/qwenClient.js +185 -0
  105. package/dist/utils/qwenClient.js.map +1 -0
  106. 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