@aifabrix/builder 2.31.1 → 2.32.1

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 (118) hide show
  1. package/README.md +9 -9
  2. package/integration/hubspot/README.md +2 -2
  3. package/integration/hubspot/hubspot-deploy-company.json +17 -14
  4. package/integration/hubspot/hubspot-deploy-contact.json +19 -16
  5. package/integration/hubspot/hubspot-deploy-deal.json +21 -18
  6. package/lib/api/types/datasources.types.js +31 -5
  7. package/lib/api/types/wizard.types.js +142 -0
  8. package/lib/api/wizard.api.js +177 -0
  9. package/lib/{app-config.js → app/config.js} +4 -4
  10. package/lib/{app-deploy.js → app/deploy.js} +8 -8
  11. package/lib/app/display.js +90 -0
  12. package/lib/{app-dockerfile.js → app/dockerfile.js} +4 -4
  13. package/lib/{app-down.js → app/down.js} +4 -4
  14. package/lib/app/helpers.js +218 -0
  15. package/lib/app/index.js +298 -0
  16. package/lib/{app-list.js → app/list.js} +6 -6
  17. package/lib/{app-push.js → app/push.js} +4 -4
  18. package/lib/{app-readme.js → app/readme.js} +34 -13
  19. package/lib/{app-register.js → app/register.js} +9 -9
  20. package/lib/{app-rotate-secret.js → app/rotate-secret.js} +10 -10
  21. package/lib/{app-run-helpers.js → app/run-helpers.js} +10 -10
  22. package/lib/{app-run.js → app/run.js} +6 -6
  23. package/lib/{build.js → build/index.js} +59 -32
  24. package/lib/build/package.json +7 -0
  25. package/lib/cli.js +245 -179
  26. package/lib/commands/app.js +3 -3
  27. package/lib/commands/datasource.js +4 -4
  28. package/lib/commands/login-credentials.js +209 -0
  29. package/lib/commands/login-device.js +254 -0
  30. package/lib/commands/login.js +67 -378
  31. package/lib/commands/logout.js +1 -1
  32. package/lib/commands/secrets-set.js +1 -1
  33. package/lib/commands/secure.js +2 -2
  34. package/lib/commands/wizard.js +498 -0
  35. package/lib/{audit-logger.js → core/audit-logger.js} +1 -1
  36. package/lib/{config.js → core/config.js} +28 -26
  37. package/lib/{diff.js → core/diff.js} +157 -72
  38. package/lib/{secrets.js → core/secrets.js} +86 -49
  39. package/lib/{templates.js → core/templates-env.js} +14 -222
  40. package/lib/core/templates.js +279 -0
  41. package/lib/{datasource-deploy.js → datasource/deploy.js} +6 -6
  42. package/lib/{datasource-diff.js → datasource/diff.js} +2 -2
  43. package/lib/datasource/list.js +223 -0
  44. package/lib/{datasource-validate.js → datasource/validate.js} +2 -2
  45. package/lib/{deployer.js → deployment/deployer.js} +48 -18
  46. package/lib/{environment-deploy.js → deployment/environment.js} +163 -84
  47. package/lib/{push.js → deployment/push.js} +1 -1
  48. package/lib/external-system/deploy-helpers.js +145 -0
  49. package/lib/{external-system-deploy.js → external-system/deploy.js} +156 -111
  50. package/lib/external-system/download-helpers.js +114 -0
  51. package/lib/{external-system-download.js → external-system/download.js} +92 -135
  52. package/lib/{external-system-generator.js → external-system/generator.js} +15 -11
  53. package/lib/external-system/test-auth.js +40 -0
  54. package/lib/external-system/test-execution.js +84 -0
  55. package/lib/external-system/test-helpers.js +109 -0
  56. package/lib/{external-system-test.js → external-system/test.js} +174 -192
  57. package/lib/{generator-builders.js → generator/builders.js} +87 -10
  58. package/lib/{generator-external.js → generator/external.js} +115 -52
  59. package/lib/{github-generator.js → generator/github.js} +116 -15
  60. package/lib/{generator-helpers.js → generator/helpers.js} +92 -42
  61. package/lib/{generator.js → generator/index.js} +49 -22
  62. package/lib/{generator-split.js → generator/split.js} +108 -55
  63. package/lib/generator/wizard-prompts.js +357 -0
  64. package/lib/generator/wizard.js +490 -0
  65. package/lib/{infra.js → infrastructure/index.js} +49 -22
  66. package/lib/schema/external-datasource.schema.json +145 -133
  67. package/lib/schema/external-system.schema.json +42 -0
  68. package/lib/utils/api.js +9 -5
  69. package/lib/utils/app-register-api.js +60 -32
  70. package/lib/utils/app-register-auth.js +172 -47
  71. package/lib/utils/app-register-config.js +130 -59
  72. package/lib/utils/app-run-containers.js +29 -8
  73. package/lib/utils/build-helpers.js +1 -1
  74. package/lib/utils/cli-utils.js +78 -30
  75. package/lib/utils/compose-generator.js +145 -65
  76. package/lib/utils/config-paths.js +2 -0
  77. package/lib/utils/deployment-errors.js +1 -1
  78. package/lib/utils/device-code.js +99 -41
  79. package/lib/utils/env-config-loader.js +1 -1
  80. package/lib/utils/env-copy.js +21 -18
  81. package/lib/utils/env-endpoints.js +115 -67
  82. package/lib/utils/env-map.js +13 -14
  83. package/lib/utils/env-ports.js +45 -25
  84. package/lib/utils/env-template.js +84 -42
  85. package/lib/utils/error-formatter.js +26 -9
  86. package/lib/utils/error-formatters/error-parser.js +90 -4
  87. package/lib/utils/error-formatters/http-status-errors.js +54 -17
  88. package/lib/utils/error-formatters/network-errors.js +103 -26
  89. package/lib/utils/external-system-display.js +184 -90
  90. package/lib/utils/external-system-validators.js +164 -42
  91. package/lib/utils/file-upload.js +109 -0
  92. package/lib/utils/health-check.js +199 -83
  93. package/lib/utils/infra-containers.js +1 -1
  94. package/lib/utils/infra-status.js +66 -15
  95. package/lib/utils/local-secrets.js +45 -25
  96. package/lib/utils/paths.js +45 -33
  97. package/lib/utils/schema-loader.js +42 -25
  98. package/lib/utils/schema-resolver.js +123 -74
  99. package/lib/utils/secrets-encryption.js +62 -25
  100. package/lib/utils/secrets-helpers.js +126 -63
  101. package/lib/utils/secrets-path.js +1 -1
  102. package/lib/utils/secrets-url.js +1 -1
  103. package/lib/utils/token-manager-refresh.js +181 -0
  104. package/lib/utils/token-manager.js +76 -123
  105. package/lib/utils/variable-transformer.js +154 -77
  106. package/lib/utils/yaml-preserve.js +41 -47
  107. package/lib/{template-validator.js → validation/template.js} +54 -23
  108. package/lib/{validate.js → validation/validate.js} +205 -125
  109. package/lib/{validator.js → validation/validator.js} +58 -39
  110. package/package.json +31 -2
  111. package/templates/external-system/deploy.ps1.hbs +34 -0
  112. package/templates/external-system/deploy.sh.hbs +34 -0
  113. package/templates/external-system/external-datasource.json.hbs +31 -12
  114. package/lib/app.js +0 -467
  115. package/lib/datasource-list.js +0 -141
  116. /package/lib/{app-prompts.js → app/prompts.js} +0 -0
  117. /package/lib/{env-reader.js → core/env-reader.js} +0 -0
  118. /package/lib/{key-generator.js → core/key-generator.js} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@aifabrix/builder-build",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "type": "commonjs"
6
+ }
7
+
package/lib/cli.js CHANGED
@@ -10,12 +10,12 @@
10
10
  * @version 2.0.0
11
11
  */
12
12
 
13
- const infra = require('./infra');
13
+ const infra = require('./infrastructure');
14
14
  const app = require('./app');
15
- const secrets = require('./secrets');
15
+ const secrets = require('./core/secrets');
16
16
  const generator = require('./generator');
17
- const validator = require('./validator');
18
- const config = require('./config');
17
+ const validator = require('./validation/validator');
18
+ const config = require('./core/config');
19
19
  const devConfig = require('./utils/dev-config');
20
20
  const chalk = require('chalk');
21
21
  const logger = require('./utils/logger');
@@ -26,11 +26,10 @@ const { handleSecure } = require('./commands/secure');
26
26
  const { handleSecretsSet } = require('./commands/secrets-set');
27
27
 
28
28
  /**
29
- * Sets up all CLI commands on the Commander program instance
29
+ * Sets up authentication commands
30
30
  * @param {Command} program - Commander program instance
31
31
  */
32
- function setupCommands(program) {
33
- // Authentication command
32
+ function setupAuthCommands(program) {
34
33
  program.command('login')
35
34
  .description('Authenticate with Miso Controller')
36
35
  .option('-c, --controller <url>', 'Controller URL', 'http://localhost:3000')
@@ -63,8 +62,13 @@ function setupCommands(program) {
63
62
  process.exit(1);
64
63
  }
65
64
  });
65
+ }
66
66
 
67
- // Infrastructure commands
67
+ /**
68
+ * Sets up infrastructure commands
69
+ * @param {Command} program - Commander program instance
70
+ */
71
+ function setupInfraCommands(program) {
68
72
  program.command('up')
69
73
  .description('Start local infrastructure services (Postgres, Redis, pgAdmin, Redis Commander)')
70
74
  .option('-d, --developer <id>', 'Set developer ID and start infrastructure')
@@ -110,7 +114,100 @@ function setupCommands(program) {
110
114
  }
111
115
  });
112
116
 
113
- // Application commands
117
+ program.command('doctor')
118
+ .description('Check environment and configuration')
119
+ .action(async() => {
120
+ try {
121
+ const result = await validator.checkEnvironment();
122
+ logger.log('\n🔍 AI Fabrix Environment Check\n');
123
+
124
+ logger.log(`Docker: ${result.docker === 'ok' ? '✅ Running' : '❌ Not available'}`);
125
+ logger.log(`Ports: ${result.ports === 'ok' ? '✅ Available' : '⚠️ Some ports in use'}`);
126
+ logger.log(`Secrets: ${result.secrets === 'ok' ? '✅ Configured' : '❌ Missing'}`);
127
+
128
+ if (result.recommendations.length > 0) {
129
+ logger.log('\n📋 Recommendations:');
130
+ result.recommendations.forEach(rec => logger.log(` • ${rec}`));
131
+ }
132
+
133
+ // Check infrastructure health if Docker is available
134
+ if (result.docker === 'ok') {
135
+ try {
136
+ const health = await infra.checkInfraHealth();
137
+ logger.log('\n🏥 Infrastructure Health:');
138
+ Object.entries(health).forEach(([service, status]) => {
139
+ const icon = status === 'healthy' ? '✅' : status === 'unknown' ? '❓' : '❌';
140
+ logger.log(` ${icon} ${service}: ${status}`);
141
+ });
142
+ } catch (error) {
143
+ logger.log('\n🏥 Infrastructure: Not running');
144
+ }
145
+ }
146
+
147
+ logger.log('');
148
+ } catch (error) {
149
+ handleCommandError(error, 'doctor');
150
+ process.exit(1);
151
+ }
152
+ });
153
+
154
+ program.command('status')
155
+ .description('Show detailed infrastructure service status and running applications')
156
+ .action(async() => {
157
+ try {
158
+ const status = await infra.getInfraStatus();
159
+ logger.log('\n📊 Infrastructure Status\n');
160
+
161
+ Object.entries(status).forEach(([service, info]) => {
162
+ // Normalize status value for comparison (handle edge cases)
163
+ const normalizedStatus = String(info.status).trim().toLowerCase();
164
+ const icon = normalizedStatus === 'running' ? '✅' : '❌';
165
+ logger.log(`${icon} ${service}:`);
166
+ logger.log(` Status: ${info.status}`);
167
+ logger.log(` Port: ${info.port}`);
168
+ logger.log(` URL: ${info.url}`);
169
+ logger.log('');
170
+ });
171
+
172
+ // Show running applications
173
+ const apps = await infra.getAppStatus();
174
+ if (apps.length > 0) {
175
+ logger.log('📱 Running Applications\n');
176
+ apps.forEach((app) => {
177
+ const normalizedStatus = String(app.status).trim().toLowerCase();
178
+ const icon = normalizedStatus.includes('running') || normalizedStatus.includes('up') ? '✅' : '❌';
179
+ logger.log(`${icon} ${app.name}:`);
180
+ logger.log(` Container: ${app.container}`);
181
+ logger.log(` Port: ${app.port}`);
182
+ logger.log(` Status: ${app.status}`);
183
+ logger.log(` URL: ${app.url}`);
184
+ logger.log('');
185
+ });
186
+ }
187
+ } catch (error) {
188
+ handleCommandError(error, 'status');
189
+ process.exit(1);
190
+ }
191
+ });
192
+
193
+ program.command('restart <service>')
194
+ .description('Restart a specific infrastructure service')
195
+ .action(async(service) => {
196
+ try {
197
+ await infra.restartService(service);
198
+ logger.log(`✅ ${service} service restarted successfully`);
199
+ } catch (error) {
200
+ handleCommandError(error, 'restart');
201
+ process.exit(1);
202
+ }
203
+ });
204
+ }
205
+
206
+ /**
207
+ * Sets up application lifecycle commands
208
+ * @param {Command} program - Commander program instance
209
+ */
210
+ function setupAppCommands(program) {
114
211
  program.command('create <app>')
115
212
  .description('Create new application with configuration files')
116
213
  .option('-p, --port <port>', 'Application port', '3000')
@@ -125,6 +222,7 @@ function setupCommands(program) {
125
222
  .option('-g, --github', 'Generate GitHub Actions workflows')
126
223
  .option('--github-steps <steps>', 'Extra GitHub workflow steps (comma-separated, e.g., npm,test)')
127
224
  .option('--main-branch <branch>', 'Main branch name for workflows', 'main')
225
+ .option('--wizard', 'Use interactive wizard for external system creation')
128
226
  .action(async(appName, options) => {
129
227
  try {
130
228
  // Validate type if provided
@@ -132,13 +230,35 @@ function setupCommands(program) {
132
230
  if (options.type && !validTypes.includes(options.type)) {
133
231
  throw new Error(`Invalid type: ${options.type}. Must be one of: ${validTypes.join(', ')}`);
134
232
  }
135
- await app.createApp(appName, options);
233
+ // If wizard flag is set and type is external, use wizard instead
234
+ if (options.wizard && (options.type === 'external' || (!options.type && validTypes.includes('external')))) {
235
+ const { handleWizard } = require('./commands/wizard');
236
+ await handleWizard({ app: appName, ...options });
237
+ } else {
238
+ await app.createApp(appName, options);
239
+ }
136
240
  } catch (error) {
137
241
  handleCommandError(error, 'create');
138
242
  process.exit(1);
139
243
  }
140
244
  });
141
245
 
246
+ program.command('wizard')
247
+ .description('Interactive wizard for creating external systems')
248
+ .option('-a, --app <app>', 'Application name (if not provided, will prompt)')
249
+ .option('-c, --controller <url>', 'Controller URL')
250
+ .option('-e, --environment <env>', 'Environment (dev, tst, pro)', 'dev')
251
+ .option('--dataplane <url>', 'Dataplane URL (overrides controller lookup)')
252
+ .action(async(options) => {
253
+ try {
254
+ const { handleWizard } = require('./commands/wizard');
255
+ await handleWizard(options);
256
+ } catch (error) {
257
+ handleCommandError(error, 'wizard');
258
+ process.exit(1);
259
+ }
260
+ });
261
+
142
262
  program.command('build <app>')
143
263
  .description('Build container image (auto-detects runtime)')
144
264
  .option('-l, --language <lang>', 'Override language detection')
@@ -167,7 +287,6 @@ function setupCommands(program) {
167
287
  }
168
288
  });
169
289
 
170
- // Deployment commands
171
290
  program.command('push <app>')
172
291
  .description('Push image to Azure Container Registry')
173
292
  .option('-r, --registry <registry>', 'ACR registry URL (overrides variables.yaml)')
@@ -181,14 +300,47 @@ function setupCommands(program) {
181
300
  }
182
301
  });
183
302
 
184
- // Environment deployment command
185
- const environment = program
186
- .command('environment')
187
- .description('Manage environments');
303
+ program.command('deploy <app>')
304
+ .description('Deploy to Azure via Miso Controller')
305
+ .option('-c, --controller <url>', 'Controller URL')
306
+ .option('-e, --environment <env>', 'Environment (miso, dev, tst, pro)', 'dev')
307
+ .option('--client-id <id>', 'Client ID (overrides config)')
308
+ .option('--client-secret <secret>', 'Client Secret (overrides config)')
309
+ .option('--poll', 'Poll for deployment status', true)
310
+ .option('--no-poll', 'Do not poll for status')
311
+ .action(async(appName, options) => {
312
+ try {
313
+ await app.deployApp(appName, options);
314
+ } catch (error) {
315
+ handleCommandError(error, 'deploy');
316
+ process.exit(1);
317
+ }
318
+ });
188
319
 
320
+ program.command('dockerfile <app>')
321
+ .description('Generate Dockerfile for an application')
322
+ .option('-l, --language <lang>', 'Override language detection')
323
+ .option('-f, --force', 'Overwrite existing Dockerfile')
324
+ .action(async(appName, options) => {
325
+ try {
326
+ const dockerfilePath = await app.generateDockerfileForApp(appName, options);
327
+ logger.log(chalk.green('\n✅ Dockerfile generated successfully!'));
328
+ logger.log(chalk.gray(`Location: ${dockerfilePath}`));
329
+ } catch (error) {
330
+ handleCommandError(error, 'dockerfile');
331
+ process.exit(1);
332
+ }
333
+ });
334
+ }
335
+
336
+ /**
337
+ * Sets up environment deployment commands
338
+ * @param {Command} program - Commander program instance
339
+ */
340
+ function setupEnvironmentCommands(program) {
189
341
  const deployEnvHandler = async(envKey, options) => {
190
342
  try {
191
- const environmentDeploy = require('./environment-deploy');
343
+ const environmentDeploy = require('./deployment/environment');
192
344
  await environmentDeploy.deployEnvironment(envKey, options);
193
345
  } catch (error) {
194
346
  handleCommandError(error, 'environment deploy');
@@ -196,6 +348,10 @@ function setupCommands(program) {
196
348
  }
197
349
  };
198
350
 
351
+ const environment = program
352
+ .command('environment')
353
+ .description('Manage environments');
354
+
199
355
  environment
200
356
  .command('deploy <env>')
201
357
  .description('Deploy/setup environment in Miso Controller')
@@ -220,114 +376,13 @@ function setupCommands(program) {
220
376
  .option('--poll', 'Poll for deployment status', true)
221
377
  .option('--no-poll', 'Do not poll for status')
222
378
  .action(deployEnvHandler);
379
+ }
223
380
 
224
- program.command('deploy <app>')
225
- .description('Deploy to Azure via Miso Controller')
226
- .option('-c, --controller <url>', 'Controller URL')
227
- .option('-e, --environment <env>', 'Environment (miso, dev, tst, pro)', 'dev')
228
- .option('--client-id <id>', 'Client ID (overrides config)')
229
- .option('--client-secret <secret>', 'Client Secret (overrides config)')
230
- .option('--poll', 'Poll for deployment status', true)
231
- .option('--no-poll', 'Do not poll for status')
232
- .action(async(appName, options) => {
233
- try {
234
- await app.deployApp(appName, options);
235
- } catch (error) {
236
- handleCommandError(error, 'deploy');
237
- process.exit(1);
238
- }
239
- });
240
-
241
- // Infrastructure status and management
242
- program.command('doctor')
243
- .description('Check environment and configuration')
244
- .action(async() => {
245
- try {
246
- const result = await validator.checkEnvironment();
247
- logger.log('\n🔍 AI Fabrix Environment Check\n');
248
-
249
- logger.log(`Docker: ${result.docker === 'ok' ? '✅ Running' : '❌ Not available'}`);
250
- logger.log(`Ports: ${result.ports === 'ok' ? '✅ Available' : '⚠️ Some ports in use'}`);
251
- logger.log(`Secrets: ${result.secrets === 'ok' ? '✅ Configured' : '❌ Missing'}`);
252
-
253
- if (result.recommendations.length > 0) {
254
- logger.log('\n📋 Recommendations:');
255
- result.recommendations.forEach(rec => logger.log(` • ${rec}`));
256
- }
257
-
258
- // Check infrastructure health if Docker is available
259
- if (result.docker === 'ok') {
260
- try {
261
- const health = await infra.checkInfraHealth();
262
- logger.log('\n🏥 Infrastructure Health:');
263
- Object.entries(health).forEach(([service, status]) => {
264
- const icon = status === 'healthy' ? '✅' : status === 'unknown' ? '❓' : '❌';
265
- logger.log(` ${icon} ${service}: ${status}`);
266
- });
267
- } catch (error) {
268
- logger.log('\n🏥 Infrastructure: Not running');
269
- }
270
- }
271
-
272
- logger.log('');
273
- } catch (error) {
274
- handleCommandError(error, 'doctor');
275
- process.exit(1);
276
- }
277
- });
278
-
279
- program.command('status')
280
- .description('Show detailed infrastructure service status and running applications')
281
- .action(async() => {
282
- try {
283
- const status = await infra.getInfraStatus();
284
- logger.log('\n📊 Infrastructure Status\n');
285
-
286
- Object.entries(status).forEach(([service, info]) => {
287
- // Normalize status value for comparison (handle edge cases)
288
- const normalizedStatus = String(info.status).trim().toLowerCase();
289
- const icon = normalizedStatus === 'running' ? '✅' : '❌';
290
- logger.log(`${icon} ${service}:`);
291
- logger.log(` Status: ${info.status}`);
292
- logger.log(` Port: ${info.port}`);
293
- logger.log(` URL: ${info.url}`);
294
- logger.log('');
295
- });
296
-
297
- // Show running applications
298
- const apps = await infra.getAppStatus();
299
- if (apps.length > 0) {
300
- logger.log('📱 Running Applications\n');
301
- apps.forEach((app) => {
302
- const normalizedStatus = String(app.status).trim().toLowerCase();
303
- const icon = normalizedStatus.includes('running') || normalizedStatus.includes('up') ? '✅' : '❌';
304
- logger.log(`${icon} ${app.name}:`);
305
- logger.log(` Container: ${app.container}`);
306
- logger.log(` Port: ${app.port}`);
307
- logger.log(` Status: ${app.status}`);
308
- logger.log(` URL: ${app.url}`);
309
- logger.log('');
310
- });
311
- }
312
- } catch (error) {
313
- handleCommandError(error, 'status');
314
- process.exit(1);
315
- }
316
- });
317
-
318
- program.command('restart <service>')
319
- .description('Restart a specific infrastructure service')
320
- .action(async(service) => {
321
- try {
322
- await infra.restartService(service);
323
- logger.log(`✅ ${service} service restarted successfully`);
324
- } catch (error) {
325
- handleCommandError(error, 'restart');
326
- process.exit(1);
327
- }
328
- });
329
-
330
- // Utility commands
381
+ /**
382
+ * Sets up utility commands
383
+ * @param {Command} program - Commander program instance
384
+ */
385
+ function setupUtilityCommands(program) {
331
386
  program.command('resolve <app>')
332
387
  .description('Generate .env file from template and validate application files')
333
388
  .option('-f, --force', 'Generate missing secret keys in secrets file')
@@ -341,7 +396,7 @@ function setupCommands(program) {
341
396
 
342
397
  // Validate application files after generating .env
343
398
  if (!options.skipValidation) {
344
- const validate = require('./validate');
399
+ const validate = require('./validation/validate');
345
400
  const result = await validate.validateAppOrFile(appName);
346
401
  validate.displayValidationResults(result);
347
402
  if (!result.valid) {
@@ -439,12 +494,11 @@ function setupCommands(program) {
439
494
  }
440
495
  });
441
496
 
442
- // Validation command
443
497
  program.command('validate <appOrFile>')
444
498
  .description('Validate application or external integration file')
445
499
  .action(async(appOrFile) => {
446
500
  try {
447
- const validate = require('./validate');
501
+ const validate = require('./validation/validate');
448
502
  const result = await validate.validateAppOrFile(appOrFile);
449
503
  validate.displayValidationResults(result);
450
504
  if (!result.valid) {
@@ -456,12 +510,11 @@ function setupCommands(program) {
456
510
  }
457
511
  });
458
512
 
459
- // Diff command
460
513
  program.command('diff <file1> <file2>')
461
514
  .description('Compare two configuration files (for deployment pipeline)')
462
515
  .action(async(file1, file2) => {
463
516
  try {
464
- const diff = require('./diff');
517
+ const diff = require('./core/diff');
465
518
  const result = await diff.compareFiles(file1, file2);
466
519
  diff.formatDiffOutput(result);
467
520
  if (!result.identical) {
@@ -472,54 +525,46 @@ function setupCommands(program) {
472
525
  process.exit(1);
473
526
  }
474
527
  });
528
+ }
475
529
 
476
- program.command('dockerfile <app>')
477
- .description('Generate Dockerfile for an application')
478
- .option('-l, --language <lang>', 'Override language detection')
479
- .option('-f, --force', 'Overwrite existing Dockerfile')
480
- .action(async(appName, options) => {
481
- try {
482
- const dockerfilePath = await app.generateDockerfileForApp(appName, options);
483
- logger.log(chalk.green('\n✅ Dockerfile generated successfully!'));
484
- logger.log(chalk.gray(`Location: ${dockerfilePath}`));
485
- } catch (error) {
486
- handleCommandError(error, 'dockerfile');
487
- process.exit(1);
488
- }
489
- });
530
+ /**
531
+ * Helper function to display developer configuration
532
+ * @param {string} devId - Developer ID
533
+ */
534
+ async function displayDevConfig(devId) {
535
+ const devIdNum = parseInt(devId, 10);
536
+ const ports = devConfig.getDevPorts(devIdNum);
537
+ const configVars = [
538
+ { key: 'aifabrix-home', value: await config.getAifabrixHomeOverride() },
539
+ { key: 'aifabrix-secrets', value: await config.getAifabrixSecretsPath() },
540
+ { key: 'aifabrix-env-config', value: await config.getAifabrixEnvConfigPath() }
541
+ ].filter(v => v.value);
542
+
543
+ logger.log('\n🔧 Developer Configuration\n');
544
+ logger.log(`Developer ID: ${devId}`);
545
+ logger.log('\nPorts:');
546
+ logger.log(` App: ${ports.app}`);
547
+ logger.log(` Postgres: ${ports.postgres}`);
548
+ logger.log(` Redis: ${ports.redis}`);
549
+ logger.log(` pgAdmin: ${ports.pgadmin}`);
550
+ logger.log(` Redis Commander: ${ports.redisCommander}`);
551
+
552
+ if (configVars.length > 0) {
553
+ logger.log('\nConfiguration:');
554
+ configVars.forEach(v => logger.log(` ${v.key}: ${v.value}`));
555
+ }
556
+ logger.log('');
557
+ }
490
558
 
491
- // Developer configuration commands
559
+ /**
560
+ * Sets up developer configuration commands
561
+ * @param {Command} program - Commander program instance
562
+ */
563
+ function setupDevCommands(program) {
492
564
  const dev = program
493
565
  .command('dev')
494
566
  .description('Developer configuration and isolation');
495
567
 
496
- // Helper function to display developer configuration
497
- async function displayDevConfig(devId) {
498
- const devIdNum = parseInt(devId, 10);
499
- const ports = devConfig.getDevPorts(devIdNum);
500
- const configVars = [
501
- { key: 'aifabrix-home', value: await config.getAifabrixHomeOverride() },
502
- { key: 'aifabrix-secrets', value: await config.getAifabrixSecretsPath() },
503
- { key: 'aifabrix-env-config', value: await config.getAifabrixEnvConfigPath() }
504
- ].filter(v => v.value);
505
-
506
- logger.log('\n🔧 Developer Configuration\n');
507
- logger.log(`Developer ID: ${devId}`);
508
- logger.log('\nPorts:');
509
- logger.log(` App: ${ports.app}`);
510
- logger.log(` Postgres: ${ports.postgres}`);
511
- logger.log(` Redis: ${ports.redis}`);
512
- logger.log(` pgAdmin: ${ports.pgadmin}`);
513
- logger.log(` Redis Commander: ${ports.redisCommander}`);
514
-
515
- if (configVars.length > 0) {
516
- logger.log('\nConfiguration:');
517
- configVars.forEach(v => logger.log(` ${v.key}: ${v.value}`));
518
- }
519
- logger.log('');
520
- }
521
-
522
- // Config subcommand
523
568
  dev
524
569
  .command('config')
525
570
  .description('Show or set developer configuration')
@@ -550,7 +595,6 @@ function setupCommands(program) {
550
595
  }
551
596
  });
552
597
 
553
- // Set-id subcommand
554
598
  dev
555
599
  .command('set-id <id>')
556
600
  .description('Set developer ID (convenience alias for "dev config --set-id")')
@@ -571,8 +615,13 @@ function setupCommands(program) {
571
615
  process.exit(1);
572
616
  }
573
617
  });
618
+ }
574
619
 
575
- // Secrets management commands
620
+ /**
621
+ * Sets up secrets and security commands
622
+ * @param {Command} program - Commander program instance
623
+ */
624
+ function setupSecretsCommands(program) {
576
625
  const secretsCmd = program
577
626
  .command('secrets')
578
627
  .description('Manage secrets in secrets files');
@@ -590,7 +639,6 @@ function setupCommands(program) {
590
639
  }
591
640
  });
592
641
 
593
- // Security command
594
642
  program.command('secure')
595
643
  .description('Encrypt secrets in secrets.local.yaml files for ISO 27001 compliance')
596
644
  .option('--secrets-encryption <key>', 'Encryption key (32 bytes, hex or base64)')
@@ -602,8 +650,13 @@ function setupCommands(program) {
602
650
  process.exit(1);
603
651
  }
604
652
  });
653
+ }
605
654
 
606
- // External system download command
655
+ /**
656
+ * Sets up external system commands
657
+ * @param {Command} program - Commander program instance
658
+ */
659
+ function setupExternalSystemCommands(program) {
607
660
  program.command('download <system-key>')
608
661
  .description('Download external system from dataplane to local development structure')
609
662
  .option('-e, --environment <env>', 'Environment (dev, tst, pro)', 'dev')
@@ -611,7 +664,7 @@ function setupCommands(program) {
611
664
  .option('--dry-run', 'Show what would be downloaded without actually downloading')
612
665
  .action(async(systemKey, options) => {
613
666
  try {
614
- const download = require('./external-system-download');
667
+ const download = require('./external-system/download');
615
668
  await download.downloadExternalSystem(systemKey, options);
616
669
  } catch (error) {
617
670
  handleCommandError(error, 'download');
@@ -619,14 +672,13 @@ function setupCommands(program) {
619
672
  }
620
673
  });
621
674
 
622
- // Unit test command (local validation)
623
675
  program.command('test <app>')
624
676
  .description('Run unit tests for external system (local validation, no API calls)')
625
677
  .option('-d, --datasource <key>', 'Test specific datasource only')
626
678
  .option('-v, --verbose', 'Show detailed validation output')
627
679
  .action(async(appName, options) => {
628
680
  try {
629
- const test = require('./external-system-test');
681
+ const test = require('./external-system/test');
630
682
  const results = await test.testExternalSystem(appName, options);
631
683
  test.displayTestResults(results, options.verbose);
632
684
  if (!results.valid) {
@@ -638,7 +690,6 @@ function setupCommands(program) {
638
690
  }
639
691
  });
640
692
 
641
- // Integration test command (via dataplane)
642
693
  program.command('test-integration <app>')
643
694
  .description('Run integration tests via dataplane pipeline API')
644
695
  .option('-d, --datasource <key>', 'Test specific datasource only')
@@ -649,7 +700,7 @@ function setupCommands(program) {
649
700
  .option('--timeout <ms>', 'Request timeout in milliseconds', '30000')
650
701
  .action(async(appName, options) => {
651
702
  try {
652
- const test = require('./external-system-test');
703
+ const test = require('./external-system/test');
653
704
  const results = await test.testExternalSystemIntegration(appName, options);
654
705
  test.displayIntegrationTestResults(results, options.verbose);
655
706
  if (!results.success) {
@@ -662,6 +713,21 @@ function setupCommands(program) {
662
713
  });
663
714
  }
664
715
 
716
+ /**
717
+ * Sets up all CLI commands on the Commander program instance
718
+ * @param {Command} program - Commander program instance
719
+ */
720
+ function setupCommands(program) {
721
+ setupAuthCommands(program);
722
+ setupInfraCommands(program);
723
+ setupAppCommands(program);
724
+ setupEnvironmentCommands(program);
725
+ setupUtilityCommands(program);
726
+ setupDevCommands(program);
727
+ setupSecretsCommands(program);
728
+ setupExternalSystemCommands(program);
729
+ }
730
+
665
731
  module.exports = {
666
732
  setupCommands,
667
733
  validateCommand,
@@ -11,9 +11,9 @@
11
11
 
12
12
  const chalk = require('chalk');
13
13
  const logger = require('../utils/logger');
14
- const { listApplications } = require('../app-list');
15
- const { registerApplication } = require('../app-register');
16
- const { rotateSecret } = require('../app-rotate-secret');
14
+ const { listApplications } = require('../app/list');
15
+ const { registerApplication } = require('../app/register');
16
+ const { rotateSecret } = require('../app/rotate-secret');
17
17
 
18
18
  /**
19
19
  * Setup application management commands
@@ -11,10 +11,10 @@
11
11
 
12
12
  const chalk = require('chalk');
13
13
  const logger = require('../utils/logger');
14
- const { validateDatasourceFile } = require('../datasource-validate');
15
- const { listDatasources } = require('../datasource-list');
16
- const { compareDatasources } = require('../datasource-diff');
17
- const { deployDatasource } = require('../datasource-deploy');
14
+ const { validateDatasourceFile } = require('../datasource/validate');
15
+ const { listDatasources } = require('../datasource/list');
16
+ const { compareDatasources } = require('../datasource/diff');
17
+ const { deployDatasource } = require('../datasource/deploy');
18
18
 
19
19
  /**
20
20
  * Setup datasource management commands