@aifabrix/builder 2.41.0 → 2.42.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 (142) hide show
  1. package/.cursor/rules/docs-rules.mdc +30 -0
  2. package/README.md +2 -2
  3. package/integration/hubspot/README.md +11 -5
  4. package/integration/hubspot/application.json +54 -0
  5. package/integration/hubspot/create-hubspot.js +9 -136
  6. package/integration/hubspot/env.template +3 -4
  7. package/integration/hubspot/hubspot-datasource-company.json +343 -5
  8. package/integration/hubspot/hubspot-datasource-contact.json +413 -5
  9. package/integration/hubspot/hubspot-datasource-deal.json +341 -4
  10. package/integration/hubspot/hubspot-datasource-users.json +116 -0
  11. package/integration/hubspot/hubspot-deploy.json +1250 -108
  12. package/integration/hubspot/hubspot-system.json +15 -32
  13. package/integration/hubspot/test-dataplane-down-tests.js +17 -16
  14. package/integration/hubspot/test-dataplane-down.js +2 -2
  15. package/jest.config.manual.js +2 -1
  16. package/lib/api/external-test.api.js +111 -0
  17. package/lib/api/index.js +42 -19
  18. package/lib/api/pipeline.api.js +66 -120
  19. package/lib/api/types/pipeline.types.js +37 -0
  20. package/lib/api/wizard-platform.api.js +61 -0
  21. package/lib/api/wizard.api.js +36 -2
  22. package/lib/app/config.js +23 -11
  23. package/lib/app/index.js +5 -3
  24. package/lib/app/prompts.js +46 -31
  25. package/lib/app/readme.js +11 -4
  26. package/lib/app/run-env-compose.js +64 -1
  27. package/lib/app/run-helpers.js +1 -1
  28. package/lib/app/show-display.js +1 -1
  29. package/lib/cli/setup-app.js +45 -14
  30. package/lib/cli/setup-credential-deployment.js +31 -6
  31. package/lib/cli/setup-dev.js +27 -0
  32. package/lib/cli/setup-environment.js +12 -4
  33. package/lib/cli/setup-external-system.js +19 -4
  34. package/lib/cli/setup-infra.js +54 -14
  35. package/lib/cli/setup-utility.js +117 -21
  36. package/lib/commands/auth-config.js +22 -12
  37. package/lib/commands/credential-env.js +162 -0
  38. package/lib/commands/credential-list.js +17 -22
  39. package/lib/commands/credential-push.js +96 -0
  40. package/lib/commands/datasource.js +77 -6
  41. package/lib/commands/dev-init.js +39 -1
  42. package/lib/commands/repair-auth-config.js +99 -0
  43. package/lib/commands/repair-datasource-keys.js +208 -0
  44. package/lib/commands/repair-datasource.js +235 -0
  45. package/lib/commands/repair-env-template.js +348 -0
  46. package/lib/commands/repair-internal.js +85 -0
  47. package/lib/commands/repair-rbac.js +158 -0
  48. package/lib/commands/repair.js +518 -0
  49. package/lib/commands/secrets-set.js +6 -0
  50. package/lib/commands/test-e2e-external.js +165 -0
  51. package/lib/commands/up-dataplane.js +90 -6
  52. package/lib/commands/upload.js +71 -40
  53. package/lib/commands/wizard-core-helpers.js +230 -5
  54. package/lib/commands/wizard-core.js +68 -29
  55. package/lib/commands/wizard-dataplane.js +1 -1
  56. package/lib/commands/wizard-entity-selection.js +43 -0
  57. package/lib/commands/wizard-headless.js +49 -5
  58. package/lib/commands/wizard-helpers.js +7 -3
  59. package/lib/commands/wizard.js +93 -64
  60. package/lib/core/config.js +7 -1
  61. package/lib/core/secrets.js +33 -12
  62. package/lib/datasource/deploy.js +12 -3
  63. package/lib/datasource/test-e2e.js +219 -0
  64. package/lib/datasource/test-integration.js +154 -0
  65. package/lib/deployment/deployer.js +7 -5
  66. package/lib/external-system/download-helpers.js +3 -1
  67. package/lib/external-system/download.js +182 -204
  68. package/lib/external-system/generator.js +204 -56
  69. package/lib/external-system/test-execution.js +2 -1
  70. package/lib/external-system/test-system-level.js +73 -0
  71. package/lib/external-system/test.js +51 -18
  72. package/lib/generator/external-controller-manifest.js +29 -2
  73. package/lib/generator/external-schema-utils.js +4 -2
  74. package/lib/generator/external.js +10 -3
  75. package/lib/generator/index.js +4 -1
  76. package/lib/generator/split-readme.js +1 -0
  77. package/lib/generator/split-variables.js +7 -1
  78. package/lib/generator/split.js +194 -54
  79. package/lib/generator/wizard-prompts-secondary.js +326 -0
  80. package/lib/generator/wizard-prompts.js +105 -106
  81. package/lib/generator/wizard-readme.js +91 -0
  82. package/lib/generator/wizard.js +180 -179
  83. package/lib/infrastructure/compose.js +11 -1
  84. package/lib/infrastructure/index.js +11 -3
  85. package/lib/infrastructure/services.js +22 -11
  86. package/lib/schema/application-schema.json +8 -5
  87. package/lib/schema/external-datasource.schema.json +49 -26
  88. package/lib/schema/external-system.schema.json +82 -6
  89. package/lib/schema/wizard-config.schema.json +23 -1
  90. package/lib/utils/api.js +38 -10
  91. package/lib/utils/auth-headers.js +8 -7
  92. package/lib/utils/compose-generator.js +1 -1
  93. package/lib/utils/compose-handlebars-helpers.js +11 -0
  94. package/lib/utils/config-format-preference.js +51 -0
  95. package/lib/utils/config-format.js +36 -0
  96. package/lib/utils/configuration-env-resolver.js +179 -0
  97. package/lib/utils/credential-display.js +83 -0
  98. package/lib/utils/credential-secrets-env.js +115 -25
  99. package/lib/utils/dataplane-pipeline-warning.js +28 -0
  100. package/lib/utils/deployment-validation-helpers.js +4 -4
  101. package/lib/utils/dev-ca-install.js +139 -0
  102. package/lib/utils/env-copy.js +23 -3
  103. package/lib/utils/error-formatters/http-status-errors.js +0 -1
  104. package/lib/utils/error-formatters/permission-errors.js +0 -1
  105. package/lib/utils/error-formatters/validation-errors.js +0 -1
  106. package/lib/utils/external-readme.js +89 -30
  107. package/lib/utils/external-system-display.js +59 -1
  108. package/lib/utils/external-system-test-helpers.js +21 -8
  109. package/lib/utils/external-system-validators.js +3 -0
  110. package/lib/utils/file-upload.js +20 -50
  111. package/lib/utils/help-builder.js +1 -0
  112. package/lib/utils/infra-status.js +50 -44
  113. package/lib/utils/local-secrets.js +5 -5
  114. package/lib/utils/paths.js +85 -4
  115. package/lib/utils/secrets-canonical.js +93 -0
  116. package/lib/utils/secrets-generator.js +20 -0
  117. package/lib/utils/secrets-helpers.js +75 -89
  118. package/lib/utils/test-log-writer.js +56 -0
  119. package/lib/utils/token-manager.js +24 -32
  120. package/lib/validation/env-template-auth.js +157 -0
  121. package/lib/validation/env-template-kv.js +41 -0
  122. package/lib/validation/external-manifest-validator.js +25 -0
  123. package/lib/validation/external-system-auth-rules.js +86 -0
  124. package/lib/validation/validate-batch.js +149 -0
  125. package/lib/validation/validate-datasource-keys-api.js +33 -0
  126. package/lib/validation/validate-display.js +94 -16
  127. package/lib/validation/validate.js +25 -12
  128. package/lib/validation/validator.js +7 -9
  129. package/lib/validation/wizard-datasource-validation.js +50 -0
  130. package/package.json +7 -2
  131. package/templates/applications/dataplane/application.yaml +1 -1
  132. package/templates/applications/dataplane/env.template +5 -5
  133. package/templates/applications/dataplane/rbac.yaml +2 -2
  134. package/templates/applications/miso-controller/env.template +1 -1
  135. package/templates/external-system/README.md.hbs +75 -22
  136. package/templates/external-system/deploy.js.hbs +4 -2
  137. package/templates/external-system/external-datasource.yaml.hbs +217 -0
  138. package/templates/external-system/external-system.json.hbs +1 -18
  139. package/templates/infra/compose.yaml.hbs +6 -0
  140. package/templates/python/docker-compose.hbs +4 -4
  141. package/templates/typescript/docker-compose.hbs +4 -4
  142. package/integration/hubspot/application.yaml +0 -37
@@ -3,19 +3,21 @@
3
3
  * @author AI Fabrix Team
4
4
  * @version 2.0.0
5
5
  */
6
+ /* eslint-disable max-lines */
6
7
 
7
8
  const chalk = require('chalk');
8
9
  const ora = require('ora');
9
10
  const path = require('path');
10
11
  const fs = require('fs').promises;
11
12
  const logger = require('../utils/logger');
12
- const { getDeploymentAuth } = require('../utils/token-manager');
13
+ const { getDeploymentAuth, requireBearerForDataplanePipeline } = require('../utils/token-manager');
13
14
  const { resolveControllerUrl } = require('../utils/controller-url');
14
15
  const { normalizeWizardConfigs } = require('./wizard-config-normalizer');
15
16
  const {
16
17
  createWizardSession,
17
18
  updateWizardSession,
18
19
  detectType,
20
+ getPlatformConfig,
19
21
  generateConfig,
20
22
  validateWizardConfig,
21
23
  getDeploymentDocs,
@@ -29,9 +31,17 @@ const {
29
31
  runCredentialSelectionLoop,
30
32
  buildConfigPreferences,
31
33
  buildConfigPayload,
34
+ buildPlatformConfigPayload,
32
35
  extractConfigurationFromResponse,
33
- throwConfigGenerationError
36
+ writeDebugLog,
37
+ saveDebugManifestOnErrorAndThrow,
38
+ throwValidationFailureWithDebug,
39
+ resolveCredentialConfig,
40
+ fetchSystemsListForAddDatasource,
41
+ resolveExternalSystemForAddDatasource
34
42
  } = require('./wizard-core-helpers');
43
+ const { validateDatasourceKeysBeforePlatformConfig } = require('../validation/validate-datasource-keys-api');
44
+ const { handleEntitySelection } = require('./wizard-entity-selection');
35
45
 
36
46
  /**
37
47
  * Validate app name and check if directory exists
@@ -263,35 +273,57 @@ async function handleTypeDetection(dataplaneUrl, authConfig, openapiSpec) {
263
273
  * @param {Object} [options.configPrefs] - Preferences from wizard.yaml
264
274
  * @param {string} [options.credentialIdOrKey] - Credential ID or key (optional)
265
275
  * @param {string} [options.systemIdOrKey] - System ID or key (optional)
276
+ * @param {string} [options.sourceType] - Source type (use 'known-platform' to call platforms config endpoint)
277
+ * @param {string} [options.platformKey] - Platform key for known-platform (e.g. 'hubspot')
278
+ * @param {string} [options.appName] - App name for writing debug.log when debug=true
266
279
  * @returns {Promise<Object>} Generated configuration
267
280
  */
281
+ async function callGenerateApi(dataplaneUrl, authConfig, options, prefs) {
282
+ if (options.sourceType === 'known-platform' && options.platformKey) {
283
+ await validateDatasourceKeysBeforePlatformConfig(
284
+ dataplaneUrl, authConfig, options.platformKey, options.datasourceKeys
285
+ );
286
+ const platformPayload = buildPlatformConfigPayload({
287
+ credentialIdOrKey: options.credentialIdOrKey,
288
+ datasourceKeys: options.datasourceKeys,
289
+ configurationValues: options.configurationValues,
290
+ debug: prefs.debug
291
+ });
292
+ return await getPlatformConfig(dataplaneUrl, authConfig, options.platformKey, platformPayload);
293
+ }
294
+ const configPayload = buildConfigPayload({
295
+ openapiSpec: options.openapiSpec,
296
+ detectedType: options.detectedType,
297
+ mode: options.mode,
298
+ prefs,
299
+ credentialIdOrKey: options.credentialIdOrKey,
300
+ systemIdOrKey: options.systemIdOrKey,
301
+ entityName: options.entityName,
302
+ systemDisplayName: options.systemDisplayName
303
+ });
304
+ return await generateConfig(dataplaneUrl, authConfig, configPayload);
305
+ }
268
306
 
269
307
  async function handleConfigurationGeneration(dataplaneUrl, authConfig, options) {
270
308
  logger.log(chalk.blue('\n\uD83D\uDCCB Step 5: Generate Configuration'));
271
309
  const prefs = buildConfigPreferences(options.configPrefs);
272
310
  const spinner = ora('Generating configuration via AI (10-30 seconds)...').start();
273
311
  try {
274
- const configPayload = buildConfigPayload({
275
- openapiSpec: options.openapiSpec,
276
- detectedType: options.detectedType,
277
- mode: options.mode,
278
- prefs,
279
- credentialIdOrKey: options.credentialIdOrKey,
280
- systemIdOrKey: options.systemIdOrKey
281
- });
282
- const generateResponse = await generateConfig(dataplaneUrl, authConfig, configPayload);
312
+ const generateResponse = await callGenerateApi(dataplaneUrl, authConfig, options, prefs);
283
313
  spinner.stop();
284
314
  if (!generateResponse.success) {
285
- throwConfigGenerationError(generateResponse);
315
+ await saveDebugManifestOnErrorAndThrow(generateResponse, { enableDebug: prefs.debug, appName: options.appName });
286
316
  }
287
317
  const result = extractConfigurationFromResponse(generateResponse);
288
318
  const normalized = normalizeWizardConfigs(result.systemConfig, result.datasourceConfigs);
319
+ if (prefs.debug && options.appName) {
320
+ const debugLog = generateResponse.data?.debugLog;
321
+ if (debugLog && typeof debugLog === 'string') {
322
+ await writeDebugLog(options.appName, debugLog);
323
+ }
324
+ }
289
325
  logger.log(chalk.green('\u2713 Configuration generated successfully'));
290
- return {
291
- systemConfig: normalized.systemConfig,
292
- datasourceConfigs: normalized.datasourceConfigs,
293
- systemKey: result.systemKey
294
- };
326
+ return { systemConfig: normalized.systemConfig, datasourceConfigs: normalized.datasourceConfigs, systemKey: result.systemKey };
295
327
  } catch (error) {
296
328
  spinner.stop();
297
329
  throw error;
@@ -306,9 +338,11 @@ async function handleConfigurationGeneration(dataplaneUrl, authConfig, options)
306
338
  * @param {Object} authConfig - Authentication configuration
307
339
  * @param {Object} systemConfig - System configuration
308
340
  * @param {Object[]} datasourceConfigs - Datasource configurations
341
+ * @param {Object} [options] - Optional options
342
+ * @param {boolean} [options.debug] - When true, save debug manifest on validation failure
343
+ * @param {string} [options.appName] - App name for writing debug files
309
344
  */
310
- // eslint-disable-next-line max-statements
311
- async function validateWizardConfiguration(dataplaneUrl, authConfig, systemConfig, datasourceConfigs) {
345
+ async function validateWizardConfiguration(dataplaneUrl, authConfig, systemConfig, datasourceConfigs, options = {}) {
312
346
  logger.log(chalk.blue('\n\uD83D\uDCCB Step 6: Validate Configuration'));
313
347
  const spinner = ora('Validating configuration...').start();
314
348
  try {
@@ -322,16 +356,13 @@ async function validateWizardConfiguration(dataplaneUrl, authConfig, systemConfi
322
356
  const errorDetail = validateResponse.errorData?.detail || validateResponse.errorData?.message;
323
357
  const errorMsg = errors.length > 0 ? errors.map(e => e.message || e).join(', ') : errorDetail || validateResponse.error || 'Validation failed';
324
358
  spinner.stop();
325
- throw new Error(`Configuration validation failed: ${errorMsg}`);
359
+ await throwValidationFailureWithDebug(validateResponse, systemConfig, configs, errorMsg, options);
326
360
  }
327
361
  if (validateResponse.data?.warnings?.length > 0) warnings.push(...validateResponse.data.warnings);
328
362
  }
329
363
  spinner.stop();
330
364
  logger.log(chalk.green('\u2713 Configuration validated successfully'));
331
- if (warnings.length > 0) {
332
- logger.log(chalk.yellow('\n\u26A0 Warnings:'));
333
- warnings.forEach(w => logger.log(chalk.yellow(` - ${w.message || w}`)));
334
- }
365
+ if (warnings.length > 0) logger.log(chalk.yellow('\n\u26A0 Warnings:\n' + warnings.map(w => ` - ${w.message || w}`).join('\n')));
335
366
  } catch (error) {
336
367
  spinner.stop();
337
368
  throw error;
@@ -370,7 +401,9 @@ async function tryUpdateReadmeFromDeploymentDocs(appPath, appName, dataplaneUrl,
370
401
  ? await postDeploymentDocs(dataplaneUrl, authConfig, systemKey, body)
371
402
  : await getDeploymentDocs(dataplaneUrl, authConfig, systemKey);
372
403
  const content = docsResponse?.data?.content ?? docsResponse?.content;
373
- if (content && typeof content === 'string') {
404
+ // Only overwrite README when the API returns substantial content; otherwise keep the template README
405
+ const MIN_README_LENGTH = 400;
406
+ if (content && typeof content === 'string' && content.trim().length >= MIN_README_LENGTH) {
374
407
  const readmePath = path.join(appPath, 'README.md');
375
408
  await fs.writeFile(readmePath, content, 'utf8');
376
409
  logger.log(chalk.gray(' Updated README.md from deployment-docs API (application config + deploy JSON).'));
@@ -393,7 +426,9 @@ async function handleFileSaving(appName, systemConfig, datasourceConfigs, system
393
426
  logger.log(chalk.blue('\n\uD83D\uDCCB Step 7: Save Files'));
394
427
  const spinner = ora('Saving files...').start();
395
428
  try {
396
- const generatedFiles = await generateWizardFiles(appName, systemConfig, datasourceConfigs, systemKey, { aiGeneratedReadme: null });
429
+ const config = require('../core/config');
430
+ const format = (await config.getFormat()) || 'yaml';
431
+ const generatedFiles = await generateWizardFiles(appName, systemConfig, datasourceConfigs, systemKey, { aiGeneratedReadme: null, format });
397
432
  if (systemKey && dataplaneUrl && authConfig && generatedFiles.appPath) {
398
433
  try {
399
434
  await tryUpdateReadmeFromDeploymentDocs(generatedFiles.appPath, appName, dataplaneUrl, authConfig, systemKey);
@@ -427,14 +462,14 @@ async function setupDataplaneAndAuth(options, appName) {
427
462
  const { resolveEnvironment } = require('../core/config');
428
463
  const environment = await resolveEnvironment();
429
464
  const controllerUrl = await resolveControllerUrl();
430
- // Prefer device token; use client token or client credentials when available.
431
- // Some dataplanes accept only client credentials; getDeploymentAuth tries all.
465
+ // getDeploymentAuth returns token-based auth only (Bearer); never client-credentials for app endpoints.
432
466
  let authConfig;
433
467
  try {
434
468
  authConfig = await getDeploymentAuth(controllerUrl, environment, appName);
435
469
  } catch (error) {
436
470
  throw new Error(`Authentication failed: ${error.message}`);
437
471
  }
472
+ requireBearerForDataplanePipeline(authConfig);
438
473
  const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
439
474
  let dataplaneUrl;
440
475
  try {
@@ -459,8 +494,12 @@ module.exports = {
459
494
  handleOpenApiParsing,
460
495
  handleCredentialSelection,
461
496
  handleTypeDetection,
497
+ handleEntitySelection,
462
498
  handleConfigurationGeneration,
463
499
  validateWizardConfiguration,
464
500
  handleFileSaving,
465
- setupDataplaneAndAuth
501
+ setupDataplaneAndAuth,
502
+ resolveCredentialConfig,
503
+ fetchSystemsListForAddDatasource,
504
+ resolveExternalSystemForAddDatasource
466
505
  };
@@ -59,7 +59,7 @@ function isNotFoundError(error) {
59
59
  function createDataplaneNotFoundError() {
60
60
  return new Error(
61
61
  'Could not discover dataplane URL from controller. No dataplane service application found in this environment. ' +
62
- 'Please provide the dataplane URL using --dataplane <url> flag.'
62
+ 'Ensure the dataplane service is registered in the controller.'
63
63
  );
64
64
  }
65
65
 
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @fileoverview Entity selection step for OpenAPI multi-entity wizard flow
3
+ * @author AI Fabrix Team
4
+ * @version 2.0.0
5
+ */
6
+
7
+ const chalk = require('chalk');
8
+ const logger = require('../utils/logger');
9
+ const { discoverEntities } = require('../api/wizard.api');
10
+ const { validateEntityNameForOpenApi } = require('../validation/wizard-datasource-validation');
11
+ const { promptForEntitySelection } = require('../generator/wizard-prompts');
12
+
13
+ /**
14
+ * Handle entity selection step (OpenAPI multi-entity).
15
+ * Calls discover-entities; if entities found, prompts user to select one.
16
+ * @async
17
+ * @param {string} dataplaneUrl - Dataplane URL
18
+ * @param {Object} authConfig - Authentication configuration
19
+ * @param {Object} openapiSpec - OpenAPI specification
20
+ * @returns {Promise<string|null>} Selected entity name or null (skip)
21
+ */
22
+ async function handleEntitySelection(dataplaneUrl, authConfig, openapiSpec) {
23
+ if (!openapiSpec || typeof openapiSpec !== 'object') return null;
24
+ try {
25
+ const response = await discoverEntities(dataplaneUrl, authConfig, openapiSpec);
26
+ const entities = response?.data?.entities;
27
+ if (!Array.isArray(entities) || entities.length === 0) return null;
28
+
29
+ logger.log(chalk.blue('\n\uD83D\uDCCB Step 4.5: Select Entity'));
30
+ const entityName = await promptForEntitySelection(entities);
31
+ const validation = validateEntityNameForOpenApi(entityName, entities);
32
+ if (!validation.valid) {
33
+ throw new Error(`Invalid entity '${entityName}'. Available: ${entities.map(e => e.name).join(', ')}`);
34
+ }
35
+ logger.log(chalk.green(`\u2713 Selected entity: ${entityName}`));
36
+ return entityName;
37
+ } catch (error) {
38
+ logger.log(chalk.yellow(`Warning: Entity discovery failed, using default: ${error.message}`));
39
+ return null;
40
+ }
41
+ }
42
+
43
+ module.exports = { handleEntitySelection };
@@ -22,6 +22,30 @@ const {
22
22
  handleFileSaving,
23
23
  setupDataplaneAndAuth
24
24
  } = require('./wizard-core');
25
+ const { discoverEntities } = require('../api/wizard.api');
26
+ const { validateEntityNameForOpenApi } = require('../validation/wizard-datasource-validation');
27
+ const { humanizeAppKey } = require('../generator/wizard-prompts-secondary');
28
+
29
+ /**
30
+ * Validate entityName for headless config (throws if invalid)
31
+ * @async
32
+ * @param {string} entityName - Entity from source
33
+ * @param {Object} openapiSpec - OpenAPI spec
34
+ * @param {string} sourceType - Source type
35
+ * @param {string} dataplaneUrl - Dataplane URL
36
+ * @param {Object} authConfig - Auth config
37
+ * @throws {Error} If entityName invalid
38
+ */
39
+ async function validateHeadlessEntityName(entityName, openapiSpec, sourceType, dataplaneUrl, authConfig) {
40
+ if (!entityName || !openapiSpec || sourceType === 'known-platform') return;
41
+ const discoverResponse = await discoverEntities(dataplaneUrl, authConfig, openapiSpec);
42
+ const entities = discoverResponse?.data?.entities || [];
43
+ const validation = validateEntityNameForOpenApi(entityName, entities);
44
+ if (!validation.valid) {
45
+ const available = entities.map(e => e.name).join(', ');
46
+ throw new Error(`Invalid entityName '${entityName}'. Available from discover-entities: ${available || 'none'}`);
47
+ }
48
+ }
25
49
 
26
50
  /**
27
51
  * Execute wizard flow from config file (headless mode)
@@ -30,11 +54,15 @@ const {
30
54
  * @param {Object} wizardConfig - Validated wizard configuration
31
55
  * @param {string} dataplaneUrl - Dataplane URL
32
56
  * @param {Object} authConfig - Authentication configuration
57
+ * @param {Object} [opts] - Optional overrides
58
+ * @param {boolean} [opts.debug] - Enable debug (CLI --debug); overrides wizard.yaml preferences.debug
33
59
  * @returns {Promise<void>} Resolves when wizard flow completes
34
60
  * @throws {Error} If wizard flow fails
35
61
  */
36
- async function executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig) {
62
+ async function executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig, opts = {}) {
37
63
  const { appName, mode, systemIdOrKey, source, credential, preferences } = wizardConfig;
64
+ const configPrefs = { ...preferences };
65
+ if (opts.debug === true) configPrefs.debug = true;
38
66
 
39
67
  // Step 1: Create Session
40
68
  const { sessionId } = await handleModeSelection(dataplaneUrl, authConfig, mode, systemIdOrKey);
@@ -51,18 +79,31 @@ async function executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig) {
51
79
  // Step 4: Detect Type
52
80
  const detectedType = await handleTypeDetection(dataplaneUrl, authConfig, openapiSpec);
53
81
 
82
+ await validateHeadlessEntityName(source?.entityName, openapiSpec, sourceType, dataplaneUrl, authConfig);
83
+
84
+ const systemDisplayName = wizardConfig.systemDisplayName ||
85
+ (mode === 'create-system' ? humanizeAppKey(appName) : undefined);
86
+
54
87
  // Step 5: Generate Configuration
55
88
  const { systemConfig, datasourceConfigs, systemKey } = await handleConfigurationGeneration(dataplaneUrl, authConfig, {
56
89
  mode,
57
90
  openapiSpec,
58
91
  detectedType,
59
- configPrefs: preferences,
92
+ configPrefs,
60
93
  credentialIdOrKey,
61
- systemIdOrKey
94
+ systemIdOrKey,
95
+ sourceType,
96
+ platformKey: sourceType === 'known-platform' ? sourceData : undefined,
97
+ datasourceKeys: source?.datasourceKeys,
98
+ configurationValues: source?.configurationValues,
99
+ entityName: source?.entityName,
100
+ appName,
101
+ systemDisplayName
62
102
  });
63
103
 
64
104
  // Step 6: Validate Configuration
65
- await validateWizardConfiguration(dataplaneUrl, authConfig, systemConfig, datasourceConfigs);
105
+ const debugOpts = opts.debug ? { debug: true, appName } : {};
106
+ await validateWizardConfiguration(dataplaneUrl, authConfig, systemConfig, datasourceConfigs, debugOpts);
66
107
 
67
108
  // Step 7: Save Files
68
109
  await handleFileSaving(
@@ -87,6 +128,9 @@ async function executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig) {
87
128
  async function handleWizardHeadless(options) {
88
129
  logger.log(chalk.blue('\n\uD83E\uDDD9 AI Fabrix External System Wizard (Headless Mode)\n'));
89
130
  logger.log(chalk.gray(`Reading configuration from: ${options.config}`));
131
+ if (options.debug) {
132
+ logger.log(chalk.gray('[DEBUG] Wizard debug mode enabled'));
133
+ }
90
134
 
91
135
  // Validate wizard config file
92
136
  const validationResult = await validateWizardConfigFile(options.config);
@@ -109,7 +153,7 @@ async function handleWizardHeadless(options) {
109
153
  const { dataplaneUrl, authConfig } = await setupDataplaneAndAuth(options, appName);
110
154
 
111
155
  // Execute wizard flow from config
112
- await executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig);
156
+ await executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig, { debug: options.debug });
113
157
  }
114
158
 
115
159
  module.exports = { handleWizardHeadless, executeWizardFromConfig };
@@ -10,15 +10,17 @@ const chalk = require('chalk');
10
10
  const logger = require('../utils/logger');
11
11
 
12
12
  /**
13
- * Build preferences object for wizard.yaml (schema shape: intent, fieldOnboardingLevel, enableOpenAPIGeneration, enableMCP, enableABAC, enableRBAC)
13
+ * Build preferences object for wizard.yaml (schema shape: intent, fieldOnboardingLevel, enableOpenAPIGeneration, enableMCP, enableABAC, enableRBAC, debug)
14
14
  * @param {string} intent - User intent
15
15
  * @param {Object} preferences - From promptForUserPreferences (fieldOnboardingLevel, mcp, abac, rbac)
16
+ * @param {Object} [opts] - Optional overrides
17
+ * @param {boolean} [opts.debug] - Enable debug (CLI --debug); saved to wizard.yaml for headless runs
16
18
  * @returns {Object} Preferences for wizard-config schema
17
19
  */
18
- function buildPreferencesForSave(intent, preferences) {
20
+ function buildPreferencesForSave(intent, preferences, opts = {}) {
19
21
  const level = preferences?.fieldOnboardingLevel;
20
22
  const validLevel = level === 'standard' || level === 'minimal' ? level : 'full';
21
- return {
23
+ const result = {
22
24
  intent: intent || 'general integration',
23
25
  fieldOnboardingLevel: validLevel,
24
26
  enableOpenAPIGeneration: true,
@@ -26,6 +28,8 @@ function buildPreferencesForSave(intent, preferences) {
26
28
  enableABAC: Boolean(preferences?.abac),
27
29
  enableRBAC: Boolean(preferences?.rbac)
28
30
  };
31
+ if (opts.debug === true || preferences?.debug === true) result.debug = true;
32
+ return result;
29
33
  }
30
34
 
31
35
  /**