mycontext-cli 0.1.0

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 (94) hide show
  1. package/README.md +440 -0
  2. package/dist/cli/src/agents/implementations/CodeGenSubAgent.d.ts +43 -0
  3. package/dist/cli/src/agents/implementations/CodeGenSubAgent.d.ts.map +1 -0
  4. package/dist/cli/src/agents/implementations/CodeGenSubAgent.js +1440 -0
  5. package/dist/cli/src/agents/implementations/CodeGenSubAgent.js.map +1 -0
  6. package/dist/cli/src/agents/implementations/DocsSubAgent.d.ts +35 -0
  7. package/dist/cli/src/agents/implementations/DocsSubAgent.d.ts.map +1 -0
  8. package/dist/cli/src/agents/implementations/DocsSubAgent.js +351 -0
  9. package/dist/cli/src/agents/implementations/DocsSubAgent.js.map +1 -0
  10. package/dist/cli/src/agents/implementations/QASubAgent.d.ts +31 -0
  11. package/dist/cli/src/agents/implementations/QASubAgent.d.ts.map +1 -0
  12. package/dist/cli/src/agents/implementations/QASubAgent.js +190 -0
  13. package/dist/cli/src/agents/implementations/QASubAgent.js.map +1 -0
  14. package/dist/cli/src/agents/interfaces/SubAgent.d.ts +157 -0
  15. package/dist/cli/src/agents/interfaces/SubAgent.d.ts.map +1 -0
  16. package/dist/cli/src/agents/interfaces/SubAgent.js +7 -0
  17. package/dist/cli/src/agents/interfaces/SubAgent.js.map +1 -0
  18. package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.d.ts +59 -0
  19. package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.d.ts.map +1 -0
  20. package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.js +305 -0
  21. package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.js.map +1 -0
  22. package/dist/cli/src/agents/personalities/definitions.d.ts +34 -0
  23. package/dist/cli/src/agents/personalities/definitions.d.ts.map +1 -0
  24. package/dist/cli/src/agents/personalities/definitions.js +360 -0
  25. package/dist/cli/src/agents/personalities/definitions.js.map +1 -0
  26. package/dist/cli/src/cli.d.ts +3 -0
  27. package/dist/cli/src/cli.d.ts.map +1 -0
  28. package/dist/cli/src/cli.js +286 -0
  29. package/dist/cli/src/cli.js.map +1 -0
  30. package/dist/cli/src/commands/auth.d.ts +23 -0
  31. package/dist/cli/src/commands/auth.d.ts.map +1 -0
  32. package/dist/cli/src/commands/auth.js +212 -0
  33. package/dist/cli/src/commands/auth.js.map +1 -0
  34. package/dist/cli/src/commands/generate-components.d.ts +28 -0
  35. package/dist/cli/src/commands/generate-components.d.ts.map +1 -0
  36. package/dist/cli/src/commands/generate-components.js +680 -0
  37. package/dist/cli/src/commands/generate-components.js.map +1 -0
  38. package/dist/cli/src/commands/generate.d.ts +108 -0
  39. package/dist/cli/src/commands/generate.d.ts.map +1 -0
  40. package/dist/cli/src/commands/generate.js +1984 -0
  41. package/dist/cli/src/commands/generate.js.map +1 -0
  42. package/dist/cli/src/commands/init.d.ts +13 -0
  43. package/dist/cli/src/commands/init.d.ts.map +1 -0
  44. package/dist/cli/src/commands/init.js +91 -0
  45. package/dist/cli/src/commands/init.js.map +1 -0
  46. package/dist/cli/src/commands/list.d.ts +17 -0
  47. package/dist/cli/src/commands/list.d.ts.map +1 -0
  48. package/dist/cli/src/commands/list.js +209 -0
  49. package/dist/cli/src/commands/list.js.map +1 -0
  50. package/dist/cli/src/commands/preview.d.ts +23 -0
  51. package/dist/cli/src/commands/preview.d.ts.map +1 -0
  52. package/dist/cli/src/commands/preview.js +1200 -0
  53. package/dist/cli/src/commands/preview.js.map +1 -0
  54. package/dist/cli/src/commands/status.d.ts +21 -0
  55. package/dist/cli/src/commands/status.d.ts.map +1 -0
  56. package/dist/cli/src/commands/status.js +287 -0
  57. package/dist/cli/src/commands/status.js.map +1 -0
  58. package/dist/cli/src/commands/validate.d.ts +22 -0
  59. package/dist/cli/src/commands/validate.d.ts.map +1 -0
  60. package/dist/cli/src/commands/validate.js +259 -0
  61. package/dist/cli/src/commands/validate.js.map +1 -0
  62. package/dist/cli/src/types/index.d.ts +152 -0
  63. package/dist/cli/src/types/index.d.ts.map +1 -0
  64. package/dist/cli/src/types/index.js +3 -0
  65. package/dist/cli/src/types/index.js.map +1 -0
  66. package/dist/cli/src/utils/apiKeyManager.d.ts +137 -0
  67. package/dist/cli/src/utils/apiKeyManager.d.ts.map +1 -0
  68. package/dist/cli/src/utils/apiKeyManager.js +471 -0
  69. package/dist/cli/src/utils/apiKeyManager.js.map +1 -0
  70. package/dist/cli/src/utils/errorHandler.d.ts +105 -0
  71. package/dist/cli/src/utils/errorHandler.d.ts.map +1 -0
  72. package/dist/cli/src/utils/errorHandler.js +332 -0
  73. package/dist/cli/src/utils/errorHandler.js.map +1 -0
  74. package/dist/cli/src/utils/fileSystem.d.ts +58 -0
  75. package/dist/cli/src/utils/fileSystem.d.ts.map +1 -0
  76. package/dist/cli/src/utils/fileSystem.js +230 -0
  77. package/dist/cli/src/utils/fileSystem.js.map +1 -0
  78. package/dist/cli/src/utils/githubModels.d.ts +53 -0
  79. package/dist/cli/src/utils/githubModels.d.ts.map +1 -0
  80. package/dist/cli/src/utils/githubModels.js +239 -0
  81. package/dist/cli/src/utils/githubModels.js.map +1 -0
  82. package/dist/cli/src/utils/spinner.d.ts +28 -0
  83. package/dist/cli/src/utils/spinner.d.ts.map +1 -0
  84. package/dist/cli/src/utils/spinner.js +112 -0
  85. package/dist/cli/src/utils/spinner.js.map +1 -0
  86. package/dist/cli/src/utils/xaiClient.d.ts +59 -0
  87. package/dist/cli/src/utils/xaiClient.d.ts.map +1 -0
  88. package/dist/cli/src/utils/xaiClient.js +244 -0
  89. package/dist/cli/src/utils/xaiClient.js.map +1 -0
  90. package/dist/lib/analytics/usage-tracker.d.ts +125 -0
  91. package/dist/lib/analytics/usage-tracker.d.ts.map +1 -0
  92. package/dist/lib/analytics/usage-tracker.js +429 -0
  93. package/dist/lib/analytics/usage-tracker.js.map +1 -0
  94. package/package.json +64 -0
@@ -0,0 +1,680 @@
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.GenerateComponentsCommand = void 0;
40
+ const fileSystem_1 = require("../utils/fileSystem");
41
+ const spinner_1 = require("../utils/spinner");
42
+ const chalk_1 = __importDefault(require("chalk"));
43
+ const fs = __importStar(require("fs-extra"));
44
+ const path = __importStar(require("path"));
45
+ // Code Generation Sub-Agent
46
+ class CodeGenSubAgent {
47
+ constructor() {
48
+ this.name = "CodeGenSubAgent";
49
+ }
50
+ async run({ component, group, options }) {
51
+ // Use the existing generateComponentCode logic
52
+ return new GenerateComponentsCommand().generateComponentCode(component, group, options);
53
+ }
54
+ }
55
+ // QA Sub-Agent (stub for demonstration)
56
+ class QASubAgent {
57
+ constructor() {
58
+ this.name = "QASubAgent";
59
+ }
60
+ async run({ code, component }) {
61
+ // Placeholder: In real implementation, run static analysis, lint, or type checks
62
+ // For now, always return true (pass)
63
+ return true;
64
+ }
65
+ }
66
+ // Docs Writer Sub-Agent (stub for demonstration)
67
+ class DocsSubAgent {
68
+ constructor() {
69
+ this.name = "DocsSubAgent";
70
+ }
71
+ async run({ component, group }) {
72
+ // Placeholder: Generate markdown or JSDoc for the component
73
+ return `# ${component.name}\n\n${component.description}\n`;
74
+ }
75
+ }
76
+ // --- Orchestration in GenerateComponentsCommand ---
77
+ class GenerateComponentsCommand {
78
+ constructor() {
79
+ this.fs = new fileSystem_1.FileSystemManager();
80
+ }
81
+ async execute(target, options) {
82
+ const spinner = new spinner_1.EnhancedSpinner("Initializing component generation...");
83
+ try {
84
+ // Check authentication first
85
+ const { AuthCommand } = await Promise.resolve().then(() => __importStar(require("./auth")));
86
+ const authCommand = new AuthCommand();
87
+ if (!(await authCommand.requireAuth())) {
88
+ console.log(chalk_1.default.yellow("🔐 Authentication required"));
89
+ console.log(chalk_1.default.gray("Please run 'mycontext auth' to authenticate first"));
90
+ return;
91
+ }
92
+ // Get user info for component storage
93
+ const userInfo = await authCommand.getUserInfo();
94
+ if (!userInfo) {
95
+ console.log(chalk_1.default.red("❌ Authentication failed"));
96
+ return;
97
+ }
98
+ console.log(chalk_1.default.green(`✅ Authenticated as ${userInfo.email}`));
99
+ // Determine if we're generating a specific group or all components
100
+ const isAll = target === "all" || options.all;
101
+ const groupName = isAll ? undefined : target;
102
+ if (isAll) {
103
+ await this.generateAllComponents(options, spinner, userInfo.userId);
104
+ }
105
+ else if (groupName) {
106
+ await this.generateComponentGroup(groupName, options, spinner, userInfo.userId);
107
+ }
108
+ else {
109
+ throw new Error("Please specify a group name or 'all' to generate components");
110
+ }
111
+ }
112
+ catch (error) {
113
+ spinner.error({ text: "Component generation failed" });
114
+ throw error;
115
+ }
116
+ }
117
+ async generateAllComponents(options, spinner, userId) {
118
+ spinner.updateText("Generating all component groups...");
119
+ // Read component list
120
+ const componentListPath = "context/component-list.json";
121
+ if (!(await this.fs.exists(componentListPath))) {
122
+ throw new Error("Component list not found. Run 'mycontext generate components-list' first.");
123
+ }
124
+ const componentList = JSON.parse(await this.fs.readFile(componentListPath));
125
+ const groups = componentList.groups || [];
126
+ if (groups.length === 0) {
127
+ throw new Error("No component groups found in component-list.json");
128
+ }
129
+ // Create components directory
130
+ const componentsDir = options.output || "components";
131
+ await this.fs.ensureDir(componentsDir);
132
+ let totalComponents = 0;
133
+ let generatedGroups = 0;
134
+ for (const group of groups) {
135
+ spinner.updateText(`Generating ${group.name} components...`);
136
+ const groupDir = path.join(componentsDir, group.name.toLowerCase());
137
+ await this.fs.ensureDir(groupDir);
138
+ const components = group.components || [];
139
+ for (const component of components) {
140
+ await this.generateComponent(component, group, groupDir, options, userId);
141
+ totalComponents++;
142
+ }
143
+ // Generate group index file
144
+ await this.generateGroupIndex(group, groupDir);
145
+ // Generate preview page
146
+ await this.generatePreviewPage(group, groupDir);
147
+ generatedGroups++;
148
+ }
149
+ spinner.success({
150
+ text: `Generated ${totalComponents} components across ${generatedGroups} groups!`,
151
+ });
152
+ console.log(chalk_1.default.green("\n✅ Generated Files:"));
153
+ console.log(chalk_1.default.gray(` • ${componentsDir}/`));
154
+ groups.forEach((group) => {
155
+ console.log(chalk_1.default.gray(` • ${group.name.toLowerCase()}/`));
156
+ const components = group.components || [];
157
+ components.forEach((comp) => {
158
+ console.log(chalk_1.default.gray(` • ${comp.name}.tsx`));
159
+ });
160
+ console.log(chalk_1.default.gray(` • index.ts`));
161
+ console.log(chalk_1.default.gray(` • page.tsx`));
162
+ });
163
+ }
164
+ async generateComponentGroup(groupName, options, spinner, userId) {
165
+ spinner.updateText(`Generating ${groupName} components...`);
166
+ // Read component list
167
+ const componentListPath = "context/component-list.json";
168
+ if (!(await this.fs.exists(componentListPath))) {
169
+ throw new Error("Component list not found. Run 'mycontext generate components-list' first.");
170
+ }
171
+ const componentList = JSON.parse(await this.fs.readFile(componentListPath));
172
+ const groups = componentList.groups || [];
173
+ const group = groups.find((g) => g.name.toLowerCase() === groupName.toLowerCase());
174
+ if (!group) {
175
+ throw new Error(`Group '${groupName}' not found in component-list.json`);
176
+ }
177
+ // Create group directory
178
+ const componentsDir = options.output || "components";
179
+ const groupDir = path.join(componentsDir, group.name.toLowerCase());
180
+ await this.fs.ensureDir(groupDir);
181
+ const components = group.components || [];
182
+ for (const component of components) {
183
+ await this.generateComponent(component, group, groupDir, options, userId);
184
+ }
185
+ // Generate group index file
186
+ await this.generateGroupIndex(group, groupDir);
187
+ // Generate preview page
188
+ await this.generatePreviewPage(group, groupDir);
189
+ spinner.success({
190
+ text: `Generated ${components.length} components in ${group.name}!`,
191
+ });
192
+ console.log(chalk_1.default.green("\n✅ Generated Files:"));
193
+ console.log(chalk_1.default.gray(` • ${groupDir}/`));
194
+ components.forEach((comp) => {
195
+ console.log(chalk_1.default.gray(` • ${comp.name}.tsx`));
196
+ });
197
+ console.log(chalk_1.default.gray(` • index.ts`));
198
+ console.log(chalk_1.default.gray(` • page.tsx`));
199
+ }
200
+ async generateComponent(component, group, groupDir, options, userId) {
201
+ try {
202
+ // Use sub-agent orchestration for component generation
203
+ const { orchestrator } = await Promise.resolve().then(() => __importStar(require("../agents/orchestrator/SubAgentOrchestrator")));
204
+ // Execute code generation first
205
+ const codeResult = (await orchestrator.executeAgent("CodeGenSubAgent", {
206
+ component,
207
+ group,
208
+ options: {
209
+ ...options,
210
+ useXAI: options.useXAI || false,
211
+ },
212
+ }));
213
+ const componentPath = path.join(groupDir, `${component.name}.tsx`);
214
+ await this.fs.writeFile(componentPath, codeResult.code);
215
+ // Execute QA and docs in parallel
216
+ const [qaResult, docsResult] = (await Promise.all([
217
+ orchestrator.executeAgent("QASubAgent", {
218
+ code: codeResult.code,
219
+ component,
220
+ standards: ["typescript", "react", "accessibility"],
221
+ }),
222
+ orchestrator.executeAgent("DocsSubAgent", {
223
+ code: codeResult.code,
224
+ component,
225
+ format: "readme",
226
+ }),
227
+ ]));
228
+ // Write documentation
229
+ const docsPath = path.join(groupDir, `${component.name}.md`);
230
+ await this.fs.writeFile(docsPath, docsResult.content);
231
+ // Log QA results
232
+ if (qaResult.score < 70) {
233
+ console.log(chalk_1.default.yellow(`⚠️ QA Score for ${component.name}: ${qaResult.score}/100`));
234
+ if (qaResult.issues.length > 0) {
235
+ console.log(chalk_1.default.gray(` Issues found: ${qaResult.issues.length}`));
236
+ }
237
+ }
238
+ else {
239
+ console.log(chalk_1.default.green(`✅ QA Score for ${component.name}: ${qaResult.score}/100`));
240
+ }
241
+ // Store component in InstantDB
242
+ await this.storeComponent({
243
+ userId,
244
+ name: component.name,
245
+ code: codeResult.code,
246
+ metadata: {
247
+ prompt: component.description || "",
248
+ model: "claude-sonnet",
249
+ executionTime: Date.now(),
250
+ qualityScore: qaResult.score,
251
+ group: group.name,
252
+ dependencies: codeResult.metadata?.dependencies || [],
253
+ tags: codeResult.metadata?.tags || [],
254
+ },
255
+ group: group.name,
256
+ qualityScore: qaResult.score,
257
+ });
258
+ }
259
+ catch (error) {
260
+ // Fallback to original method if sub-agent system fails
261
+ console.log(chalk_1.default.yellow(`⚠️ Sub-agent system failed for ${component.name}, using fallback method`));
262
+ const code = this.generateComponentCode(component, group, options);
263
+ const componentPath = path.join(groupDir, `${component.name}.tsx`);
264
+ await this.fs.writeFile(componentPath, code);
265
+ // Store component with fallback data
266
+ await this.storeComponent({
267
+ userId,
268
+ name: component.name,
269
+ code,
270
+ metadata: {
271
+ prompt: component.description || "",
272
+ model: "fallback",
273
+ executionTime: Date.now(),
274
+ qualityScore: null,
275
+ group: group.name,
276
+ },
277
+ group: group.name,
278
+ qualityScore: null,
279
+ });
280
+ }
281
+ }
282
+ async storeComponent(componentData) {
283
+ try {
284
+ const response = await fetch("http://localhost:3000/api/components/store", {
285
+ method: "POST",
286
+ headers: {
287
+ "Content-Type": "application/json",
288
+ },
289
+ body: JSON.stringify(componentData),
290
+ });
291
+ const result = (await response.json());
292
+ if (result.success) {
293
+ console.log(chalk_1.default.green(`💾 Component stored: ${componentData.name}`));
294
+ }
295
+ else {
296
+ console.log(chalk_1.default.yellow(`⚠️ Failed to store component: ${result.error}`));
297
+ }
298
+ }
299
+ catch (error) {
300
+ console.log(chalk_1.default.yellow(`⚠️ Component storage failed: ${error}`));
301
+ }
302
+ }
303
+ generateComponentCode(component, group, options) {
304
+ // Handle both string and object inputs
305
+ let name, description, type, userStories, actionFunctions, dependencies, tags;
306
+ if (typeof component === "string") {
307
+ // Simple string input - create a basic component structure
308
+ name = this.generateComponentName(component);
309
+ description = component;
310
+ type = "form"; // Default type
311
+ userStories = [
312
+ `As a user, I want to use ${name} to ${component.toLowerCase()}`,
313
+ ];
314
+ actionFunctions = ["handleSubmit", "handleChange"];
315
+ dependencies = ["react", "tailwindcss"];
316
+ tags = ["ui", "component"];
317
+ }
318
+ else {
319
+ // Structured component object
320
+ ({
321
+ name,
322
+ description,
323
+ type,
324
+ userStories,
325
+ actionFunctions,
326
+ dependencies,
327
+ tags,
328
+ } = component);
329
+ }
330
+ // Read branding for styling
331
+ const brandingPath = "context/branding.json";
332
+ let branding = {};
333
+ try {
334
+ if (fs.existsSync(brandingPath)) {
335
+ branding = JSON.parse(fs.readFileSync(brandingPath, "utf8"));
336
+ }
337
+ }
338
+ catch (error) {
339
+ // Use default branding if file doesn't exist
340
+ }
341
+ return `"use client";
342
+
343
+ import React from "react";
344
+ import { cn } from "@/lib/utils";
345
+
346
+ /**
347
+ * ${name} Component
348
+ *
349
+ * ${description}
350
+ *
351
+ * User Stories:
352
+ ${userStories.map((story) => ` * - ${story}`).join("\n")}
353
+ *
354
+ * Action Functions:
355
+ ${actionFunctions.map((func) => ` * - ${func}`).join("\n")}
356
+ *
357
+ * Dependencies: ${dependencies.join(", ")}
358
+ * Tags: ${tags.join(", ")}
359
+ */
360
+
361
+ interface ${name}Props {
362
+ className?: string;
363
+ // Add specific props based on component type
364
+ ${this.generatePropsForType(type)}
365
+ }
366
+
367
+ export function ${name}({
368
+ className,
369
+ ${this.generatePropsDestructuring(type)}
370
+ ...props
371
+ }: ${name}Props) {
372
+ ${this.generateComponentLogic(type, actionFunctions)}
373
+
374
+ return (
375
+ <div className={cn("${this.generateBaseClasses(type, branding)}", className)} {...props}>
376
+ ${this.generateComponentJSX(type, name)}
377
+ </div>
378
+ );
379
+ }
380
+
381
+ ${this.generateActionFunctions(actionFunctions, name)}
382
+
383
+ export default ${name};
384
+ `;
385
+ }
386
+ generateComponentName(description) {
387
+ // Convert description to PascalCase component name
388
+ return description
389
+ .split(" ")
390
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
391
+ .join("")
392
+ .replace(/[^a-zA-Z0-9]/g, "");
393
+ }
394
+ generatePropsForType(type) {
395
+ switch (type) {
396
+ case "form":
397
+ return `
398
+ onSubmit?: (data: any) => void;
399
+ loading?: boolean;
400
+ error?: string;`;
401
+ case "layout":
402
+ return `
403
+ children: React.ReactNode;
404
+ sidebar?: React.ReactNode;`;
405
+ case "card":
406
+ return `
407
+ title?: string;
408
+ content?: React.ReactNode;
409
+ actions?: React.ReactNode;`;
410
+ case "button":
411
+ return `
412
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
413
+ size?: "default" | "sm" | "lg" | "icon";
414
+ disabled?: boolean;
415
+ onClick?: () => void;`;
416
+ default:
417
+ return `
418
+ // Add component-specific props here`;
419
+ }
420
+ }
421
+ generatePropsDestructuring(type) {
422
+ switch (type) {
423
+ case "form":
424
+ return `
425
+ onSubmit,
426
+ loading = false,
427
+ error,`;
428
+ case "layout":
429
+ return `
430
+ children,
431
+ sidebar,`;
432
+ case "card":
433
+ return `
434
+ title,
435
+ content,
436
+ actions,`;
437
+ case "button":
438
+ return `
439
+ variant = "default",
440
+ size = "default",
441
+ disabled = false,
442
+ onClick,`;
443
+ default:
444
+ return "";
445
+ }
446
+ }
447
+ generateComponentLogic(type, actionFunctions) {
448
+ const logic = [];
449
+ if (type === "form") {
450
+ logic.push(`
451
+ const [formData, setFormData] = React.useState({});
452
+ const [isSubmitting, setIsSubmitting] = React.useState(false);`);
453
+ }
454
+ if (type === "form") {
455
+ logic.push(`
456
+ const handleSubmit = async (e: React.FormEvent) => {
457
+ e.preventDefault();
458
+ setIsSubmitting(true);
459
+ try {
460
+ // TODO: Implement form submission logic
461
+ onSubmit?.(formData);
462
+ } catch (error) {
463
+ console.error("Form submission error:", error);
464
+ } finally {
465
+ setIsSubmitting(false);
466
+ }
467
+ };`);
468
+ }
469
+ return logic.join("\n");
470
+ }
471
+ generateBaseClasses(type, branding) {
472
+ const baseClasses = [];
473
+ switch (type) {
474
+ case "form":
475
+ baseClasses.push("space-y-4", "w-full", "max-w-md");
476
+ break;
477
+ case "layout":
478
+ baseClasses.push("min-h-screen", "flex", "flex-col");
479
+ break;
480
+ case "card":
481
+ baseClasses.push("rounded-lg", "border", "bg-card", "p-6", "shadow-sm");
482
+ break;
483
+ case "button":
484
+ baseClasses.push("inline-flex", "items-center", "justify-center", "rounded-md", "text-sm", "font-medium", "transition-colors", "focus-visible:outline-none", "focus-visible:ring-2", "focus-visible:ring-ring", "focus-visible:ring-offset-2", "disabled:opacity-50", "disabled:pointer-events-none");
485
+ break;
486
+ default:
487
+ baseClasses.push("w-full");
488
+ }
489
+ return baseClasses.join(" ");
490
+ }
491
+ generateComponentJSX(type, name) {
492
+ switch (type) {
493
+ case "form":
494
+ return `
495
+ <form onSubmit={handleSubmit} className="space-y-4">
496
+ <div className="space-y-2">
497
+ <label htmlFor="email" className="text-sm font-medium">
498
+ Email
499
+ </label>
500
+ <input
501
+ id="email"
502
+ type="email"
503
+ className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
504
+ placeholder="Enter your email"
505
+ required
506
+ />
507
+ </div>
508
+ <div className="space-y-2">
509
+ <label htmlFor="password" className="text-sm font-medium">
510
+ Password
511
+ </label>
512
+ <input
513
+ id="password"
514
+ type="password"
515
+ className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
516
+ placeholder="Enter your password"
517
+ required
518
+ />
519
+ </div>
520
+ {error && (
521
+ <div className="text-sm text-destructive">
522
+ {error}
523
+ </div>
524
+ )}
525
+ <button
526
+ type="submit"
527
+ disabled={loading || isSubmitting}
528
+ className="inline-flex h-10 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground ring-offset-background transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
529
+ >
530
+ {loading || isSubmitting ? "Loading..." : "Submit"}
531
+ </button>
532
+ </form>`;
533
+ case "layout":
534
+ return `
535
+ <header className="border-b bg-background">
536
+ <div className="container mx-auto px-4 py-4">
537
+ <h1 className="text-2xl font-bold">${name}</h1>
538
+ </div>
539
+ </header>
540
+ <main className="flex-1">
541
+ <div className="container mx-auto px-4 py-8">
542
+ {children}
543
+ </div>
544
+ </main>
545
+ <footer className="border-t bg-background">
546
+ <div className="container mx-auto px-4 py-4 text-center text-sm text-muted-foreground">
547
+ © 2024 MyContext. All rights reserved.
548
+ </div>
549
+ </footer>`;
550
+ case "card":
551
+ return `
552
+ {title && (
553
+ <h3 className="text-lg font-semibold leading-none tracking-tight">
554
+ {title}
555
+ </h3>
556
+ )}
557
+ {content && (
558
+ <div className="mt-4">
559
+ {content}
560
+ </div>
561
+ )}
562
+ {actions && (
563
+ <div className="mt-4 flex justify-end space-x-2">
564
+ {actions}
565
+ </div>
566
+ )}`;
567
+ case "button":
568
+ return `
569
+ <span className="sr-only">${name}</span>
570
+ <span>${name}</span>`;
571
+ default:
572
+ return `
573
+ <div className="p-4">
574
+ <h3 className="text-lg font-semibold">${name}</h3>
575
+ <p className="text-sm text-muted-foreground">
576
+ This is a ${type} component. Customize it based on your needs.
577
+ </p>
578
+ </div>`;
579
+ }
580
+ }
581
+ generateActionFunctions(actionFunctions, componentName) {
582
+ if (actionFunctions.length === 0)
583
+ return "";
584
+ const functions = actionFunctions.map((func) => {
585
+ switch (func) {
586
+ case "handleSubmit":
587
+ return `// Already implemented in component logic`;
588
+ case "handleLogin":
589
+ return `
590
+ export async function handleLogin(email: string, password: string) {
591
+ // TODO: Implement login logic
592
+ console.log("Logging in with:", { email, password });
593
+ return { success: true };
594
+ }`;
595
+ case "handleSignup":
596
+ return `
597
+ export async function handleSignup(email: string, password: string, name: string) {
598
+ // TODO: Implement signup logic
599
+ console.log("Signing up with:", { email, password, name });
600
+ return { success: true };
601
+ }`;
602
+ case "validateEmail":
603
+ return `
604
+ export function validateEmail(email: string): boolean {
605
+ const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
606
+ return emailRegex.test(email);
607
+ }`;
608
+ case "checkUsername":
609
+ return `
610
+ export async function checkUsername(username: string): Promise<boolean> {
611
+ // TODO: Implement username availability check
612
+ console.log("Checking username:", username);
613
+ return true;
614
+ }`;
615
+ default:
616
+ return `
617
+ export function ${func}() {
618
+ // TODO: Implement ${func} logic
619
+ console.log("${func} called");
620
+ }`;
621
+ }
622
+ });
623
+ return functions.join("\n");
624
+ }
625
+ async generateGroupIndex(group, groupDir) {
626
+ const components = group.components || [];
627
+ const exports = components.map((comp) => `export { ${comp.name} } from "./${comp.name}";`);
628
+ const indexContent = `/**
629
+ * ${group.name} Components
630
+ *
631
+ * ${group.description}
632
+ *
633
+ * Generated components: ${components.length}
634
+ */
635
+
636
+ ${exports.join("\n")}
637
+
638
+ // Re-export default exports
639
+ ${components
640
+ .map((comp) => `export { default as ${comp.name}Default } from "./${comp.name}";`)
641
+ .join("\n")}
642
+ `;
643
+ await this.fs.writeFile(path.join(groupDir, "index.ts"), indexContent);
644
+ }
645
+ async generatePreviewPage(group, groupDir) {
646
+ const components = group.components || [];
647
+ const previewContent = `import React from "react";
648
+ ${components
649
+ .map((comp) => `import { ${comp.name} } from "./${comp.name}";`)
650
+ .join("\n")}
651
+
652
+ export default function ${group.name}Preview() {
653
+ return (
654
+ <div className="container mx-auto p-8 space-y-8">
655
+ <div className="text-center">
656
+ <h1 className="text-3xl font-bold mb-2">${group.name} Components</h1>
657
+ <p className="text-muted-foreground">${group.description}</p>
658
+ </div>
659
+
660
+ <div className="grid gap-8">
661
+ ${components
662
+ .map((comp) => `
663
+ <section className="space-y-4">
664
+ <h2 className="text-2xl font-semibold">${comp.name}</h2>
665
+ <p className="text-muted-foreground">${comp.description}</p>
666
+ <div className="border rounded-lg p-6 bg-card">
667
+ <${comp.name} />
668
+ </div>
669
+ </section>`)
670
+ .join("\n")}
671
+ </div>
672
+ </div>
673
+ );
674
+ }
675
+ `;
676
+ await this.fs.writeFile(path.join(groupDir, "page.tsx"), previewContent);
677
+ }
678
+ }
679
+ exports.GenerateComponentsCommand = GenerateComponentsCommand;
680
+ //# sourceMappingURL=generate-components.js.map