@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,848 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { ConfigManager } from '../utils/config-manager';
|
|
6
|
+
import { PluginManager } from '../plugins/plugin-manager';
|
|
7
|
+
import { logger } from '../utils/logger';
|
|
8
|
+
import { errorHandler } from '../utils/error-handler';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Plugin commands for managing CLI extensions
|
|
12
|
+
*/
|
|
13
|
+
export class PluginCommands {
|
|
14
|
+
constructor(
|
|
15
|
+
private program: Command,
|
|
16
|
+
private configManager: ConfigManager,
|
|
17
|
+
private pluginManager: PluginManager
|
|
18
|
+
) {
|
|
19
|
+
this.registerCommands();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private registerCommands(): void {
|
|
23
|
+
const pluginCmd = this.program
|
|
24
|
+
.command('plugin')
|
|
25
|
+
.alias('plugins')
|
|
26
|
+
.description('manage CLI plugins and extensions');
|
|
27
|
+
|
|
28
|
+
// List plugins
|
|
29
|
+
pluginCmd
|
|
30
|
+
.command('list')
|
|
31
|
+
.alias('ls')
|
|
32
|
+
.description('list installed plugins')
|
|
33
|
+
.option('--available', 'show available plugins from registry')
|
|
34
|
+
.option('--enabled-only', 'show only enabled plugins')
|
|
35
|
+
.action(async options => {
|
|
36
|
+
await this.listPlugins(options);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Install plugin
|
|
40
|
+
pluginCmd
|
|
41
|
+
.command('install <plugin>')
|
|
42
|
+
.description('install a plugin')
|
|
43
|
+
.option('--version <version>', 'specific version to install')
|
|
44
|
+
.option('--registry <url>', 'custom registry URL')
|
|
45
|
+
.option('--force', 'force reinstall if already exists')
|
|
46
|
+
.action(async (plugin, options) => {
|
|
47
|
+
await this.installPlugin(plugin, options);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Uninstall plugin
|
|
51
|
+
pluginCmd
|
|
52
|
+
.command('uninstall <plugin>')
|
|
53
|
+
.alias('remove')
|
|
54
|
+
.description('uninstall a plugin')
|
|
55
|
+
.option('--force', 'skip confirmation')
|
|
56
|
+
.action(async (plugin, options) => {
|
|
57
|
+
await this.uninstallPlugin(plugin, options);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Enable plugin
|
|
61
|
+
pluginCmd
|
|
62
|
+
.command('enable <plugin>')
|
|
63
|
+
.description('enable a plugin')
|
|
64
|
+
.action(async plugin => {
|
|
65
|
+
await this.enablePlugin(plugin);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Disable plugin
|
|
69
|
+
pluginCmd
|
|
70
|
+
.command('disable <plugin>')
|
|
71
|
+
.description('disable a plugin')
|
|
72
|
+
.action(async plugin => {
|
|
73
|
+
await this.disablePlugin(plugin);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Plugin info
|
|
77
|
+
pluginCmd
|
|
78
|
+
.command('info <plugin>')
|
|
79
|
+
.description('show plugin information')
|
|
80
|
+
.action(async plugin => {
|
|
81
|
+
await this.showPluginInfo(plugin);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Update plugins
|
|
85
|
+
pluginCmd
|
|
86
|
+
.command('update [plugin]')
|
|
87
|
+
.description('update plugin(s)')
|
|
88
|
+
.option('--all', 'update all plugins')
|
|
89
|
+
.action(async (plugin, options) => {
|
|
90
|
+
await this.updatePlugin(plugin, options);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Create plugin
|
|
94
|
+
pluginCmd
|
|
95
|
+
.command('create <name>')
|
|
96
|
+
.description('create a new plugin')
|
|
97
|
+
.option('--template <template>', 'plugin template', 'basic')
|
|
98
|
+
.option('--interactive', 'create plugin interactively')
|
|
99
|
+
.action(async (name, options) => {
|
|
100
|
+
await this.createPlugin(name, options);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Publish plugin
|
|
104
|
+
pluginCmd
|
|
105
|
+
.command('publish')
|
|
106
|
+
.description('publish plugin to registry')
|
|
107
|
+
.option('--registry <url>', 'registry URL')
|
|
108
|
+
.option('--dry-run', 'show what would be published')
|
|
109
|
+
.action(async options => {
|
|
110
|
+
await this.publishPlugin(options);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Search plugins
|
|
114
|
+
pluginCmd
|
|
115
|
+
.command('search <query>')
|
|
116
|
+
.description('search for plugins')
|
|
117
|
+
.option('--registry <url>', 'registry URL')
|
|
118
|
+
.option('--limit <count>', 'limit results', '20')
|
|
119
|
+
.action(async (query, options) => {
|
|
120
|
+
await this.searchPlugins(query, options);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Plugin development
|
|
124
|
+
pluginCmd.command('dev').description('plugin development tools');
|
|
125
|
+
|
|
126
|
+
pluginCmd
|
|
127
|
+
.command('dev link <path>')
|
|
128
|
+
.description('link local plugin for development')
|
|
129
|
+
.action(async pluginPath => {
|
|
130
|
+
await this.linkPlugin(pluginPath);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
pluginCmd
|
|
134
|
+
.command('dev unlink <plugin>')
|
|
135
|
+
.description('unlink development plugin')
|
|
136
|
+
.action(async plugin => {
|
|
137
|
+
await this.unlinkPlugin(plugin);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
pluginCmd
|
|
141
|
+
.command('dev test <plugin>')
|
|
142
|
+
.description('test a plugin')
|
|
143
|
+
.option('--coverage', 'run with coverage')
|
|
144
|
+
.action(async (plugin, options) => {
|
|
145
|
+
await this.testPlugin(plugin, options);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Plugin configuration
|
|
149
|
+
pluginCmd
|
|
150
|
+
.command('config <plugin>')
|
|
151
|
+
.description('configure plugin settings');
|
|
152
|
+
|
|
153
|
+
pluginCmd
|
|
154
|
+
.command('config <plugin> set <key> <value>')
|
|
155
|
+
.description('set plugin configuration')
|
|
156
|
+
.action(async (plugin, key, value) => {
|
|
157
|
+
await this.setPluginConfig(plugin, key, value);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
pluginCmd
|
|
161
|
+
.command('config <plugin> get [key]')
|
|
162
|
+
.description('get plugin configuration')
|
|
163
|
+
.action(async (plugin, key) => {
|
|
164
|
+
await this.getPluginConfig(plugin, key);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* List installed plugins
|
|
170
|
+
*/
|
|
171
|
+
private async listPlugins(options: any): Promise<void> {
|
|
172
|
+
try {
|
|
173
|
+
if (options.available) {
|
|
174
|
+
await this.listAvailablePlugins();
|
|
175
|
+
} else {
|
|
176
|
+
await this.listInstalledPlugins(options.enabledOnly);
|
|
177
|
+
}
|
|
178
|
+
} catch (error) {
|
|
179
|
+
throw errorHandler.createError(
|
|
180
|
+
'WUNDR_PLUGIN_LIST_FAILED',
|
|
181
|
+
'Failed to list plugins',
|
|
182
|
+
{ options },
|
|
183
|
+
true
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Install a plugin
|
|
190
|
+
*/
|
|
191
|
+
private async installPlugin(plugin: string, options: any): Promise<void> {
|
|
192
|
+
try {
|
|
193
|
+
logger.info(`Installing plugin: ${chalk.cyan(plugin)}`);
|
|
194
|
+
|
|
195
|
+
// Check if plugin already exists
|
|
196
|
+
if (
|
|
197
|
+
!options.force &&
|
|
198
|
+
(await this.pluginManager.isPluginInstalled(plugin))
|
|
199
|
+
) {
|
|
200
|
+
logger.warn(
|
|
201
|
+
`Plugin ${plugin} is already installed. Use --force to reinstall.`
|
|
202
|
+
);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
await this.pluginManager.installPlugin(plugin, {
|
|
207
|
+
version: options.version,
|
|
208
|
+
registry: options.registry,
|
|
209
|
+
force: options.force,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
logger.success(`Plugin ${plugin} installed successfully`);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
throw errorHandler.createError(
|
|
215
|
+
'WUNDR_PLUGIN_INSTALL_FAILED',
|
|
216
|
+
'Failed to install plugin',
|
|
217
|
+
{ plugin, options },
|
|
218
|
+
true
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Uninstall a plugin
|
|
225
|
+
*/
|
|
226
|
+
private async uninstallPlugin(plugin: string, options: any): Promise<void> {
|
|
227
|
+
try {
|
|
228
|
+
if (!(await this.pluginManager.isPluginInstalled(plugin))) {
|
|
229
|
+
logger.warn(`Plugin ${plugin} is not installed`);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (!options.force) {
|
|
234
|
+
const inquirer = await import('inquirer');
|
|
235
|
+
const { confirm } = await inquirer.default.prompt([
|
|
236
|
+
{
|
|
237
|
+
type: 'confirm',
|
|
238
|
+
name: 'confirm',
|
|
239
|
+
message: `Uninstall plugin ${plugin}?`,
|
|
240
|
+
default: false,
|
|
241
|
+
},
|
|
242
|
+
]);
|
|
243
|
+
|
|
244
|
+
if (!confirm) {
|
|
245
|
+
logger.info('Uninstall cancelled');
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
await this.pluginManager.uninstallPlugin(plugin);
|
|
251
|
+
logger.success(`Plugin ${plugin} uninstalled successfully`);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
throw errorHandler.createError(
|
|
254
|
+
'WUNDR_PLUGIN_UNINSTALL_FAILED',
|
|
255
|
+
'Failed to uninstall plugin',
|
|
256
|
+
{ plugin, options },
|
|
257
|
+
true
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Enable a plugin
|
|
264
|
+
*/
|
|
265
|
+
private async enablePlugin(plugin: string): Promise<void> {
|
|
266
|
+
try {
|
|
267
|
+
if (!(await this.pluginManager.isPluginInstalled(plugin))) {
|
|
268
|
+
throw new Error(`Plugin ${plugin} is not installed`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
await this.pluginManager.enablePlugin(plugin);
|
|
272
|
+
logger.success(`Plugin ${plugin} enabled`);
|
|
273
|
+
} catch (error) {
|
|
274
|
+
throw errorHandler.createError(
|
|
275
|
+
'WUNDR_PLUGIN_ENABLE_FAILED',
|
|
276
|
+
'Failed to enable plugin',
|
|
277
|
+
{ plugin },
|
|
278
|
+
true
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Disable a plugin
|
|
285
|
+
*/
|
|
286
|
+
private async disablePlugin(plugin: string): Promise<void> {
|
|
287
|
+
try {
|
|
288
|
+
if (!(await this.pluginManager.isPluginInstalled(plugin))) {
|
|
289
|
+
throw new Error(`Plugin ${plugin} is not installed`);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
await this.pluginManager.disablePlugin(plugin);
|
|
293
|
+
logger.success(`Plugin ${plugin} disabled`);
|
|
294
|
+
} catch (error) {
|
|
295
|
+
throw errorHandler.createError(
|
|
296
|
+
'WUNDR_PLUGIN_DISABLE_FAILED',
|
|
297
|
+
'Failed to disable plugin',
|
|
298
|
+
{ plugin },
|
|
299
|
+
true
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Show plugin information
|
|
306
|
+
*/
|
|
307
|
+
private async showPluginInfo(plugin: string): Promise<void> {
|
|
308
|
+
try {
|
|
309
|
+
const pluginInfo = await this.pluginManager.getPluginInfo(plugin);
|
|
310
|
+
|
|
311
|
+
if (!pluginInfo) {
|
|
312
|
+
logger.warn(`Plugin ${plugin} not found`);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
console.log(chalk.blue(`\nPlugin Information: ${plugin}`));
|
|
317
|
+
console.log(`Name: ${pluginInfo.name}`);
|
|
318
|
+
console.log(`Version: ${pluginInfo.version}`);
|
|
319
|
+
console.log(`Description: ${pluginInfo.description || 'No description'}`);
|
|
320
|
+
console.log(`Author: ${pluginInfo.author || 'Unknown'}`);
|
|
321
|
+
console.log(`Status: ${pluginInfo.enabled ? 'Enabled' : 'Disabled'}`);
|
|
322
|
+
console.log(`Commands: ${pluginInfo.commands?.length || 0}`);
|
|
323
|
+
console.log(`Hooks: ${pluginInfo.hooks?.length || 0}`);
|
|
324
|
+
|
|
325
|
+
if (pluginInfo.dependencies && pluginInfo.dependencies.length > 0) {
|
|
326
|
+
console.log(`Dependencies: ${pluginInfo.dependencies.join(', ')}`);
|
|
327
|
+
}
|
|
328
|
+
} catch (error) {
|
|
329
|
+
throw errorHandler.createError(
|
|
330
|
+
'WUNDR_PLUGIN_INFO_FAILED',
|
|
331
|
+
'Failed to show plugin info',
|
|
332
|
+
{ plugin },
|
|
333
|
+
true
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Update plugin(s)
|
|
340
|
+
*/
|
|
341
|
+
private async updatePlugin(plugin: string, options: any): Promise<void> {
|
|
342
|
+
try {
|
|
343
|
+
if (options.all) {
|
|
344
|
+
logger.info('Updating all plugins...');
|
|
345
|
+
await this.pluginManager.updateAllPlugins();
|
|
346
|
+
logger.success('All plugins updated');
|
|
347
|
+
} else if (plugin) {
|
|
348
|
+
logger.info(`Updating plugin: ${chalk.cyan(plugin)}`);
|
|
349
|
+
await this.pluginManager.updatePlugin(plugin);
|
|
350
|
+
logger.success(`Plugin ${plugin} updated`);
|
|
351
|
+
} else {
|
|
352
|
+
throw new Error('Specify a plugin name or use --all');
|
|
353
|
+
}
|
|
354
|
+
} catch (error) {
|
|
355
|
+
throw errorHandler.createError(
|
|
356
|
+
'WUNDR_PLUGIN_UPDATE_FAILED',
|
|
357
|
+
'Failed to update plugin(s)',
|
|
358
|
+
{ plugin, options },
|
|
359
|
+
true
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Create a new plugin
|
|
366
|
+
*/
|
|
367
|
+
private async createPlugin(name: string, options: any): Promise<void> {
|
|
368
|
+
try {
|
|
369
|
+
logger.info(`Creating plugin: ${chalk.cyan(name)}`);
|
|
370
|
+
|
|
371
|
+
let pluginConfig: any;
|
|
372
|
+
|
|
373
|
+
if (options.interactive) {
|
|
374
|
+
pluginConfig = await this.createInteractivePlugin(name);
|
|
375
|
+
} else {
|
|
376
|
+
pluginConfig = await this.createPluginFromTemplate(
|
|
377
|
+
name,
|
|
378
|
+
options.template
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const pluginPath = path.join(process.cwd(), name);
|
|
383
|
+
await this.generatePluginStructure(pluginPath, pluginConfig);
|
|
384
|
+
|
|
385
|
+
logger.success(`Plugin ${name} created at ${pluginPath}`);
|
|
386
|
+
logger.info('Next steps:');
|
|
387
|
+
logger.info(` cd ${name}`);
|
|
388
|
+
logger.info(' npm install');
|
|
389
|
+
logger.info(' wundr plugin dev link .');
|
|
390
|
+
} catch (error) {
|
|
391
|
+
throw errorHandler.createError(
|
|
392
|
+
'WUNDR_PLUGIN_CREATE_FAILED',
|
|
393
|
+
'Failed to create plugin',
|
|
394
|
+
{ name, options },
|
|
395
|
+
true
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Publish plugin to registry
|
|
402
|
+
*/
|
|
403
|
+
private async publishPlugin(options: any): Promise<void> {
|
|
404
|
+
try {
|
|
405
|
+
logger.info('Publishing plugin...');
|
|
406
|
+
|
|
407
|
+
if (options.dryRun) {
|
|
408
|
+
logger.info('Dry run - would publish:');
|
|
409
|
+
// Show what would be published
|
|
410
|
+
} else {
|
|
411
|
+
await this.pluginManager.publishPlugin({
|
|
412
|
+
registry: options.registry,
|
|
413
|
+
});
|
|
414
|
+
logger.success('Plugin published successfully');
|
|
415
|
+
}
|
|
416
|
+
} catch (error) {
|
|
417
|
+
throw errorHandler.createError(
|
|
418
|
+
'WUNDR_PLUGIN_PUBLISH_FAILED',
|
|
419
|
+
'Failed to publish plugin',
|
|
420
|
+
{ options },
|
|
421
|
+
true
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Search for plugins
|
|
428
|
+
*/
|
|
429
|
+
private async searchPlugins(query: string, options: any): Promise<void> {
|
|
430
|
+
try {
|
|
431
|
+
logger.info(`Searching for plugins: ${chalk.cyan(query)}`);
|
|
432
|
+
|
|
433
|
+
const results = await this.pluginManager.searchPlugins(query, {
|
|
434
|
+
registry: options.registry,
|
|
435
|
+
limit: parseInt(options.limit),
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
if (results.length === 0) {
|
|
439
|
+
logger.info('No plugins found');
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
console.log(`\nFound ${results.length} plugin(s):`);
|
|
444
|
+
console.table(
|
|
445
|
+
results.map(plugin => ({
|
|
446
|
+
Name: plugin.name,
|
|
447
|
+
Version: plugin.version,
|
|
448
|
+
Description: plugin.description || 'No description',
|
|
449
|
+
Downloads: plugin.downloads || 0,
|
|
450
|
+
Updated: plugin.updated
|
|
451
|
+
? new Date(plugin.updated).toLocaleDateString()
|
|
452
|
+
: 'Unknown',
|
|
453
|
+
}))
|
|
454
|
+
);
|
|
455
|
+
} catch (error) {
|
|
456
|
+
throw errorHandler.createError(
|
|
457
|
+
'WUNDR_PLUGIN_SEARCH_FAILED',
|
|
458
|
+
'Failed to search plugins',
|
|
459
|
+
{ query, options },
|
|
460
|
+
true
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Link local plugin for development
|
|
467
|
+
*/
|
|
468
|
+
private async linkPlugin(pluginPath: string): Promise<void> {
|
|
469
|
+
try {
|
|
470
|
+
const absolutePath = path.resolve(pluginPath);
|
|
471
|
+
|
|
472
|
+
if (!(await fs.pathExists(absolutePath))) {
|
|
473
|
+
throw new Error(`Plugin path does not exist: ${absolutePath}`);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
await this.pluginManager.linkPlugin(absolutePath);
|
|
477
|
+
logger.success(`Plugin linked: ${absolutePath}`);
|
|
478
|
+
} catch (error) {
|
|
479
|
+
throw errorHandler.createError(
|
|
480
|
+
'WUNDR_PLUGIN_LINK_FAILED',
|
|
481
|
+
'Failed to link plugin',
|
|
482
|
+
{ pluginPath },
|
|
483
|
+
true
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Unlink development plugin
|
|
490
|
+
*/
|
|
491
|
+
private async unlinkPlugin(plugin: string): Promise<void> {
|
|
492
|
+
try {
|
|
493
|
+
await this.pluginManager.unlinkPlugin(plugin);
|
|
494
|
+
logger.success(`Plugin unlinked: ${plugin}`);
|
|
495
|
+
} catch (error) {
|
|
496
|
+
throw errorHandler.createError(
|
|
497
|
+
'WUNDR_PLUGIN_UNLINK_FAILED',
|
|
498
|
+
'Failed to unlink plugin',
|
|
499
|
+
{ plugin },
|
|
500
|
+
true
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Test a plugin
|
|
507
|
+
*/
|
|
508
|
+
private async testPlugin(plugin: string, options: any): Promise<void> {
|
|
509
|
+
try {
|
|
510
|
+
logger.info(`Testing plugin: ${chalk.cyan(plugin)}`);
|
|
511
|
+
|
|
512
|
+
await this.pluginManager.testPlugin(plugin, {
|
|
513
|
+
coverage: options.coverage,
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
logger.success(`Plugin ${plugin} tests passed`);
|
|
517
|
+
} catch (error) {
|
|
518
|
+
throw errorHandler.createError(
|
|
519
|
+
'WUNDR_PLUGIN_TEST_FAILED',
|
|
520
|
+
'Failed to test plugin',
|
|
521
|
+
{ plugin, options },
|
|
522
|
+
true
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Set plugin configuration
|
|
529
|
+
*/
|
|
530
|
+
private async setPluginConfig(
|
|
531
|
+
plugin: string,
|
|
532
|
+
key: string,
|
|
533
|
+
value: string
|
|
534
|
+
): Promise<void> {
|
|
535
|
+
try {
|
|
536
|
+
await this.pluginManager.setPluginConfig(plugin, key, value);
|
|
537
|
+
logger.success(
|
|
538
|
+
`Plugin configuration updated: ${plugin}.${key} = ${value}`
|
|
539
|
+
);
|
|
540
|
+
} catch (error) {
|
|
541
|
+
throw errorHandler.createError(
|
|
542
|
+
'WUNDR_PLUGIN_CONFIG_SET_FAILED',
|
|
543
|
+
'Failed to set plugin configuration',
|
|
544
|
+
{ plugin, key, value },
|
|
545
|
+
true
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Get plugin configuration
|
|
552
|
+
*/
|
|
553
|
+
private async getPluginConfig(plugin: string, key?: string): Promise<void> {
|
|
554
|
+
try {
|
|
555
|
+
if (key) {
|
|
556
|
+
const value = await this.pluginManager.getPluginConfig(plugin, key);
|
|
557
|
+
console.log(`${key}: ${value}`);
|
|
558
|
+
} else {
|
|
559
|
+
const config = await this.pluginManager.getPluginConfig(plugin);
|
|
560
|
+
console.log(JSON.stringify(config, null, 2));
|
|
561
|
+
}
|
|
562
|
+
} catch (error) {
|
|
563
|
+
throw errorHandler.createError(
|
|
564
|
+
'WUNDR_PLUGIN_CONFIG_GET_FAILED',
|
|
565
|
+
'Failed to get plugin configuration',
|
|
566
|
+
{ plugin, key },
|
|
567
|
+
true
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Helper methods for plugin operations
|
|
574
|
+
*/
|
|
575
|
+
private async listInstalledPlugins(
|
|
576
|
+
enabledOnly: boolean = false
|
|
577
|
+
): Promise<void> {
|
|
578
|
+
const plugins = await this.pluginManager.getInstalledPlugins();
|
|
579
|
+
const filteredPlugins = enabledOnly
|
|
580
|
+
? plugins.filter(p => p.enabled)
|
|
581
|
+
: plugins;
|
|
582
|
+
|
|
583
|
+
if (filteredPlugins.length === 0) {
|
|
584
|
+
logger.info(
|
|
585
|
+
enabledOnly ? 'No enabled plugins found' : 'No plugins installed'
|
|
586
|
+
);
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
logger.info(
|
|
591
|
+
`${enabledOnly ? 'Enabled plugins' : 'Installed plugins'} (${filteredPlugins.length}):`
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
const pluginData = filteredPlugins.map(plugin => ({
|
|
595
|
+
Name: plugin.name,
|
|
596
|
+
Version: plugin.version,
|
|
597
|
+
Status: plugin.enabled ? '✅ Enabled' : '❌ Disabled',
|
|
598
|
+
Commands: plugin.commands?.length || 0,
|
|
599
|
+
Description: plugin.description || 'No description',
|
|
600
|
+
}));
|
|
601
|
+
|
|
602
|
+
console.table(pluginData);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
private async listAvailablePlugins(): Promise<void> {
|
|
606
|
+
const plugins = await this.pluginManager.getAvailablePlugins();
|
|
607
|
+
|
|
608
|
+
if (plugins.length === 0) {
|
|
609
|
+
logger.info('No plugins available in registry');
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
logger.info(`Available plugins (${plugins.length}):`);
|
|
614
|
+
|
|
615
|
+
const pluginData = plugins.map(plugin => ({
|
|
616
|
+
Name: plugin.name,
|
|
617
|
+
Version: plugin.version,
|
|
618
|
+
Downloads: plugin.downloads || 0,
|
|
619
|
+
Updated: plugin.updated
|
|
620
|
+
? new Date(plugin.updated).toLocaleDateString()
|
|
621
|
+
: 'Unknown',
|
|
622
|
+
Description: plugin.description || 'No description',
|
|
623
|
+
}));
|
|
624
|
+
|
|
625
|
+
console.table(pluginData);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
private async createInteractivePlugin(name: string): Promise<any> {
|
|
629
|
+
const inquirer = await import('inquirer');
|
|
630
|
+
|
|
631
|
+
return await inquirer.default.prompt([
|
|
632
|
+
{
|
|
633
|
+
type: 'input',
|
|
634
|
+
name: 'description',
|
|
635
|
+
message: 'Plugin description:',
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
type: 'input',
|
|
639
|
+
name: 'author',
|
|
640
|
+
message: 'Author name:',
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
type: 'input',
|
|
644
|
+
name: 'version',
|
|
645
|
+
message: 'Initial version:',
|
|
646
|
+
default: '1.0.0',
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
type: 'checkbox',
|
|
650
|
+
name: 'features',
|
|
651
|
+
message: 'Plugin features:',
|
|
652
|
+
choices: [
|
|
653
|
+
'Commands',
|
|
654
|
+
'Hooks',
|
|
655
|
+
'Configuration',
|
|
656
|
+
'Templates',
|
|
657
|
+
'Middleware',
|
|
658
|
+
],
|
|
659
|
+
},
|
|
660
|
+
]);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
private async createPluginFromTemplate(
|
|
664
|
+
name: string,
|
|
665
|
+
template: string
|
|
666
|
+
): Promise<any> {
|
|
667
|
+
const templates: Record<string, any> = {
|
|
668
|
+
basic: {
|
|
669
|
+
description: `A basic Wundr plugin: ${name}`,
|
|
670
|
+
features: ['Commands'],
|
|
671
|
+
},
|
|
672
|
+
advanced: {
|
|
673
|
+
description: `An advanced Wundr plugin: ${name}`,
|
|
674
|
+
features: ['Commands', 'Hooks', 'Configuration'],
|
|
675
|
+
},
|
|
676
|
+
template: {
|
|
677
|
+
description: `A template-based Wundr plugin: ${name}`,
|
|
678
|
+
features: ['Templates', 'Commands'],
|
|
679
|
+
},
|
|
680
|
+
};
|
|
681
|
+
|
|
682
|
+
return templates[template] || templates['basic'];
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
private async generatePluginStructure(
|
|
686
|
+
pluginPath: string,
|
|
687
|
+
config: any
|
|
688
|
+
): Promise<void> {
|
|
689
|
+
await fs.ensureDir(pluginPath);
|
|
690
|
+
|
|
691
|
+
// Create package.json
|
|
692
|
+
const packageJson = {
|
|
693
|
+
name: path.basename(pluginPath),
|
|
694
|
+
version: config.version || '1.0.0',
|
|
695
|
+
description: config.description,
|
|
696
|
+
main: 'dist/index.js',
|
|
697
|
+
types: 'dist/index.d.ts',
|
|
698
|
+
files: ['dist'],
|
|
699
|
+
scripts: {
|
|
700
|
+
build: 'tsc',
|
|
701
|
+
dev: 'tsc --watch',
|
|
702
|
+
test: 'jest',
|
|
703
|
+
},
|
|
704
|
+
peerDependencies: {
|
|
705
|
+
'@wundr/cli': '^1.0.0',
|
|
706
|
+
},
|
|
707
|
+
devDependencies: {
|
|
708
|
+
typescript: '^5.0.0',
|
|
709
|
+
'@types/node': '^20.0.0',
|
|
710
|
+
jest: '^29.0.0',
|
|
711
|
+
},
|
|
712
|
+
wundr: {
|
|
713
|
+
plugin: true,
|
|
714
|
+
commands: config.features?.includes('Commands') || false,
|
|
715
|
+
hooks: config.features?.includes('Hooks') || false,
|
|
716
|
+
templates: config.features?.includes('Templates') || false,
|
|
717
|
+
},
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
await fs.writeJson(path.join(pluginPath, 'package.json'), packageJson, {
|
|
721
|
+
spaces: 2,
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
// Create TypeScript config
|
|
725
|
+
const tsConfig = {
|
|
726
|
+
compilerOptions: {
|
|
727
|
+
target: 'ES2020',
|
|
728
|
+
module: 'CommonJS',
|
|
729
|
+
outDir: './dist',
|
|
730
|
+
rootDir: './src',
|
|
731
|
+
strict: true,
|
|
732
|
+
esModuleInterop: true,
|
|
733
|
+
skipLibCheck: true,
|
|
734
|
+
forceConsistentCasingInFileNames: true,
|
|
735
|
+
declaration: true,
|
|
736
|
+
declarationMap: true,
|
|
737
|
+
sourceMap: true,
|
|
738
|
+
},
|
|
739
|
+
include: ['src/**/*'],
|
|
740
|
+
exclude: ['node_modules', 'dist'],
|
|
741
|
+
};
|
|
742
|
+
|
|
743
|
+
await fs.writeJson(path.join(pluginPath, 'tsconfig.json'), tsConfig, {
|
|
744
|
+
spaces: 2,
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
// Create source directory and files
|
|
748
|
+
const srcDir = path.join(pluginPath, 'src');
|
|
749
|
+
await fs.ensureDir(srcDir);
|
|
750
|
+
|
|
751
|
+
// Create main plugin file
|
|
752
|
+
const pluginCode = this.generatePluginCode(
|
|
753
|
+
path.basename(pluginPath),
|
|
754
|
+
config
|
|
755
|
+
);
|
|
756
|
+
await fs.writeFile(path.join(srcDir, 'index.ts'), pluginCode);
|
|
757
|
+
|
|
758
|
+
// Create README
|
|
759
|
+
const readme = this.generatePluginReadme(path.basename(pluginPath), config);
|
|
760
|
+
await fs.writeFile(path.join(pluginPath, 'README.md'), readme);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
private generatePluginCode(name: string, config: any): string {
|
|
764
|
+
return `import { Plugin, PluginContext } from '@wundr/cli';
|
|
765
|
+
|
|
766
|
+
export default class ${this.toPascalCase(name)}Plugin implements Plugin {
|
|
767
|
+
name = '${name}';
|
|
768
|
+
version = '${config.version || '1.0.0'}';
|
|
769
|
+
description = '${config.description}';
|
|
770
|
+
|
|
771
|
+
async activate(context: PluginContext): Promise<void> {
|
|
772
|
+
// Plugin activation logic
|
|
773
|
+
context.logger.info('${name} plugin activated');
|
|
774
|
+
|
|
775
|
+
${config.features?.includes('Commands') ? this.generateCommandCode(name) : ''}
|
|
776
|
+
${config.features?.includes('Hooks') ? this.generateHookCode(name) : ''}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
async deactivate(): Promise<void> {
|
|
780
|
+
// Plugin deactivation logic
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
`;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
private generateCommandCode(name: string): string {
|
|
787
|
+
return `
|
|
788
|
+
// Register commands
|
|
789
|
+
context.registerCommand({
|
|
790
|
+
name: '${name}',
|
|
791
|
+
description: '${name} plugin command',
|
|
792
|
+
action: async (args, options, ctx) => {
|
|
793
|
+
ctx.logger.info('${name} command executed');
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
`;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
private generateHookCode(name: string): string {
|
|
800
|
+
return `
|
|
801
|
+
// Register hooks
|
|
802
|
+
context.registerHook({
|
|
803
|
+
event: 'before-command',
|
|
804
|
+
handler: async (data, ctx) => {
|
|
805
|
+
ctx.logger.debug('${name} hook: before-command');
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
`;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
private generatePluginReadme(name: string, config: any): string {
|
|
812
|
+
return `# ${name}
|
|
813
|
+
|
|
814
|
+
${config.description}
|
|
815
|
+
|
|
816
|
+
## Installation
|
|
817
|
+
|
|
818
|
+
\`\`\`bash
|
|
819
|
+
wundr plugin install ${name}
|
|
820
|
+
\`\`\`
|
|
821
|
+
|
|
822
|
+
## Usage
|
|
823
|
+
|
|
824
|
+
\`\`\`bash
|
|
825
|
+
wundr ${name}
|
|
826
|
+
\`\`\`
|
|
827
|
+
|
|
828
|
+
## Development
|
|
829
|
+
|
|
830
|
+
\`\`\`bash
|
|
831
|
+
npm install
|
|
832
|
+
npm run build
|
|
833
|
+
wundr plugin dev link .
|
|
834
|
+
\`\`\`
|
|
835
|
+
|
|
836
|
+
## License
|
|
837
|
+
|
|
838
|
+
MIT
|
|
839
|
+
`;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
private toPascalCase(str: string): string {
|
|
843
|
+
return str
|
|
844
|
+
.split(/[-_\s]/)
|
|
845
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
846
|
+
.join('');
|
|
847
|
+
}
|
|
848
|
+
}
|