@aifabrix/builder 2.40.2 → 2.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/docs-rules.mdc +30 -0
- package/README.md +7 -5
- package/integration/hubspot/README.md +8 -4
- package/integration/hubspot/application.json +54 -0
- package/integration/hubspot/create-hubspot.js +9 -136
- package/integration/hubspot/env.template +3 -4
- package/integration/hubspot/hubspot-datasource-company.json +343 -5
- package/integration/hubspot/hubspot-datasource-contact.json +413 -5
- package/integration/hubspot/hubspot-datasource-deal.json +341 -4
- package/integration/hubspot/hubspot-datasource-users.json +116 -0
- package/integration/hubspot/hubspot-deploy.json +1250 -108
- package/integration/hubspot/hubspot-system.json +15 -32
- package/integration/hubspot/test-dataplane-down-tests.js +17 -16
- package/integration/hubspot/test-dataplane-down.js +2 -2
- package/integration/hubspot/test.js +1 -1
- package/jest.config.manual.js +2 -1
- package/lib/api/credential.api.js +40 -0
- package/lib/api/dev.api.js +423 -0
- package/lib/api/external-test.api.js +111 -0
- package/lib/api/index.js +42 -19
- package/lib/api/pipeline.api.js +66 -120
- package/lib/api/types/credential.types.js +23 -0
- package/lib/api/types/dev.types.js +140 -0
- package/lib/api/types/pipeline.types.js +37 -0
- package/lib/api/wizard-platform.api.js +61 -0
- package/lib/api/wizard.api.js +34 -1
- package/lib/app/config.js +44 -11
- package/lib/app/down.js +2 -1
- package/lib/app/index.js +12 -1
- package/lib/app/prompts.js +44 -29
- package/lib/app/push.js +36 -12
- package/lib/app/readme.js +9 -6
- package/lib/app/run-env-compose.js +264 -0
- package/lib/app/run-helpers.js +121 -118
- package/lib/app/run.js +148 -28
- package/lib/app/show-display.js +1 -1
- package/lib/app/show.js +5 -2
- package/lib/build/index.js +11 -3
- package/lib/cli/setup-app.js +172 -15
- package/lib/cli/setup-credential-deployment.js +31 -6
- package/lib/cli/setup-dev.js +206 -16
- package/lib/cli/setup-environment.js +16 -6
- package/lib/cli/setup-external-system.js +89 -24
- package/lib/cli/setup-infra.js +82 -15
- package/lib/cli/setup-secrets.js +52 -5
- package/lib/cli/setup-utility.js +129 -24
- package/lib/commands/app-install.js +172 -0
- package/lib/commands/app-shell.js +75 -0
- package/lib/commands/app-test.js +282 -0
- package/lib/commands/app.js +1 -1
- package/lib/commands/credential-env.js +162 -0
- package/lib/commands/credential-list.js +17 -22
- package/lib/commands/credential-push.js +96 -0
- package/lib/commands/datasource.js +77 -6
- package/lib/commands/dev-cli-handlers.js +141 -0
- package/lib/commands/dev-down.js +114 -0
- package/lib/commands/dev-init.js +347 -0
- package/lib/commands/repair-auth-config.js +99 -0
- package/lib/commands/repair-datasource-keys.js +208 -0
- package/lib/commands/repair-datasource.js +235 -0
- package/lib/commands/repair-env-template.js +348 -0
- package/lib/commands/repair-internal.js +85 -0
- package/lib/commands/repair-rbac.js +158 -0
- package/lib/commands/repair.js +507 -0
- package/lib/commands/secrets-list.js +118 -0
- package/lib/commands/secrets-remove.js +97 -0
- package/lib/commands/secrets-set.js +30 -17
- package/lib/commands/secrets-validate.js +50 -0
- package/lib/commands/test-e2e-external.js +165 -0
- package/lib/commands/up-dataplane.js +2 -2
- package/lib/commands/up-miso.js +0 -25
- package/lib/commands/upload.js +96 -40
- package/lib/commands/wizard-core-helpers.js +226 -4
- package/lib/commands/wizard-core.js +67 -29
- package/lib/commands/wizard-dataplane.js +1 -1
- package/lib/commands/wizard-entity-selection.js +43 -0
- package/lib/commands/wizard-headless.js +44 -5
- package/lib/commands/wizard-helpers.js +7 -3
- package/lib/commands/wizard.js +86 -64
- package/lib/core/admin-secrets.js +96 -0
- package/lib/core/config.js +7 -1
- package/lib/core/secrets-ensure.js +378 -0
- package/lib/core/secrets-env-write.js +157 -0
- package/lib/core/secrets.js +176 -89
- package/lib/datasource/deploy.js +12 -3
- package/lib/datasource/field-reference-validator.js +91 -0
- package/lib/datasource/test-e2e.js +219 -0
- package/lib/datasource/test-integration.js +154 -0
- package/lib/datasource/validate.js +21 -3
- package/lib/deployment/deployer.js +7 -5
- package/lib/deployment/environment-config.js +137 -0
- package/lib/deployment/environment.js +21 -98
- package/lib/deployment/push.js +32 -2
- package/lib/external-system/download.js +188 -203
- package/lib/external-system/generator.js +204 -56
- package/lib/external-system/test-auth.js +7 -3
- package/lib/external-system/test-execution.js +2 -1
- package/lib/external-system/test-system-level.js +73 -0
- package/lib/external-system/test.js +56 -19
- package/lib/generator/external-controller-manifest.js +29 -2
- package/lib/generator/external-schema-utils.js +1 -1
- package/lib/generator/external.js +10 -3
- package/lib/generator/index.js +177 -25
- package/lib/generator/split-readme.js +1 -0
- package/lib/generator/split-variables.js +7 -1
- package/lib/generator/split.js +194 -54
- package/lib/generator/wizard-prompts-secondary.js +294 -0
- package/lib/generator/wizard-prompts.js +105 -106
- package/lib/generator/wizard-readme.js +88 -0
- package/lib/generator/wizard.js +155 -158
- package/lib/infrastructure/compose.js +11 -1
- package/lib/infrastructure/helpers.js +103 -20
- package/lib/infrastructure/index.js +98 -12
- package/lib/infrastructure/services.js +88 -22
- package/lib/schema/application-schema.json +32 -8
- package/lib/schema/external-datasource.schema.json +49 -26
- package/lib/schema/external-system.schema.json +509 -411
- package/lib/schema/wizard-config.schema.json +16 -0
- package/lib/utils/api.js +41 -13
- package/lib/utils/app-register-auth.js +25 -3
- package/lib/utils/auth-headers.js +8 -7
- package/lib/utils/cli-utils.js +20 -0
- package/lib/utils/compose-generator.js +77 -76
- package/lib/utils/compose-handlebars-helpers.js +54 -0
- package/lib/utils/compose-vector-helper.js +18 -0
- package/lib/utils/config-format-preference.js +51 -0
- package/lib/utils/config-format.js +36 -0
- package/lib/utils/config-paths.js +127 -2
- package/lib/utils/configuration-env-resolver.js +179 -0
- package/lib/utils/credential-display.js +83 -0
- package/lib/utils/credential-secrets-env.js +357 -0
- package/lib/utils/dataplane-pipeline-warning.js +28 -0
- package/lib/utils/deployment-validation-helpers.js +4 -4
- package/lib/utils/dev-ca-install.js +139 -0
- package/lib/utils/dev-cert-helper.js +122 -0
- package/lib/utils/device-code-helpers.js +224 -0
- package/lib/utils/device-code.js +37 -336
- package/lib/utils/docker-build.js +40 -8
- package/lib/utils/env-copy.js +103 -13
- package/lib/utils/env-map.js +35 -5
- package/lib/utils/env-template.js +6 -5
- package/lib/utils/error-formatters/http-status-errors.js +20 -2
- package/lib/utils/error-formatters/permission-errors.js +0 -1
- package/lib/utils/error-formatters/validation-errors.js +0 -1
- package/lib/utils/external-readme.js +56 -29
- package/lib/utils/external-system-display.js +59 -1
- package/lib/utils/external-system-test-helpers.js +21 -8
- package/lib/utils/external-system-validators.js +3 -0
- package/lib/utils/file-upload.js +20 -50
- package/lib/utils/help-builder.js +16 -2
- package/lib/utils/infra-status.js +80 -45
- package/lib/utils/local-secrets.js +7 -52
- package/lib/utils/mutagen-install.js +195 -0
- package/lib/utils/mutagen.js +146 -0
- package/lib/utils/paths.js +128 -37
- package/lib/utils/port-resolver.js +28 -16
- package/lib/utils/remote-dev-auth.js +38 -0
- package/lib/utils/remote-docker-env.js +43 -0
- package/lib/utils/remote-secrets-loader.js +60 -0
- package/lib/utils/secrets-canonical.js +93 -0
- package/lib/utils/secrets-generator.js +114 -6
- package/lib/utils/secrets-helpers.js +108 -114
- package/lib/utils/secrets-path.js +2 -2
- package/lib/utils/secrets-utils.js +52 -1
- package/lib/utils/secrets-validation.js +84 -0
- package/lib/utils/ssh-key-helper.js +116 -0
- package/lib/utils/test-log-writer.js +56 -0
- package/lib/utils/token-manager-messages.js +90 -0
- package/lib/utils/token-manager.js +29 -36
- package/lib/utils/variable-transformer.js +3 -3
- package/lib/validation/env-template-auth.js +157 -0
- package/lib/validation/env-template-kv.js +41 -0
- package/lib/validation/external-manifest-validator.js +25 -0
- package/lib/validation/external-system-auth-rules.js +86 -0
- package/lib/validation/validate-batch.js +149 -0
- package/lib/validation/validate-datasource-keys-api.js +33 -0
- package/lib/validation/validate-display.js +94 -16
- package/lib/validation/validate.js +25 -12
- package/lib/validation/validator.js +72 -9
- package/lib/validation/wizard-datasource-validation.js +50 -0
- package/package.json +8 -3
- package/scripts/install-local.js +34 -15
- package/templates/README.md +0 -1
- package/templates/applications/README.md.hbs +4 -4
- package/templates/applications/dataplane/application.yaml +6 -5
- package/templates/applications/dataplane/env.template +15 -10
- package/templates/applications/dataplane/rbac.yaml +2 -2
- package/templates/applications/keycloak/env.template +2 -0
- package/templates/applications/miso-controller/application.yaml +1 -0
- package/templates/applications/miso-controller/env.template +12 -10
- package/templates/external-system/README.md.hbs +65 -25
- package/templates/external-system/deploy.js.hbs +4 -2
- package/templates/external-system/external-datasource.yaml.hbs +217 -0
- package/templates/external-system/external-system.json.hbs +1 -18
- package/templates/infra/compose.yaml.hbs +6 -0
- package/templates/python/docker-compose.hbs +49 -23
- package/templates/typescript/docker-compose.hbs +48 -22
- 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
|
-
|
|
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,56 @@ 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
|
+
});
|
|
303
|
+
return await generateConfig(dataplaneUrl, authConfig, configPayload);
|
|
304
|
+
}
|
|
268
305
|
|
|
269
306
|
async function handleConfigurationGeneration(dataplaneUrl, authConfig, options) {
|
|
270
307
|
logger.log(chalk.blue('\n\uD83D\uDCCB Step 5: Generate Configuration'));
|
|
271
308
|
const prefs = buildConfigPreferences(options.configPrefs);
|
|
272
309
|
const spinner = ora('Generating configuration via AI (10-30 seconds)...').start();
|
|
273
310
|
try {
|
|
274
|
-
const
|
|
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);
|
|
311
|
+
const generateResponse = await callGenerateApi(dataplaneUrl, authConfig, options, prefs);
|
|
283
312
|
spinner.stop();
|
|
284
313
|
if (!generateResponse.success) {
|
|
285
|
-
|
|
314
|
+
await saveDebugManifestOnErrorAndThrow(generateResponse, { enableDebug: prefs.debug, appName: options.appName });
|
|
286
315
|
}
|
|
287
316
|
const result = extractConfigurationFromResponse(generateResponse);
|
|
288
317
|
const normalized = normalizeWizardConfigs(result.systemConfig, result.datasourceConfigs);
|
|
318
|
+
if (prefs.debug && options.appName) {
|
|
319
|
+
const debugLog = generateResponse.data?.debugLog;
|
|
320
|
+
if (debugLog && typeof debugLog === 'string') {
|
|
321
|
+
await writeDebugLog(options.appName, debugLog);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
289
324
|
logger.log(chalk.green('\u2713 Configuration generated successfully'));
|
|
290
|
-
return {
|
|
291
|
-
systemConfig: normalized.systemConfig,
|
|
292
|
-
datasourceConfigs: normalized.datasourceConfigs,
|
|
293
|
-
systemKey: result.systemKey
|
|
294
|
-
};
|
|
325
|
+
return { systemConfig: normalized.systemConfig, datasourceConfigs: normalized.datasourceConfigs, systemKey: result.systemKey };
|
|
295
326
|
} catch (error) {
|
|
296
327
|
spinner.stop();
|
|
297
328
|
throw error;
|
|
@@ -306,9 +337,11 @@ async function handleConfigurationGeneration(dataplaneUrl, authConfig, options)
|
|
|
306
337
|
* @param {Object} authConfig - Authentication configuration
|
|
307
338
|
* @param {Object} systemConfig - System configuration
|
|
308
339
|
* @param {Object[]} datasourceConfigs - Datasource configurations
|
|
340
|
+
* @param {Object} [options] - Optional options
|
|
341
|
+
* @param {boolean} [options.debug] - When true, save debug manifest on validation failure
|
|
342
|
+
* @param {string} [options.appName] - App name for writing debug files
|
|
309
343
|
*/
|
|
310
|
-
|
|
311
|
-
async function validateWizardConfiguration(dataplaneUrl, authConfig, systemConfig, datasourceConfigs) {
|
|
344
|
+
async function validateWizardConfiguration(dataplaneUrl, authConfig, systemConfig, datasourceConfigs, options = {}) {
|
|
312
345
|
logger.log(chalk.blue('\n\uD83D\uDCCB Step 6: Validate Configuration'));
|
|
313
346
|
const spinner = ora('Validating configuration...').start();
|
|
314
347
|
try {
|
|
@@ -322,16 +355,13 @@ async function validateWizardConfiguration(dataplaneUrl, authConfig, systemConfi
|
|
|
322
355
|
const errorDetail = validateResponse.errorData?.detail || validateResponse.errorData?.message;
|
|
323
356
|
const errorMsg = errors.length > 0 ? errors.map(e => e.message || e).join(', ') : errorDetail || validateResponse.error || 'Validation failed';
|
|
324
357
|
spinner.stop();
|
|
325
|
-
|
|
358
|
+
await throwValidationFailureWithDebug(validateResponse, systemConfig, configs, errorMsg, options);
|
|
326
359
|
}
|
|
327
360
|
if (validateResponse.data?.warnings?.length > 0) warnings.push(...validateResponse.data.warnings);
|
|
328
361
|
}
|
|
329
362
|
spinner.stop();
|
|
330
363
|
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
|
-
}
|
|
364
|
+
if (warnings.length > 0) logger.log(chalk.yellow('\n\u26A0 Warnings:\n' + warnings.map(w => ` - ${w.message || w}`).join('\n')));
|
|
335
365
|
} catch (error) {
|
|
336
366
|
spinner.stop();
|
|
337
367
|
throw error;
|
|
@@ -370,7 +400,9 @@ async function tryUpdateReadmeFromDeploymentDocs(appPath, appName, dataplaneUrl,
|
|
|
370
400
|
? await postDeploymentDocs(dataplaneUrl, authConfig, systemKey, body)
|
|
371
401
|
: await getDeploymentDocs(dataplaneUrl, authConfig, systemKey);
|
|
372
402
|
const content = docsResponse?.data?.content ?? docsResponse?.content;
|
|
373
|
-
|
|
403
|
+
// Only overwrite README when the API returns substantial content; otherwise keep the template README
|
|
404
|
+
const MIN_README_LENGTH = 400;
|
|
405
|
+
if (content && typeof content === 'string' && content.trim().length >= MIN_README_LENGTH) {
|
|
374
406
|
const readmePath = path.join(appPath, 'README.md');
|
|
375
407
|
await fs.writeFile(readmePath, content, 'utf8');
|
|
376
408
|
logger.log(chalk.gray(' Updated README.md from deployment-docs API (application config + deploy JSON).'));
|
|
@@ -393,7 +425,9 @@ async function handleFileSaving(appName, systemConfig, datasourceConfigs, system
|
|
|
393
425
|
logger.log(chalk.blue('\n\uD83D\uDCCB Step 7: Save Files'));
|
|
394
426
|
const spinner = ora('Saving files...').start();
|
|
395
427
|
try {
|
|
396
|
-
const
|
|
428
|
+
const config = require('../core/config');
|
|
429
|
+
const format = (await config.getFormat()) || 'yaml';
|
|
430
|
+
const generatedFiles = await generateWizardFiles(appName, systemConfig, datasourceConfigs, systemKey, { aiGeneratedReadme: null, format });
|
|
397
431
|
if (systemKey && dataplaneUrl && authConfig && generatedFiles.appPath) {
|
|
398
432
|
try {
|
|
399
433
|
await tryUpdateReadmeFromDeploymentDocs(generatedFiles.appPath, appName, dataplaneUrl, authConfig, systemKey);
|
|
@@ -427,14 +461,14 @@ async function setupDataplaneAndAuth(options, appName) {
|
|
|
427
461
|
const { resolveEnvironment } = require('../core/config');
|
|
428
462
|
const environment = await resolveEnvironment();
|
|
429
463
|
const controllerUrl = await resolveControllerUrl();
|
|
430
|
-
//
|
|
431
|
-
// Some dataplanes accept only client credentials; getDeploymentAuth tries all.
|
|
464
|
+
// getDeploymentAuth returns token-based auth only (Bearer); never client-credentials for app endpoints.
|
|
432
465
|
let authConfig;
|
|
433
466
|
try {
|
|
434
467
|
authConfig = await getDeploymentAuth(controllerUrl, environment, appName);
|
|
435
468
|
} catch (error) {
|
|
436
469
|
throw new Error(`Authentication failed: ${error.message}`);
|
|
437
470
|
}
|
|
471
|
+
requireBearerForDataplanePipeline(authConfig);
|
|
438
472
|
const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
|
|
439
473
|
let dataplaneUrl;
|
|
440
474
|
try {
|
|
@@ -459,8 +493,12 @@ module.exports = {
|
|
|
459
493
|
handleOpenApiParsing,
|
|
460
494
|
handleCredentialSelection,
|
|
461
495
|
handleTypeDetection,
|
|
496
|
+
handleEntitySelection,
|
|
462
497
|
handleConfigurationGeneration,
|
|
463
498
|
validateWizardConfiguration,
|
|
464
499
|
handleFileSaving,
|
|
465
|
-
setupDataplaneAndAuth
|
|
500
|
+
setupDataplaneAndAuth,
|
|
501
|
+
resolveCredentialConfig,
|
|
502
|
+
fetchSystemsListForAddDatasource,
|
|
503
|
+
resolveExternalSystemForAddDatasource
|
|
466
504
|
};
|
|
@@ -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
|
-
'
|
|
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,29 @@ 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
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Validate entityName for headless config (throws if invalid)
|
|
30
|
+
* @async
|
|
31
|
+
* @param {string} entityName - Entity from source
|
|
32
|
+
* @param {Object} openapiSpec - OpenAPI spec
|
|
33
|
+
* @param {string} sourceType - Source type
|
|
34
|
+
* @param {string} dataplaneUrl - Dataplane URL
|
|
35
|
+
* @param {Object} authConfig - Auth config
|
|
36
|
+
* @throws {Error} If entityName invalid
|
|
37
|
+
*/
|
|
38
|
+
async function validateHeadlessEntityName(entityName, openapiSpec, sourceType, dataplaneUrl, authConfig) {
|
|
39
|
+
if (!entityName || !openapiSpec || sourceType === 'known-platform') return;
|
|
40
|
+
const discoverResponse = await discoverEntities(dataplaneUrl, authConfig, openapiSpec);
|
|
41
|
+
const entities = discoverResponse?.data?.entities || [];
|
|
42
|
+
const validation = validateEntityNameForOpenApi(entityName, entities);
|
|
43
|
+
if (!validation.valid) {
|
|
44
|
+
const available = entities.map(e => e.name).join(', ');
|
|
45
|
+
throw new Error(`Invalid entityName '${entityName}'. Available from discover-entities: ${available || 'none'}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
25
48
|
|
|
26
49
|
/**
|
|
27
50
|
* Execute wizard flow from config file (headless mode)
|
|
@@ -30,11 +53,15 @@ const {
|
|
|
30
53
|
* @param {Object} wizardConfig - Validated wizard configuration
|
|
31
54
|
* @param {string} dataplaneUrl - Dataplane URL
|
|
32
55
|
* @param {Object} authConfig - Authentication configuration
|
|
56
|
+
* @param {Object} [opts] - Optional overrides
|
|
57
|
+
* @param {boolean} [opts.debug] - Enable debug (CLI --debug); overrides wizard.yaml preferences.debug
|
|
33
58
|
* @returns {Promise<void>} Resolves when wizard flow completes
|
|
34
59
|
* @throws {Error} If wizard flow fails
|
|
35
60
|
*/
|
|
36
|
-
async function executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig) {
|
|
61
|
+
async function executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig, opts = {}) {
|
|
37
62
|
const { appName, mode, systemIdOrKey, source, credential, preferences } = wizardConfig;
|
|
63
|
+
const configPrefs = { ...preferences };
|
|
64
|
+
if (opts.debug === true) configPrefs.debug = true;
|
|
38
65
|
|
|
39
66
|
// Step 1: Create Session
|
|
40
67
|
const { sessionId } = await handleModeSelection(dataplaneUrl, authConfig, mode, systemIdOrKey);
|
|
@@ -51,18 +78,27 @@ async function executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig) {
|
|
|
51
78
|
// Step 4: Detect Type
|
|
52
79
|
const detectedType = await handleTypeDetection(dataplaneUrl, authConfig, openapiSpec);
|
|
53
80
|
|
|
81
|
+
await validateHeadlessEntityName(source?.entityName, openapiSpec, sourceType, dataplaneUrl, authConfig);
|
|
82
|
+
|
|
54
83
|
// Step 5: Generate Configuration
|
|
55
84
|
const { systemConfig, datasourceConfigs, systemKey } = await handleConfigurationGeneration(dataplaneUrl, authConfig, {
|
|
56
85
|
mode,
|
|
57
86
|
openapiSpec,
|
|
58
87
|
detectedType,
|
|
59
|
-
configPrefs
|
|
88
|
+
configPrefs,
|
|
60
89
|
credentialIdOrKey,
|
|
61
|
-
systemIdOrKey
|
|
90
|
+
systemIdOrKey,
|
|
91
|
+
sourceType,
|
|
92
|
+
platformKey: sourceType === 'known-platform' ? sourceData : undefined,
|
|
93
|
+
datasourceKeys: source?.datasourceKeys,
|
|
94
|
+
configurationValues: source?.configurationValues,
|
|
95
|
+
entityName: source?.entityName,
|
|
96
|
+
appName
|
|
62
97
|
});
|
|
63
98
|
|
|
64
99
|
// Step 6: Validate Configuration
|
|
65
|
-
|
|
100
|
+
const debugOpts = opts.debug ? { debug: true, appName } : {};
|
|
101
|
+
await validateWizardConfiguration(dataplaneUrl, authConfig, systemConfig, datasourceConfigs, debugOpts);
|
|
66
102
|
|
|
67
103
|
// Step 7: Save Files
|
|
68
104
|
await handleFileSaving(
|
|
@@ -87,6 +123,9 @@ async function executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig) {
|
|
|
87
123
|
async function handleWizardHeadless(options) {
|
|
88
124
|
logger.log(chalk.blue('\n\uD83E\uDDD9 AI Fabrix External System Wizard (Headless Mode)\n'));
|
|
89
125
|
logger.log(chalk.gray(`Reading configuration from: ${options.config}`));
|
|
126
|
+
if (options.debug) {
|
|
127
|
+
logger.log(chalk.gray('[DEBUG] Wizard debug mode enabled'));
|
|
128
|
+
}
|
|
90
129
|
|
|
91
130
|
// Validate wizard config file
|
|
92
131
|
const validationResult = await validateWizardConfigFile(options.config);
|
|
@@ -109,7 +148,7 @@ async function handleWizardHeadless(options) {
|
|
|
109
148
|
const { dataplaneUrl, authConfig } = await setupDataplaneAndAuth(options, appName);
|
|
110
149
|
|
|
111
150
|
// Execute wizard flow from config
|
|
112
|
-
await executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig);
|
|
151
|
+
await executeWizardFromConfig(wizardConfig, dataplaneUrl, authConfig, { debug: options.debug });
|
|
113
152
|
}
|
|
114
153
|
|
|
115
154
|
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
|
-
|
|
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
|
/**
|
package/lib/commands/wizard.js
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
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 logger = require('../utils/logger');
|
|
9
10
|
const {
|
|
10
11
|
promptForMode,
|
|
11
|
-
|
|
12
|
+
promptForExistingSystem,
|
|
12
13
|
promptForSourceType,
|
|
13
14
|
promptForOpenApiFile,
|
|
14
15
|
promptForOpenApiUrl,
|
|
@@ -24,46 +25,30 @@ const {
|
|
|
24
25
|
const {
|
|
25
26
|
validateAndCheckAppDirectory,
|
|
26
27
|
formatDataplaneRejectedTokenMessage,
|
|
28
|
+
extractSessionId,
|
|
27
29
|
handleOpenApiParsing,
|
|
28
30
|
handleCredentialSelection,
|
|
29
31
|
handleTypeDetection,
|
|
32
|
+
handleEntitySelection,
|
|
30
33
|
handleConfigurationGeneration,
|
|
31
34
|
validateWizardConfiguration,
|
|
32
35
|
handleFileSaving,
|
|
33
|
-
setupDataplaneAndAuth
|
|
36
|
+
setupDataplaneAndAuth,
|
|
37
|
+
resolveCredentialConfig,
|
|
38
|
+
fetchSystemsListForAddDatasource,
|
|
39
|
+
resolveExternalSystemForAddDatasource
|
|
34
40
|
} = require('./wizard-core');
|
|
35
41
|
const { handleWizardHeadless } = require('./wizard-headless');
|
|
36
|
-
const { createWizardSession, updateWizardSession, getWizardPlatforms } = require('../api/wizard.api');
|
|
37
|
-
const { getExternalSystem } = require('../api/external-systems.api');
|
|
42
|
+
const { createWizardSession, updateWizardSession, getWizardPlatforms, getPreview } = require('../api/wizard.api');
|
|
38
43
|
const { writeWizardConfig, wizardConfigExists, validateWizardConfig } = require('../validation/wizard-config-validator');
|
|
39
44
|
const { appendWizardError } = require('../utils/cli-utils');
|
|
40
45
|
const {
|
|
41
46
|
buildPreferencesForSave,
|
|
42
47
|
buildWizardStateForSave,
|
|
43
48
|
showWizardConfigSummary,
|
|
44
|
-
ensureIntegrationDir
|
|
45
|
-
isExternalSystemForAddDatasource
|
|
49
|
+
ensureIntegrationDir
|
|
46
50
|
} = require('./wizard-helpers');
|
|
47
51
|
|
|
48
|
-
/**
|
|
49
|
-
* Extract session ID from response data
|
|
50
|
-
* @function extractSessionId
|
|
51
|
-
* @param {Object} responseData - Response data from API
|
|
52
|
-
* @returns {string} Session ID
|
|
53
|
-
* @throws {Error} If session ID not found or invalid
|
|
54
|
-
*/
|
|
55
|
-
function extractSessionId(responseData) {
|
|
56
|
-
let sessionId = responseData?.data?.sessionId || responseData?.sessionId ||
|
|
57
|
-
responseData?.data?.session_id || responseData?.session_id;
|
|
58
|
-
if (sessionId && typeof sessionId === 'object') {
|
|
59
|
-
sessionId = sessionId.id || sessionId.sessionId || sessionId.session_id;
|
|
60
|
-
}
|
|
61
|
-
if (!sessionId || typeof sessionId !== 'string') {
|
|
62
|
-
throw new Error(`Session ID not found: ${JSON.stringify(responseData, null, 2)}`);
|
|
63
|
-
}
|
|
64
|
-
return sessionId;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
52
|
/**
|
|
68
53
|
* Create wizard session with given mode and optional systemIdOrKey (no prompts)
|
|
69
54
|
* @async
|
|
@@ -151,7 +136,8 @@ async function handleInteractiveConfigGeneration(options) {
|
|
|
151
136
|
fieldOnboardingLevel: preferences.fieldOnboardingLevel || 'full',
|
|
152
137
|
enableMCP: preferences.mcp,
|
|
153
138
|
enableABAC: preferences.abac,
|
|
154
|
-
enableRBAC: preferences.rbac
|
|
139
|
+
enableRBAC: preferences.rbac,
|
|
140
|
+
debug: options.debug === true
|
|
155
141
|
};
|
|
156
142
|
|
|
157
143
|
const result = await handleConfigurationGeneration(options.dataplaneUrl, options.authConfig, {
|
|
@@ -160,28 +146,51 @@ async function handleInteractiveConfigGeneration(options) {
|
|
|
160
146
|
detectedType: options.detectedType,
|
|
161
147
|
configPrefs,
|
|
162
148
|
credentialIdOrKey: options.credentialIdOrKey,
|
|
163
|
-
systemIdOrKey: options.systemIdOrKey
|
|
149
|
+
systemIdOrKey: options.systemIdOrKey,
|
|
150
|
+
sourceType: options.sourceType,
|
|
151
|
+
platformKey: options.sourceType === 'known-platform' ? options.sourceData : undefined,
|
|
152
|
+
entityName: options.entityName,
|
|
153
|
+
appName: options.appName
|
|
164
154
|
});
|
|
165
155
|
|
|
166
156
|
return {
|
|
167
157
|
...result,
|
|
168
|
-
preferences: buildPreferencesForSave(userIntent, preferences)
|
|
158
|
+
preferences: buildPreferencesForSave(userIntent, preferences, { debug: options.debug })
|
|
169
159
|
};
|
|
170
160
|
}
|
|
171
161
|
|
|
172
162
|
/**
|
|
173
163
|
* Handle configuration review and validation step (interactive mode only)
|
|
164
|
+
* Fetches preview summary from dataplane; falls back to YAML dump if preview unavailable.
|
|
174
165
|
* @async
|
|
175
166
|
* @function handleConfigurationReview
|
|
176
167
|
* @param {string} dataplaneUrl - Dataplane URL
|
|
177
168
|
* @param {Object} authConfig - Authentication configuration
|
|
169
|
+
* @param {string} sessionId - Wizard session ID
|
|
178
170
|
* @param {Object} systemConfig - System configuration
|
|
179
171
|
* @param {Object[]} datasourceConfigs - Datasource configurations
|
|
180
|
-
* @
|
|
172
|
+
* @param {Object} [opts] - Optional options
|
|
173
|
+
* @param {string} [opts.appKey] - App key for debug manifest path
|
|
174
|
+
* @param {boolean} [opts.debug] - When true, save debug manifest on validation failure
|
|
175
|
+
* @returns {Promise<Object|null>} Final configurations or null if cancelled
|
|
181
176
|
*/
|
|
182
|
-
async function handleConfigurationReview(dataplaneUrl, authConfig, systemConfig, datasourceConfigs) {
|
|
177
|
+
async function handleConfigurationReview(dataplaneUrl, authConfig, sessionId, systemConfig, datasourceConfigs, opts = {}) {
|
|
183
178
|
logger.log(chalk.blue('\n\uD83D\uDCCB Step 6-7: Review & Validate'));
|
|
184
|
-
|
|
179
|
+
|
|
180
|
+
let preview = null;
|
|
181
|
+
try {
|
|
182
|
+
const previewResponse = await getPreview(dataplaneUrl, sessionId, authConfig);
|
|
183
|
+
if (previewResponse?.success && previewResponse?.data) {
|
|
184
|
+
preview = previewResponse.data;
|
|
185
|
+
}
|
|
186
|
+
} catch {
|
|
187
|
+
// Fall back to YAML display
|
|
188
|
+
}
|
|
189
|
+
if (!preview) {
|
|
190
|
+
logger.warn('Preview unavailable, showing full configuration.');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const reviewResult = await promptForConfigReview({ preview, systemConfig, datasourceConfigs });
|
|
185
194
|
|
|
186
195
|
if (reviewResult.action === 'cancel') {
|
|
187
196
|
logger.log(chalk.yellow('Wizard cancelled.'));
|
|
@@ -191,7 +200,10 @@ async function handleConfigurationReview(dataplaneUrl, authConfig, systemConfig,
|
|
|
191
200
|
const finalSystemConfig = reviewResult.systemConfig || systemConfig;
|
|
192
201
|
const finalDatasourceConfigs = reviewResult.datasourceConfigs || datasourceConfigs;
|
|
193
202
|
|
|
194
|
-
await validateWizardConfiguration(dataplaneUrl, authConfig, finalSystemConfig, finalDatasourceConfigs
|
|
203
|
+
await validateWizardConfiguration(dataplaneUrl, authConfig, finalSystemConfig, finalDatasourceConfigs, {
|
|
204
|
+
debug: opts.debug,
|
|
205
|
+
appName: opts.appKey
|
|
206
|
+
});
|
|
195
207
|
|
|
196
208
|
return { systemConfig: finalSystemConfig, datasourceConfigs: finalDatasourceConfigs };
|
|
197
209
|
}
|
|
@@ -208,7 +220,7 @@ async function handleConfigurationReview(dataplaneUrl, authConfig, systemConfig,
|
|
|
208
220
|
* @returns {Promise<Object>} Collected state (source, credential, preferences) for wizard.yaml save
|
|
209
221
|
*/
|
|
210
222
|
async function doWizardSteps(appKey, dataplaneUrl, authConfig, sessionId, flowOpts, state) {
|
|
211
|
-
const { mode, systemIdOrKey, platforms } = flowOpts;
|
|
223
|
+
const { mode, systemIdOrKey, platforms, debug } = flowOpts;
|
|
212
224
|
const { sourceType, sourceData } = await handleInteractiveSourceSelection(
|
|
213
225
|
dataplaneUrl, sessionId, authConfig, platforms
|
|
214
226
|
);
|
|
@@ -220,13 +232,13 @@ async function doWizardSteps(appKey, dataplaneUrl, authConfig, sessionId, flowOp
|
|
|
220
232
|
|
|
221
233
|
const openapiSpec = await handleOpenApiParsing(dataplaneUrl, authConfig, sourceType, sourceData);
|
|
222
234
|
const credentialAction = await promptForCredentialAction();
|
|
223
|
-
const configCredential =
|
|
224
|
-
? { action: 'skip' }
|
|
225
|
-
: { action: credentialAction.action, credentialIdOrKey: credentialAction.credentialIdOrKey };
|
|
235
|
+
const configCredential = await resolveCredentialConfig(dataplaneUrl, authConfig, credentialAction);
|
|
226
236
|
state.credential = configCredential;
|
|
227
237
|
const credentialIdOrKey = await handleCredentialSelection(dataplaneUrl, authConfig, configCredential);
|
|
228
238
|
|
|
229
239
|
const detectedType = await handleTypeDetection(dataplaneUrl, authConfig, openapiSpec);
|
|
240
|
+
const entityName = openapiSpec && sourceType !== 'known-platform'
|
|
241
|
+
? await handleEntitySelection(dataplaneUrl, authConfig, openapiSpec) : null;
|
|
230
242
|
const genResult = await handleInteractiveConfigGeneration({
|
|
231
243
|
dataplaneUrl,
|
|
232
244
|
authConfig,
|
|
@@ -234,12 +246,24 @@ async function doWizardSteps(appKey, dataplaneUrl, authConfig, sessionId, flowOp
|
|
|
234
246
|
openapiSpec,
|
|
235
247
|
detectedType,
|
|
236
248
|
credentialIdOrKey,
|
|
237
|
-
systemIdOrKey
|
|
249
|
+
systemIdOrKey,
|
|
250
|
+
sourceType,
|
|
251
|
+
sourceData,
|
|
252
|
+
entityName: entityName || undefined,
|
|
253
|
+
appName: appKey,
|
|
254
|
+
debug
|
|
238
255
|
});
|
|
239
256
|
const { systemConfig, datasourceConfigs, systemKey, preferences: savedPrefs } = genResult;
|
|
240
257
|
state.preferences = savedPrefs || {};
|
|
241
258
|
|
|
242
|
-
const finalConfigs = await handleConfigurationReview(
|
|
259
|
+
const finalConfigs = await handleConfigurationReview(
|
|
260
|
+
dataplaneUrl,
|
|
261
|
+
authConfig,
|
|
262
|
+
sessionId,
|
|
263
|
+
systemConfig,
|
|
264
|
+
datasourceConfigs,
|
|
265
|
+
{ appKey, debug }
|
|
266
|
+
);
|
|
243
267
|
if (!finalConfigs) return null;
|
|
244
268
|
|
|
245
269
|
await handleFileSaving(
|
|
@@ -290,18 +314,22 @@ async function runWizardStepsAfterSession(appKey, dataplaneUrl, authConfig, sess
|
|
|
290
314
|
* @returns {Promise<void>} Resolves when wizard flow completes
|
|
291
315
|
*/
|
|
292
316
|
async function executeWizardFlow(appKey, dataplaneUrl, authConfig, flowOpts = {}) {
|
|
293
|
-
const { mode, systemIdOrKey, configPath } = flowOpts;
|
|
317
|
+
const { mode, systemIdOrKey, configPath, debug } = flowOpts;
|
|
294
318
|
|
|
319
|
+
if (debug) {
|
|
320
|
+
logger.log(chalk.gray(`[DEBUG] Wizard debug mode enabled for app: ${appKey}`));
|
|
321
|
+
}
|
|
295
322
|
logger.log(chalk.blue('\n\uD83D\uDCCB Step 1: Create Session'));
|
|
296
323
|
const sessionId = await createSessionFromParams(dataplaneUrl, authConfig, mode, systemIdOrKey, appKey);
|
|
297
324
|
logger.log(chalk.green('\u2713 Session created'));
|
|
298
325
|
|
|
299
|
-
const platforms = await getWizardPlatforms(dataplaneUrl, authConfig);
|
|
326
|
+
const platforms = mode === 'add-datasource' ? [] : await getWizardPlatforms(dataplaneUrl, authConfig);
|
|
300
327
|
const state = await runWizardStepsAfterSession(appKey, dataplaneUrl, authConfig, sessionId, {
|
|
301
328
|
mode,
|
|
302
329
|
systemIdOrKey,
|
|
303
330
|
platforms,
|
|
304
|
-
configPath
|
|
331
|
+
configPath,
|
|
332
|
+
debug: flowOpts.debug
|
|
305
333
|
});
|
|
306
334
|
if (!state) return;
|
|
307
335
|
|
|
@@ -362,26 +390,15 @@ async function resolveCreateNewPath(options, loadedConfig) {
|
|
|
362
390
|
* @returns {Promise<Object>} { appKey, configPath, dataplaneUrl, authConfig, systemIdOrKey }
|
|
363
391
|
*/
|
|
364
392
|
async function resolveAddDatasourcePath(options, loadedConfig) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
logger.log(chalk.red('Cannot add datasource to a webapp. Please enter an external system ID or key.'));
|
|
375
|
-
systemIdOrKey = await promptForSystemIdOrKey(systemIdOrKey);
|
|
376
|
-
continue;
|
|
377
|
-
}
|
|
378
|
-
break;
|
|
379
|
-
}
|
|
380
|
-
} catch (err) {
|
|
381
|
-
logger.log(chalk.red(`System not found or error: ${err.message}`));
|
|
382
|
-
}
|
|
383
|
-
systemIdOrKey = await promptForSystemIdOrKey(systemIdOrKey);
|
|
384
|
-
}
|
|
393
|
+
const { dataplaneUrl, authConfig } = await setupDataplaneAndAuth(
|
|
394
|
+
options,
|
|
395
|
+
loadedConfig?.systemIdOrKey || loadedConfig?.appKey || 'wizard'
|
|
396
|
+
);
|
|
397
|
+
const systemsList = await fetchSystemsListForAddDatasource(dataplaneUrl, authConfig);
|
|
398
|
+
const initialSystemIdOrKey = loadedConfig?.systemIdOrKey || (await promptForExistingSystem(systemsList, loadedConfig?.systemIdOrKey));
|
|
399
|
+
const { systemResponse, systemIdOrKey } = await resolveExternalSystemForAddDatasource(
|
|
400
|
+
dataplaneUrl, authConfig, systemsList, initialSystemIdOrKey
|
|
401
|
+
);
|
|
385
402
|
const sys = systemResponse?.data || systemResponse;
|
|
386
403
|
const appKey = sys?.key || sys?.systemKey || systemIdOrKey;
|
|
387
404
|
const configPath = await ensureIntegrationDir(appKey);
|
|
@@ -449,7 +466,8 @@ async function handleWizardWithSavedConfig(options, loadedConfig, displayPath) {
|
|
|
449
466
|
}
|
|
450
467
|
|
|
451
468
|
async function handleWizardInteractive(options) {
|
|
452
|
-
const
|
|
469
|
+
const allowAddDatasource = !options.app;
|
|
470
|
+
const mode = allowAddDatasource ? await promptForMode(undefined, true) : 'create-system';
|
|
453
471
|
const resolved = mode === 'create-system'
|
|
454
472
|
? await resolveCreateNewPath(options, null)
|
|
455
473
|
: await resolveAddDatasourcePath(options, null);
|
|
@@ -457,7 +475,12 @@ async function handleWizardInteractive(options) {
|
|
|
457
475
|
const { appKey, configPath, dataplaneUrl, authConfig } = resolved;
|
|
458
476
|
const systemIdOrKey = mode === 'add-datasource' ? resolved.systemIdOrKey : undefined;
|
|
459
477
|
try {
|
|
460
|
-
await executeWizardFlow(appKey, dataplaneUrl, authConfig, {
|
|
478
|
+
await executeWizardFlow(appKey, dataplaneUrl, authConfig, {
|
|
479
|
+
mode,
|
|
480
|
+
systemIdOrKey,
|
|
481
|
+
configPath,
|
|
482
|
+
debug: options.debug
|
|
483
|
+
});
|
|
461
484
|
logger.log(chalk.gray(`To change settings, edit integration/${appKey}/wizard.yaml and run: aifabrix wizard ${appKey}`));
|
|
462
485
|
} catch (error) {
|
|
463
486
|
await handleWizardError(appKey, configPath, mode, systemIdOrKey, error);
|
|
@@ -480,5 +503,4 @@ async function handleWizard(options = {}) {
|
|
|
480
503
|
}
|
|
481
504
|
return await handleWizardInteractive(options);
|
|
482
505
|
}
|
|
483
|
-
|
|
484
506
|
module.exports = { handleWizard, handleWizardHeadless };
|