@wundr.io/cli 1.0.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.
- package/README.md +551 -0
- package/bin/wundr.js +39 -0
- package/dist/ai/ai-service.d.ts +152 -0
- package/dist/ai/ai-service.d.ts.map +1 -0
- package/dist/ai/ai-service.js +430 -0
- package/dist/ai/ai-service.js.map +1 -0
- package/dist/ai/claude-client.d.ts +130 -0
- package/dist/ai/claude-client.d.ts.map +1 -0
- package/dist/ai/claude-client.js +339 -0
- package/dist/ai/claude-client.js.map +1 -0
- package/dist/ai/conversation-manager.d.ts +164 -0
- package/dist/ai/conversation-manager.d.ts.map +1 -0
- package/dist/ai/conversation-manager.js +612 -0
- package/dist/ai/conversation-manager.js.map +1 -0
- package/dist/ai/index.d.ts +5 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +8 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/cli.d.ts +36 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +173 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/ai.d.ts +89 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +735 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/analyze-optimized.d.ts +14 -0
- package/dist/commands/analyze-optimized.d.ts.map +1 -0
- package/dist/commands/analyze-optimized.js +437 -0
- package/dist/commands/analyze-optimized.js.map +1 -0
- package/dist/commands/analyze.d.ts +65 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +435 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/batch.d.ts +71 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +738 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/chat.d.ts +71 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +674 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/claude-init.d.ts +28 -0
- package/dist/commands/claude-init.d.ts.map +1 -0
- package/dist/commands/claude-init.js +587 -0
- package/dist/commands/claude-init.js.map +1 -0
- package/dist/commands/claude-setup.d.ts +32 -0
- package/dist/commands/claude-setup.d.ts.map +1 -0
- package/dist/commands/claude-setup.js +570 -0
- package/dist/commands/claude-setup.js.map +1 -0
- package/dist/commands/computer-setup-commands.d.ts +39 -0
- package/dist/commands/computer-setup-commands.d.ts.map +1 -0
- package/dist/commands/computer-setup-commands.js +563 -0
- package/dist/commands/computer-setup-commands.js.map +1 -0
- package/dist/commands/computer-setup.d.ts +7 -0
- package/dist/commands/computer-setup.d.ts.map +1 -0
- package/dist/commands/computer-setup.js +481 -0
- package/dist/commands/computer-setup.js.map +1 -0
- package/dist/commands/create-command.d.ts +7 -0
- package/dist/commands/create-command.d.ts.map +1 -0
- package/dist/commands/create-command.js +158 -0
- package/dist/commands/create-command.js.map +1 -0
- package/dist/commands/create.d.ts +74 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +556 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/dashboard.d.ts +91 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +537 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/govern.d.ts +70 -0
- package/dist/commands/govern.d.ts.map +1 -0
- package/dist/commands/govern.js +480 -0
- package/dist/commands/govern.js.map +1 -0
- package/dist/commands/init.d.ts +55 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +584 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/performance-optimizer.d.ts +30 -0
- package/dist/commands/performance-optimizer.d.ts.map +1 -0
- package/dist/commands/performance-optimizer.js +649 -0
- package/dist/commands/performance-optimizer.js.map +1 -0
- package/dist/commands/plugins.d.ts +87 -0
- package/dist/commands/plugins.d.ts.map +1 -0
- package/dist/commands/plugins.js +685 -0
- package/dist/commands/plugins.js.map +1 -0
- package/dist/commands/setup.d.ts +29 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +399 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/test-init.d.ts +9 -0
- package/dist/commands/test-init.d.ts.map +1 -0
- package/dist/commands/test-init.js +222 -0
- package/dist/commands/test-init.js.map +1 -0
- package/dist/commands/test.d.ts +25 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +217 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/watch.d.ts +76 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +610 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/context/context-manager.d.ts +155 -0
- package/dist/context/context-manager.d.ts.map +1 -0
- package/dist/context/context-manager.js +383 -0
- package/dist/context/context-manager.js.map +1 -0
- package/dist/context/index.d.ts +3 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +6 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/session-manager.d.ts +207 -0
- package/dist/context/session-manager.d.ts.map +1 -0
- package/dist/context/session-manager.js +682 -0
- package/dist/context/session-manager.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive/interactive-mode.d.ts +76 -0
- package/dist/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/interactive/interactive-mode.js +730 -0
- package/dist/interactive/interactive-mode.js.map +1 -0
- package/dist/nlp/command-mapper.d.ts +174 -0
- package/dist/nlp/command-mapper.d.ts.map +1 -0
- package/dist/nlp/command-mapper.js +623 -0
- package/dist/nlp/command-mapper.js.map +1 -0
- package/dist/nlp/command-parser.d.ts +106 -0
- package/dist/nlp/command-parser.d.ts.map +1 -0
- package/dist/nlp/command-parser.js +416 -0
- package/dist/nlp/command-parser.js.map +1 -0
- package/dist/nlp/index.d.ts +5 -0
- package/dist/nlp/index.d.ts.map +1 -0
- package/dist/nlp/index.js +8 -0
- package/dist/nlp/index.js.map +1 -0
- package/dist/nlp/intent-classifier.d.ts +59 -0
- package/dist/nlp/intent-classifier.d.ts.map +1 -0
- package/dist/nlp/intent-classifier.js +384 -0
- package/dist/nlp/intent-classifier.js.map +1 -0
- package/dist/nlp/intent-parser.d.ts +152 -0
- package/dist/nlp/intent-parser.d.ts.map +1 -0
- package/dist/nlp/intent-parser.js +739 -0
- package/dist/nlp/intent-parser.js.map +1 -0
- package/dist/plugins/plugin-manager.d.ts +120 -0
- package/dist/plugins/plugin-manager.d.ts.map +1 -0
- package/dist/plugins/plugin-manager.js +595 -0
- package/dist/plugins/plugin-manager.js.map +1 -0
- package/dist/types/index.d.ts +224 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/config-manager.d.ts +73 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +339 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/error-handler.d.ts +46 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +169 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/logger.d.ts +25 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +94 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +119 -0
- package/src/ai/ai-service.ts +595 -0
- package/src/ai/claude-client.ts +490 -0
- package/src/ai/conversation-manager.ts +907 -0
- package/src/ai/index.ts +8 -0
- package/src/cli.ts +202 -0
- package/src/commands/ai.ts +995 -0
- package/src/commands/analyze-optimized.ts +641 -0
- package/src/commands/analyze.ts +576 -0
- package/src/commands/batch.ts +935 -0
- package/src/commands/chat.ts +876 -0
- package/src/commands/claude-init.ts +715 -0
- package/src/commands/claude-setup.ts +697 -0
- package/src/commands/computer-setup-commands.ts +709 -0
- package/src/commands/computer-setup.ts +565 -0
- package/src/commands/create-command.ts +175 -0
- package/src/commands/create.ts +727 -0
- package/src/commands/dashboard.ts +691 -0
- package/src/commands/govern.ts +635 -0
- package/src/commands/init.ts +677 -0
- package/src/commands/performance-optimizer.ts +864 -0
- package/src/commands/plugins.ts +848 -0
- package/src/commands/setup.ts +508 -0
- package/src/commands/test-init.ts +242 -0
- package/src/commands/test.ts +264 -0
- package/src/commands/watch.ts +755 -0
- package/src/context/context-manager.ts +546 -0
- package/src/context/index.ts +9 -0
- package/src/context/session-manager.ts +1019 -0
- package/src/index.ts +64 -0
- package/src/interactive/interactive-mode.ts +830 -0
- package/src/nlp/command-mapper.ts +885 -0
- package/src/nlp/command-parser.ts +564 -0
- package/src/nlp/index.ts +4 -0
- package/src/nlp/intent-classifier.ts +458 -0
- package/src/nlp/intent-parser.ts +1101 -0
- package/src/plugins/plugin-manager.ts +744 -0
- package/src/types/index.ts +252 -0
- package/src/types/modules.d.ts +56 -0
- package/src/utils/config-manager.ts +391 -0
- package/src/utils/error-handler.ts +192 -0
- package/src/utils/logger.ts +104 -0
- package/templates/batch/ci-cd.yaml +62 -0
- package/templates/component/{{fileName}}.test.tsx +17 -0
- package/templates/component/{{fileName}}.tsx +21 -0
- package/templates/service/{{fileName}}.ts +98 -0
- package/templates/wundr-test.config.js +0 -0
- package/test-suites/api/health.spec.ts +134 -0
- package/test-suites/helpers/test-config.ts +84 -0
- package/test-suites/ui/accessibility.spec.ts +102 -0
- package/test-suites/ui/smoke.spec.ts +92 -0
|
@@ -0,0 +1,727 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { ConfigManager } from '../utils/config-manager';
|
|
7
|
+
import { PluginManager } from '../plugins/plugin-manager';
|
|
8
|
+
import { logger } from '../utils/logger';
|
|
9
|
+
import { errorHandler } from '../utils/error-handler';
|
|
10
|
+
// import { projectTemplates } from '@wundr/project-templates';
|
|
11
|
+
// TODO: Fix this import - project-templates package needs to be created
|
|
12
|
+
const projectTemplates = {
|
|
13
|
+
createProject: async (options: any) => {
|
|
14
|
+
console.log('Creating project with options:', options);
|
|
15
|
+
// TODO: Implement actual project creation logic
|
|
16
|
+
console.log('Project creation not yet implemented');
|
|
17
|
+
},
|
|
18
|
+
createInteractive: async () => {
|
|
19
|
+
console.log('Interactive project creation not yet implemented');
|
|
20
|
+
// TODO: Implement interactive project creation
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Create commands for generating components, services, and templates
|
|
26
|
+
*/
|
|
27
|
+
export class CreateCommands {
|
|
28
|
+
constructor(
|
|
29
|
+
private program: Command,
|
|
30
|
+
private configManager: ConfigManager,
|
|
31
|
+
private pluginManager: PluginManager
|
|
32
|
+
) {
|
|
33
|
+
this.registerCommands();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private registerCommands(): void {
|
|
37
|
+
const createCmd = this.program
|
|
38
|
+
.command('create')
|
|
39
|
+
.description(
|
|
40
|
+
'create new wundr-compliant projects, components, services, and templates'
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
// Create new project (full wundr-compliant project)
|
|
44
|
+
createCmd
|
|
45
|
+
.command('project <type> [name]')
|
|
46
|
+
.alias('p')
|
|
47
|
+
.description('create a new wundr-compliant project')
|
|
48
|
+
.option('-f, --framework <framework>', 'framework to use')
|
|
49
|
+
.option('-d, --description <description>', 'project description')
|
|
50
|
+
.option('-a, --author <author>', 'project author')
|
|
51
|
+
.option('--no-git', 'skip git initialization')
|
|
52
|
+
.option('--no-install', 'skip dependency installation')
|
|
53
|
+
.option('--typescript', 'use TypeScript', true)
|
|
54
|
+
.option('--testing', 'include testing setup', true)
|
|
55
|
+
.option('--ci', 'include CI/CD workflows', true)
|
|
56
|
+
.option('--docker', 'include Docker configuration')
|
|
57
|
+
.option('-p, --path <path>', 'path to create project in')
|
|
58
|
+
.action(async (type: string, name: string | undefined, options: any) => {
|
|
59
|
+
await this.createProject(type, name, options);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Quick project creation commands
|
|
63
|
+
createCmd
|
|
64
|
+
.command('frontend <name>')
|
|
65
|
+
.description('create a frontend application')
|
|
66
|
+
.option(
|
|
67
|
+
'-f, --framework <framework>',
|
|
68
|
+
'framework (next|react|vue)',
|
|
69
|
+
'next'
|
|
70
|
+
)
|
|
71
|
+
.action(async (name: string, options: any) => {
|
|
72
|
+
await projectTemplates.createProject({
|
|
73
|
+
name,
|
|
74
|
+
type: 'frontend',
|
|
75
|
+
framework: options.framework,
|
|
76
|
+
install: true,
|
|
77
|
+
git: true,
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
createCmd
|
|
82
|
+
.command('backend <name>')
|
|
83
|
+
.description('create a backend API')
|
|
84
|
+
.option(
|
|
85
|
+
'-f, --framework <framework>',
|
|
86
|
+
'framework (fastify|express|nestjs)',
|
|
87
|
+
'fastify'
|
|
88
|
+
)
|
|
89
|
+
.action(async (name: string, options: any) => {
|
|
90
|
+
await projectTemplates.createProject({
|
|
91
|
+
name,
|
|
92
|
+
type: 'backend',
|
|
93
|
+
framework: options.framework,
|
|
94
|
+
install: true,
|
|
95
|
+
git: true,
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
createCmd
|
|
100
|
+
.command('monorepo <name>')
|
|
101
|
+
.description('create a monorepo platform')
|
|
102
|
+
.action(async (name: string) => {
|
|
103
|
+
await projectTemplates.createProject({
|
|
104
|
+
name,
|
|
105
|
+
type: 'monorepo',
|
|
106
|
+
framework: 'turborepo',
|
|
107
|
+
install: true,
|
|
108
|
+
git: true,
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
createCmd
|
|
113
|
+
.command('fullstack <name>')
|
|
114
|
+
.description('create a full-stack application')
|
|
115
|
+
.action(async (name: string) => {
|
|
116
|
+
await projectTemplates.createProject({
|
|
117
|
+
name,
|
|
118
|
+
type: 'monorepo',
|
|
119
|
+
framework: 'turborepo',
|
|
120
|
+
install: true,
|
|
121
|
+
git: true,
|
|
122
|
+
description: 'Full-stack wundr-compliant application',
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Create component
|
|
127
|
+
createCmd
|
|
128
|
+
.command('component <name>')
|
|
129
|
+
.description('create a new component')
|
|
130
|
+
.option('--type <type>', 'component type (react, vue, angular)', 'react')
|
|
131
|
+
.option('--template <template>', 'component template')
|
|
132
|
+
.option('--with-tests', 'generate test files')
|
|
133
|
+
.option('--with-stories', 'generate storybook stories')
|
|
134
|
+
.action(async (name, options) => {
|
|
135
|
+
await this.createComponent(name, options);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Create service
|
|
139
|
+
createCmd
|
|
140
|
+
.command('service <name>')
|
|
141
|
+
.description('create a new service')
|
|
142
|
+
.option(
|
|
143
|
+
'--type <type>',
|
|
144
|
+
'service type (api, worker, microservice)',
|
|
145
|
+
'api'
|
|
146
|
+
)
|
|
147
|
+
.option(
|
|
148
|
+
'--framework <framework>',
|
|
149
|
+
'framework (express, fastify, nest)',
|
|
150
|
+
'express'
|
|
151
|
+
)
|
|
152
|
+
.option('--with-tests', 'generate test files')
|
|
153
|
+
.option('--with-docs', 'generate API documentation')
|
|
154
|
+
.action(async (name, options) => {
|
|
155
|
+
await this.createService(name, options);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Create package
|
|
159
|
+
createCmd
|
|
160
|
+
.command('package <name>')
|
|
161
|
+
.description('create a new package in monorepo')
|
|
162
|
+
.option('--type <type>', 'package type (library, app, tool)', 'library')
|
|
163
|
+
.option('--template <template>', 'package template')
|
|
164
|
+
.option('--public', 'make package public')
|
|
165
|
+
.action(async (name, options) => {
|
|
166
|
+
await this.createPackage(name, options);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Create template
|
|
170
|
+
createCmd
|
|
171
|
+
.command('template <name>')
|
|
172
|
+
.description('create a new template')
|
|
173
|
+
.option('--from <source>', 'create template from existing code')
|
|
174
|
+
.option('--interactive', 'use interactive template creation')
|
|
175
|
+
.action(async (name, options) => {
|
|
176
|
+
await this.createTemplate(name, options);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Create workflow
|
|
180
|
+
createCmd
|
|
181
|
+
.command('workflow <name>')
|
|
182
|
+
.description('create a new workflow or automation')
|
|
183
|
+
.option('--type <type>', 'workflow type (ci, deployment, analysis)', 'ci')
|
|
184
|
+
.option(
|
|
185
|
+
'--platform <platform>',
|
|
186
|
+
'platform (github, gitlab, jenkins)',
|
|
187
|
+
'github'
|
|
188
|
+
)
|
|
189
|
+
.action(async (name, options) => {
|
|
190
|
+
await this.createWorkflow(name, options);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Create config
|
|
194
|
+
createCmd
|
|
195
|
+
.command('config <name>')
|
|
196
|
+
.description('create configuration files')
|
|
197
|
+
.option(
|
|
198
|
+
'--type <type>',
|
|
199
|
+
'config type (eslint, prettier, jest, typescript)'
|
|
200
|
+
)
|
|
201
|
+
.option('--preset <preset>', 'configuration preset')
|
|
202
|
+
.action(async (name, options) => {
|
|
203
|
+
await this.createConfig(name, options);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Create a new wundr-compliant project
|
|
209
|
+
*/
|
|
210
|
+
private async createProject(
|
|
211
|
+
type: string,
|
|
212
|
+
name: string | undefined,
|
|
213
|
+
options: any
|
|
214
|
+
): Promise<void> {
|
|
215
|
+
try {
|
|
216
|
+
// If no name provided, launch interactive mode
|
|
217
|
+
if (!name) {
|
|
218
|
+
await projectTemplates.createInteractive();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Validate project type
|
|
223
|
+
const validTypes = [
|
|
224
|
+
'frontend',
|
|
225
|
+
'backend',
|
|
226
|
+
'fullstack',
|
|
227
|
+
'monorepo',
|
|
228
|
+
'library',
|
|
229
|
+
'cli',
|
|
230
|
+
];
|
|
231
|
+
if (!validTypes.includes(type)) {
|
|
232
|
+
logger.error(`Invalid project type: ${type}`);
|
|
233
|
+
logger.info(`Valid types: ${validTypes.join(', ')}`);
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
logger.info(`Creating ${type} project: ${chalk.cyan(name)}`);
|
|
238
|
+
|
|
239
|
+
// Create project with options
|
|
240
|
+
await projectTemplates.createProject({
|
|
241
|
+
name,
|
|
242
|
+
type: type as any,
|
|
243
|
+
framework: options.framework,
|
|
244
|
+
description: options.description,
|
|
245
|
+
author: options.author,
|
|
246
|
+
git: options.git,
|
|
247
|
+
install: options.install,
|
|
248
|
+
typescript: options.typescript,
|
|
249
|
+
testing: options.testing,
|
|
250
|
+
ci: options.ci,
|
|
251
|
+
docker: options.docker,
|
|
252
|
+
path: options.path,
|
|
253
|
+
});
|
|
254
|
+
} catch (error) {
|
|
255
|
+
throw errorHandler.createError(
|
|
256
|
+
'WUNDR_CREATE_PROJECT_FAILED',
|
|
257
|
+
'Failed to create project',
|
|
258
|
+
{ type, name, options },
|
|
259
|
+
true
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Create a new component
|
|
266
|
+
*/
|
|
267
|
+
private async createComponent(name: string, options: any): Promise<void> {
|
|
268
|
+
try {
|
|
269
|
+
logger.info(`Creating component: ${chalk.cyan(name)}`);
|
|
270
|
+
|
|
271
|
+
const componentData = await this.gatherComponentData(name, options);
|
|
272
|
+
const outputPath = await this.determineOutputPath('components', name);
|
|
273
|
+
|
|
274
|
+
await this.generateFromTemplate('component', componentData, outputPath);
|
|
275
|
+
|
|
276
|
+
if (options.withTests) {
|
|
277
|
+
await this.generateFromTemplate(
|
|
278
|
+
'component-test',
|
|
279
|
+
componentData,
|
|
280
|
+
outputPath
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (options.withStories) {
|
|
285
|
+
await this.generateFromTemplate(
|
|
286
|
+
'component-stories',
|
|
287
|
+
componentData,
|
|
288
|
+
outputPath
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
logger.success(`Component ${name} created successfully at ${outputPath}`);
|
|
293
|
+
} catch (error) {
|
|
294
|
+
throw errorHandler.createError(
|
|
295
|
+
'WUNDR_CREATE_COMPONENT_FAILED',
|
|
296
|
+
'Failed to create component',
|
|
297
|
+
{ name, options },
|
|
298
|
+
true
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Create a new service
|
|
305
|
+
*/
|
|
306
|
+
private async createService(name: string, options: any): Promise<void> {
|
|
307
|
+
try {
|
|
308
|
+
logger.info(`Creating service: ${chalk.cyan(name)}`);
|
|
309
|
+
|
|
310
|
+
const serviceData = await this.gatherServiceData(name, options);
|
|
311
|
+
const outputPath = await this.determineOutputPath('services', name);
|
|
312
|
+
|
|
313
|
+
await this.generateFromTemplate('service', serviceData, outputPath);
|
|
314
|
+
|
|
315
|
+
if (options.withTests) {
|
|
316
|
+
await this.generateFromTemplate(
|
|
317
|
+
'service-test',
|
|
318
|
+
serviceData,
|
|
319
|
+
outputPath
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (options.withDocs) {
|
|
324
|
+
await this.generateApiDocs(serviceData, outputPath);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
logger.success(`Service ${name} created successfully at ${outputPath}`);
|
|
328
|
+
} catch (error) {
|
|
329
|
+
throw errorHandler.createError(
|
|
330
|
+
'WUNDR_CREATE_SERVICE_FAILED',
|
|
331
|
+
'Failed to create service',
|
|
332
|
+
{ name, options },
|
|
333
|
+
true
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Create a new package in monorepo
|
|
340
|
+
*/
|
|
341
|
+
private async createPackage(name: string, options: any): Promise<void> {
|
|
342
|
+
try {
|
|
343
|
+
logger.info(`Creating package: ${chalk.cyan(name)}`);
|
|
344
|
+
|
|
345
|
+
const packageData = await this.gatherPackageData(name, options);
|
|
346
|
+
const outputPath = await this.determinePackagePath(name, options.type);
|
|
347
|
+
|
|
348
|
+
await this.generateFromTemplate('package', packageData, outputPath);
|
|
349
|
+
await this.updateWorkspaceConfig(name, options.type);
|
|
350
|
+
|
|
351
|
+
logger.success(`Package ${name} created successfully at ${outputPath}`);
|
|
352
|
+
} catch (error) {
|
|
353
|
+
throw errorHandler.createError(
|
|
354
|
+
'WUNDR_CREATE_PACKAGE_FAILED',
|
|
355
|
+
'Failed to create package',
|
|
356
|
+
{ name, options },
|
|
357
|
+
true
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Create a new template
|
|
364
|
+
*/
|
|
365
|
+
private async createTemplate(name: string, options: any): Promise<void> {
|
|
366
|
+
try {
|
|
367
|
+
logger.info(`Creating template: ${chalk.cyan(name)}`);
|
|
368
|
+
|
|
369
|
+
if (options.interactive) {
|
|
370
|
+
await this.interactiveTemplateCreation(name);
|
|
371
|
+
} else if (options.from) {
|
|
372
|
+
await this.createTemplateFromSource(name, options.from);
|
|
373
|
+
} else {
|
|
374
|
+
await this.createBlankTemplate(name);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
logger.success(`Template ${name} created successfully`);
|
|
378
|
+
} catch (error) {
|
|
379
|
+
throw errorHandler.createError(
|
|
380
|
+
'WUNDR_CREATE_TEMPLATE_FAILED',
|
|
381
|
+
'Failed to create template',
|
|
382
|
+
{ name, options },
|
|
383
|
+
true
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Create a new workflow
|
|
390
|
+
*/
|
|
391
|
+
private async createWorkflow(name: string, options: any): Promise<void> {
|
|
392
|
+
try {
|
|
393
|
+
logger.info(`Creating workflow: ${chalk.cyan(name)}`);
|
|
394
|
+
|
|
395
|
+
const workflowData = await this.gatherWorkflowData(name, options);
|
|
396
|
+
const outputPath = this.getWorkflowPath(options.platform);
|
|
397
|
+
|
|
398
|
+
await this.generateFromTemplate('workflow', workflowData, outputPath);
|
|
399
|
+
|
|
400
|
+
logger.success(`Workflow ${name} created successfully at ${outputPath}`);
|
|
401
|
+
} catch (error) {
|
|
402
|
+
throw errorHandler.createError(
|
|
403
|
+
'WUNDR_CREATE_WORKFLOW_FAILED',
|
|
404
|
+
'Failed to create workflow',
|
|
405
|
+
{ name, options },
|
|
406
|
+
true
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Create configuration files
|
|
413
|
+
*/
|
|
414
|
+
private async createConfig(name: string, options: any): Promise<void> {
|
|
415
|
+
try {
|
|
416
|
+
logger.info(`Creating config: ${chalk.cyan(name)}`);
|
|
417
|
+
|
|
418
|
+
const configData = await this.gatherConfigData(name, options);
|
|
419
|
+
const outputPath = process.cwd();
|
|
420
|
+
|
|
421
|
+
await this.generateFromTemplate('config', configData, outputPath);
|
|
422
|
+
|
|
423
|
+
logger.success(`Configuration ${name} created successfully`);
|
|
424
|
+
} catch (error) {
|
|
425
|
+
throw errorHandler.createError(
|
|
426
|
+
'WUNDR_CREATE_CONFIG_FAILED',
|
|
427
|
+
'Failed to create configuration',
|
|
428
|
+
{ name, options },
|
|
429
|
+
true
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Data gathering methods
|
|
436
|
+
*/
|
|
437
|
+
private async gatherComponentData(name: string, options: any): Promise<any> {
|
|
438
|
+
return {
|
|
439
|
+
name,
|
|
440
|
+
type: options.type,
|
|
441
|
+
template: options.template,
|
|
442
|
+
className: this.toPascalCase(name),
|
|
443
|
+
fileName: this.toKebabCase(name),
|
|
444
|
+
withTests: options.withTests,
|
|
445
|
+
withStories: options.withStories,
|
|
446
|
+
timestamp: new Date().toISOString(),
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
private async gatherServiceData(name: string, options: any): Promise<any> {
|
|
451
|
+
return {
|
|
452
|
+
name,
|
|
453
|
+
type: options.type,
|
|
454
|
+
framework: options.framework,
|
|
455
|
+
className: this.toPascalCase(name),
|
|
456
|
+
fileName: this.toKebabCase(name),
|
|
457
|
+
withTests: options.withTests,
|
|
458
|
+
withDocs: options.withDocs,
|
|
459
|
+
timestamp: new Date().toISOString(),
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
private async gatherPackageData(name: string, options: any): Promise<any> {
|
|
464
|
+
const packageName = name.startsWith('@') ? name : `@wundr/${name}`;
|
|
465
|
+
|
|
466
|
+
return {
|
|
467
|
+
name: packageName,
|
|
468
|
+
shortName: name,
|
|
469
|
+
type: options.type,
|
|
470
|
+
template: options.template,
|
|
471
|
+
public: options.public,
|
|
472
|
+
className: this.toPascalCase(name),
|
|
473
|
+
fileName: this.toKebabCase(name),
|
|
474
|
+
timestamp: new Date().toISOString(),
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
private async gatherWorkflowData(name: string, options: any): Promise<any> {
|
|
479
|
+
return {
|
|
480
|
+
name,
|
|
481
|
+
type: options.type,
|
|
482
|
+
platform: options.platform,
|
|
483
|
+
fileName: this.toKebabCase(name),
|
|
484
|
+
timestamp: new Date().toISOString(),
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
private async gatherConfigData(name: string, options: any): Promise<any> {
|
|
489
|
+
return {
|
|
490
|
+
name,
|
|
491
|
+
type: options.type,
|
|
492
|
+
preset: options.preset,
|
|
493
|
+
fileName: this.getConfigFileName(name, options.type),
|
|
494
|
+
timestamp: new Date().toISOString(),
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Template generation methods
|
|
500
|
+
*/
|
|
501
|
+
private async generateFromTemplate(
|
|
502
|
+
templateType: string,
|
|
503
|
+
data: any,
|
|
504
|
+
outputPath: string
|
|
505
|
+
): Promise<void> {
|
|
506
|
+
const templatePath = this.getTemplatePath(templateType);
|
|
507
|
+
|
|
508
|
+
if (!(await fs.pathExists(templatePath))) {
|
|
509
|
+
throw new Error(`Template ${templateType} not found`);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
await fs.ensureDir(outputPath);
|
|
513
|
+
|
|
514
|
+
// Copy template files and replace placeholders
|
|
515
|
+
await this.copyTemplateWithReplacements(templatePath, outputPath, data);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
private async copyTemplateWithReplacements(
|
|
519
|
+
srcPath: string,
|
|
520
|
+
destPath: string,
|
|
521
|
+
data: any
|
|
522
|
+
): Promise<void> {
|
|
523
|
+
const files = await fs.readdir(srcPath);
|
|
524
|
+
|
|
525
|
+
for (const file of files) {
|
|
526
|
+
const srcFile = path.join(srcPath, file);
|
|
527
|
+
const destFile = path.join(
|
|
528
|
+
destPath,
|
|
529
|
+
this.replacePlaceholders(file, data)
|
|
530
|
+
);
|
|
531
|
+
|
|
532
|
+
const stat = await fs.stat(srcFile);
|
|
533
|
+
|
|
534
|
+
if (stat.isDirectory()) {
|
|
535
|
+
await fs.ensureDir(destFile);
|
|
536
|
+
await this.copyTemplateWithReplacements(srcFile, destFile, data);
|
|
537
|
+
} else {
|
|
538
|
+
const content = await fs.readFile(srcFile, 'utf8');
|
|
539
|
+
const processedContent = this.replacePlaceholders(content, data);
|
|
540
|
+
await fs.writeFile(destFile, processedContent);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
private replacePlaceholders(content: string, data: any): string {
|
|
546
|
+
let result = content;
|
|
547
|
+
|
|
548
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
549
|
+
const placeholder = new RegExp(`{{${key}}}`, 'g');
|
|
550
|
+
result = result.replace(placeholder, String(value));
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
return result;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Path determination methods
|
|
558
|
+
*/
|
|
559
|
+
private async determineOutputPath(
|
|
560
|
+
category: string,
|
|
561
|
+
name: string
|
|
562
|
+
): Promise<string> {
|
|
563
|
+
const projectRoot = process.cwd();
|
|
564
|
+
const srcPath = path.join(projectRoot, 'src');
|
|
565
|
+
|
|
566
|
+
if (await fs.pathExists(srcPath)) {
|
|
567
|
+
return path.join(srcPath, category, this.toKebabCase(name));
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return path.join(projectRoot, category, this.toKebabCase(name));
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
private async determinePackagePath(
|
|
574
|
+
name: string,
|
|
575
|
+
type: string
|
|
576
|
+
): Promise<string> {
|
|
577
|
+
const projectRoot = process.cwd();
|
|
578
|
+
const packagesPath = path.join(projectRoot, 'packages');
|
|
579
|
+
const appsPath = path.join(projectRoot, 'apps');
|
|
580
|
+
|
|
581
|
+
if (type === 'app' && (await fs.pathExists(appsPath))) {
|
|
582
|
+
return path.join(appsPath, this.toKebabCase(name));
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
return path.join(packagesPath, this.toKebabCase(name));
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
private getWorkflowPath(platform: string): string {
|
|
589
|
+
const paths = {
|
|
590
|
+
github: '.github/workflows',
|
|
591
|
+
gitlab: '.gitlab-ci',
|
|
592
|
+
jenkins: 'jenkins',
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
return paths[platform as keyof typeof paths] || '.github/workflows';
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
private getTemplatePath(templateType: string): string {
|
|
599
|
+
return path.join(__dirname, '../../templates', templateType);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
private getConfigFileName(name: string, type: string): string {
|
|
603
|
+
const fileNames = {
|
|
604
|
+
eslint: '.eslintrc.js',
|
|
605
|
+
prettier: '.prettierrc.js',
|
|
606
|
+
jest: 'jest.config.js',
|
|
607
|
+
typescript: 'tsconfig.json',
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
return fileNames[type as keyof typeof fileNames] || `${name}.config.js`;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Utility methods
|
|
615
|
+
*/
|
|
616
|
+
private toPascalCase(str: string): string {
|
|
617
|
+
return str
|
|
618
|
+
.split(/[-_\s]/)
|
|
619
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
620
|
+
.join('');
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
private toKebabCase(str: string): string {
|
|
624
|
+
return str
|
|
625
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
626
|
+
.replace(/[\s_]+/g, '-')
|
|
627
|
+
.toLowerCase();
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
private async updateWorkspaceConfig(
|
|
631
|
+
name: string,
|
|
632
|
+
type: string
|
|
633
|
+
): Promise<void> {
|
|
634
|
+
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
635
|
+
|
|
636
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
637
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
638
|
+
|
|
639
|
+
if (packageJson.workspaces) {
|
|
640
|
+
const workspace = type === 'app' ? 'apps/*' : 'packages/*';
|
|
641
|
+
if (!packageJson.workspaces.includes(workspace)) {
|
|
642
|
+
packageJson.workspaces.push(workspace);
|
|
643
|
+
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
private async generateApiDocs(
|
|
650
|
+
serviceData: any,
|
|
651
|
+
outputPath: string
|
|
652
|
+
): Promise<void> {
|
|
653
|
+
// Generate API documentation based on service type and framework
|
|
654
|
+
const docsPath = path.join(outputPath, 'docs');
|
|
655
|
+
await fs.ensureDir(docsPath);
|
|
656
|
+
|
|
657
|
+
const apiDoc = `# ${serviceData.name} API Documentation
|
|
658
|
+
|
|
659
|
+
## Overview
|
|
660
|
+
|
|
661
|
+
Service: ${serviceData.name}
|
|
662
|
+
Type: ${serviceData.type}
|
|
663
|
+
Framework: ${serviceData.framework}
|
|
664
|
+
|
|
665
|
+
## Endpoints
|
|
666
|
+
|
|
667
|
+
### GET /health
|
|
668
|
+
Health check endpoint
|
|
669
|
+
|
|
670
|
+
### GET /api/${serviceData.fileName}
|
|
671
|
+
Get ${serviceData.name} data
|
|
672
|
+
|
|
673
|
+
### POST /api/${serviceData.fileName}
|
|
674
|
+
Create new ${serviceData.name}
|
|
675
|
+
|
|
676
|
+
## Authentication
|
|
677
|
+
|
|
678
|
+
[Add authentication details here]
|
|
679
|
+
|
|
680
|
+
## Error Handling
|
|
681
|
+
|
|
682
|
+
[Add error handling information here]
|
|
683
|
+
`;
|
|
684
|
+
|
|
685
|
+
await fs.writeFile(path.join(docsPath, 'api.md'), apiDoc);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
private async interactiveTemplateCreation(name: string): Promise<void> {
|
|
689
|
+
const answers = await inquirer.prompt([
|
|
690
|
+
{
|
|
691
|
+
type: 'input',
|
|
692
|
+
name: 'description',
|
|
693
|
+
message: 'Template description:',
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
type: 'checkbox',
|
|
697
|
+
name: 'features',
|
|
698
|
+
message: 'Template features:',
|
|
699
|
+
choices: [
|
|
700
|
+
'TypeScript',
|
|
701
|
+
'React',
|
|
702
|
+
'Vue',
|
|
703
|
+
'Node.js',
|
|
704
|
+
'Testing',
|
|
705
|
+
'Storybook',
|
|
706
|
+
'Documentation',
|
|
707
|
+
],
|
|
708
|
+
},
|
|
709
|
+
]);
|
|
710
|
+
|
|
711
|
+
// Create template based on answers
|
|
712
|
+
logger.debug('Creating interactive template with:', answers);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
private async createTemplateFromSource(
|
|
716
|
+
name: string,
|
|
717
|
+
sourcePath: string
|
|
718
|
+
): Promise<void> {
|
|
719
|
+
logger.debug(`Creating template ${name} from source: ${sourcePath}`);
|
|
720
|
+
// Implementation for creating template from existing source
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
private async createBlankTemplate(name: string): Promise<void> {
|
|
724
|
+
logger.debug(`Creating blank template: ${name}`);
|
|
725
|
+
// Implementation for creating blank template structure
|
|
726
|
+
}
|
|
727
|
+
}
|