mycontext-cli 2.0.28 → 2.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -14
- package/dist/cli.js +89 -99
- package/dist/cli.js.map +1 -1
- package/dist/commands/generate-components.d.ts +10 -0
- package/dist/commands/generate-components.d.ts.map +1 -1
- package/dist/commands/generate-components.js +300 -3
- package/dist/commands/generate-components.js.map +1 -1
- package/dist/commands/generate-context-files.d.ts +9 -0
- package/dist/commands/generate-context-files.d.ts.map +1 -1
- package/dist/commands/generate-context-files.js +57 -0
- package/dist/commands/generate-context-files.js.map +1 -1
- package/dist/commands/generate.d.ts +5 -0
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +75 -1
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +223 -68
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/preview-components.d.ts +12 -0
- package/dist/commands/preview-components.d.ts.map +1 -0
- package/dist/commands/preview-components.js +122 -0
- package/dist/commands/preview-components.js.map +1 -0
- package/dist/commands/refine-component.d.ts +43 -0
- package/dist/commands/refine-component.d.ts.map +1 -0
- package/dist/commands/refine-component.js +313 -0
- package/dist/commands/refine-component.js.map +1 -0
- package/dist/commands/review-context.d.ts +47 -0
- package/dist/commands/review-context.d.ts.map +1 -0
- package/dist/commands/review-context.js +335 -0
- package/dist/commands/review-context.js.map +1 -0
- package/dist/package.json +11 -2
- package/dist/services/ContextValidator.d.ts +99 -0
- package/dist/services/ContextValidator.d.ts.map +1 -0
- package/dist/services/ContextValidator.js +433 -0
- package/dist/services/ContextValidator.js.map +1 -0
- package/dist/services/MutationLogger.d.ts +54 -0
- package/dist/services/MutationLogger.d.ts.map +1 -0
- package/dist/services/MutationLogger.js +164 -0
- package/dist/services/MutationLogger.js.map +1 -0
- package/dist/services/RegressionRunner.d.ts +49 -0
- package/dist/services/RegressionRunner.d.ts.map +1 -0
- package/dist/services/RegressionRunner.js +285 -0
- package/dist/services/RegressionRunner.js.map +1 -0
- package/dist/services/TriggerLogger.d.ts +101 -0
- package/dist/services/TriggerLogger.d.ts.map +1 -0
- package/dist/services/TriggerLogger.js +263 -0
- package/dist/services/TriggerLogger.js.map +1 -0
- package/dist/templates/instantdb/db.template.ts +14 -0
- package/dist/templates/instantdb/home-client.template.tsx +127 -0
- package/dist/templates/instantdb/page.template.tsx +5 -0
- package/dist/templates/instantdb/perms.template.ts +9 -0
- package/dist/templates/instantdb/schema.template.ts +28 -0
- package/dist/templates/playbooks/instantdb-integration.md +851 -0
- package/dist/templates/playbooks/mpesa-integration.md +652 -0
- package/dist/templates/pm-integration-config.json +20 -0
- package/dist/templates/ui-spec-examples.md +318 -0
- package/dist/templates/ui-spec-templates.json +244 -0
- package/dist/utils/envExampleGenerator.d.ts.map +1 -1
- package/dist/utils/envExampleGenerator.js +9 -3
- package/dist/utils/envExampleGenerator.js.map +1 -1
- package/dist/utils/hybridAIClient.d.ts.map +1 -1
- package/dist/utils/hybridAIClient.js +21 -0
- package/dist/utils/hybridAIClient.js.map +1 -1
- package/dist/utils/openRouterClient.d.ts +10 -0
- package/dist/utils/openRouterClient.d.ts.map +1 -0
- package/dist/utils/openRouterClient.js +61 -0
- package/dist/utils/openRouterClient.js.map +1 -0
- package/package.json +11 -2
|
@@ -46,6 +46,8 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
46
46
|
const fs = __importStar(require("fs-extra"));
|
|
47
47
|
const path = __importStar(require("path"));
|
|
48
48
|
const child_process_1 = require("child_process");
|
|
49
|
+
const review_context_1 = require("./review-context");
|
|
50
|
+
const TriggerLogger_1 = require("../services/TriggerLogger");
|
|
49
51
|
// --- Orchestration in GenerateComponentsCommand ---
|
|
50
52
|
class GenerateComponentsCommand {
|
|
51
53
|
constructor() {
|
|
@@ -53,6 +55,7 @@ class GenerateComponentsCommand {
|
|
|
53
55
|
this.hostedApi = new hostedApiClient_1.HostedApiClient();
|
|
54
56
|
this.architectureEngine = new completeArchitectureEngine_1.CompleteArchitectureEngine();
|
|
55
57
|
this.contextLoader = new unifiedDesignContextLoader_1.UnifiedDesignContextLoader();
|
|
58
|
+
this.triggerLogger = new TriggerLogger_1.TriggerLogger();
|
|
56
59
|
this.contextArtifacts = {
|
|
57
60
|
prd: "",
|
|
58
61
|
types: "",
|
|
@@ -288,15 +291,21 @@ class GenerateComponentsCommand {
|
|
|
288
291
|
}
|
|
289
292
|
// Determine if we're generating a specific group or all components
|
|
290
293
|
const isAll = target === "all" || options.all || options["--all"];
|
|
291
|
-
const
|
|
292
|
-
|
|
294
|
+
const isCoreOnly = target === "core" ||
|
|
295
|
+
options.coreOnly ||
|
|
296
|
+
options["--core-only"];
|
|
297
|
+
const groupName = isAll || isCoreOnly ? undefined : target;
|
|
298
|
+
if (isCoreOnly) {
|
|
299
|
+
await this.generateCoreComponents(options, spinner, userInfo.userId);
|
|
300
|
+
}
|
|
301
|
+
else if (isAll) {
|
|
293
302
|
await this.generateAllComponents(options, spinner, userInfo.userId);
|
|
294
303
|
}
|
|
295
304
|
else if (groupName) {
|
|
296
305
|
await this.generateComponentGroup(groupName, options, spinner, userInfo.userId);
|
|
297
306
|
}
|
|
298
307
|
else {
|
|
299
|
-
throw new Error("Please specify a group name
|
|
308
|
+
throw new Error("Please specify a group name, 'all', or use --core-only to generate components");
|
|
300
309
|
}
|
|
301
310
|
// Optionally run final canvas normalization
|
|
302
311
|
if (options.finalCanvas) {
|
|
@@ -550,6 +559,294 @@ class GenerateComponentsCommand {
|
|
|
550
559
|
catch { }
|
|
551
560
|
}
|
|
552
561
|
}
|
|
562
|
+
async generateCoreComponents(options, spinner, userId) {
|
|
563
|
+
spinner.updateText("Generating core 10 components for validation...");
|
|
564
|
+
// Check if critical gaps are addressed
|
|
565
|
+
const criticalGapsAddressed = await review_context_1.ReviewContextCommand.areCriticalGapsAddressed();
|
|
566
|
+
if (!criticalGapsAddressed) {
|
|
567
|
+
console.log(chalk_1.default.red("❌ Critical gaps must be addressed before generating components"));
|
|
568
|
+
console.log(chalk_1.default.blue("💡 Run 'mycontext review:context' to address critical gaps"));
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
// Read component list
|
|
572
|
+
let componentListPath = ".mycontext/04-component-list.json";
|
|
573
|
+
if (!(await this.fs.exists(componentListPath))) {
|
|
574
|
+
componentListPath = ".mycontext/component-list.json";
|
|
575
|
+
}
|
|
576
|
+
if (!(await this.fs.exists(componentListPath))) {
|
|
577
|
+
componentListPath = "context/component-list.json";
|
|
578
|
+
}
|
|
579
|
+
if (!(await this.fs.exists(componentListPath))) {
|
|
580
|
+
throw new Error("Component list not found. Run 'mycontext generate components-list' first.");
|
|
581
|
+
}
|
|
582
|
+
const componentList = JSON.parse(await this.fs.readFile(componentListPath));
|
|
583
|
+
const groups = this.convertHierarchicalToFlat(componentList);
|
|
584
|
+
if (groups.length === 0) {
|
|
585
|
+
throw new Error("No component groups found in component-list.json");
|
|
586
|
+
}
|
|
587
|
+
// Select first 10 components across all groups
|
|
588
|
+
const coreComponents = [];
|
|
589
|
+
let componentCount = 0;
|
|
590
|
+
const maxCoreComponents = 10;
|
|
591
|
+
for (const group of groups) {
|
|
592
|
+
if (componentCount >= maxCoreComponents)
|
|
593
|
+
break;
|
|
594
|
+
const components = group.components || [];
|
|
595
|
+
for (const component of components) {
|
|
596
|
+
if (componentCount >= maxCoreComponents)
|
|
597
|
+
break;
|
|
598
|
+
coreComponents.push({
|
|
599
|
+
...component,
|
|
600
|
+
groupName: group.name,
|
|
601
|
+
group: group,
|
|
602
|
+
});
|
|
603
|
+
componentCount++;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
if (coreComponents.length === 0) {
|
|
607
|
+
throw new Error("No components found in component-list.json");
|
|
608
|
+
}
|
|
609
|
+
console.log(chalk_1.default.blue(`🎯 Generating ${coreComponents.length} core components for validation`));
|
|
610
|
+
// Ensure shadcn/ui components are available
|
|
611
|
+
await this.ensureShadcnComponentsInstalled(groups, spinner);
|
|
612
|
+
// Ensure form dependencies exist
|
|
613
|
+
await this.ensureFormDeps(spinner);
|
|
614
|
+
// Ensure test scaffold exists (optional)
|
|
615
|
+
if (options.withTests) {
|
|
616
|
+
await this.ensureTestsScaffold(spinner);
|
|
617
|
+
}
|
|
618
|
+
// Create core components directory structure
|
|
619
|
+
const componentsDir = options.output || path.join(".mycontext", "components");
|
|
620
|
+
const mobileDir = path.join(componentsDir, "mobile");
|
|
621
|
+
const desktopDir = path.join(componentsDir, "desktop");
|
|
622
|
+
await this.fs.ensureDir(mobileDir);
|
|
623
|
+
await this.fs.ensureDir(desktopDir);
|
|
624
|
+
let generatedCount = 0;
|
|
625
|
+
// Generate mobile and desktop variants for each core component
|
|
626
|
+
for (const component of coreComponents) {
|
|
627
|
+
spinner.updateText(`Generating ${component.name} (${generatedCount + 1}/${coreComponents.length})...`);
|
|
628
|
+
// Check if component feature is approved
|
|
629
|
+
const featureId = component.name.toLowerCase().replace(/\s+/g, "-");
|
|
630
|
+
const approval = await review_context_1.ReviewContextCommand.getFeatureApproval(featureId);
|
|
631
|
+
if (approval === false) {
|
|
632
|
+
console.log(chalk_1.default.yellow(` ⏭️ Skipping ${component.name} (rejected in review)`));
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
if (approval === null) {
|
|
636
|
+
console.log(chalk_1.default.yellow(` ⚠️ ${component.name} not reviewed yet - generating anyway`));
|
|
637
|
+
}
|
|
638
|
+
// Generate mobile variant
|
|
639
|
+
await this.generateComponentVariant(component, "mobile", mobileDir, options, userId);
|
|
640
|
+
// Generate desktop variant
|
|
641
|
+
await this.generateComponentVariant(component, "desktop", desktopDir, options, userId);
|
|
642
|
+
// Generate tests if requested
|
|
643
|
+
if (options.withTests) {
|
|
644
|
+
await this.generateComponentTest(component, mobileDir);
|
|
645
|
+
await this.generateComponentTest(component, desktopDir);
|
|
646
|
+
}
|
|
647
|
+
generatedCount++;
|
|
648
|
+
}
|
|
649
|
+
// Generate index files for both variants
|
|
650
|
+
await this.generateCoreIndexFiles(coreComponents, mobileDir, desktopDir);
|
|
651
|
+
// Update preview registry
|
|
652
|
+
if (options.updatePreview !== false) {
|
|
653
|
+
await this.updatePreviewRegistry(componentsDir);
|
|
654
|
+
await this.ensurePreviewRoute();
|
|
655
|
+
}
|
|
656
|
+
// Post-generation checks
|
|
657
|
+
if (options.check) {
|
|
658
|
+
await this.runPostGenerationChecks(componentsDir);
|
|
659
|
+
}
|
|
660
|
+
// Open preview if requested
|
|
661
|
+
if (options.openPreview !== false) {
|
|
662
|
+
await this.openPreview();
|
|
663
|
+
}
|
|
664
|
+
console.log(chalk_1.default.green(`✅ Generated ${generatedCount} core components with mobile and desktop variants`));
|
|
665
|
+
console.log(chalk_1.default.blue(`📁 Components saved to: ${componentsDir}/mobile/ and ${componentsDir}/desktop/`));
|
|
666
|
+
console.log(chalk_1.default.yellow(`🔍 Next: Run 'mycontext preview:components' to validate the core components`));
|
|
667
|
+
// Log trigger event
|
|
668
|
+
await this.triggerLogger.logTrigger("component-refinement", `Generated ${generatedCount} core components for validation`, coreComponents.map((c) => c.name), "Core component generation completed");
|
|
669
|
+
}
|
|
670
|
+
async generateComponentVariant(component, variant, outputDir, options, userId) {
|
|
671
|
+
try {
|
|
672
|
+
// Check if user has local AI keys configured
|
|
673
|
+
const hasLocalKeys = this.hasLocalAIKeys();
|
|
674
|
+
let codeResult;
|
|
675
|
+
if (hasLocalKeys) {
|
|
676
|
+
// Use local AI first (user's own keys) - sub-agent orchestration
|
|
677
|
+
const { orchestrator } = await Promise.resolve().then(() => __importStar(require("../agents/orchestrator/SubAgentOrchestrator")));
|
|
678
|
+
// Execute code generation with retry logic
|
|
679
|
+
let retryCount = 0;
|
|
680
|
+
const maxRetries = 3;
|
|
681
|
+
const baseDelay = 2000; // 2 seconds base delay
|
|
682
|
+
while (retryCount <= maxRetries) {
|
|
683
|
+
try {
|
|
684
|
+
console.log(`🔍 DEBUG: About to call orchestrator.executeAgent for CodeGenSubAgent (attempt ${retryCount + 1}/${maxRetries + 1})`);
|
|
685
|
+
// Use stack configuration timeout if available
|
|
686
|
+
const timeout = this.stackConfig?.timeouts?.generation || 60000;
|
|
687
|
+
// Get enriched context for better AI generation
|
|
688
|
+
const { enrichedContext } = await this.contextLoader.loadUnifiedDesignContext();
|
|
689
|
+
const formattedContext = this.contextLoader
|
|
690
|
+
.getContextEnricher()
|
|
691
|
+
.formatContextForModel(enrichedContext);
|
|
692
|
+
const result = await orchestrator.executeAgent("CodeGenSubAgent", {
|
|
693
|
+
componentName: component.name,
|
|
694
|
+
componentDescription: component.description,
|
|
695
|
+
componentType: component.type,
|
|
696
|
+
variant: variant,
|
|
697
|
+
groupName: component.groupName,
|
|
698
|
+
dependencies: component.dependencies || [],
|
|
699
|
+
enrichedContext: formattedContext,
|
|
700
|
+
userId: userId,
|
|
701
|
+
timeout: timeout,
|
|
702
|
+
temperature: options.temperature || 0.7,
|
|
703
|
+
maxTokens: options.maxTokens || 4000,
|
|
704
|
+
});
|
|
705
|
+
if (result && result.code) {
|
|
706
|
+
codeResult = result;
|
|
707
|
+
break; // Success, exit retry loop
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
throw new Error("No code generated");
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
catch (error) {
|
|
714
|
+
console.log(chalk_1.default.yellow(`⚠️ Generation attempt ${retryCount + 1} failed: ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
715
|
+
retryCount++;
|
|
716
|
+
if (retryCount <= maxRetries) {
|
|
717
|
+
const delay = baseDelay * Math.pow(2, retryCount - 1); // Exponential backoff
|
|
718
|
+
console.log(chalk_1.default.gray(` Retrying in ${delay / 1000} seconds...`));
|
|
719
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
if (!codeResult) {
|
|
724
|
+
throw new Error("All generation attempts failed");
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
// No local keys - try hosted API only
|
|
729
|
+
console.log(chalk_1.default.blue("🔧 Using hosted API for component generation..."));
|
|
730
|
+
try {
|
|
731
|
+
const hostedResult = await this.hostedApi.generateComponent(component.description, {
|
|
732
|
+
componentName: component.name,
|
|
733
|
+
model: "mycontext",
|
|
734
|
+
context: {
|
|
735
|
+
prd: this.contextArtifacts.prd,
|
|
736
|
+
types: this.contextArtifacts.types,
|
|
737
|
+
brand: this.contextArtifacts.brand,
|
|
738
|
+
componentList: this.contextArtifacts.compList,
|
|
739
|
+
},
|
|
740
|
+
variant: variant,
|
|
741
|
+
});
|
|
742
|
+
if (hostedResult.success && hostedResult.data) {
|
|
743
|
+
codeResult = {
|
|
744
|
+
code: hostedResult.data,
|
|
745
|
+
metadata: {
|
|
746
|
+
model: "hosted",
|
|
747
|
+
tokens: hostedResult.data.length / 4,
|
|
748
|
+
latency: 600,
|
|
749
|
+
},
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
else {
|
|
753
|
+
throw new Error("Hosted API generation failed");
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
catch (error) {
|
|
757
|
+
console.log(chalk_1.default.red("❌ Hosted API failed"));
|
|
758
|
+
console.log(chalk_1.default.yellow("💡 MyContext requires 100% accuracy - no fallbacks"));
|
|
759
|
+
console.log(chalk_1.default.blue("🔄 Retry options:"));
|
|
760
|
+
console.log(chalk_1.default.gray(" 1. Configure a local AI provider API key"));
|
|
761
|
+
console.log(chalk_1.default.gray(" 2. Check your API key configuration"));
|
|
762
|
+
console.log(chalk_1.default.gray(" 3. Try again later with: mycontext generate components"));
|
|
763
|
+
throw new Error("Hosted API unavailable - configure local AI provider");
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
// Write component file
|
|
767
|
+
const fileName = `${component.name}.tsx`;
|
|
768
|
+
const filePath = path.join(outputDir, fileName);
|
|
769
|
+
// Add variant-specific styling and imports
|
|
770
|
+
const variantCode = this.addVariantSpecificCode(codeResult.code, variant);
|
|
771
|
+
await this.fs.writeFile(filePath, variantCode);
|
|
772
|
+
console.log(chalk_1.default.green(` ✅ Generated ${variant} variant: ${fileName}`));
|
|
773
|
+
}
|
|
774
|
+
catch (error) {
|
|
775
|
+
console.log(chalk_1.default.red(` ❌ Failed to generate ${variant} variant for ${component.name}: ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
776
|
+
throw error;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
addVariantSpecificCode(code, variant) {
|
|
780
|
+
// Add variant-specific styling and responsive behavior
|
|
781
|
+
const variantImports = variant === "mobile"
|
|
782
|
+
? `import { cn } from "@/lib/utils";\n`
|
|
783
|
+
: `import { cn } from "@/lib/utils";\n`;
|
|
784
|
+
const variantStyles = variant === "mobile"
|
|
785
|
+
? `className={cn("min-h-[44px] min-w-[44px] p-2 text-sm", className)}`
|
|
786
|
+
: `className={cn("min-h-[32px] min-w-[32px] p-4 text-base", className)}`;
|
|
787
|
+
// Replace className patterns with variant-specific ones
|
|
788
|
+
let modifiedCode = code.replace(/className=\{cn\([^}]+\)\}/g, variantStyles);
|
|
789
|
+
// Add variant-specific imports if not present
|
|
790
|
+
if (!modifiedCode.includes("import { cn }")) {
|
|
791
|
+
modifiedCode = variantImports + modifiedCode;
|
|
792
|
+
}
|
|
793
|
+
return modifiedCode;
|
|
794
|
+
}
|
|
795
|
+
async generateCoreIndexFiles(coreComponents, mobileDir, desktopDir) {
|
|
796
|
+
// Generate mobile index
|
|
797
|
+
const mobileIndexContent = coreComponents
|
|
798
|
+
.map((comp) => `export { ${comp.name} } from './${comp.name}';`)
|
|
799
|
+
.join("\n");
|
|
800
|
+
await this.fs.writeFile(path.join(mobileDir, "index.ts"), mobileIndexContent);
|
|
801
|
+
// Generate desktop index
|
|
802
|
+
const desktopIndexContent = coreComponents
|
|
803
|
+
.map((comp) => `export { ${comp.name} } from './${comp.name}';`)
|
|
804
|
+
.join("\n");
|
|
805
|
+
await this.fs.writeFile(path.join(desktopDir, "index.ts"), desktopIndexContent);
|
|
806
|
+
console.log(chalk_1.default.green(" ✅ Generated index files for mobile and desktop variants"));
|
|
807
|
+
}
|
|
808
|
+
async openPreview() {
|
|
809
|
+
try {
|
|
810
|
+
// Try to open in browser
|
|
811
|
+
const url = "http://localhost:3000/mycontext-preview";
|
|
812
|
+
// Check if Next.js dev server is running
|
|
813
|
+
try {
|
|
814
|
+
(0, child_process_1.execSync)("curl -s http://localhost:3000 > /dev/null", {
|
|
815
|
+
stdio: "pipe",
|
|
816
|
+
});
|
|
817
|
+
console.log(chalk_1.default.green(`✅ Opening preview at ${url}`));
|
|
818
|
+
// Open in browser
|
|
819
|
+
(0, child_process_1.execSync)(`open ${url}`, { stdio: "pipe" });
|
|
820
|
+
}
|
|
821
|
+
catch {
|
|
822
|
+
console.log(chalk_1.default.yellow("⚠️ Next.js dev server not running"));
|
|
823
|
+
console.log(chalk_1.default.blue("💡 Start your Next.js app with: npm run dev"));
|
|
824
|
+
console.log(chalk_1.default.blue(` Then visit: ${url}`));
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
catch (error) {
|
|
828
|
+
console.log(chalk_1.default.yellow("⚠️ Could not open browser automatically"));
|
|
829
|
+
console.log(chalk_1.default.blue("💡 Manually visit: http://localhost:3000/mycontext-preview"));
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
async runPostGenerationChecks(componentsDir) {
|
|
833
|
+
console.log(chalk_1.default.blue("🔍 Running post-generation checks..."));
|
|
834
|
+
try {
|
|
835
|
+
// TypeScript check
|
|
836
|
+
console.log(chalk_1.default.gray(" Running TypeScript check..."));
|
|
837
|
+
(0, child_process_1.execSync)("npx tsc --noEmit", { stdio: "pipe" });
|
|
838
|
+
console.log(chalk_1.default.green(" ✅ TypeScript check passed"));
|
|
839
|
+
// Lint check
|
|
840
|
+
console.log(chalk_1.default.gray(" Running ESLint..."));
|
|
841
|
+
(0, child_process_1.execSync)("npx eslint .mycontext/components --ext .ts,.tsx", {
|
|
842
|
+
stdio: "pipe",
|
|
843
|
+
});
|
|
844
|
+
console.log(chalk_1.default.green(" ✅ ESLint check passed"));
|
|
845
|
+
}
|
|
846
|
+
catch (error) {
|
|
847
|
+
console.log(chalk_1.default.yellow(" ⚠️ Some checks failed, but components were generated"));
|
|
848
|
+
}
|
|
849
|
+
}
|
|
553
850
|
async generateComponentGroup(groupName, options, spinner, userId) {
|
|
554
851
|
spinner.updateText(`Generating ${groupName} components...`);
|
|
555
852
|
// Read component list
|