@aifabrix/builder 2.43.0 → 2.44.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/anchor-docs.mdc +15 -0
- package/README.md +1 -1
- package/anchor-docs/README.md +10 -0
- package/anchor-docs/_TEMPLATE +24 -0
- package/bin/aifabrix.js +13 -4
- package/integration/hubspot-test/README.md +31 -0
- package/integration/hubspot-test/create-hubspot.js +5 -5
- package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
- package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
- package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
- package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
- package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
- package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
- package/integration/hubspot-test/test-dataplane-down.js +3 -3
- package/integration/hubspot-test/test.js +35 -43
- package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
- package/integration/roundtrip-test-local/README.md +144 -0
- package/integration/roundtrip-test-local/application.yaml +13 -0
- package/integration/roundtrip-test-local/env.template +15 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
- package/integration/roundtrip-test-local2/README.md +144 -0
- package/integration/roundtrip-test-local2/application.yaml +13 -0
- package/integration/roundtrip-test-local2/env.template +15 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
- package/integration/test/wizard.yaml +8 -0
- package/jest.config.default.js +10 -0
- package/jest.config.integration.fixtures.js +22 -0
- package/jest.config.integration.js +21 -18
- package/jest.config.isolated.js +10 -0
- package/jest.projects.js +288 -0
- package/lib/api/datasources-core.api.js +3 -3
- package/lib/api/dev-mtls-request.js +110 -0
- package/lib/api/dev-server-https.js +145 -0
- package/lib/api/dev.api.js +133 -144
- package/lib/api/index.js +0 -1
- package/lib/api/pipeline.api.js +67 -20
- package/lib/api/types/dev.types.js +4 -3
- package/lib/api/types/pipeline.types.js +8 -5
- package/lib/api/types/validation-run.types.js +56 -0
- package/lib/api/validation-run.api.js +99 -0
- package/lib/api/validation-runner.js +99 -0
- package/lib/app/config.js +1 -1
- package/lib/app/deploy-status-display.js +2 -2
- package/lib/app/deploy.js +7 -6
- package/lib/app/display.js +2 -1
- package/lib/app/dockerfile.js +3 -2
- package/lib/app/down.js +2 -1
- package/lib/app/helpers.js +6 -5
- package/lib/app/index.js +27 -8
- package/lib/app/list.js +7 -6
- package/lib/app/push.js +4 -3
- package/lib/app/register.js +16 -7
- package/lib/app/rotate-secret.js +14 -13
- package/lib/app/run-container-start.js +184 -0
- package/lib/app/run-docker-fallback.js +108 -0
- package/lib/app/run-env-compose.js +30 -42
- package/lib/app/run-helpers.js +49 -126
- package/lib/app/run-infra-requirements.js +30 -0
- package/lib/app/run-resolve-image.js +21 -0
- package/lib/app/run.js +74 -21
- package/lib/app/show-display.js +1 -1
- package/lib/app/show.js +1 -1
- package/lib/build/index.js +13 -10
- package/lib/cli/index.js +2 -0
- package/lib/cli/setup-app.help.js +67 -0
- package/lib/cli/setup-app.js +57 -121
- package/lib/cli/setup-app.test-commands.js +179 -0
- package/lib/cli/setup-auth.js +19 -5
- package/lib/cli/setup-credential-deployment.js +22 -8
- package/lib/cli/setup-dev-path-commands.js +124 -0
- package/lib/cli/setup-dev.js +170 -113
- package/lib/cli/setup-environment.js +7 -1
- package/lib/cli/setup-external-system.js +62 -22
- package/lib/cli/setup-infra.js +126 -47
- package/lib/cli/setup-parameters.js +32 -0
- package/lib/cli/setup-secrets.js +106 -8
- package/lib/cli/setup-service-user.js +1 -1
- package/lib/cli/setup-utility.js +36 -20
- package/lib/commands/app-down.js +5 -7
- package/lib/commands/app-install.js +14 -7
- package/lib/commands/app-logs.js +13 -10
- package/lib/commands/app-shell.js +4 -1
- package/lib/commands/app-test.js +25 -19
- package/lib/commands/app.js +22 -10
- package/lib/commands/auth-config.js +6 -6
- package/lib/commands/auth-status.js +4 -3
- package/lib/commands/credential-env.js +4 -3
- package/lib/commands/credential-list.js +5 -4
- package/lib/commands/credential-push.js +4 -3
- package/lib/commands/datasource-unified-test-cli.js +495 -0
- package/lib/commands/datasource-unified-test-cli.options.js +149 -0
- package/lib/commands/datasource-validation-cli.js +129 -0
- package/lib/commands/datasource.js +105 -98
- package/lib/commands/deployment-list.js +6 -5
- package/lib/commands/dev-cli-handlers.js +122 -18
- package/lib/commands/dev-down.js +4 -3
- package/lib/commands/dev-init.js +231 -116
- package/lib/commands/dev-show-display.js +473 -0
- package/lib/commands/login-credentials.js +3 -2
- package/lib/commands/login-device.js +4 -3
- package/lib/commands/login.js +5 -4
- package/lib/commands/logout.js +8 -7
- package/lib/commands/parameters-validate.js +54 -0
- package/lib/commands/repair-datasource.js +314 -68
- package/lib/commands/repair-env-template.js +2 -2
- package/lib/commands/repair.js +21 -3
- package/lib/commands/secrets-list.js +23 -12
- package/lib/commands/secrets-remove-all.js +220 -0
- package/lib/commands/secrets-remove.js +21 -12
- package/lib/commands/secrets-set.js +21 -12
- package/lib/commands/secrets-validate.js +4 -4
- package/lib/commands/secure.js +10 -9
- package/lib/commands/service-user.js +26 -25
- package/lib/commands/test-e2e-external.js +27 -1
- package/lib/commands/up-common.js +3 -2
- package/lib/commands/up-dataplane.js +29 -16
- package/lib/commands/up-miso.js +19 -29
- package/lib/commands/upload.js +138 -39
- package/lib/commands/wizard-core-helpers.js +1 -1
- package/lib/commands/wizard-dataplane.js +4 -3
- package/lib/commands/wizard-helpers.js +3 -3
- package/lib/commands/wizard.js +2 -2
- package/lib/core/admin-secrets.js +14 -5
- package/lib/core/audit-logger.js +12 -4
- package/lib/core/config-attach-extensions.js +46 -0
- package/lib/core/config-runtime-paths.js +29 -0
- package/lib/core/config.js +55 -56
- package/lib/core/diff.js +3 -2
- package/lib/core/ensure-encryption-key.js +1 -1
- package/lib/core/secrets-ensure-infra.js +77 -0
- package/lib/core/secrets-ensure.js +120 -64
- package/lib/core/secrets-env-write.js +35 -7
- package/lib/core/secrets-infra-placeholder-sync.js +61 -0
- package/lib/core/secrets.js +200 -37
- package/lib/core/templates-env.js +4 -3
- package/lib/datasource/abac-validator.js +1 -10
- package/lib/datasource/deploy.js +75 -53
- package/lib/datasource/field-reference-validator.js +9 -6
- package/lib/datasource/integration-context.js +63 -0
- package/lib/datasource/list.js +8 -7
- package/lib/datasource/log-viewer.js +84 -53
- package/lib/datasource/resolve-app.js +4 -4
- package/lib/datasource/test-e2e.js +95 -146
- package/lib/datasource/test-integration.js +114 -122
- package/lib/datasource/unified-validation-run-body.js +65 -0
- package/lib/datasource/unified-validation-run-post.js +23 -0
- package/lib/datasource/unified-validation-run-resolve.js +43 -0
- package/lib/datasource/unified-validation-run.js +92 -0
- package/lib/datasource/validate.js +157 -13
- package/lib/deployment/deployer.js +4 -3
- package/lib/deployment/environment.js +7 -6
- package/lib/deployment/push.js +17 -8
- package/lib/external-system/delete.js +4 -3
- package/lib/external-system/deploy.js +131 -53
- package/lib/external-system/download-helpers.js +1 -1
- package/lib/external-system/download.js +7 -6
- package/lib/external-system/generator.js +92 -6
- package/lib/external-system/integration-test-dispatch.js +26 -0
- package/lib/external-system/test-execution.js +5 -1
- package/lib/external-system/test-helpers.js +0 -4
- package/lib/external-system/test-system-level-helpers.js +110 -0
- package/lib/external-system/test-system-level.js +83 -44
- package/lib/external-system/test.js +59 -8
- package/lib/generator/builders.js +23 -11
- package/lib/generator/deploy-manifest-azure-kv.js +81 -0
- package/lib/generator/external.js +16 -4
- package/lib/generator/helpers.js +58 -3
- package/lib/generator/index.js +4 -0
- package/lib/generator/split-readme.js +12 -7
- package/lib/generator/split-variables.js +2 -1
- package/lib/generator/split.js +1 -1
- package/lib/generator/wizard-readme.js +3 -3
- package/lib/generator/wizard.js +8 -8
- package/lib/infrastructure/compose.js +60 -6
- package/lib/infrastructure/helpers.js +201 -29
- package/lib/infrastructure/index.js +28 -17
- package/lib/infrastructure/services.js +21 -15
- package/lib/internal/fs-real-sync.js +104 -0
- package/lib/internal/node-fs.js +98 -0
- package/lib/parameters/database-secret-values.js +173 -0
- package/lib/parameters/infra-kv-discovery.js +121 -0
- package/lib/parameters/infra-parameter-catalog.js +458 -0
- package/lib/parameters/infra-parameter-validate.js +64 -0
- package/lib/schema/application-schema.json +37 -17
- package/lib/schema/datasource-test-run.schema.json +493 -0
- package/lib/schema/deployment-rules.yaml +102 -63
- package/lib/schema/external-datasource.schema.json +1200 -442
- package/lib/schema/external-system.schema.json +181 -5
- package/lib/schema/flag-map-validation-run.json +31 -0
- package/lib/schema/infra-parameter.schema.json +106 -0
- package/lib/schema/infra.parameter.yaml +421 -0
- package/lib/schema/type/credential-auth-templates.json +40 -0
- package/lib/schema/type/document-storage.json +213 -0
- package/lib/schema/type/message-service.json +123 -0
- package/lib/schema/type/vector-store.json +88 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
- package/lib/utils/api-error-handler.js +2 -2
- package/lib/utils/api.js +49 -14
- package/lib/utils/app-register-api.js +3 -2
- package/lib/utils/app-register-auth.js +1 -1
- package/lib/utils/app-register-config.js +4 -4
- package/lib/utils/app-register-display.js +3 -2
- package/lib/utils/app-register-validator.js +3 -2
- package/lib/utils/app-run-containers.js +26 -22
- package/lib/utils/app-scoped-config.js +31 -0
- package/lib/utils/app-service-env-from-builder.js +164 -0
- package/lib/utils/build-copy.js +1 -1
- package/lib/utils/build-helpers.js +20 -20
- package/lib/utils/build-resolve-image.js +165 -0
- package/lib/utils/cli-layout-chalk.js +8 -0
- package/lib/utils/cli-test-layout-chalk.js +267 -0
- package/lib/utils/cli-utils.js +88 -11
- package/lib/utils/compose-db-passwords.js +138 -0
- package/lib/utils/compose-generate-docker-compose.js +216 -0
- package/lib/utils/compose-generator.js +197 -291
- package/lib/utils/compose-miso-env.js +18 -0
- package/lib/utils/compose-traefik-ingress-base.js +158 -0
- package/lib/utils/config-paths.js +166 -7
- package/lib/utils/config-scoped-resources-preference.js +41 -0
- package/lib/utils/controller-deployment-outcome.js +68 -0
- package/lib/utils/credential-display.js +2 -2
- package/lib/utils/dataplane-pipeline-warning.js +4 -3
- package/lib/utils/datasource-test-run-capability-scope.js +43 -0
- package/lib/utils/datasource-test-run-debug-display.js +137 -0
- package/lib/utils/datasource-test-run-debug-slice.js +93 -0
- package/lib/utils/datasource-test-run-display.js +442 -0
- package/lib/utils/datasource-test-run-exit.js +58 -0
- package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
- package/lib/utils/datasource-test-run-report-version.js +51 -0
- package/lib/utils/datasource-test-run-schema-sync.js +59 -0
- package/lib/utils/datasource-test-run-tty-log.js +81 -0
- package/lib/utils/datasource-validation-watch.js +266 -0
- package/lib/utils/declarative-url-ports.js +47 -0
- package/lib/utils/derive-env-key-from-client-id.js +41 -0
- package/lib/utils/dev-ca-install.js +185 -23
- package/lib/utils/dev-cert-helper.js +266 -17
- package/lib/utils/dev-hosts-helper.js +307 -0
- package/lib/utils/dev-init-cert-hints.js +37 -0
- package/lib/utils/dev-init-health-messages.js +52 -0
- package/lib/utils/dev-init-resolve.js +86 -0
- package/lib/utils/dev-init-ssh-merge.js +65 -0
- package/lib/utils/dev-ssh-config-helper.js +196 -0
- package/lib/utils/dev-user-groups.js +93 -0
- package/lib/utils/docker-build.js +42 -17
- package/lib/utils/docker-exec.js +28 -0
- package/lib/utils/docker-manifest-public-port.js +116 -0
- package/lib/utils/docker-not-running-hint.js +52 -0
- package/lib/utils/docker.js +98 -11
- package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
- package/lib/utils/env-config-loader.js +10 -91
- package/lib/utils/env-copy.js +19 -10
- package/lib/utils/env-map.js +35 -8
- package/lib/utils/env-template.js +2 -2
- package/lib/utils/environment-scoped-resources.js +144 -0
- package/lib/utils/error-formatter.js +92 -13
- package/lib/utils/error-formatters/http-status-errors.js +6 -5
- package/lib/utils/error-formatters/network-errors.js +2 -1
- package/lib/utils/error-formatters/permission-errors.js +2 -1
- package/lib/utils/error-formatters/validation-errors.js +2 -1
- package/lib/utils/external-readme.js +8 -1
- package/lib/utils/external-system-display.js +234 -136
- package/lib/utils/external-system-local-test-tty.js +389 -0
- package/lib/utils/external-system-readiness-core.js +377 -0
- package/lib/utils/external-system-readiness-deploy-display.js +270 -0
- package/lib/utils/external-system-readiness-display-internals.js +150 -0
- package/lib/utils/external-system-readiness-display.js +186 -0
- package/lib/utils/external-system-test-helpers.js +24 -6
- package/lib/utils/external-system-validators.js +30 -12
- package/lib/utils/health-check-url.js +119 -0
- package/lib/utils/health-check.js +59 -25
- package/lib/utils/help-builder.js +11 -8
- package/lib/utils/image-version.js +4 -8
- package/lib/utils/infra-containers.js +4 -7
- package/lib/utils/infra-env-defaults.js +162 -0
- package/lib/utils/infra-status-display.js +167 -0
- package/lib/utils/infra-status.js +16 -8
- package/lib/utils/local-secrets.js +3 -4
- package/lib/utils/paths.js +134 -47
- package/lib/utils/port-resolver.js +10 -23
- package/lib/utils/redis-env-scope.js +62 -0
- package/lib/utils/register-aifabrix-shell-env.js +204 -0
- package/lib/utils/remote-builder-validation.js +99 -0
- package/lib/utils/remote-dev-auth.js +117 -21
- package/lib/utils/remote-docker-env.js +67 -15
- package/lib/utils/remote-secrets-loader.js +13 -4
- package/lib/utils/resolve-docker-image-ref.js +124 -0
- package/lib/utils/schema-loader.js +22 -9
- package/lib/utils/secrets-bash-kv.js +25 -0
- package/lib/utils/secrets-generator.js +169 -49
- package/lib/utils/secrets-helpers.js +70 -59
- package/lib/utils/secrets-kv-scope.js +60 -0
- package/lib/utils/secrets-utils.js +32 -38
- package/lib/utils/secrets-validation.js +3 -1
- package/lib/utils/secrets-yaml-preserve.js +109 -0
- package/lib/utils/ssh-key-helper.js +4 -2
- package/lib/utils/template-helpers.js +2 -2
- package/lib/utils/test-log-writer.js +3 -3
- package/lib/utils/token-manager.js +1 -2
- package/lib/utils/url-declarative-public-base.js +188 -0
- package/lib/utils/url-declarative-resolve-build.js +493 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
- package/lib/utils/url-declarative-resolve.js +220 -0
- package/lib/utils/url-declarative-token-parse.js +74 -0
- package/lib/utils/url-declarative-url-flags.js +50 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
- package/lib/utils/url-public-path-prefix.js +34 -0
- package/lib/utils/urls-local-registry.js +220 -0
- package/lib/utils/validation-report-tty-kit.js +77 -0
- package/lib/utils/validation-run-poll.js +89 -0
- package/lib/utils/validation-run-post-retry.js +73 -0
- package/lib/utils/validation-run-request.js +98 -0
- package/lib/utils/variable-transformer.js +21 -4
- package/lib/utils/yaml-preserve.js +33 -14
- package/lib/validation/datasource-warnings.js +56 -0
- package/lib/validation/env-template-auth.js +1 -1
- package/lib/validation/external-manifest-validator.js +27 -7
- package/lib/validation/validate-display.js +37 -31
- package/lib/validation/validate.js +4 -13
- package/lib/validation/validator-unresolved-placeholders.js +98 -0
- package/lib/validation/validator.js +22 -65
- package/lib/validation/wizard-config-validator.js +2 -1
- package/package.json +7 -3
- package/scripts/check-datasource-test-run-schema-sync.js +34 -0
- package/scripts/diagnose-cli.js +150 -0
- package/scripts/install-local.js +304 -55
- package/templates/README.md +15 -2
- package/templates/applications/dataplane/application.yaml +52 -2
- package/templates/applications/dataplane/env.template +75 -17
- package/templates/applications/dataplane/rbac.yaml +8 -0
- package/templates/applications/keycloak/application.yaml +9 -1
- package/templates/applications/keycloak/env.template +15 -6
- package/templates/applications/miso-controller/application.yaml +10 -2
- package/templates/applications/miso-controller/env.template +42 -12
- package/templates/applications/miso-controller/rbac.yaml +5 -0
- package/templates/external-system/README.md.hbs +20 -7
- package/templates/external-system/deploy.js.hbs +5 -5
- package/templates/external-system/external-datasource.yaml.hbs +197 -118
- package/templates/infra/compose.yaml.hbs +20 -4
- package/templates/python/docker-compose.hbs +16 -0
- package/templates/typescript/docker-compose.hbs +16 -0
- package/lib/api/external-test.api.js +0 -111
- package/lib/schema/env-config.yaml +0 -60
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Chalk helpers aligned with `.cursor/plans/layout.md` (CLI TTY / validation summaries).
|
|
3
|
+
* @see `.cursor/plans/layout.md` — Contributor appendix for glyph rules and the implementation map.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
|
|
10
|
+
/** Canonical success glyph (green), layout §CORE / §3. */
|
|
11
|
+
function successGlyph() {
|
|
12
|
+
return chalk.green('✔');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Failure glyph only (red), layout §18 — compose with other chalk segments if needed. */
|
|
16
|
+
function failureGlyph() {
|
|
17
|
+
return chalk.red('✖');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Single-line success message: green ✔ + green rest (layout §CORE).
|
|
22
|
+
* @param {string} message - text after the ✔ (no leading space)
|
|
23
|
+
* @returns {string}
|
|
24
|
+
*/
|
|
25
|
+
function formatSuccessLine(message) {
|
|
26
|
+
return chalk.green(`✔ ${message}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Success line with leading newline (common for footers / deploy summaries).
|
|
31
|
+
* @param {string} message
|
|
32
|
+
* @returns {string}
|
|
33
|
+
*/
|
|
34
|
+
function formatSuccessParagraph(message) {
|
|
35
|
+
return chalk.green(`\n✔ ${message}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Blocking error line: red ✖ + red message (layout §18).
|
|
40
|
+
* @param {string} message
|
|
41
|
+
* @returns {string}
|
|
42
|
+
*/
|
|
43
|
+
function formatBlockingError(message) {
|
|
44
|
+
return `${chalk.red('✖')} ${chalk.red(message)}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Failure with optional hint (layout §7).
|
|
49
|
+
* @param {string} title - main error text (red)
|
|
50
|
+
* @param {string} [hint] - optional hint (gray "Hint:" + yellow text)
|
|
51
|
+
* @returns {string}
|
|
52
|
+
*/
|
|
53
|
+
function formatIssue(title, hint) {
|
|
54
|
+
const head = `${chalk.red('✖')} ${chalk.red(title)}`;
|
|
55
|
+
if (!hint) {
|
|
56
|
+
return head;
|
|
57
|
+
}
|
|
58
|
+
return `${head}\n ${chalk.gray('Hint:')} ${chalk.yellow(hint)}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Next actions list (layout §19): bold title, cyan bullets, white lines.
|
|
63
|
+
* @param {string[]} lines - action text without leading "-"
|
|
64
|
+
* @returns {string}
|
|
65
|
+
*/
|
|
66
|
+
function formatNextActions(lines) {
|
|
67
|
+
const body = (lines || [])
|
|
68
|
+
.map(line => `${chalk.cyan('-')} ${chalk.white(line)}`)
|
|
69
|
+
.join('\n');
|
|
70
|
+
return `${sectionTitle('Next actions:')}\n${body}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Docs / link line (layout §14): gray label, cyan URL.
|
|
75
|
+
* @param {string} label - e.g. "Docs:" or "Docs"
|
|
76
|
+
* @param {string} url
|
|
77
|
+
* @returns {string}
|
|
78
|
+
*/
|
|
79
|
+
function formatDocsLine(label, url) {
|
|
80
|
+
const lbl = label.endsWith(':') ? label : `${label}:`;
|
|
81
|
+
return `${chalk.gray(lbl)} ${chalk.cyan(url)}`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Progress / async (layout §15): yellow ⏳ + white message.
|
|
86
|
+
* @param {string} message
|
|
87
|
+
* @returns {string}
|
|
88
|
+
*/
|
|
89
|
+
function formatProgress(message) {
|
|
90
|
+
return `${chalk.yellow('⏳')} ${chalk.white(message)}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Section title + bullet list (layout §3, §9 impact-style).
|
|
95
|
+
* @param {string} title
|
|
96
|
+
* @param {string[]} items - lines without bullet prefix
|
|
97
|
+
* @param {{ bullet?: 'cyan'|'red' }} [opts]
|
|
98
|
+
* @returns {string}
|
|
99
|
+
*/
|
|
100
|
+
function formatBulletSection(title, items, opts) {
|
|
101
|
+
const bulletColor = opts && opts.bullet === 'red' ? chalk.red : chalk.cyan;
|
|
102
|
+
const body = (items || []).map(line => `${bulletColor('-')} ${chalk.white(line)}`).join('\n');
|
|
103
|
+
return `${sectionTitle(title)}\n${body}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Bold white section title (layout: Section).
|
|
108
|
+
* @param {string} text
|
|
109
|
+
* @returns {string}
|
|
110
|
+
*/
|
|
111
|
+
function sectionTitle(text) {
|
|
112
|
+
return chalk.white.bold(text);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Gray label + bold white value (layout: HEADER BLOCK).
|
|
117
|
+
* @param {string} label - e.g. "System:"
|
|
118
|
+
* @param {string} value
|
|
119
|
+
* @returns {string}
|
|
120
|
+
*/
|
|
121
|
+
function headerKeyValue(label, value) {
|
|
122
|
+
return `${chalk.gray(label)} ${chalk.white.bold(value)}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Info line (cyan ℹ / neutral progress).
|
|
127
|
+
* @param {string} text
|
|
128
|
+
* @returns {string}
|
|
129
|
+
*/
|
|
130
|
+
function infoLine(text) {
|
|
131
|
+
return chalk.cyan(text);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Metadata (URLs, hints).
|
|
136
|
+
* @param {string} text
|
|
137
|
+
* @returns {string}
|
|
138
|
+
*/
|
|
139
|
+
function metadata(text) {
|
|
140
|
+
return chalk.gray(text);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @param {'ok'|'warn'|'fail'|'skipped'} agg
|
|
145
|
+
* @returns {string} Uppercase status word for header
|
|
146
|
+
*/
|
|
147
|
+
function aggregateStatusWord(agg) {
|
|
148
|
+
if (agg === 'warn') return 'WARN';
|
|
149
|
+
if (agg === 'fail') return 'FAIL';
|
|
150
|
+
if (agg === 'skipped') return 'SKIPPED';
|
|
151
|
+
return 'OK';
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Colored glyph from aggregate status.
|
|
156
|
+
* @param {'ok'|'warn'|'fail'|'skipped'} agg
|
|
157
|
+
* @param {string} glyph - unicode ✔ ⚠ ✖ ⏭
|
|
158
|
+
* @returns {string}
|
|
159
|
+
*/
|
|
160
|
+
function colorAggregateGlyph(agg, glyph) {
|
|
161
|
+
if (agg === 'ok') return chalk.green(glyph);
|
|
162
|
+
if (agg === 'warn') return chalk.yellow(glyph);
|
|
163
|
+
if (agg === 'fail') return chalk.red(glyph);
|
|
164
|
+
return chalk.gray(glyph);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Full "Status: ✔ OK" line (glyph + word same color family).
|
|
169
|
+
* @param {'ok'|'warn'|'fail'|'skipped'} agg
|
|
170
|
+
* @param {string} glyph
|
|
171
|
+
* @returns {string}
|
|
172
|
+
*/
|
|
173
|
+
function formatStatusKeyValue(agg, glyph) {
|
|
174
|
+
const g = colorAggregateGlyph(agg, glyph);
|
|
175
|
+
const w = aggregateStatusWord(agg);
|
|
176
|
+
const word =
|
|
177
|
+
agg === 'ok'
|
|
178
|
+
? chalk.green(w)
|
|
179
|
+
: agg === 'warn'
|
|
180
|
+
? chalk.yellow(w)
|
|
181
|
+
: agg === 'fail'
|
|
182
|
+
? chalk.red(w)
|
|
183
|
+
: chalk.gray(w);
|
|
184
|
+
return `${chalk.gray('Status:')} ${g} ${word}`;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Datasource list row (layout §5): symbol + name (white) + status hint (gray).
|
|
189
|
+
* @param {'ok'|'warn'|'fail'|'skipped'} rowStatus
|
|
190
|
+
* @param {string} name
|
|
191
|
+
* @param {string} [statusHint] - e.g. "Ready", shown in gray parens
|
|
192
|
+
* @returns {string}
|
|
193
|
+
*/
|
|
194
|
+
function formatDatasourceListRow(rowStatus, name, statusHint) {
|
|
195
|
+
const sym =
|
|
196
|
+
rowStatus === 'ok'
|
|
197
|
+
? chalk.green('✔')
|
|
198
|
+
: rowStatus === 'warn'
|
|
199
|
+
? chalk.yellow('⚠')
|
|
200
|
+
: rowStatus === 'fail'
|
|
201
|
+
? chalk.red('✖')
|
|
202
|
+
: chalk.gray('⏭');
|
|
203
|
+
const hint = statusHint ? ` ${chalk.gray(`(${statusHint})`)}` : '';
|
|
204
|
+
return ` ${sym} ${chalk.white(name)}${hint}`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Footer line for all-pass / warn / fail.
|
|
209
|
+
* @param {boolean} success
|
|
210
|
+
* @param {'ok'|'warn'|'fail'} [agg]
|
|
211
|
+
* @param {string} okMsg
|
|
212
|
+
* @param {string} warnMsg
|
|
213
|
+
* @param {string} failMsg
|
|
214
|
+
* @returns {string}
|
|
215
|
+
*/
|
|
216
|
+
function integrationFooterLine(success, agg, okMsg, warnMsg, failMsg) {
|
|
217
|
+
if (success && agg === 'warn') {
|
|
218
|
+
return chalk.yellow(`\n⚠ ${warnMsg}`);
|
|
219
|
+
}
|
|
220
|
+
if (success) {
|
|
221
|
+
return formatSuccessParagraph(okMsg);
|
|
222
|
+
}
|
|
223
|
+
return chalk.red(`\n✖ ${failMsg}`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Color a single data-quality / rollup line that starts with ✔, ⚠, or ✖.
|
|
228
|
+
* @param {string} line
|
|
229
|
+
* @returns {string}
|
|
230
|
+
*/
|
|
231
|
+
function colorRollupPrefixedLine(line) {
|
|
232
|
+
const trimmed = line.trimStart();
|
|
233
|
+
const first = trimmed[0];
|
|
234
|
+
if (first === '✔') {
|
|
235
|
+
return chalk.green('✔') + chalk.white(trimmed.slice(1));
|
|
236
|
+
}
|
|
237
|
+
if (first === '⚠') {
|
|
238
|
+
return chalk.yellow('⚠') + chalk.white(trimmed.slice(1));
|
|
239
|
+
}
|
|
240
|
+
if (first === '✖') {
|
|
241
|
+
return chalk.red('✖') + chalk.white(trimmed.slice(1));
|
|
242
|
+
}
|
|
243
|
+
return line;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
module.exports = {
|
|
247
|
+
sectionTitle,
|
|
248
|
+
headerKeyValue,
|
|
249
|
+
infoLine,
|
|
250
|
+
metadata,
|
|
251
|
+
aggregateStatusWord,
|
|
252
|
+
colorAggregateGlyph,
|
|
253
|
+
formatStatusKeyValue,
|
|
254
|
+
formatDatasourceListRow,
|
|
255
|
+
integrationFooterLine,
|
|
256
|
+
colorRollupPrefixedLine,
|
|
257
|
+
successGlyph,
|
|
258
|
+
failureGlyph,
|
|
259
|
+
formatSuccessLine,
|
|
260
|
+
formatSuccessParagraph,
|
|
261
|
+
formatBlockingError,
|
|
262
|
+
formatIssue,
|
|
263
|
+
formatNextActions,
|
|
264
|
+
formatDocsLine,
|
|
265
|
+
formatProgress,
|
|
266
|
+
formatBulletSection
|
|
267
|
+
};
|
package/lib/utils/cli-utils.js
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const chalk = require('chalk');
|
|
13
|
-
const fs = require('fs').promises;
|
|
14
13
|
const logger = require('./logger');
|
|
14
|
+
const { getDockerDaemonStartHintSentence, getDockerApiOverTcpHintLines } = require('./docker-not-running-hint');
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Validates a command and its options
|
|
@@ -96,7 +96,47 @@ function isPermissionDeniedError(errorMsg) {
|
|
|
96
96
|
function isDockerPermissionDeniedError(errorMsg) {
|
|
97
97
|
if (!isPermissionDeniedError(errorMsg)) return false;
|
|
98
98
|
const lower = errorMsg.toLowerCase();
|
|
99
|
-
|
|
99
|
+
// Do not treat every EACCES as Docker (e.g. mkdir on a bogus server-side secrets path).
|
|
100
|
+
return lower.includes('docker') || lower.includes('docker.sock') || lower.includes('/var/run/docker');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* True for Node fs errno messages (mkdir, open, …), not HTTP 403 from Controller/Dataplane.
|
|
105
|
+
* Those strings also match {@link isPermissionDeniedError} and must not get API token hints.
|
|
106
|
+
* @param {string} errorMsg
|
|
107
|
+
* @returns {boolean}
|
|
108
|
+
*/
|
|
109
|
+
function isLocalFilesystemPermissionDeniedError(errorMsg) {
|
|
110
|
+
if (!errorMsg || typeof errorMsg !== 'string') return false;
|
|
111
|
+
const lower = errorMsg.toLowerCase();
|
|
112
|
+
const looksLikeFsErrno =
|
|
113
|
+
lower.includes('eacces') ||
|
|
114
|
+
lower.includes('eperm') ||
|
|
115
|
+
lower.includes('enoent') ||
|
|
116
|
+
lower.includes('enospc');
|
|
117
|
+
if (!looksLikeFsErrno && !lower.includes('permission denied')) return false;
|
|
118
|
+
return (
|
|
119
|
+
/\bmkdir\b/i.test(errorMsg) ||
|
|
120
|
+
/\brmdir\b/i.test(errorMsg) ||
|
|
121
|
+
/\brename\b/i.test(errorMsg) ||
|
|
122
|
+
/\bunlink\b/i.test(errorMsg) ||
|
|
123
|
+
/\bchmod\b/i.test(errorMsg) ||
|
|
124
|
+
/permission denied,?\s*open\b/i.test(lower) ||
|
|
125
|
+
/,\s*open\s+['"]/i.test(errorMsg)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Local fs EACCES (wrong AIFABRIX_HOME path, etc.) — not API/RBAC.
|
|
131
|
+
* @param {string} errorMsg
|
|
132
|
+
* @returns {string[]|null}
|
|
133
|
+
*/
|
|
134
|
+
function formatLocalFilesystemPermissionError(errorMsg) {
|
|
135
|
+
if (!isLocalFilesystemPermissionDeniedError(errorMsg)) return null;
|
|
136
|
+
return [
|
|
137
|
+
` ${errorMsg}`,
|
|
138
|
+
' This is a local filesystem path or permissions issue, not an API or RBAC token. Check AIFABRIX_HOME, AIFABRIX_CONFIG, and that the target directory is writable.'
|
|
139
|
+
];
|
|
100
140
|
}
|
|
101
141
|
|
|
102
142
|
/**
|
|
@@ -118,7 +158,8 @@ function formatDockerError(errorMsg) {
|
|
|
118
158
|
if (isDockerNotRunningError(errorMsg)) {
|
|
119
159
|
return [
|
|
120
160
|
' Docker is not running or not installed.',
|
|
121
|
-
|
|
161
|
+
` ${getDockerDaemonStartHintSentence()}`,
|
|
162
|
+
...getDockerApiOverTcpHintLines()
|
|
122
163
|
];
|
|
123
164
|
}
|
|
124
165
|
if (isPortConflictError(errorMsg)) {
|
|
@@ -129,20 +170,37 @@ function formatDockerError(errorMsg) {
|
|
|
129
170
|
}
|
|
130
171
|
if (isDockerPermissionDeniedError(errorMsg)) {
|
|
131
172
|
return [
|
|
132
|
-
' Permission denied.',
|
|
133
|
-
'
|
|
173
|
+
' Permission denied when using Docker (e.g. unix socket).',
|
|
174
|
+
' On Linux you can add your user to the "docker" group and log in again, or use the Engine API via docker-endpoint:',
|
|
175
|
+
...getDockerApiOverTcpHintLines()
|
|
134
176
|
];
|
|
135
177
|
}
|
|
136
178
|
return null;
|
|
137
179
|
}
|
|
138
180
|
|
|
181
|
+
/**
|
|
182
|
+
* True when the message indicates the Azure CLI binary is missing or not logged in.
|
|
183
|
+
* Do not use a naive "az"+"failed" substring match: "azurecr.io", "Azure", "lazy", "amazon", etc. contain "az".
|
|
184
|
+
* @param {string} errorMsg - Error message
|
|
185
|
+
* @returns {boolean}
|
|
186
|
+
*/
|
|
187
|
+
function isAzureCliToolingError(errorMsg) {
|
|
188
|
+
if (errorMsg.includes('Azure CLI is not installed')) return true;
|
|
189
|
+
if (errorMsg.includes('az --version failed')) return true;
|
|
190
|
+
if (errorMsg.includes('Not logged in to Azure')) return true;
|
|
191
|
+
if (errorMsg.includes('az: command not found')) return true;
|
|
192
|
+
if (errorMsg.includes('az.cmd: command not found')) return true;
|
|
193
|
+
if (errorMsg.includes('\'az\' is not recognized') || errorMsg.includes('"az" is not recognized')) return true;
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
139
197
|
/**
|
|
140
198
|
* Format Azure-related errors
|
|
141
199
|
* @param {string} errorMsg - Error message
|
|
142
200
|
* @returns {string[]|null} Array of error message lines or null if not an Azure error
|
|
143
201
|
*/
|
|
144
202
|
function formatAzureError(errorMsg) {
|
|
145
|
-
if (
|
|
203
|
+
if (isAzureCliToolingError(errorMsg)) {
|
|
146
204
|
return [
|
|
147
205
|
' Azure CLI is not installed or not working properly.',
|
|
148
206
|
' Install from: https://docs.microsoft.com/cli/azure/install-azure-cli',
|
|
@@ -249,6 +307,7 @@ function formatValidationError(errorMsg) {
|
|
|
249
307
|
function formatApiPermissionError(errorMsg) {
|
|
250
308
|
if (!isPermissionDeniedError(errorMsg)) return null;
|
|
251
309
|
if (isDockerPermissionDeniedError(errorMsg)) return null;
|
|
310
|
+
if (isLocalFilesystemPermissionDeniedError(errorMsg)) return null;
|
|
252
311
|
return [
|
|
253
312
|
` ${errorMsg}`,
|
|
254
313
|
' Ensure your token has the required permission (e.g. external-system:delete for delete).'
|
|
@@ -267,8 +326,25 @@ function formatApiPermissionError(errorMsg) {
|
|
|
267
326
|
* @param {string} errorMsg - Error message
|
|
268
327
|
* @returns {string[]|null} Formatted error messages or null if no formatter matched
|
|
269
328
|
*/
|
|
329
|
+
/**
|
|
330
|
+
* up-infra / checkDockerAvailability: multi-line "Cannot use Docker for infrastructure" + docker-endpoint hint.
|
|
331
|
+
* @param {string} errorMsg - Error message
|
|
332
|
+
* @returns {string[]|null}
|
|
333
|
+
*/
|
|
334
|
+
function formatCannotUseDockerInfrastructureError(errorMsg) {
|
|
335
|
+
if (!errorMsg.includes('Cannot use Docker for infrastructure')) {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
const lines = errorMsg.split('\n').map((l) => l.trim()).filter(Boolean);
|
|
339
|
+
const out = lines.map((l) => ` ${l}`);
|
|
340
|
+
out.push(...getDockerApiOverTcpHintLines());
|
|
341
|
+
return out;
|
|
342
|
+
}
|
|
343
|
+
|
|
270
344
|
function tryFormatErrorWithFormatters(errorMsg) {
|
|
271
345
|
const formatters = [
|
|
346
|
+
formatCannotUseDockerInfrastructureError,
|
|
347
|
+
formatLocalFilesystemPermissionError,
|
|
272
348
|
formatApiPermissionError,
|
|
273
349
|
formatDockerError,
|
|
274
350
|
formatAzureError,
|
|
@@ -312,13 +388,13 @@ function formatError(error) {
|
|
|
312
388
|
* @param {string[]} errorMessages - Error message lines
|
|
313
389
|
*/
|
|
314
390
|
function logError(command, errorMessages) {
|
|
315
|
-
logger.error(`\n
|
|
391
|
+
logger.error(`\n✖ Error in ${command} command:`);
|
|
316
392
|
errorMessages.forEach(msg => logger.error(msg));
|
|
317
393
|
logger.error('\n💡 Run "aifabrix doctor" for environment diagnostics.\n');
|
|
318
394
|
}
|
|
319
395
|
|
|
320
396
|
/**
|
|
321
|
-
* Logs the resolved app path so the user can see which directory (integration/<
|
|
397
|
+
* Logs the resolved app path so the user can see which directory (integration/<systemKey> or builder/<appKey>) is used.
|
|
322
398
|
* Path resolution order is always integration first, then builder; no CLI flag overrides this.
|
|
323
399
|
*
|
|
324
400
|
* @param {string} appPath - Resolved application directory path
|
|
@@ -366,7 +442,7 @@ function stripAnsi(str) {
|
|
|
366
442
|
}
|
|
367
443
|
|
|
368
444
|
/**
|
|
369
|
-
* Appends a wizard error to integration/<
|
|
445
|
+
* Appends a wizard error to integration/<systemKey>/error.log (timestamp + message only; no stack or secrets).
|
|
370
446
|
* Uses full formatted message (with validation details) when error.formatted is set, stripped of ANSI.
|
|
371
447
|
* Does not throw; logs and ignores write failures.
|
|
372
448
|
* @param {string} appKey - Application/integration key (e.g. app name or system key)
|
|
@@ -384,8 +460,9 @@ async function appendWizardError(appKey, error) {
|
|
|
384
460
|
const message = fullPlain && fullPlain.length > rawMessage.length ? fullPlain : rawMessage;
|
|
385
461
|
const line = `${new Date().toISOString()} ${message}\n`;
|
|
386
462
|
try {
|
|
387
|
-
|
|
388
|
-
await
|
|
463
|
+
const fsp = require('fs').promises;
|
|
464
|
+
await fsp.mkdir(dir, { recursive: true });
|
|
465
|
+
await fsp.appendFile(logPath, line, 'utf8');
|
|
389
466
|
} catch (e) {
|
|
390
467
|
logger.warn(`Could not write wizard error.log: ${e.message}`);
|
|
391
468
|
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read database passwords from .env for Docker Compose generation.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Compose DB password helpers
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 2.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fsSync = require('fs');
|
|
10
|
+
const fs = require('fs').promises;
|
|
11
|
+
const { formatMissingDbPasswordError } = require('./error-formatter');
|
|
12
|
+
|
|
13
|
+
/** Reads and parses .env file. @param {string} envPath - Path to .env file. @returns {Promise<Object>} env vars. @throws {Error} If file not found. */
|
|
14
|
+
async function readEnvFile(envPath) {
|
|
15
|
+
if (!fsSync.existsSync(envPath)) {
|
|
16
|
+
throw new Error(`.env file not found: ${envPath}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const envContent = await fs.readFile(envPath, 'utf8');
|
|
21
|
+
if (envContent === undefined || envContent === null) {
|
|
22
|
+
throw new Error('Failed to read .env file: file content is empty or undefined');
|
|
23
|
+
}
|
|
24
|
+
const lines = envContent.split('\n');
|
|
25
|
+
const envVars = {};
|
|
26
|
+
|
|
27
|
+
for (const line of lines) {
|
|
28
|
+
const trimmed = line.trim();
|
|
29
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const equalIndex = trimmed.indexOf('=');
|
|
34
|
+
if (equalIndex > 0) {
|
|
35
|
+
const key = trimmed.substring(0, equalIndex).trim();
|
|
36
|
+
const value = trimmed.substring(equalIndex + 1).trim();
|
|
37
|
+
envVars[key] = value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return envVars;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
throw new Error(`Failed to read .env file: ${error.message}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Validates and extracts password from environment variables
|
|
49
|
+
* @function extractPassword
|
|
50
|
+
* @param {Object} envVars - Environment variables
|
|
51
|
+
* @param {string} passwordKey - Password key to look up
|
|
52
|
+
* @param {Object} [context] - Optional: { appKey, multi } for clearer error messages
|
|
53
|
+
* @returns {string} Password value
|
|
54
|
+
* @throws {Error} If password is missing or empty
|
|
55
|
+
*/
|
|
56
|
+
function extractPassword(envVars, passwordKey, context = {}) {
|
|
57
|
+
const { appKey, multi } = context;
|
|
58
|
+
const appSuffix = appKey ? ` for application '${appKey}'` : '';
|
|
59
|
+
|
|
60
|
+
if (!(passwordKey in envVars)) {
|
|
61
|
+
throw new Error(multi && appKey ? formatMissingDbPasswordError(appKey, { multiDb: true, passwordKey }) : 'Missing required password variable ' + passwordKey + ' in .env file' + appSuffix + '. Add ' + passwordKey + '=your_secret to your .env file.');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const password = envVars[passwordKey].trim();
|
|
65
|
+
if (!password || password.length === 0) {
|
|
66
|
+
throw new Error('Password variable ' + passwordKey + ' is empty in .env file' + appSuffix + '. Set a non-empty value.');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return password;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Processes multiple databases
|
|
74
|
+
* @function processMultipleDatabases
|
|
75
|
+
* @param {Array} databases - Array of database configurations
|
|
76
|
+
* @param {Object} envVars - Environment variables
|
|
77
|
+
* @param {string} appKey - Application key
|
|
78
|
+
* @returns {Object} Object with passwords map and array
|
|
79
|
+
*/
|
|
80
|
+
function processMultipleDatabases(databases, envVars, appKey) {
|
|
81
|
+
const passwords = {};
|
|
82
|
+
const passwordsArray = [];
|
|
83
|
+
for (let i = 0; i < databases.length; i++) {
|
|
84
|
+
const db = databases[i];
|
|
85
|
+
const dbName = db.name || appKey;
|
|
86
|
+
const passwordKey = `DB_${i}_PASSWORD`;
|
|
87
|
+
const password = extractPassword(envVars, passwordKey, { appKey, multi: true });
|
|
88
|
+
passwords[dbName] = password;
|
|
89
|
+
passwordsArray.push(password);
|
|
90
|
+
}
|
|
91
|
+
return { passwords, passwordsArray };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Processes single database case
|
|
96
|
+
* @function processSingleDatabase
|
|
97
|
+
* @param {Object} envVars - Environment variables
|
|
98
|
+
* @param {string} appKey - Application key
|
|
99
|
+
* @returns {Object} Object with passwords map and array
|
|
100
|
+
*/
|
|
101
|
+
function processSingleDatabase(envVars, appKey) {
|
|
102
|
+
const passwords = {};
|
|
103
|
+
const passwordsArray = [];
|
|
104
|
+
const passwordKey = ('DB_0_PASSWORD' in envVars) ? 'DB_0_PASSWORD' : 'DB_PASSWORD';
|
|
105
|
+
if (!(passwordKey in envVars)) {
|
|
106
|
+
throw new Error(formatMissingDbPasswordError(appKey));
|
|
107
|
+
}
|
|
108
|
+
const password = extractPassword(envVars, passwordKey, { appKey });
|
|
109
|
+
passwords[appKey] = password;
|
|
110
|
+
passwordsArray.push(password);
|
|
111
|
+
return { passwords, passwordsArray };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Reads database passwords from .env file
|
|
116
|
+
* @async
|
|
117
|
+
* @function readDatabasePasswords
|
|
118
|
+
* @param {string} envPath - Path to .env file
|
|
119
|
+
* @param {Array<Object>} databases - Array of database configurations
|
|
120
|
+
* @param {string} appKey - Application key (fallback for single database)
|
|
121
|
+
* @returns {Promise<Object>} Object with passwords map and array
|
|
122
|
+
* @throws {Error} If required password variables are missing
|
|
123
|
+
*/
|
|
124
|
+
async function readDatabasePasswords(envPath, databases, appKey) {
|
|
125
|
+
const envVars = await readEnvFile(envPath);
|
|
126
|
+
if (databases && databases.length > 0) {
|
|
127
|
+
const { passwords, passwordsArray } = processMultipleDatabases(databases, envVars, appKey);
|
|
128
|
+
return { map: passwords, array: passwordsArray };
|
|
129
|
+
}
|
|
130
|
+
const { passwords, passwordsArray } = processSingleDatabase(envVars, appKey);
|
|
131
|
+
return { map: passwords, array: passwordsArray };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
module.exports = {
|
|
135
|
+
readDatabasePasswords,
|
|
136
|
+
readEnvFile,
|
|
137
|
+
extractPassword
|
|
138
|
+
};
|