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,740 @@
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.AnalyzeCommand = void 0;
40
+ const chalk_1 = __importDefault(require("chalk"));
41
+ const path_1 = __importDefault(require("path"));
42
+ const fs = __importStar(require("fs-extra"));
43
+ const spinner_1 = require("../utils/spinner");
44
+ const hybridAIClient_1 = require("../utils/hybridAIClient");
45
+ const fileSystem_1 = require("../utils/fileSystem");
46
+ class AnalyzeCommand {
47
+ constructor() {
48
+ this.spinner = new spinner_1.EnhancedSpinner("Analyzing project...");
49
+ this.ai = new hybridAIClient_1.HybridAIClient();
50
+ this.fs = new fileSystem_1.FileSystemManager();
51
+ }
52
+ async execute(target, options) {
53
+ const { output = ".mycontext", generateContext = true, includeBrand = true, includeTypes = true, includeComponents = true, verbose = false, } = options;
54
+ console.log(chalk_1.default.blue.bold("šŸ” Analyzing Existing Project\n"));
55
+ try {
56
+ // Step 1: Analyze project structure
57
+ this.spinner.start().updateText("Analyzing project structure...");
58
+ const analysis = await this.analyzeProject(target);
59
+ this.spinner.succeed("Project structure analyzed");
60
+ // Step 2: Display analysis results
61
+ this.displayAnalysisResults(analysis);
62
+ // Step 3: Generate context files if requested
63
+ if (generateContext) {
64
+ this.spinner.start().updateText("Generating context files...");
65
+ await this.generateContextFiles(analysis, output, {
66
+ includeBrand,
67
+ includeTypes,
68
+ includeComponents,
69
+ });
70
+ this.spinner.succeed("Context files generated");
71
+ }
72
+ console.log(chalk_1.default.green.bold("\nāœ… Project analysis completed!"));
73
+ this.printNextSteps(analysis, generateContext);
74
+ }
75
+ catch (error) {
76
+ this.spinner.fail("Analysis failed");
77
+ throw error;
78
+ }
79
+ }
80
+ async analyzeProject(projectPath) {
81
+ const resolvedPath = path_1.default.resolve(projectPath);
82
+ // Check if it's a valid project
83
+ if (!(await this.isValidProject(resolvedPath))) {
84
+ throw new Error("Not a valid Next.js project");
85
+ }
86
+ // Analyze project structure
87
+ const structure = await this.analyzeStructure(resolvedPath);
88
+ // Analyze components
89
+ const components = await this.analyzeComponents(resolvedPath);
90
+ // Analyze types
91
+ const types = await this.analyzeTypes(resolvedPath);
92
+ // Analyze styling
93
+ const styling = await this.analyzeStyling(resolvedPath);
94
+ // Analyze dependencies
95
+ const dependencies = await this.analyzeDependencies(resolvedPath);
96
+ // Get package.json
97
+ const packageJson = await this.getPackageJson(resolvedPath);
98
+ // Infer project purpose using AI
99
+ const inferredPurpose = await this.inferProjectPurpose(components, types, styling, packageJson);
100
+ // Generate recommendations
101
+ const recommendations = this.generateRecommendations(structure, components, types, styling);
102
+ return {
103
+ projectType: "nextjs",
104
+ framework: "nextjs",
105
+ structure,
106
+ components,
107
+ types,
108
+ styling,
109
+ dependencies,
110
+ packageJson,
111
+ inferredPurpose,
112
+ recommendations,
113
+ };
114
+ }
115
+ async isValidProject(projectPath) {
116
+ const packageJsonPath = path_1.default.join(projectPath, "package.json");
117
+ const nextConfigPath = path_1.default.join(projectPath, "next.config.js");
118
+ const nextConfigTsPath = path_1.default.join(projectPath, "next.config.ts");
119
+ const hasPackageJson = await fs.pathExists(packageJsonPath);
120
+ const hasNextConfig = (await fs.pathExists(nextConfigPath)) ||
121
+ (await fs.pathExists(nextConfigTsPath));
122
+ if (!hasPackageJson)
123
+ return false;
124
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
125
+ const hasNextDependency = packageJson.dependencies?.next || packageJson.devDependencies?.next;
126
+ return hasNextDependency && hasNextConfig;
127
+ }
128
+ async analyzeStructure(projectPath) {
129
+ const srcPath = path_1.default.join(projectPath, "src");
130
+ const appPath = path_1.default.join(srcPath, "app");
131
+ const pagesPath = path_1.default.join(srcPath, "pages");
132
+ const componentsPath = path_1.default.join(srcPath, "components");
133
+ const libPath = path_1.default.join(srcPath, "lib");
134
+ const stylesPath = path_1.default.join(srcPath, "styles");
135
+ return {
136
+ hasAppRouter: await fs.pathExists(appPath),
137
+ hasPagesRouter: await fs.pathExists(pagesPath),
138
+ hasComponents: await fs.pathExists(componentsPath),
139
+ hasLib: await fs.pathExists(libPath),
140
+ hasStyles: await fs.pathExists(stylesPath),
141
+ };
142
+ }
143
+ async analyzeComponents(projectPath) {
144
+ const components = [];
145
+ const srcPath = path_1.default.join(projectPath, "src");
146
+ // Analyze app directory (App Router)
147
+ const appPath = path_1.default.join(srcPath, "app");
148
+ if (await fs.pathExists(appPath)) {
149
+ const appComponents = await this.scanDirectory(appPath, "page", "app");
150
+ components.push(...appComponents);
151
+ }
152
+ // Analyze pages directory (Pages Router)
153
+ const pagesPath = path_1.default.join(srcPath, "pages");
154
+ if (await fs.pathExists(pagesPath)) {
155
+ const pageComponents = await this.scanDirectory(pagesPath, "page", "pages");
156
+ components.push(...pageComponents);
157
+ }
158
+ // Analyze components directory
159
+ const componentsPath = path_1.default.join(srcPath, "components");
160
+ if (await fs.pathExists(componentsPath)) {
161
+ const componentFiles = await this.scanDirectory(componentsPath, "component", "components");
162
+ components.push(...componentFiles);
163
+ }
164
+ return components;
165
+ }
166
+ async scanDirectory(dirPath, type, group) {
167
+ const components = [];
168
+ const scan = async (currentPath, relativePath = "") => {
169
+ const items = await fs.readdir(currentPath);
170
+ for (const item of items) {
171
+ const itemPath = path_1.default.join(currentPath, item);
172
+ const stat = await fs.stat(itemPath);
173
+ if (stat.isDirectory()) {
174
+ await scan(itemPath, path_1.default.join(relativePath, item));
175
+ }
176
+ else if (item.endsWith(".tsx") || item.endsWith(".jsx")) {
177
+ const component = await this.analyzeComponentFile(itemPath, type, group, relativePath);
178
+ if (component) {
179
+ components.push(component);
180
+ }
181
+ }
182
+ }
183
+ };
184
+ await scan(dirPath);
185
+ return components;
186
+ }
187
+ async analyzeComponentFile(filePath, type, group, relativePath) {
188
+ try {
189
+ const content = await fs.readFile(filePath, "utf-8");
190
+ const fileName = path_1.default.basename(filePath, path_1.default.extname(filePath));
191
+ // Extract component name
192
+ const componentName = this.extractComponentName(content, fileName);
193
+ // Analyze props
194
+ const props = this.extractProps(content);
195
+ // Analyze dependencies
196
+ const dependencies = this.extractDependencies(content);
197
+ // Analyze complexity
198
+ const complexity = this.calculateComplexity(content);
199
+ // Check for hooks and state
200
+ const hasState = this.hasStateManagement(content);
201
+ const hasEffects = this.hasSideEffects(content);
202
+ // Check if it's client or server component
203
+ const isClient = content.includes("'use client'");
204
+ const isServer = !isClient && type === "component";
205
+ return {
206
+ name: componentName,
207
+ path: filePath,
208
+ type,
209
+ group,
210
+ props,
211
+ dependencies,
212
+ complexity,
213
+ hasState,
214
+ hasEffects,
215
+ isClient,
216
+ isServer,
217
+ };
218
+ }
219
+ catch (error) {
220
+ console.warn(`Failed to analyze component ${filePath}:`, error);
221
+ return null;
222
+ }
223
+ }
224
+ extractComponentName(content, fileName) {
225
+ // Try to extract from function declaration
226
+ const functionMatch = content.match(/function\s+(\w+)/);
227
+ if (functionMatch)
228
+ return functionMatch[1];
229
+ // Try to extract from const declaration
230
+ const constMatch = content.match(/const\s+(\w+)\s*=/);
231
+ if (constMatch)
232
+ return constMatch[1];
233
+ // Try to extract from export default
234
+ const exportMatch = content.match(/export\s+default\s+(\w+)/);
235
+ if (exportMatch)
236
+ return exportMatch[1];
237
+ // Fallback to filename
238
+ return fileName.charAt(0).toUpperCase() + fileName.slice(1);
239
+ }
240
+ extractProps(content) {
241
+ const props = [];
242
+ // Extract from interface/type definitions
243
+ const interfaceMatch = content.match(/interface\s+(\w+)Props\s*\{([^}]+)\}/);
244
+ if (interfaceMatch) {
245
+ const propsContent = interfaceMatch[2];
246
+ const propMatches = propsContent.match(/(\w+)\s*:/g);
247
+ if (propMatches) {
248
+ props.push(...propMatches.map((match) => match.replace(":", "").trim()));
249
+ }
250
+ }
251
+ // Extract from function parameters
252
+ const functionMatch = content.match(/function\s+\w+\s*\(\s*\{([^}]+)\}/);
253
+ if (functionMatch) {
254
+ const paramsContent = functionMatch[1];
255
+ const paramMatches = paramsContent.match(/(\w+)/g);
256
+ if (paramMatches) {
257
+ props.push(...paramMatches);
258
+ }
259
+ }
260
+ return [...new Set(props)];
261
+ }
262
+ extractDependencies(content) {
263
+ const dependencies = [];
264
+ // Extract imports
265
+ const importMatches = content.match(/import\s+.*?\s+from\s+['"]([^'"]+)['"]/g);
266
+ if (importMatches) {
267
+ dependencies.push(...importMatches
268
+ .map((match) => {
269
+ const fromMatch = match.match(/from\s+['"]([^'"]+)['"]/);
270
+ return fromMatch ? fromMatch[1] : "";
271
+ })
272
+ .filter(Boolean));
273
+ }
274
+ return dependencies;
275
+ }
276
+ calculateComplexity(content) {
277
+ let complexity = 0;
278
+ // Count conditional statements
279
+ complexity += (content.match(/\b(if|else|switch|case)\b/g) || []).length;
280
+ // Count loops
281
+ complexity += (content.match(/\b(for|while|do)\b/g) || []).length;
282
+ // Count function calls
283
+ complexity += (content.match(/\w+\(/g) || []).length;
284
+ // Count JSX elements
285
+ complexity += (content.match(/<[A-Z]\w*/g) || []).length;
286
+ return complexity;
287
+ }
288
+ hasStateManagement(content) {
289
+ return (content.includes("useState") ||
290
+ content.includes("useReducer") ||
291
+ content.includes("useContext"));
292
+ }
293
+ hasSideEffects(content) {
294
+ return content.includes("useEffect") || content.includes("useLayoutEffect");
295
+ }
296
+ async analyzeTypes(projectPath) {
297
+ const types = [];
298
+ const srcPath = path_1.default.join(projectPath, "src");
299
+ const scanTypes = async (dirPath) => {
300
+ const items = await fs.readdir(dirPath);
301
+ for (const item of items) {
302
+ const itemPath = path_1.default.join(dirPath, item);
303
+ const stat = await fs.stat(itemPath);
304
+ if (stat.isDirectory()) {
305
+ await scanTypes(itemPath);
306
+ }
307
+ else if (item.endsWith(".ts") || item.endsWith(".tsx")) {
308
+ const fileTypes = await this.extractTypesFromFile(itemPath);
309
+ types.push(...fileTypes);
310
+ }
311
+ }
312
+ };
313
+ await scanTypes(srcPath);
314
+ return types;
315
+ }
316
+ async extractTypesFromFile(filePath) {
317
+ try {
318
+ const content = await fs.readFile(filePath, "utf-8");
319
+ const types = [];
320
+ // Extract interfaces
321
+ const interfaceMatches = content.match(/export\s+interface\s+(\w+)\s*\{([^}]+)\}/g);
322
+ if (interfaceMatches) {
323
+ interfaceMatches.forEach((match) => {
324
+ const nameMatch = match.match(/interface\s+(\w+)/);
325
+ const propsMatch = match.match(/\{([^}]+)\}/);
326
+ if (nameMatch) {
327
+ types.push({
328
+ name: nameMatch[1],
329
+ type: "interface",
330
+ path: filePath,
331
+ properties: propsMatch
332
+ ? propsMatch[1].split(",").map((p) => p.trim())
333
+ : [],
334
+ isExported: true,
335
+ isGeneric: match.includes("<"),
336
+ });
337
+ }
338
+ });
339
+ }
340
+ // Extract types
341
+ const typeMatches = content.match(/export\s+type\s+(\w+)\s*=/g);
342
+ if (typeMatches) {
343
+ typeMatches.forEach((match) => {
344
+ const nameMatch = match.match(/type\s+(\w+)/);
345
+ if (nameMatch) {
346
+ types.push({
347
+ name: nameMatch[1],
348
+ type: "type",
349
+ path: filePath,
350
+ properties: [],
351
+ isExported: true,
352
+ isGeneric: match.includes("<"),
353
+ });
354
+ }
355
+ });
356
+ }
357
+ return types;
358
+ }
359
+ catch (error) {
360
+ console.warn(`Failed to extract types from ${filePath}:`, error);
361
+ return [];
362
+ }
363
+ }
364
+ async analyzeStyling(projectPath) {
365
+ const srcPath = path_1.default.join(projectPath, "src");
366
+ const stylesPath = path_1.default.join(srcPath, "styles");
367
+ const appPath = path_1.default.join(srcPath, "app");
368
+ let framework = "vanilla";
369
+ let hasDesignSystem = false;
370
+ const colors = [];
371
+ const fonts = [];
372
+ const spacing = [];
373
+ const breakpoints = [];
374
+ const customProperties = [];
375
+ // Check for Tailwind
376
+ const tailwindConfig = (await fs.pathExists(path_1.default.join(projectPath, "tailwind.config.js"))) ||
377
+ (await fs.pathExists(path_1.default.join(projectPath, "tailwind.config.ts")));
378
+ if (tailwindConfig) {
379
+ framework = "tailwind";
380
+ hasDesignSystem = true;
381
+ }
382
+ // Check for CSS modules
383
+ const cssModules = await this.hasCSSModules(srcPath);
384
+ if (cssModules) {
385
+ framework = "css-modules";
386
+ }
387
+ // Check for styled-components
388
+ const styledComponents = await this.hasStyledComponents(srcPath);
389
+ if (styledComponents) {
390
+ framework = "styled-components";
391
+ }
392
+ // Analyze CSS files
393
+ if (await fs.pathExists(stylesPath)) {
394
+ const cssFiles = await this.findCSSFiles(stylesPath);
395
+ for (const cssFile of cssFiles) {
396
+ const content = await fs.readFile(cssFile, "utf-8");
397
+ colors.push(...this.extractColors(content));
398
+ fonts.push(...this.extractFonts(content));
399
+ spacing.push(...this.extractSpacing(content));
400
+ breakpoints.push(...this.extractBreakpoints(content));
401
+ customProperties.push(...this.extractCustomProperties(content));
402
+ }
403
+ }
404
+ return {
405
+ framework,
406
+ hasDesignSystem,
407
+ colors: [...new Set(colors)],
408
+ fonts: [...new Set(fonts)],
409
+ spacing: [...new Set(spacing)],
410
+ breakpoints: [...new Set(breakpoints)],
411
+ customProperties: [...new Set(customProperties)],
412
+ };
413
+ }
414
+ async hasCSSModules(srcPath) {
415
+ const items = await fs.readdir(srcPath);
416
+ return items.some((item) => item.endsWith(".module.css"));
417
+ }
418
+ async hasStyledComponents(srcPath) {
419
+ const items = await fs.readdir(srcPath);
420
+ return items.some((item) => item.includes("styled"));
421
+ }
422
+ async findCSSFiles(dirPath) {
423
+ const files = [];
424
+ const items = await fs.readdir(dirPath);
425
+ for (const item of items) {
426
+ const itemPath = path_1.default.join(dirPath, item);
427
+ const stat = await fs.stat(itemPath);
428
+ if (stat.isDirectory()) {
429
+ files.push(...(await this.findCSSFiles(itemPath)));
430
+ }
431
+ else if (item.endsWith(".css") ||
432
+ item.endsWith(".scss") ||
433
+ item.endsWith(".sass")) {
434
+ files.push(itemPath);
435
+ }
436
+ }
437
+ return files;
438
+ }
439
+ extractColors(content) {
440
+ const colorRegex = /#[0-9a-fA-F]{3,6}|rgb\([^)]+\)|rgba\([^)]+\)|hsl\([^)]+\)|hsla\([^)]+\)/g;
441
+ return content.match(colorRegex) || [];
442
+ }
443
+ extractFonts(content) {
444
+ const fontRegex = /font-family:\s*([^;]+)/g;
445
+ const matches = content.match(fontRegex) || [];
446
+ return matches.map((match) => match.replace("font-family:", "").trim());
447
+ }
448
+ extractSpacing(content) {
449
+ const spacingRegex = /(?:margin|padding|gap):\s*([^;]+)/g;
450
+ const matches = content.match(spacingRegex) || [];
451
+ return matches.map((match) => match.replace(/(?:margin|padding|gap):/, "").trim());
452
+ }
453
+ extractBreakpoints(content) {
454
+ const breakpointRegex = /@media\s+\([^)]+\)/g;
455
+ return content.match(breakpointRegex) || [];
456
+ }
457
+ extractCustomProperties(content) {
458
+ const customPropRegex = /--[a-zA-Z-]+/g;
459
+ return content.match(customPropRegex) || [];
460
+ }
461
+ async analyzeDependencies(projectPath) {
462
+ const packageJsonPath = path_1.default.join(projectPath, "package.json");
463
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
464
+ const dependencies = Object.keys(packageJson.dependencies || {});
465
+ const devDependencies = Object.keys(packageJson.devDependencies || {});
466
+ return [...dependencies, ...devDependencies];
467
+ }
468
+ async getPackageJson(projectPath) {
469
+ const packageJsonPath = path_1.default.join(projectPath, "package.json");
470
+ return JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
471
+ }
472
+ async inferProjectPurpose(components, types, styling, packageJson) {
473
+ const context = {
474
+ components: components.map((c) => ({
475
+ name: c.name,
476
+ type: c.type,
477
+ group: c.group,
478
+ })),
479
+ types: types.map((t) => ({ name: t.name, type: t.type })),
480
+ styling: styling.framework,
481
+ dependencies: Object.keys(packageJson.dependencies || {}),
482
+ name: packageJson.name,
483
+ description: packageJson.description,
484
+ };
485
+ const prompt = `Analyze this Next.js project and infer its purpose:
486
+
487
+ Project Context:
488
+ ${JSON.stringify(context, null, 2)}
489
+
490
+ Based on the components, types, styling, and dependencies, what is this project's main purpose? Provide a brief 2-3 sentence description of what this application does.`;
491
+ try {
492
+ const response = await this.ai.generateText(prompt);
493
+ return response.text.trim();
494
+ }
495
+ catch (error) {
496
+ console.warn("Failed to infer project purpose with AI, using fallback");
497
+ return "A Next.js application with custom components and functionality";
498
+ }
499
+ }
500
+ generateRecommendations(structure, components, types, styling) {
501
+ const recommendations = [];
502
+ if (!structure.hasComponents) {
503
+ recommendations.push("Consider organizing components in a dedicated src/components directory");
504
+ }
505
+ if (!structure.hasLib) {
506
+ recommendations.push("Consider creating a src/lib directory for utilities and shared functions");
507
+ }
508
+ if (components.length === 0) {
509
+ recommendations.push("No components found - consider creating reusable UI components");
510
+ }
511
+ if (types.length === 0) {
512
+ recommendations.push("Consider adding TypeScript interfaces for better type safety");
513
+ }
514
+ if (styling.framework === "vanilla") {
515
+ recommendations.push("Consider using a CSS framework like Tailwind CSS for better styling");
516
+ }
517
+ return recommendations;
518
+ }
519
+ displayAnalysisResults(analysis) {
520
+ console.log(chalk_1.default.blue.bold("\nšŸ“Š Project Analysis Results"));
521
+ console.log(chalk_1.default.gray("=".repeat(50)));
522
+ console.log(chalk_1.default.yellow("\nšŸ—ļø Structure:"));
523
+ console.log(chalk_1.default.gray(` • App Router: ${analysis.structure.hasAppRouter ? "āœ…" : "āŒ"}`));
524
+ console.log(chalk_1.default.gray(` • Pages Router: ${analysis.structure.hasPagesRouter ? "āœ…" : "āŒ"}`));
525
+ console.log(chalk_1.default.gray(` • Components: ${analysis.structure.hasComponents ? "āœ…" : "āŒ"}`));
526
+ console.log(chalk_1.default.gray(` • Lib: ${analysis.structure.hasLib ? "āœ…" : "āŒ"}`));
527
+ console.log(chalk_1.default.gray(` • Styles: ${analysis.structure.hasStyles ? "āœ…" : "āŒ"}`));
528
+ console.log(chalk_1.default.yellow("\n🧩 Components:"));
529
+ console.log(chalk_1.default.gray(` • Total: ${analysis.components.length}`));
530
+ console.log(chalk_1.default.gray(` • Pages: ${analysis.components.filter((c) => c.type === "page").length}`));
531
+ console.log(chalk_1.default.gray(` • Components: ${analysis.components.filter((c) => c.type === "component").length}`));
532
+ console.log(chalk_1.default.gray(` • Client: ${analysis.components.filter((c) => c.isClient).length}`));
533
+ console.log(chalk_1.default.gray(` • Server: ${analysis.components.filter((c) => c.isServer).length}`));
534
+ console.log(chalk_1.default.yellow("\nšŸ“ Types:"));
535
+ console.log(chalk_1.default.gray(` • Total: ${analysis.types.length}`));
536
+ console.log(chalk_1.default.gray(` • Interfaces: ${analysis.types.filter((t) => t.type === "interface").length}`));
537
+ console.log(chalk_1.default.gray(` • Types: ${analysis.types.filter((t) => t.type === "type").length}`));
538
+ console.log(chalk_1.default.yellow("\nšŸŽØ Styling:"));
539
+ console.log(chalk_1.default.gray(` • Framework: ${analysis.styling.framework}`));
540
+ console.log(chalk_1.default.gray(` • Design System: ${analysis.styling.hasDesignSystem ? "āœ…" : "āŒ"}`));
541
+ console.log(chalk_1.default.gray(` • Colors: ${analysis.styling.colors.length}`));
542
+ console.log(chalk_1.default.gray(` • Fonts: ${analysis.styling.fonts.length}`));
543
+ console.log(chalk_1.default.yellow("\nšŸŽÆ Inferred Purpose:"));
544
+ console.log(chalk_1.default.gray(` ${analysis.inferredPurpose}`));
545
+ if (analysis.recommendations.length > 0) {
546
+ console.log(chalk_1.default.yellow("\nšŸ’” Recommendations:"));
547
+ analysis.recommendations.forEach((rec) => {
548
+ console.log(chalk_1.default.gray(` • ${rec}`));
549
+ });
550
+ }
551
+ }
552
+ async generateContextFiles(analysis, outputDir, options) {
553
+ const contextDir = path_1.default.join(process.cwd(), outputDir);
554
+ await fs.ensureDir(contextDir);
555
+ // Generate PRD
556
+ const prdContent = this.generatePRD(analysis);
557
+ await fs.writeFile(path_1.default.join(contextDir, "01-prd.md"), prdContent);
558
+ // Generate types
559
+ if (options.includeTypes) {
560
+ const typesContent = this.generateTypes(analysis);
561
+ await fs.writeFile(path_1.default.join(contextDir, "02-types.ts"), typesContent);
562
+ }
563
+ // Generate brand guidelines
564
+ if (options.includeBrand) {
565
+ const brandContent = this.generateBrand(analysis);
566
+ await fs.writeFile(path_1.default.join(contextDir, "03-brand.md"), brandContent);
567
+ }
568
+ // Generate component list
569
+ if (options.includeComponents) {
570
+ const componentListContent = this.generateComponentList(analysis);
571
+ await fs.writeFile(path_1.default.join(contextDir, "04-component-list.json"), componentListContent);
572
+ }
573
+ }
574
+ generatePRD(analysis) {
575
+ return `# Product Requirements Document
576
+
577
+ ## Project Overview
578
+ **Name:** ${analysis.packageJson.name || "MyContext Project"}
579
+ **Description:** ${analysis.inferredPurpose}
580
+ **Framework:** ${analysis.framework}
581
+ **Analysis Date:** ${new Date().toISOString()}
582
+
583
+ ## Current State Analysis
584
+
585
+ ### Project Structure
586
+ - **App Router:** ${analysis.structure.hasAppRouter ? "Yes" : "No"}
587
+ - **Pages Router:** ${analysis.structure.hasPagesRouter ? "Yes" : "No"}
588
+ - **Components Directory:** ${analysis.structure.hasComponents ? "Yes" : "No"}
589
+ - **Lib Directory:** ${analysis.structure.hasLib ? "Yes" : "No"}
590
+
591
+ ### Components Inventory
592
+ Total Components: ${analysis.components.length}
593
+
594
+ #### Pages (${analysis.components.filter((c) => c.type === "page").length})
595
+ ${analysis.components
596
+ .filter((c) => c.type === "page")
597
+ .map((c) => `- ${c.name} (${c.group})`)
598
+ .join("\n")}
599
+
600
+ #### UI Components (${analysis.components.filter((c) => c.type === "component").length})
601
+ ${analysis.components
602
+ .filter((c) => c.type === "component")
603
+ .map((c) => `- ${c.name} (${c.group})`)
604
+ .join("\n")}
605
+
606
+ ### Type System
607
+ Total Types: ${analysis.types.length}
608
+
609
+ #### Interfaces (${analysis.types.filter((t) => t.type === "interface").length})
610
+ ${analysis.types
611
+ .filter((t) => t.type === "interface")
612
+ .map((t) => `- ${t.name}`)
613
+ .join("\n")}
614
+
615
+ #### Type Aliases (${analysis.types.filter((t) => t.type === "type").length})
616
+ ${analysis.types
617
+ .filter((t) => t.type === "type")
618
+ .map((t) => `- ${t.name}`)
619
+ .join("\n")}
620
+
621
+ ### Styling System
622
+ - **Framework:** ${analysis.styling.framework}
623
+ - **Design System:** ${analysis.styling.hasDesignSystem ? "Yes" : "No"}
624
+ - **Custom Colors:** ${analysis.styling.colors.length}
625
+ - **Custom Fonts:** ${analysis.styling.fonts.length}
626
+
627
+ ## Recommendations
628
+
629
+ ${analysis.recommendations.map((rec) => `- ${rec}`).join("\n")}
630
+
631
+ ## Next Steps
632
+
633
+ 1. Review and refine the generated context files
634
+ 2. Implement missing server actions and hooks
635
+ 3. Enhance component functionality
636
+ 4. Improve type safety where needed
637
+ 5. Consider implementing a design system
638
+
639
+ ## Dependencies
640
+
641
+ ${analysis.dependencies.map((dep) => `- ${dep}`).join("\n")}
642
+ `;
643
+ }
644
+ generateTypes(analysis) {
645
+ let content = `// Generated types from existing project analysis
646
+ // Date: ${new Date().toISOString()}
647
+
648
+ `;
649
+ // Generate interfaces from existing types
650
+ analysis.types.forEach((type) => {
651
+ if (type.type === "interface") {
652
+ content += `export interface ${type.name} {\n`;
653
+ type.properties.forEach((prop) => {
654
+ content += ` ${prop};\n`;
655
+ });
656
+ content += `}\n\n`;
657
+ }
658
+ else if (type.type === "type") {
659
+ content += `export type ${type.name} = any; // TODO: Define proper type\n\n`;
660
+ }
661
+ });
662
+ // Generate component prop interfaces
663
+ analysis.components.forEach((component) => {
664
+ if (component.props.length > 0) {
665
+ content += `export interface ${component.name}Props {\n`;
666
+ component.props.forEach((prop) => {
667
+ content += ` ${prop}: any; // TODO: Define proper type\n`;
668
+ });
669
+ content += `}\n\n`;
670
+ }
671
+ });
672
+ return content;
673
+ }
674
+ generateBrand(analysis) {
675
+ return `# Brand Guidelines
676
+
677
+ ## Color Palette
678
+ ${analysis.styling.colors.map((color) => `- ${color}`).join("\n")}
679
+
680
+ ## Typography
681
+ ${analysis.styling.fonts.map((font) => `- ${font}`).join("\n")}
682
+
683
+ ## Spacing System
684
+ ${analysis.styling.spacing.map((space) => `- ${space}`).join("\n")}
685
+
686
+ ## Breakpoints
687
+ ${analysis.styling.breakpoints.map((bp) => `- ${bp}`).join("\n")}
688
+
689
+ ## Custom Properties
690
+ ${analysis.styling.customProperties.map((prop) => `- ${prop}`).join("\n")}
691
+
692
+ ## Design System Status
693
+ - **Framework:** ${analysis.styling.framework}
694
+ - **Has Design System:** ${analysis.styling.hasDesignSystem ? "Yes" : "No"}
695
+
696
+ ## Recommendations
697
+ ${analysis.styling.framework === "vanilla"
698
+ ? "- Consider implementing a design system with consistent tokens"
699
+ : ""}
700
+ ${!analysis.styling.hasDesignSystem
701
+ ? "- Consider using a design system like Tailwind CSS or Chakra UI"
702
+ : ""}
703
+ `;
704
+ }
705
+ generateComponentList(analysis) {
706
+ const componentList = {
707
+ groups: analysis.components.reduce((acc, component) => {
708
+ const group = component.group || "default";
709
+ if (!acc[group]) {
710
+ acc[group] = [];
711
+ }
712
+ acc[group].push({
713
+ name: component.name,
714
+ description: `${component.type} component`,
715
+ type: component.type,
716
+ priority: "medium",
717
+ dependencies: component.dependencies,
718
+ tags: [component.type, component.isClient ? "client" : "server"],
719
+ });
720
+ return acc;
721
+ }, {}),
722
+ };
723
+ return JSON.stringify(componentList, null, 2);
724
+ }
725
+ printNextSteps(analysis, generateContext) {
726
+ console.log(chalk_1.default.yellow("\nšŸ“‹ Next Steps:"));
727
+ if (generateContext) {
728
+ console.log(chalk_1.default.gray("1. Review the generated context files in .mycontext/"));
729
+ console.log(chalk_1.default.gray("2. Update the PRD with your specific requirements"));
730
+ console.log(chalk_1.default.gray("3. Refine the types and interfaces"));
731
+ console.log(chalk_1.default.gray("4. Customize the brand guidelines"));
732
+ }
733
+ console.log(chalk_1.default.gray("5. Run 'mycontext generate context' to enhance the context"));
734
+ console.log(chalk_1.default.gray("6. Run 'mycontext generate components-list' to plan new components"));
735
+ console.log(chalk_1.default.gray("7. Run 'mycontext generate-components' to create new components"));
736
+ console.log(chalk_1.default.gray("8. Use 'mycontext promote' to move components to production"));
737
+ }
738
+ }
739
+ exports.AnalyzeCommand = AnalyzeCommand;
740
+ //# sourceMappingURL=analyze.js.map