@wundr.io/cli 1.0.11 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/bin/wundr.js +8 -4
  2. package/package.json +23 -23
  3. package/src/ai/ai-service.ts +16 -17
  4. package/src/ai/claude-client.ts +16 -16
  5. package/src/ai/conversation-manager.ts +29 -29
  6. package/src/cli.ts +4 -4
  7. package/src/commands/ai.ts +246 -78
  8. package/src/commands/alignment.ts +74 -74
  9. package/src/commands/analyze-optimized.ts +111 -78
  10. package/src/commands/analyze.ts +14 -14
  11. package/src/commands/batch.ts +179 -42
  12. package/src/commands/chat.ts +37 -30
  13. package/src/commands/claude-init.ts +41 -45
  14. package/src/commands/claude-setup.ts +204 -119
  15. package/src/commands/computer-setup.ts +85 -43
  16. package/src/commands/create-command.ts +4 -4
  17. package/src/commands/create.ts +27 -27
  18. package/src/commands/dashboard.ts +24 -24
  19. package/src/commands/govern.ts +25 -25
  20. package/src/commands/governance.ts +34 -34
  21. package/src/commands/guardian.ts +56 -56
  22. package/src/commands/init.ts +25 -22
  23. package/src/commands/orchestrator.ts +68 -41
  24. package/src/commands/performance-optimizer.ts +34 -35
  25. package/src/commands/plugins.ts +27 -27
  26. package/src/commands/project-update.ts +175 -72
  27. package/src/commands/rag.ts +185 -78
  28. package/src/commands/session.ts +35 -35
  29. package/src/commands/setup.ts +40 -344
  30. package/src/commands/test-init.ts +3 -3
  31. package/src/commands/test.ts +4 -4
  32. package/src/commands/watch.ts +28 -29
  33. package/src/commands/worktree.ts +49 -49
  34. package/src/context/context-manager.ts +10 -10
  35. package/src/context/session-manager.ts +41 -41
  36. package/src/framework/command-interface.ts +520 -0
  37. package/src/framework/command-registry.ts +942 -0
  38. package/src/framework/completion-exporter.ts +383 -0
  39. package/src/framework/debug-logger.ts +519 -0
  40. package/src/framework/error-handler.ts +867 -0
  41. package/src/framework/help-generator.ts +540 -0
  42. package/src/framework/index.ts +169 -0
  43. package/src/framework/interactive-repl.ts +703 -0
  44. package/src/framework/output-formatter.ts +834 -0
  45. package/src/framework/progress-manager.ts +539 -0
  46. package/src/index.ts +4 -4
  47. package/src/interactive/interactive-mode.ts +16 -16
  48. package/src/lib/conflict-resolution.ts +799 -9
  49. package/src/lib/merge-strategy.ts +529 -7
  50. package/src/lib/safety-mechanisms.ts +422 -18
  51. package/src/lib/state-detection.ts +1015 -13
  52. package/src/nlp/command-mapper.ts +29 -29
  53. package/src/nlp/command-parser.ts +17 -17
  54. package/src/nlp/intent-classifier.ts +7 -7
  55. package/src/nlp/intent-parser.ts +54 -52
  56. package/src/plugins/plugin-manager.ts +61 -39
  57. package/src/tests/computer-setup-integration.test.ts +46 -15
  58. package/src/types/modules.d.ts +424 -1
  59. package/src/utils/backup-rollback-manager.ts +11 -8
  60. package/src/utils/config-manager.ts +3 -3
  61. package/src/utils/error-handler.ts +2 -2
  62. package/src/utils/logger.ts +22 -22
  63. package/templates/batch/ci-cd.yaml +7 -7
  64. package/test-suites/api/health.spec.ts +20 -23
  65. package/test-suites/helpers/test-config.ts +14 -13
  66. package/test-suites/ui/accessibility.spec.ts +27 -22
  67. package/test-suites/ui/smoke.spec.ts +26 -21
  68. package/LICENSE +0 -21
  69. package/dist/ai/ai-service.d.ts +0 -152
  70. package/dist/ai/ai-service.d.ts.map +0 -1
  71. package/dist/ai/ai-service.js +0 -430
  72. package/dist/ai/ai-service.js.map +0 -1
  73. package/dist/ai/claude-client.d.ts +0 -130
  74. package/dist/ai/claude-client.d.ts.map +0 -1
  75. package/dist/ai/claude-client.js +0 -340
  76. package/dist/ai/claude-client.js.map +0 -1
  77. package/dist/ai/conversation-manager.d.ts +0 -164
  78. package/dist/ai/conversation-manager.d.ts.map +0 -1
  79. package/dist/ai/conversation-manager.js +0 -614
  80. package/dist/ai/conversation-manager.js.map +0 -1
  81. package/dist/ai/index.d.ts +0 -5
  82. package/dist/ai/index.d.ts.map +0 -1
  83. package/dist/ai/index.js +0 -8
  84. package/dist/ai/index.js.map +0 -1
  85. package/dist/cli.d.ts +0 -36
  86. package/dist/cli.d.ts.map +0 -1
  87. package/dist/cli.js +0 -192
  88. package/dist/cli.js.map +0 -1
  89. package/dist/commands/ai.d.ts +0 -89
  90. package/dist/commands/ai.d.ts.map +0 -1
  91. package/dist/commands/ai.js +0 -799
  92. package/dist/commands/ai.js.map +0 -1
  93. package/dist/commands/alignment.d.ts +0 -78
  94. package/dist/commands/alignment.d.ts.map +0 -1
  95. package/dist/commands/alignment.js +0 -817
  96. package/dist/commands/alignment.js.map +0 -1
  97. package/dist/commands/analyze-optimized.d.ts +0 -14
  98. package/dist/commands/analyze-optimized.d.ts.map +0 -1
  99. package/dist/commands/analyze-optimized.js +0 -600
  100. package/dist/commands/analyze-optimized.js.map +0 -1
  101. package/dist/commands/analyze.d.ts +0 -65
  102. package/dist/commands/analyze.d.ts.map +0 -1
  103. package/dist/commands/analyze.js +0 -435
  104. package/dist/commands/analyze.js.map +0 -1
  105. package/dist/commands/batch.d.ts +0 -71
  106. package/dist/commands/batch.d.ts.map +0 -1
  107. package/dist/commands/batch.js +0 -738
  108. package/dist/commands/batch.js.map +0 -1
  109. package/dist/commands/chat.d.ts +0 -71
  110. package/dist/commands/chat.d.ts.map +0 -1
  111. package/dist/commands/chat.js +0 -674
  112. package/dist/commands/chat.js.map +0 -1
  113. package/dist/commands/claude-init.d.ts +0 -28
  114. package/dist/commands/claude-init.d.ts.map +0 -1
  115. package/dist/commands/claude-init.js +0 -591
  116. package/dist/commands/claude-init.js.map +0 -1
  117. package/dist/commands/claude-setup.d.ts +0 -119
  118. package/dist/commands/claude-setup.d.ts.map +0 -1
  119. package/dist/commands/claude-setup.js +0 -1073
  120. package/dist/commands/claude-setup.js.map +0 -1
  121. package/dist/commands/computer-setup-commands.d.ts +0 -53
  122. package/dist/commands/computer-setup-commands.d.ts.map +0 -1
  123. package/dist/commands/computer-setup-commands.js +0 -705
  124. package/dist/commands/computer-setup-commands.js.map +0 -1
  125. package/dist/commands/computer-setup.d.ts +0 -7
  126. package/dist/commands/computer-setup.d.ts.map +0 -1
  127. package/dist/commands/computer-setup.js +0 -849
  128. package/dist/commands/computer-setup.js.map +0 -1
  129. package/dist/commands/create-command.d.ts +0 -7
  130. package/dist/commands/create-command.d.ts.map +0 -1
  131. package/dist/commands/create-command.js +0 -158
  132. package/dist/commands/create-command.js.map +0 -1
  133. package/dist/commands/create.d.ts +0 -74
  134. package/dist/commands/create.d.ts.map +0 -1
  135. package/dist/commands/create.js +0 -556
  136. package/dist/commands/create.js.map +0 -1
  137. package/dist/commands/dashboard.d.ts +0 -91
  138. package/dist/commands/dashboard.d.ts.map +0 -1
  139. package/dist/commands/dashboard.js +0 -538
  140. package/dist/commands/dashboard.js.map +0 -1
  141. package/dist/commands/govern.d.ts +0 -70
  142. package/dist/commands/govern.d.ts.map +0 -1
  143. package/dist/commands/govern.js +0 -481
  144. package/dist/commands/govern.js.map +0 -1
  145. package/dist/commands/governance.d.ts +0 -17
  146. package/dist/commands/governance.d.ts.map +0 -1
  147. package/dist/commands/governance.js +0 -703
  148. package/dist/commands/governance.js.map +0 -1
  149. package/dist/commands/guardian.d.ts +0 -20
  150. package/dist/commands/guardian.d.ts.map +0 -1
  151. package/dist/commands/guardian.js +0 -597
  152. package/dist/commands/guardian.js.map +0 -1
  153. package/dist/commands/init.d.ts +0 -59
  154. package/dist/commands/init.d.ts.map +0 -1
  155. package/dist/commands/init.js +0 -650
  156. package/dist/commands/init.js.map +0 -1
  157. package/dist/commands/orchestrator.d.ts +0 -7
  158. package/dist/commands/orchestrator.d.ts.map +0 -1
  159. package/dist/commands/orchestrator.js +0 -571
  160. package/dist/commands/orchestrator.js.map +0 -1
  161. package/dist/commands/performance-optimizer.d.ts +0 -30
  162. package/dist/commands/performance-optimizer.d.ts.map +0 -1
  163. package/dist/commands/performance-optimizer.js +0 -650
  164. package/dist/commands/performance-optimizer.js.map +0 -1
  165. package/dist/commands/plugins.d.ts +0 -87
  166. package/dist/commands/plugins.d.ts.map +0 -1
  167. package/dist/commands/plugins.js +0 -685
  168. package/dist/commands/plugins.js.map +0 -1
  169. package/dist/commands/rag.d.ts +0 -7
  170. package/dist/commands/rag.d.ts.map +0 -1
  171. package/dist/commands/rag.js +0 -748
  172. package/dist/commands/rag.js.map +0 -1
  173. package/dist/commands/session.d.ts +0 -41
  174. package/dist/commands/session.d.ts.map +0 -1
  175. package/dist/commands/session.js +0 -441
  176. package/dist/commands/session.js.map +0 -1
  177. package/dist/commands/setup.d.ts +0 -29
  178. package/dist/commands/setup.d.ts.map +0 -1
  179. package/dist/commands/setup.js +0 -397
  180. package/dist/commands/setup.js.map +0 -1
  181. package/dist/commands/test-init.d.ts +0 -9
  182. package/dist/commands/test-init.d.ts.map +0 -1
  183. package/dist/commands/test-init.js +0 -222
  184. package/dist/commands/test-init.js.map +0 -1
  185. package/dist/commands/test.d.ts +0 -25
  186. package/dist/commands/test.d.ts.map +0 -1
  187. package/dist/commands/test.js +0 -217
  188. package/dist/commands/test.js.map +0 -1
  189. package/dist/commands/vp.d.ts +0 -7
  190. package/dist/commands/vp.d.ts.map +0 -1
  191. package/dist/commands/vp.js +0 -571
  192. package/dist/commands/vp.js.map +0 -1
  193. package/dist/commands/watch.d.ts +0 -76
  194. package/dist/commands/watch.d.ts.map +0 -1
  195. package/dist/commands/watch.js +0 -613
  196. package/dist/commands/watch.js.map +0 -1
  197. package/dist/commands/worktree.d.ts +0 -63
  198. package/dist/commands/worktree.d.ts.map +0 -1
  199. package/dist/commands/worktree.js +0 -774
  200. package/dist/commands/worktree.js.map +0 -1
  201. package/dist/context/context-manager.d.ts +0 -155
  202. package/dist/context/context-manager.d.ts.map +0 -1
  203. package/dist/context/context-manager.js +0 -383
  204. package/dist/context/context-manager.js.map +0 -1
  205. package/dist/context/index.d.ts +0 -3
  206. package/dist/context/index.d.ts.map +0 -1
  207. package/dist/context/index.js +0 -6
  208. package/dist/context/index.js.map +0 -1
  209. package/dist/context/session-manager.d.ts +0 -207
  210. package/dist/context/session-manager.d.ts.map +0 -1
  211. package/dist/context/session-manager.js +0 -686
  212. package/dist/context/session-manager.js.map +0 -1
  213. package/dist/index.d.ts +0 -8
  214. package/dist/index.d.ts.map +0 -1
  215. package/dist/index.js +0 -51
  216. package/dist/index.js.map +0 -1
  217. package/dist/interactive/interactive-mode.d.ts +0 -76
  218. package/dist/interactive/interactive-mode.d.ts.map +0 -1
  219. package/dist/interactive/interactive-mode.js +0 -732
  220. package/dist/interactive/interactive-mode.js.map +0 -1
  221. package/dist/nlp/command-mapper.d.ts +0 -174
  222. package/dist/nlp/command-mapper.d.ts.map +0 -1
  223. package/dist/nlp/command-mapper.js +0 -624
  224. package/dist/nlp/command-mapper.js.map +0 -1
  225. package/dist/nlp/command-parser.d.ts +0 -106
  226. package/dist/nlp/command-parser.d.ts.map +0 -1
  227. package/dist/nlp/command-parser.js +0 -417
  228. package/dist/nlp/command-parser.js.map +0 -1
  229. package/dist/nlp/index.d.ts +0 -5
  230. package/dist/nlp/index.d.ts.map +0 -1
  231. package/dist/nlp/index.js +0 -8
  232. package/dist/nlp/index.js.map +0 -1
  233. package/dist/nlp/intent-classifier.d.ts +0 -59
  234. package/dist/nlp/intent-classifier.d.ts.map +0 -1
  235. package/dist/nlp/intent-classifier.js +0 -384
  236. package/dist/nlp/intent-classifier.js.map +0 -1
  237. package/dist/nlp/intent-parser.d.ts +0 -152
  238. package/dist/nlp/intent-parser.d.ts.map +0 -1
  239. package/dist/nlp/intent-parser.js +0 -744
  240. package/dist/nlp/intent-parser.js.map +0 -1
  241. package/dist/plugins/plugin-manager.d.ts +0 -120
  242. package/dist/plugins/plugin-manager.d.ts.map +0 -1
  243. package/dist/plugins/plugin-manager.js +0 -595
  244. package/dist/plugins/plugin-manager.js.map +0 -1
  245. package/dist/types/index.d.ts +0 -224
  246. package/dist/types/index.d.ts.map +0 -1
  247. package/dist/types/index.js +0 -3
  248. package/dist/types/index.js.map +0 -1
  249. package/dist/utils/backup-rollback-manager.d.ts +0 -72
  250. package/dist/utils/backup-rollback-manager.d.ts.map +0 -1
  251. package/dist/utils/backup-rollback-manager.js +0 -289
  252. package/dist/utils/backup-rollback-manager.js.map +0 -1
  253. package/dist/utils/claude-config-installer.d.ts +0 -98
  254. package/dist/utils/claude-config-installer.d.ts.map +0 -1
  255. package/dist/utils/claude-config-installer.js +0 -678
  256. package/dist/utils/claude-config-installer.js.map +0 -1
  257. package/dist/utils/config-manager.d.ts +0 -73
  258. package/dist/utils/config-manager.d.ts.map +0 -1
  259. package/dist/utils/config-manager.js +0 -339
  260. package/dist/utils/config-manager.js.map +0 -1
  261. package/dist/utils/error-handler.d.ts +0 -46
  262. package/dist/utils/error-handler.d.ts.map +0 -1
  263. package/dist/utils/error-handler.js +0 -169
  264. package/dist/utils/error-handler.js.map +0 -1
  265. package/dist/utils/logger.d.ts +0 -25
  266. package/dist/utils/logger.d.ts.map +0 -1
  267. package/dist/utils/logger.js +0 -105
  268. package/dist/utils/logger.js.map +0 -1
  269. package/src/commands/computer-setup-commands.ts +0 -872
@@ -1,738 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BatchCommands = void 0;
4
- const tslib_1 = require("tslib");
5
- const path_1 = tslib_1.__importDefault(require("path"));
6
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
- const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
8
- const listr2_1 = require("listr2");
9
- const yaml_1 = tslib_1.__importDefault(require("yaml"));
10
- const error_handler_1 = require("../utils/error-handler");
11
- const logger_1 = require("../utils/logger");
12
- /**
13
- * Batch commands for YAML automation and batch processing
14
- */
15
- class BatchCommands {
16
- program;
17
- configManager;
18
- pluginManager;
19
- runningJobs = new Map();
20
- constructor(program, configManager, pluginManager) {
21
- this.program = program;
22
- this.configManager = configManager;
23
- this.pluginManager = pluginManager;
24
- this.registerCommands();
25
- }
26
- registerCommands() {
27
- const batchCmd = this.program
28
- .command('batch')
29
- .description('batch processing and automation with YAML');
30
- // Run batch job
31
- batchCmd
32
- .command('run <file>')
33
- .description('run batch job from YAML file')
34
- .option('--dry-run', 'show what would be executed without running')
35
- .option('--parallel', 'run commands in parallel where possible')
36
- .option('--continue-on-error', 'continue execution on command failures')
37
- .option('--vars <vars>', 'variables to pass to batch job (JSON or key=value)')
38
- .option('--timeout <ms>', 'global timeout for batch job')
39
- .action(async (file, options) => {
40
- await this.runBatchJob(file, options);
41
- });
42
- // Create batch job
43
- batchCmd
44
- .command('create <name>')
45
- .description('create a new batch job')
46
- .option('--template <template>', 'batch job template')
47
- .option('--commands <commands>', 'commands to include (comma-separated)')
48
- .option('--interactive', 'create job interactively')
49
- .action(async (name, options) => {
50
- await this.createBatchJob(name, options);
51
- });
52
- // List batch jobs
53
- batchCmd
54
- .command('list')
55
- .alias('ls')
56
- .description('list available batch jobs')
57
- .option('--path <path>', 'custom batch jobs directory')
58
- .action(async (options) => {
59
- await this.listBatchJobs(options);
60
- });
61
- // Validate batch job
62
- batchCmd
63
- .command('validate <file>')
64
- .description('validate batch job YAML file')
65
- .action(async (file) => {
66
- await this.validateBatchJob(file);
67
- });
68
- // Stop running job
69
- batchCmd
70
- .command('stop <jobId>')
71
- .description('stop a running batch job')
72
- .action(async (jobId) => {
73
- await this.stopBatchJob(jobId);
74
- });
75
- // Show job status
76
- batchCmd
77
- .command('status [jobId]')
78
- .description('show batch job status')
79
- .action(async (jobId) => {
80
- await this.showJobStatus(jobId);
81
- });
82
- // Schedule batch job
83
- batchCmd
84
- .command('schedule <file>')
85
- .description('schedule batch job execution')
86
- .option('--cron <expression>', 'cron expression for scheduling')
87
- .option('--interval <ms>', 'interval in milliseconds')
88
- .option('--once', 'run once after delay')
89
- .action(async (file, options) => {
90
- await this.scheduleBatchJob(file, options);
91
- });
92
- // Export batch job
93
- batchCmd
94
- .command('export <file>')
95
- .description('export batch job to different formats')
96
- .option('--format <format>', 'export format (json, shell, dockerfile)', 'json')
97
- .option('--output <path>', 'output file path')
98
- .action(async (file, options) => {
99
- await this.exportBatchJob(file, options);
100
- });
101
- // Import batch job
102
- batchCmd
103
- .command('import <file>')
104
- .description('import batch job from different formats')
105
- .option('--format <format>', 'source format (json, shell, package-scripts)')
106
- .option('--name <name>', 'batch job name')
107
- .action(async (file, options) => {
108
- await this.importBatchJob(file, options);
109
- });
110
- // Template management
111
- batchCmd.command('template').description('manage batch job templates');
112
- batchCmd
113
- .command('template list')
114
- .description('list available templates')
115
- .action(async () => {
116
- await this.listTemplates();
117
- });
118
- batchCmd
119
- .command('template create <name>')
120
- .description('create a new template')
121
- .option('--from <file>', 'create template from existing batch job')
122
- .action(async (name, options) => {
123
- await this.createTemplate(name, options);
124
- });
125
- }
126
- /**
127
- * Run batch job from YAML file
128
- */
129
- async runBatchJob(file, options) {
130
- try {
131
- logger_1.logger.info(`Running batch job: ${chalk_1.default.cyan(file)}`);
132
- // Load and validate batch job
133
- const job = await this.loadBatchJob(file);
134
- await this.validateJobStructure(job);
135
- // Process variables
136
- const processedJob = await this.processJobVariables(job, options.vars);
137
- if (options.dryRun) {
138
- await this.showDryRun(processedJob);
139
- return;
140
- }
141
- // Create job ID and track execution
142
- const jobId = `job-${Date.now()}`;
143
- this.runningJobs.set(jobId, {
144
- file,
145
- job: processedJob,
146
- startTime: Date.now(),
147
- status: 'running',
148
- });
149
- try {
150
- await this.executeBatchJob(processedJob, jobId, options);
151
- logger_1.logger.success(`Batch job completed: ${file}`);
152
- }
153
- finally {
154
- this.runningJobs.delete(jobId);
155
- }
156
- }
157
- catch (error) {
158
- throw error_handler_1.errorHandler.createError('WUNDR_BATCH_RUN_FAILED', 'Failed to run batch job', { file, options }, true);
159
- }
160
- }
161
- /**
162
- * Create a new batch job
163
- */
164
- async createBatchJob(name, options) {
165
- try {
166
- logger_1.logger.info(`Creating batch job: ${chalk_1.default.cyan(name)}`);
167
- let job;
168
- if (options.interactive) {
169
- job = await this.createInteractiveBatchJob(name);
170
- }
171
- else if (options.template) {
172
- job = await this.createJobFromTemplate(name, options.template);
173
- }
174
- else {
175
- job = this.createBasicBatchJob(name, options);
176
- }
177
- const jobPath = path_1.default.join(process.cwd(), '.wundr', 'batch', `${name}.yaml`);
178
- await fs_extra_1.default.ensureDir(path_1.default.dirname(jobPath));
179
- await fs_extra_1.default.writeFile(jobPath, yaml_1.default.stringify(job));
180
- logger_1.logger.success(`Batch job created: ${jobPath}`);
181
- }
182
- catch (error) {
183
- throw error_handler_1.errorHandler.createError('WUNDR_BATCH_CREATE_FAILED', 'Failed to create batch job', { name, options }, true);
184
- }
185
- }
186
- /**
187
- * List available batch jobs
188
- */
189
- async listBatchJobs(options) {
190
- try {
191
- const batchDir = options.path || path_1.default.join(process.cwd(), '.wundr', 'batch');
192
- if (!(await fs_extra_1.default.pathExists(batchDir))) {
193
- logger_1.logger.info('No batch jobs directory found');
194
- return;
195
- }
196
- const files = await fs_extra_1.default.readdir(batchDir);
197
- const yamlFiles = files.filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
198
- if (yamlFiles.length === 0) {
199
- logger_1.logger.info('No batch jobs found');
200
- return;
201
- }
202
- logger_1.logger.info(`Batch jobs (${yamlFiles.length}):`);
203
- const jobs = [];
204
- for (const file of yamlFiles) {
205
- const filePath = path_1.default.join(batchDir, file);
206
- try {
207
- const job = await this.loadBatchJob(filePath);
208
- jobs.push({
209
- Name: path_1.default.basename(file, path_1.default.extname(file)),
210
- Description: job.description || 'No description',
211
- Commands: job.commands.length,
212
- Parallel: job.parallel ? '✓' : '✗',
213
- });
214
- }
215
- catch (error) {
216
- jobs.push({
217
- Name: path_1.default.basename(file, path_1.default.extname(file)),
218
- Description: 'Invalid YAML',
219
- Commands: 'N/A',
220
- Parallel: 'N/A',
221
- });
222
- }
223
- }
224
- console.table(jobs);
225
- }
226
- catch (error) {
227
- throw error_handler_1.errorHandler.createError('WUNDR_BATCH_LIST_FAILED', 'Failed to list batch jobs', { options }, true);
228
- }
229
- }
230
- /**
231
- * Validate batch job YAML file
232
- */
233
- async validateBatchJob(file) {
234
- try {
235
- logger_1.logger.info(`Validating batch job: ${chalk_1.default.cyan(file)}`);
236
- const job = await this.loadBatchJob(file);
237
- const validation = await this.validateJobStructure(job);
238
- if (validation.valid) {
239
- logger_1.logger.success('Batch job is valid ✓');
240
- // Show job summary
241
- console.log(chalk_1.default.blue('\nJob Summary:'));
242
- console.log(`Name: ${job.name}`);
243
- console.log(`Description: ${job.description || 'None'}`);
244
- console.log(`Commands: ${job.commands.length}`);
245
- console.log(`Parallel execution: ${job.parallel ? 'Yes' : 'No'}`);
246
- console.log(`Continue on error: ${job.continueOnError ? 'Yes' : 'No'}`);
247
- }
248
- else {
249
- logger_1.logger.error('Batch job validation failed:');
250
- validation.errors.forEach(error => {
251
- logger_1.logger.error(` - ${error}`);
252
- });
253
- process.exit(1);
254
- }
255
- }
256
- catch (error) {
257
- throw error_handler_1.errorHandler.createError('WUNDR_BATCH_VALIDATE_FAILED', 'Failed to validate batch job', { file }, true);
258
- }
259
- }
260
- /**
261
- * Stop a running batch job
262
- */
263
- async stopBatchJob(jobId) {
264
- try {
265
- const job = this.runningJobs.get(jobId);
266
- if (!job) {
267
- logger_1.logger.warn(`Job not found: ${jobId}`);
268
- return;
269
- }
270
- // Stop the job (implementation would depend on how jobs are executed)
271
- job.status = 'stopped';
272
- this.runningJobs.delete(jobId);
273
- logger_1.logger.success(`Batch job stopped: ${jobId}`);
274
- }
275
- catch (error) {
276
- throw error_handler_1.errorHandler.createError('WUNDR_BATCH_STOP_FAILED', 'Failed to stop batch job', { jobId }, true);
277
- }
278
- }
279
- /**
280
- * Show job status
281
- */
282
- async showJobStatus(jobId) {
283
- try {
284
- if (jobId) {
285
- const job = this.runningJobs.get(jobId);
286
- if (!job) {
287
- logger_1.logger.warn(`Job not found: ${jobId}`);
288
- return;
289
- }
290
- console.log(chalk_1.default.blue(`\nJob Status: ${jobId}`));
291
- console.log(`File: ${job.file}`);
292
- console.log(`Status: ${job.status}`);
293
- console.log(`Started: ${new Date(job.startTime).toLocaleString()}`);
294
- console.log(`Duration: ${Date.now() - job.startTime}ms`);
295
- }
296
- else {
297
- if (this.runningJobs.size === 0) {
298
- logger_1.logger.info('No running batch jobs');
299
- return;
300
- }
301
- console.log(chalk_1.default.blue(`\nRunning Jobs (${this.runningJobs.size}):`));
302
- const jobData = Array.from(this.runningJobs.entries()).map(([id, job]) => ({
303
- ID: id,
304
- File: path_1.default.basename(job.file),
305
- Status: job.status,
306
- Duration: `${Date.now() - job.startTime}ms`,
307
- }));
308
- console.table(jobData);
309
- }
310
- }
311
- catch (error) {
312
- throw error_handler_1.errorHandler.createError('WUNDR_BATCH_STATUS_FAILED', 'Failed to show job status', { jobId }, true);
313
- }
314
- }
315
- /**
316
- * Schedule batch job execution
317
- */
318
- async scheduleBatchJob(file, options) {
319
- try {
320
- logger_1.logger.info(`Scheduling batch job: ${chalk_1.default.cyan(file)}`);
321
- // Validate the job first
322
- await this.loadBatchJob(file);
323
- if (options.cron) {
324
- logger_1.logger.info(`Scheduled with cron: ${options.cron}`);
325
- // Implementation would use a cron library
326
- }
327
- else if (options.interval) {
328
- logger_1.logger.info(`Scheduled with interval: ${options.interval}ms`);
329
- // Implementation would use setInterval
330
- }
331
- else if (options.once) {
332
- logger_1.logger.info('Scheduled to run once');
333
- // Implementation would use setTimeout
334
- }
335
- else {
336
- throw new Error('No scheduling option provided');
337
- }
338
- logger_1.logger.success('Batch job scheduled successfully');
339
- }
340
- catch (error) {
341
- throw error_handler_1.errorHandler.createError('WUNDR_BATCH_SCHEDULE_FAILED', 'Failed to schedule batch job', { file, options }, true);
342
- }
343
- }
344
- /**
345
- * Export batch job to different formats
346
- */
347
- async exportBatchJob(file, options) {
348
- try {
349
- logger_1.logger.info(`Exporting batch job: ${chalk_1.default.cyan(file)}`);
350
- const job = await this.loadBatchJob(file);
351
- let exportedContent;
352
- switch (options.format) {
353
- case 'json':
354
- exportedContent = JSON.stringify(job, null, 2);
355
- break;
356
- case 'shell':
357
- exportedContent = this.convertToShellScript(job);
358
- break;
359
- case 'dockerfile':
360
- exportedContent = this.convertToDockerfile(job);
361
- break;
362
- default:
363
- throw new Error(`Unsupported export format: ${options.format}`);
364
- }
365
- const outputPath = options.output ||
366
- `${path_1.default.basename(file, path_1.default.extname(file))}.${options.format}`;
367
- await fs_extra_1.default.writeFile(outputPath, exportedContent);
368
- logger_1.logger.success(`Batch job exported: ${outputPath}`);
369
- }
370
- catch (error) {
371
- throw error_handler_1.errorHandler.createError('WUNDR_BATCH_EXPORT_FAILED', 'Failed to export batch job', { file, options }, true);
372
- }
373
- }
374
- /**
375
- * Import batch job from different formats
376
- */
377
- async importBatchJob(file, options) {
378
- try {
379
- logger_1.logger.info(`Importing batch job: ${chalk_1.default.cyan(file)}`);
380
- let job;
381
- switch (options.format) {
382
- case 'json':
383
- job = await this.importFromJSON(file, options.name);
384
- break;
385
- case 'shell':
386
- job = await this.importFromShell(file, options.name);
387
- break;
388
- case 'package-scripts':
389
- job = await this.importFromPackageScripts(file, options.name);
390
- break;
391
- default:
392
- throw new Error(`Unsupported import format: ${options.format}`);
393
- }
394
- const jobName = options.name || path_1.default.basename(file, path_1.default.extname(file));
395
- const jobPath = path_1.default.join(process.cwd(), '.wundr', 'batch', `${jobName}.yaml`);
396
- await fs_extra_1.default.ensureDir(path_1.default.dirname(jobPath));
397
- await fs_extra_1.default.writeFile(jobPath, yaml_1.default.stringify(job));
398
- logger_1.logger.success(`Batch job imported: ${jobPath}`);
399
- }
400
- catch (error) {
401
- throw error_handler_1.errorHandler.createError('WUNDR_BATCH_IMPORT_FAILED', 'Failed to import batch job', { file, options }, true);
402
- }
403
- }
404
- /**
405
- * Helper methods for batch job operations
406
- */
407
- async loadBatchJob(file) {
408
- if (!(await fs_extra_1.default.pathExists(file))) {
409
- throw new Error(`Batch job file not found: ${file}`);
410
- }
411
- const content = await fs_extra_1.default.readFile(file, 'utf8');
412
- const ext = path_1.default.extname(file).toLowerCase();
413
- if (ext === '.yaml' || ext === '.yml') {
414
- return yaml_1.default.parse(content);
415
- }
416
- else if (ext === '.json') {
417
- return JSON.parse(content);
418
- }
419
- else {
420
- throw new Error(`Unsupported file format: ${ext}`);
421
- }
422
- }
423
- async validateJobStructure(job) {
424
- const errors = [];
425
- if (!job.name) {
426
- errors.push('Job name is required');
427
- }
428
- if (!job.commands || job.commands.length === 0) {
429
- errors.push('At least one command is required');
430
- }
431
- else {
432
- job.commands.forEach((cmd, index) => {
433
- if (!cmd.command) {
434
- errors.push(`Command ${index + 1} is missing command property`);
435
- }
436
- });
437
- }
438
- return { valid: errors.length === 0, errors };
439
- }
440
- async processJobVariables(job, vars) {
441
- let variables = {};
442
- if (vars) {
443
- try {
444
- // Try parsing as JSON first
445
- variables = JSON.parse(vars);
446
- }
447
- catch {
448
- // Parse as key=value pairs
449
- vars.split(',').forEach(pair => {
450
- const [key, value] = pair.split('=');
451
- if (key && value) {
452
- variables[key.trim()] = value.trim();
453
- }
454
- });
455
- }
456
- }
457
- // Replace variables in job
458
- const processedJob = JSON.parse(JSON.stringify(job));
459
- const jobString = JSON.stringify(processedJob);
460
- let processedString = jobString;
461
- Object.entries(variables).forEach(([key, value]) => {
462
- const placeholder = new RegExp(`\\{\\{${key}\\}\\}`, 'g');
463
- processedString = processedString.replace(placeholder, String(value));
464
- });
465
- return JSON.parse(processedString);
466
- }
467
- async showDryRun(job) {
468
- console.log(chalk_1.default.blue('\nDry Run - Commands to be executed:'));
469
- console.log(chalk_1.default.gray('='.repeat(50)));
470
- job.commands.forEach((cmd, index) => {
471
- console.log(`${index + 1}. ${chalk_1.default.cyan(cmd.command)}`);
472
- if (cmd.args) {
473
- console.log(` Args: ${cmd.args.join(' ')}`);
474
- }
475
- if (cmd.condition) {
476
- console.log(` Condition: ${cmd.condition}`);
477
- }
478
- if (cmd.retry) {
479
- console.log(` Retry: ${cmd.retry} times`);
480
- }
481
- if (cmd.timeout) {
482
- console.log(` Timeout: ${cmd.timeout}ms`);
483
- }
484
- console.log();
485
- });
486
- console.log(chalk_1.default.gray('='.repeat(50)));
487
- console.log(`Total commands: ${job.commands.length}`);
488
- console.log(`Parallel execution: ${job.parallel ? 'Yes' : 'No'}`);
489
- console.log(`Continue on error: ${job.continueOnError ? 'Yes' : 'No'}`);
490
- }
491
- async executeBatchJob(job, _jobId, _options) {
492
- const tasks = job.commands.map((cmd, _index) => ({
493
- title: cmd.command,
494
- task: async () => {
495
- await this.executeCommand(cmd, _options);
496
- },
497
- retry: cmd.retry || 0,
498
- timeout: cmd.timeout,
499
- }));
500
- const listr = new listr2_1.Listr(tasks, {
501
- concurrent: job.parallel || _options.parallel,
502
- exitOnError: !(job.continueOnError || _options.continueOnError),
503
- rendererOptions: {
504
- showSubtasks: true,
505
- },
506
- });
507
- await listr.run();
508
- }
509
- async executeCommand(cmd, _options) {
510
- // Check condition if specified
511
- if (cmd.condition && !(await this.evaluateCondition(cmd.condition))) {
512
- logger_1.logger.debug(`Skipping command due to condition: ${cmd.condition}`);
513
- return;
514
- }
515
- const { spawn } = await Promise.resolve().then(() => tslib_1.__importStar(require('child_process')));
516
- const [command, ...args] = cmd.command.split(' ');
517
- const finalArgs = cmd.args ? [...args, ...cmd.args] : args;
518
- return new Promise((resolve, reject) => {
519
- const child = spawn(command ?? 'echo', finalArgs, {
520
- stdio: ['ignore', 'pipe', 'pipe'],
521
- shell: true,
522
- });
523
- let output = '';
524
- let error = '';
525
- child.stdout?.on('data', (data) => {
526
- output += data.toString();
527
- });
528
- child.stderr?.on('data', (data) => {
529
- error += data.toString();
530
- });
531
- child.on('exit', (code) => {
532
- if (code === 0) {
533
- resolve();
534
- }
535
- else {
536
- reject(new Error(`Command failed with exit code ${code}: ${error}`));
537
- }
538
- });
539
- // Handle timeout
540
- if (cmd.timeout) {
541
- setTimeout(() => {
542
- child.kill();
543
- reject(new Error(`Command timed out after ${cmd.timeout}ms`));
544
- }, cmd.timeout);
545
- }
546
- });
547
- }
548
- async evaluateCondition(condition) {
549
- // Simple condition evaluation
550
- // In a real implementation, this would be more sophisticated
551
- switch (condition) {
552
- case 'always':
553
- return true;
554
- case 'never':
555
- return false;
556
- default:
557
- // Could evaluate file existence, environment variables, etc.
558
- return true;
559
- }
560
- }
561
- async createInteractiveBatchJob(name) {
562
- const inquirer = await Promise.resolve().then(() => tslib_1.__importStar(require('inquirer')));
563
- const answers = await inquirer.default.prompt([
564
- {
565
- type: 'input',
566
- name: 'description',
567
- message: 'Job description:',
568
- },
569
- {
570
- type: 'confirm',
571
- name: 'parallel',
572
- message: 'Run commands in parallel?',
573
- default: false,
574
- },
575
- {
576
- type: 'confirm',
577
- name: 'continueOnError',
578
- message: 'Continue on command failure?',
579
- default: false,
580
- },
581
- ]);
582
- const commands = [];
583
- let addMore = true;
584
- while (addMore) {
585
- const cmdAnswers = await inquirer.default.prompt([
586
- {
587
- type: 'input',
588
- name: 'command',
589
- message: 'Command:',
590
- validate: input => input.length > 0 || 'Command is required',
591
- },
592
- {
593
- type: 'input',
594
- name: 'condition',
595
- message: 'Condition (optional):',
596
- },
597
- {
598
- type: 'number',
599
- name: 'retry',
600
- message: 'Retry count:',
601
- default: 0,
602
- },
603
- {
604
- type: 'confirm',
605
- name: 'addMore',
606
- message: 'Add another command?',
607
- default: true,
608
- },
609
- ]);
610
- commands.push({
611
- command: cmdAnswers.command,
612
- condition: cmdAnswers.condition || undefined,
613
- retry: cmdAnswers.retry || undefined,
614
- });
615
- addMore = cmdAnswers.addMore;
616
- }
617
- return {
618
- name,
619
- description: answers.description,
620
- commands,
621
- parallel: answers.parallel,
622
- continueOnError: answers.continueOnError,
623
- };
624
- }
625
- createBasicBatchJob(name, options) {
626
- const commands = options.commands
627
- ? options.commands
628
- .split(',')
629
- .map((cmd) => ({ command: cmd.trim() }))
630
- : [];
631
- return {
632
- name,
633
- description: `Batch job: ${name}`,
634
- commands,
635
- parallel: false,
636
- continueOnError: false,
637
- };
638
- }
639
- async createJobFromTemplate(name, template) {
640
- // Load template and create job
641
- const templatePath = path_1.default.join(__dirname, '../../templates/batch', `${template}.yaml`);
642
- if (await fs_extra_1.default.pathExists(templatePath)) {
643
- const templateJob = await this.loadBatchJob(templatePath);
644
- return { ...templateJob, name };
645
- }
646
- throw new Error(`Template not found: ${template}`);
647
- }
648
- // Format conversion methods
649
- convertToShellScript(job) {
650
- let script = `#!/bin/bash\n# Generated from batch job: ${job.name}\n\n`;
651
- if (job.description) {
652
- script += `# ${job.description}\n\n`;
653
- }
654
- script += 'set -e\n\n'; // Exit on error unless continueOnError is true
655
- job.commands.forEach(cmd => {
656
- script += `echo "Executing: ${cmd.command}"\n`;
657
- script += `${cmd.command}\n\n`;
658
- });
659
- return script;
660
- }
661
- convertToDockerfile(job) {
662
- let dockerfile = `# Generated from batch job: ${job.name}\n`;
663
- dockerfile += 'FROM node:18-alpine\n\n';
664
- if (job.description) {
665
- dockerfile += `# ${job.description}\n`;
666
- }
667
- dockerfile += 'WORKDIR /app\n';
668
- dockerfile += 'COPY . .\n\n';
669
- job.commands.forEach(cmd => {
670
- dockerfile += `RUN ${cmd.command}\n`;
671
- });
672
- return dockerfile;
673
- }
674
- async importFromJSON(file, name) {
675
- const content = await fs_extra_1.default.readJson(file);
676
- return { ...content, name: name || content.name };
677
- }
678
- async importFromShell(file, name) {
679
- const content = await fs_extra_1.default.readFile(file, 'utf8');
680
- const commands = content
681
- .split('\n')
682
- .filter(line => line.trim() && !line.startsWith('#'))
683
- .map(line => ({ command: line.trim() }));
684
- return {
685
- name: name || path_1.default.basename(file, path_1.default.extname(file)),
686
- description: `Imported from shell script: ${file}`,
687
- commands,
688
- };
689
- }
690
- async importFromPackageScripts(file, name) {
691
- const packageJson = await fs_extra_1.default.readJson(file);
692
- const scripts = packageJson.scripts || {};
693
- const commands = Object.entries(scripts).map(([script, command]) => ({
694
- command: `npm run ${script}`,
695
- args: [],
696
- condition: undefined,
697
- }));
698
- return {
699
- name: name || 'package-scripts',
700
- description: 'Imported from package.json scripts',
701
- commands,
702
- };
703
- }
704
- async listTemplates() {
705
- const templatesDir = path_1.default.join(__dirname, '../../templates/batch');
706
- if (await fs_extra_1.default.pathExists(templatesDir)) {
707
- const templates = await fs_extra_1.default.readdir(templatesDir);
708
- const yamlTemplates = templates.filter(t => t.endsWith('.yaml') || t.endsWith('.yml'));
709
- if (yamlTemplates.length > 0) {
710
- logger_1.logger.info('Available templates:');
711
- yamlTemplates.forEach(template => {
712
- console.log(` - ${path_1.default.basename(template, path_1.default.extname(template))}`);
713
- });
714
- }
715
- else {
716
- logger_1.logger.info('No templates available');
717
- }
718
- }
719
- else {
720
- logger_1.logger.info('No templates directory found');
721
- }
722
- }
723
- async createTemplate(name, options) {
724
- logger_1.logger.info(`Creating template: ${name}`);
725
- if (options.from) {
726
- const job = await this.loadBatchJob(options.from);
727
- const templatePath = path_1.default.join(__dirname, '../../templates/batch', `${name}.yaml`);
728
- await fs_extra_1.default.ensureDir(path_1.default.dirname(templatePath));
729
- await fs_extra_1.default.writeFile(templatePath, yaml_1.default.stringify(job));
730
- logger_1.logger.success(`Template created: ${templatePath}`);
731
- }
732
- else {
733
- logger_1.logger.info('Template creation from scratch not yet implemented');
734
- }
735
- }
736
- }
737
- exports.BatchCommands = BatchCommands;
738
- //# sourceMappingURL=batch.js.map