@aifabrix/builder 2.43.0 → 2.44.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.
- package/.cursor/rules/anchor-docs.mdc +15 -0
- package/.cursor/rules/cli-layout.mdc +75 -0
- package/.cursor/rules/project-rules.mdc +8 -0
- package/.npmrc.token +1 -0
- package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
- package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -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 +301 -0
- package/lib/api/certificates.api.js +62 -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 +11 -3
- package/lib/api/pipeline.api.js +67 -20
- package/lib/api/types/certificates.types.js +48 -0
- 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 +111 -0
- package/lib/api/validation-runner.js +109 -0
- package/lib/app/certification-show-enrich.js +129 -0
- package/lib/app/certification-verify-rows.js +60 -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 +44 -1
- package/lib/app/show.js +93 -9
- package/lib/build/index.js +13 -10
- package/lib/certification/cli-cert-sync-skip.js +21 -0
- package/lib/certification/merge-certification-from-artifact.js +185 -0
- package/lib/certification/post-unified-cert-sync.js +33 -0
- package/lib/certification/sync-after-external-command.js +52 -0
- package/lib/certification/sync-system-certification.js +197 -0
- package/lib/cli/index.js +2 -0
- package/lib/cli/setup-app.help.js +67 -0
- package/lib/cli/setup-app.js +61 -121
- package/lib/cli/setup-app.test-commands.js +195 -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 +84 -23
- package/lib/cli/setup-infra.js +126 -47
- package/lib/cli/setup-parameters.js +32 -0
- package/lib/cli/setup-secrets.js +137 -18
- package/lib/cli/setup-service-user.js +1 -1
- package/lib/cli/setup-utility.js +54 -22
- 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 +32 -11
- 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 +428 -0
- package/lib/commands/datasource-unified-test-cli.options.js +191 -0
- package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
- package/lib/commands/datasource-validation-cli.js +143 -0
- package/lib/commands/datasource.js +125 -95
- 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 +149 -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 +189 -67
- package/lib/datasource/resolve-app.js +4 -4
- package/lib/datasource/test-e2e.js +113 -146
- package/lib/datasource/test-integration.js +114 -122
- package/lib/datasource/unified-validation-run-body.js +68 -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 +93 -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 +166 -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 +70 -7
- package/lib/infrastructure/helpers-docker-check.js +67 -0
- package/lib/infrastructure/helpers.js +203 -42
- package/lib/infrastructure/index.js +31 -18
- package/lib/infrastructure/services.js +21 -67
- 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 +203 -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 +226 -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 +77 -17
- 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/configuration-env-resolver.js +11 -8
- package/lib/utils/controller-deployment-outcome.js +68 -0
- package/lib/utils/credential-display.js +2 -2
- package/lib/utils/credential-secrets-env.js +5 -5
- 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-certificate-tty.js +82 -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 +459 -0
- package/lib/utils/datasource-test-run-exit.js +83 -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 +242 -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-system-test-tty-overview.js +120 -0
- package/lib/utils/external-system-system-test-tty.js +417 -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 +148 -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 +112 -0
- package/lib/utils/validation-run-post-retry.js +85 -0
- package/lib/utils/validation-run-request.js +116 -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-external-cert-sync.js +23 -0
- package/lib/validation/validate.js +8 -14
- 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 +9 -4
- package/scripts/check-datasource-test-run-schema-sync.js +34 -0
- package/scripts/diagnose-cli.js +150 -0
- package/scripts/install-local.js +307 -55
- package/scripts/pnpm-global-remove.js +48 -0
- package/templates/README.md +15 -2
- package/templates/applications/dataplane/application.yaml +52 -2
- package/templates/applications/dataplane/env.template +79 -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 +33 -16
- package/templates/infra/servers.json.hbs +3 -1
- 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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatSuccessLine } = require('./cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
3
|
* Health Check Utilities
|
|
3
4
|
*
|
|
@@ -9,13 +10,41 @@
|
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
const http = require('http');
|
|
13
|
+
const https = require('https');
|
|
12
14
|
const net = require('net');
|
|
13
15
|
const chalk = require('chalk');
|
|
14
|
-
const { exec } = require('child_process');
|
|
15
|
-
const { promisify } = require('util');
|
|
16
16
|
const logger = require('./logger');
|
|
17
|
+
const { execWithDockerEnv } = require('./docker-exec');
|
|
18
|
+
const { computeTraefikHealthCheckUrl } = require('./health-check-url');
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Compute the health check URL for an app.
|
|
22
|
+
*
|
|
23
|
+
* - Default (no Traefik front-door): http://localhost:<port><healthPath>
|
|
24
|
+
* - With Traefik + app frontDoorRouting.enabled: <publicBase><frontDoorRouting.pattern><healthPath>
|
|
25
|
+
*
|
|
26
|
+
* @async
|
|
27
|
+
* @param {string} appName
|
|
28
|
+
* @param {number} healthCheckPort
|
|
29
|
+
* @param {Object|null} appConfig
|
|
30
|
+
* @param {Object} opts
|
|
31
|
+
* @param {Object} [opts.runOptions] - runApp options (may include env + effectiveEnvironmentScopedResources)
|
|
32
|
+
* @returns {Promise<string>}
|
|
33
|
+
*/
|
|
34
|
+
async function computeHealthCheckUrl(appName, healthCheckPort, appConfig, _opts = {}) {
|
|
35
|
+
const healthCheckPath = appConfig?.healthCheck?.path || '/health';
|
|
36
|
+
|
|
37
|
+
// Traefik front-door branch: probe via resolved public host + path (e.g. https://dev02.builder02.local/auth/health/ready)
|
|
38
|
+
try {
|
|
39
|
+
const traefikUrl = await computeTraefikHealthCheckUrl(appName, healthCheckPort, appConfig);
|
|
40
|
+
if (traefikUrl) return traefikUrl;
|
|
41
|
+
} catch {
|
|
42
|
+
// If any resolver step fails, fall back to localhost probing.
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Default: probe local published port.
|
|
46
|
+
return `http://localhost:${healthCheckPort}${healthCheckPath}`;
|
|
47
|
+
}
|
|
19
48
|
|
|
20
49
|
/**
|
|
21
50
|
* Checks if db-init container exists and waits for it to complete
|
|
@@ -33,7 +62,7 @@ const execAsync = promisify(exec);
|
|
|
33
62
|
*/
|
|
34
63
|
async function checkDbInitContainerExists(dbInitContainer) {
|
|
35
64
|
try {
|
|
36
|
-
const { stdout } = await
|
|
65
|
+
const { stdout } = await execWithDockerEnv(`docker ps -a --filter "name=${dbInitContainer}" --format "{{.Names}}"`);
|
|
37
66
|
return stdout.trim() === dbInitContainer;
|
|
38
67
|
} catch {
|
|
39
68
|
return false;
|
|
@@ -48,7 +77,7 @@ async function checkDbInitContainerExists(dbInitContainer) {
|
|
|
48
77
|
* @returns {Promise<string>} Exit code
|
|
49
78
|
*/
|
|
50
79
|
async function getContainerExitCode(dbInitContainer) {
|
|
51
|
-
const { stdout: exitCode } = await
|
|
80
|
+
const { stdout: exitCode } = await execWithDockerEnv(`docker inspect --format='{{.State.ExitCode}}' ${dbInitContainer}`);
|
|
52
81
|
return exitCode.trim();
|
|
53
82
|
}
|
|
54
83
|
|
|
@@ -60,11 +89,11 @@ async function getContainerExitCode(dbInitContainer) {
|
|
|
60
89
|
* @returns {Promise<boolean>} True if handled (container already exited)
|
|
61
90
|
*/
|
|
62
91
|
async function handleExitedContainer(dbInitContainer) {
|
|
63
|
-
const { stdout: status } = await
|
|
92
|
+
const { stdout: status } = await execWithDockerEnv(`docker inspect --format='{{.State.Status}}' ${dbInitContainer}`);
|
|
64
93
|
if (status.trim() === 'exited') {
|
|
65
94
|
const exitCode = await getContainerExitCode(dbInitContainer);
|
|
66
95
|
if (exitCode === '0') {
|
|
67
|
-
logger.log(
|
|
96
|
+
logger.log(formatSuccessLine('Database initialization already completed'));
|
|
68
97
|
} else {
|
|
69
98
|
logger.log(chalk.yellow(`⚠ Database initialization exited with code ${exitCode}`));
|
|
70
99
|
}
|
|
@@ -82,11 +111,11 @@ async function handleExitedContainer(dbInitContainer) {
|
|
|
82
111
|
*/
|
|
83
112
|
async function waitForContainerExit(dbInitContainer, maxAttempts) {
|
|
84
113
|
for (let attempts = 0; attempts < maxAttempts; attempts++) {
|
|
85
|
-
const { stdout: currentStatus } = await
|
|
114
|
+
const { stdout: currentStatus } = await execWithDockerEnv(`docker inspect --format='{{.State.Status}}' ${dbInitContainer}`);
|
|
86
115
|
if (currentStatus.trim() === 'exited') {
|
|
87
116
|
const exitCode = await getContainerExitCode(dbInitContainer);
|
|
88
117
|
if (exitCode === '0') {
|
|
89
|
-
logger.log(
|
|
118
|
+
logger.log(formatSuccessLine('Database initialization completed'));
|
|
90
119
|
} else {
|
|
91
120
|
logger.log(chalk.yellow(`⚠ Database initialization exited with code ${exitCode}`));
|
|
92
121
|
}
|
|
@@ -135,7 +164,7 @@ async function getPortFromDockerInspect(appName, debug) {
|
|
|
135
164
|
if (debug) {
|
|
136
165
|
logger.log(chalk.gray(`[DEBUG] Executing: ${inspectCmd}`));
|
|
137
166
|
}
|
|
138
|
-
const { stdout: portMapping } = await
|
|
167
|
+
const { stdout: portMapping } = await execWithDockerEnv(inspectCmd);
|
|
139
168
|
const ports = portMapping.trim().split('\n').filter(p => p && p !== '');
|
|
140
169
|
if (ports.length > 0) {
|
|
141
170
|
const port = parseInt(ports[0], 10);
|
|
@@ -162,7 +191,7 @@ async function getPortFromDockerPs(appName, debug) {
|
|
|
162
191
|
if (debug) {
|
|
163
192
|
logger.log(chalk.gray(`[DEBUG] Fallback: Executing: ${psCmd}`));
|
|
164
193
|
}
|
|
165
|
-
const { stdout: psOutput } = await
|
|
194
|
+
const { stdout: psOutput } = await execWithDockerEnv(psCmd);
|
|
166
195
|
const portMatch = psOutput.match(/:(\d+)->/);
|
|
167
196
|
if (!portMatch) {
|
|
168
197
|
return null;
|
|
@@ -244,6 +273,7 @@ function handleHealthResponse(res, data, debug, resolve) {
|
|
|
244
273
|
function doHealthCheckRequest(healthCheckUrl, debug, resolve, reject) {
|
|
245
274
|
try {
|
|
246
275
|
const urlObj = new URL(healthCheckUrl);
|
|
276
|
+
const transport = urlObj.protocol === 'https:' ? https : http;
|
|
247
277
|
const options = {
|
|
248
278
|
hostname: urlObj.hostname,
|
|
249
279
|
port: urlObj.port || (urlObj.protocol === 'https:' ? 443 : 80),
|
|
@@ -254,10 +284,9 @@ function doHealthCheckRequest(healthCheckUrl, debug, resolve, reject) {
|
|
|
254
284
|
logger.log(chalk.gray(`[DEBUG] Health check request: ${healthCheckUrl}`));
|
|
255
285
|
logger.log(chalk.gray(`[DEBUG] Request options: ${JSON.stringify(options, null, 2)}`));
|
|
256
286
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
clearTimeout(timeoutId);
|
|
287
|
+
const timer = { id: null };
|
|
288
|
+
const req = transport.request(options, (res) => {
|
|
289
|
+
clearTimeout(timer.id);
|
|
261
290
|
let data = '';
|
|
262
291
|
if (debug) {
|
|
263
292
|
logger.log(chalk.gray(`[DEBUG] Response status code: ${res.statusCode}`));
|
|
@@ -268,13 +297,13 @@ function doHealthCheckRequest(healthCheckUrl, debug, resolve, reject) {
|
|
|
268
297
|
});
|
|
269
298
|
res.on('end', () => handleHealthResponse(res, data, debug, resolve));
|
|
270
299
|
});
|
|
271
|
-
|
|
300
|
+
timer.id = setTimeout(() => {
|
|
272
301
|
if (debug) logger.log(chalk.gray('[DEBUG] Health check request timeout after 5 seconds'));
|
|
273
302
|
req.destroy();
|
|
274
303
|
resolve(false);
|
|
275
304
|
}, 5000);
|
|
276
305
|
req.on('error', (error) => {
|
|
277
|
-
clearTimeout(
|
|
306
|
+
clearTimeout(timer.id);
|
|
278
307
|
if (debug) logger.log(chalk.gray(`[DEBUG] Health check request error: ${error.message}`));
|
|
279
308
|
resolve(false);
|
|
280
309
|
});
|
|
@@ -341,16 +370,14 @@ async function determineHealthCheckPort(port, appName, debug) {
|
|
|
341
370
|
* @returns {Object} Health check configuration
|
|
342
371
|
*/
|
|
343
372
|
function buildHealthCheckConfig(healthCheckPort, config, timeout, debug) {
|
|
344
|
-
const healthCheckPath = config?.healthCheck?.path || '/health';
|
|
345
|
-
const healthCheckUrl = `http://localhost:${healthCheckPort}${healthCheckPath}`;
|
|
346
373
|
const maxAttempts = timeout / 2;
|
|
347
374
|
|
|
375
|
+
// URL is computed later (may use Traefik public base).
|
|
348
376
|
if (debug) {
|
|
349
|
-
logger.log(chalk.gray(`[DEBUG] Health check URL: ${healthCheckUrl}`));
|
|
350
377
|
logger.log(chalk.gray(`[DEBUG] Timeout: ${timeout} seconds, Max attempts: ${maxAttempts}`));
|
|
351
378
|
}
|
|
352
379
|
|
|
353
|
-
return {
|
|
380
|
+
return { maxAttempts };
|
|
354
381
|
}
|
|
355
382
|
|
|
356
383
|
/**
|
|
@@ -370,7 +397,7 @@ async function performHealthCheckAttempt(healthCheckUrl, attempt, maxAttempts, d
|
|
|
370
397
|
}
|
|
371
398
|
const healthCheckPassed = await checkHealthEndpoint(healthCheckUrl, debug);
|
|
372
399
|
if (healthCheckPassed) {
|
|
373
|
-
logger.log(
|
|
400
|
+
logger.log(formatSuccessLine('Application is healthy'));
|
|
374
401
|
if (debug) {
|
|
375
402
|
logger.log(chalk.gray(`[DEBUG] Health check passed after ${attempt + 1} attempt(s)`));
|
|
376
403
|
}
|
|
@@ -384,11 +411,15 @@ async function performHealthCheckAttempt(healthCheckUrl, attempt, maxAttempts, d
|
|
|
384
411
|
return false;
|
|
385
412
|
}
|
|
386
413
|
|
|
387
|
-
async function waitForHealthCheck(appName, timeout = 90, port = null, config = null, debug = false) {
|
|
414
|
+
async function waitForHealthCheck(appName, timeout = 90, port = null, config = null, debug = false, runOptions = {}) {
|
|
388
415
|
await waitForDbInit(appName);
|
|
389
416
|
|
|
390
417
|
const healthCheckPort = await determineHealthCheckPort(port, appName, debug);
|
|
391
|
-
const {
|
|
418
|
+
const { maxAttempts } = buildHealthCheckConfig(healthCheckPort, config, timeout, debug);
|
|
419
|
+
const healthCheckUrl = await computeHealthCheckUrl(appName, healthCheckPort, config, { runOptions });
|
|
420
|
+
if (debug) {
|
|
421
|
+
logger.log(chalk.gray(`[DEBUG] Health check URL: ${healthCheckUrl}`));
|
|
422
|
+
}
|
|
392
423
|
|
|
393
424
|
for (let attempts = 0; attempts < maxAttempts; attempts++) {
|
|
394
425
|
const passed = await performHealthCheckAttempt(healthCheckUrl, attempts, maxAttempts, debug);
|
|
@@ -426,6 +457,9 @@ async function checkPortAvailable(port) {
|
|
|
426
457
|
module.exports = {
|
|
427
458
|
waitForHealthCheck,
|
|
428
459
|
checkHealthEndpoint,
|
|
429
|
-
checkPortAvailable
|
|
460
|
+
checkPortAvailable,
|
|
461
|
+
computeHealthCheckUrl,
|
|
462
|
+
// Re-exported for tests and shared usage.
|
|
463
|
+
normalizeFrontDoorPatternForHealth: require('./health-check-url').normalizeFrontDoorPatternForHealth
|
|
430
464
|
};
|
|
431
465
|
|
|
@@ -12,7 +12,7 @@ const { Help } = require('commander');
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Command categories and order. Each command can have an optional `term` override
|
|
15
|
-
* for the help line (e.g. "down [app]"); otherwise the command name is used.
|
|
15
|
+
* for the help line (e.g. "down [service|app]"); otherwise the command name is used.
|
|
16
16
|
*
|
|
17
17
|
* @type {Array<{ name: string, commands: Array<{ name: string, term?: string }> }>}
|
|
18
18
|
*/
|
|
@@ -24,10 +24,10 @@ const CATEGORIES = [
|
|
|
24
24
|
{ name: 'up-platform' },
|
|
25
25
|
{ name: 'up-miso' },
|
|
26
26
|
{ name: 'up-dataplane' },
|
|
27
|
-
{ name: 'down-infra', term: 'down-infra [app]' },
|
|
27
|
+
{ name: 'down-infra', term: 'down-infra [service|app]' },
|
|
28
28
|
{ name: 'doctor' },
|
|
29
29
|
{ name: 'status' },
|
|
30
|
-
{ name: 'restart', term: 'restart <service>' }
|
|
30
|
+
{ name: 'restart', term: 'restart <service|app>' }
|
|
31
31
|
]
|
|
32
32
|
},
|
|
33
33
|
{
|
|
@@ -82,18 +82,19 @@ const CATEGORIES = [
|
|
|
82
82
|
{ name: 'json', term: 'json <app>' },
|
|
83
83
|
{ name: 'split-json', term: 'split-json <app>' },
|
|
84
84
|
{ name: 'convert', term: 'convert <app>' },
|
|
85
|
-
{ name: 'show', term: 'show <
|
|
85
|
+
{ name: 'show', term: 'show <app>' },
|
|
86
86
|
{ name: 'validate', term: 'validate <appOrFile>' },
|
|
87
|
+
{ name: 'parameters', term: 'parameters validate' },
|
|
87
88
|
{ name: 'diff', term: 'diff <file1> <file2>' }
|
|
88
89
|
]
|
|
89
90
|
},
|
|
90
91
|
{
|
|
91
92
|
name: 'External Systems',
|
|
92
93
|
commands: [
|
|
93
|
-
{ name: 'download', term: 'download <
|
|
94
|
-
{ name: 'upload', term: 'upload <
|
|
95
|
-
{ name: 'delete', term: 'delete <
|
|
96
|
-
{ name: 'repair', term: 'repair <
|
|
94
|
+
{ name: 'download', term: 'download <systemKey>' },
|
|
95
|
+
{ name: 'upload', term: 'upload <systemKey>' },
|
|
96
|
+
{ name: 'delete', term: 'delete <systemKey>' },
|
|
97
|
+
{ name: 'repair', term: 'repair <systemKey>' },
|
|
97
98
|
{ name: 'datasource' },
|
|
98
99
|
{ name: 'test', term: 'test <app>' },
|
|
99
100
|
{ name: 'test-e2e', term: 'test-e2e <app>' },
|
|
@@ -182,6 +183,8 @@ function formatCommandCategories(helper, program) {
|
|
|
182
183
|
out.push('Help:');
|
|
183
184
|
out.push(` ${'help [command]'.padEnd(pad)}display help for command`);
|
|
184
185
|
out.push('');
|
|
186
|
+
out.push(` ${''.padEnd(pad)}Tip: aifabrix <command> --help for flags and examples`);
|
|
187
|
+
out.push('');
|
|
185
188
|
return out;
|
|
186
189
|
}
|
|
187
190
|
|
|
@@ -9,15 +9,12 @@
|
|
|
9
9
|
* @version 2.0.0
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
const { exec } = require('child_process');
|
|
13
|
-
const { promisify } = require('util');
|
|
14
12
|
const { getBuilderPath } = require('./paths');
|
|
15
13
|
const { resolveApplicationConfigPath } = require('./app-config-resolver');
|
|
16
14
|
const { loadConfigFile, writeConfigFile } = require('./config-format');
|
|
17
|
-
const composeGenerator = require('./compose-generator');
|
|
18
15
|
const containerHelpers = require('./app-run-containers');
|
|
19
|
-
|
|
20
|
-
const
|
|
16
|
+
const { resolveDockerImageRef } = require('./resolve-docker-image-ref');
|
|
17
|
+
const { execWithDockerEnv } = require('./docker-exec');
|
|
21
18
|
|
|
22
19
|
const OCI_VERSION_LABEL = 'org.opencontainers.image.version';
|
|
23
20
|
const SEMVER_REGEX = /^v?(\d+\.\d+\.\d+)(?:-[-.\w]+)?(?:\+[-.\w]+)?$/i;
|
|
@@ -38,7 +35,7 @@ async function getVersionFromImage(imageName, imageTag) {
|
|
|
38
35
|
|
|
39
36
|
try {
|
|
40
37
|
const labelFormat = `{{index .Config.Labels "${OCI_VERSION_LABEL}"}}`;
|
|
41
|
-
const { stdout } = await
|
|
38
|
+
const { stdout } = await execWithDockerEnv(
|
|
42
39
|
`docker inspect --format '${labelFormat}' "${fullImage}" 2>/dev/null || true`,
|
|
43
40
|
{ timeout: 10000 }
|
|
44
41
|
);
|
|
@@ -139,8 +136,7 @@ async function resolveVersionForApp(appName, variables, options = {}) {
|
|
|
139
136
|
return { version, fromImage: false, updated: false };
|
|
140
137
|
}
|
|
141
138
|
|
|
142
|
-
const imageName =
|
|
143
|
-
const imageTag = variables?.image?.tag || 'latest';
|
|
139
|
+
const { imageName, imageTag } = resolveDockerImageRef(appName, variables, {});
|
|
144
140
|
const imageExists = await containerHelpers.checkImageExists(imageName, imageTag);
|
|
145
141
|
|
|
146
142
|
if (!imageExists) {
|
|
@@ -9,11 +9,8 @@
|
|
|
9
9
|
* @version 2.0.0
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
const { exec } = require('child_process');
|
|
13
|
-
const { promisify } = require('util');
|
|
14
12
|
const config = require('../core/config');
|
|
15
|
-
|
|
16
|
-
const execAsync = promisify(exec);
|
|
13
|
+
const { execWithDockerEnv } = require('./docker-exec');
|
|
17
14
|
|
|
18
15
|
/**
|
|
19
16
|
* Finds container by name pattern
|
|
@@ -42,7 +39,7 @@ async function findContainer(serviceName, devId = null, options = {}) {
|
|
|
42
39
|
];
|
|
43
40
|
|
|
44
41
|
for (const pattern of patternsToTry) {
|
|
45
|
-
const { stdout } = await
|
|
42
|
+
const { stdout } = await execWithDockerEnv(`docker ps --filter "name=${pattern}" --format "{{.Names}}"`);
|
|
46
43
|
const names = stdout
|
|
47
44
|
.split('\n')
|
|
48
45
|
.map(s => s.trim())
|
|
@@ -75,7 +72,7 @@ async function checkServiceWithHealthCheck(serviceName, devId = null, options =
|
|
|
75
72
|
if (!containerName) {
|
|
76
73
|
return 'unknown';
|
|
77
74
|
}
|
|
78
|
-
const { stdout } = await
|
|
75
|
+
const { stdout } = await execWithDockerEnv(`docker inspect --format='{{.State.Health.Status}}' ${containerName}`);
|
|
79
76
|
const status = stdout.trim().replace(/['"]/g, '');
|
|
80
77
|
// Accept both 'healthy' and 'starting' as healthy (starting means it's initializing)
|
|
81
78
|
return (status === 'healthy' || status === 'starting') ? 'healthy' : status;
|
|
@@ -99,7 +96,7 @@ async function checkServiceWithoutHealthCheck(serviceName, devId = null, options
|
|
|
99
96
|
if (!containerName) {
|
|
100
97
|
return 'unknown';
|
|
101
98
|
}
|
|
102
|
-
const { stdout } = await
|
|
99
|
+
const { stdout } = await execWithDockerEnv(`docker inspect --format='{{.State.Status}}' ${containerName}`);
|
|
103
100
|
const status = stdout.trim().replace(/['"]/g, '');
|
|
104
101
|
// Treat 'running' or 'healthy' as 'healthy' for services without health checks
|
|
105
102
|
return (status === 'running' || status === 'healthy') ? 'healthy' : 'unhealthy';
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical env defaults for docker/local interpolation (formerly lib/schema/env-config.yaml).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Infra-only vs app-service layers merged for backward compatibility.
|
|
5
|
+
* True infra: DB, Redis, runtime. App rows (MISO_*, DATAPLANE_*, …) are a separate object
|
|
6
|
+
* so policy and future YAML-only sourcing stay clear — see APP_SERVICE_ENV_DEFAULTS.
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const { buildAppServiceEnvOverlay } = require('./app-service-env-from-builder');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {string|null|undefined} projectRoot
|
|
17
|
+
* @returns {string}
|
|
18
|
+
*/
|
|
19
|
+
function resolveProjectRootForEnvDefaults(projectRoot) {
|
|
20
|
+
if (projectRoot !== undefined && projectRoot !== null) {
|
|
21
|
+
return projectRoot;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const { getProjectRoot } = require('./paths');
|
|
25
|
+
if (typeof getProjectRoot === 'function') {
|
|
26
|
+
return getProjectRoot();
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
// ignore
|
|
30
|
+
}
|
|
31
|
+
return process.cwd();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Docker profile: databases, cache, process env only (no application services). */
|
|
35
|
+
const INFRA_ENV_DEFAULTS_DOCKER = Object.freeze({
|
|
36
|
+
DB_HOST: 'postgres',
|
|
37
|
+
DB_PORT: 5432,
|
|
38
|
+
REDIS_HOST: 'redis',
|
|
39
|
+
REDIS_PORT: 6379,
|
|
40
|
+
NODE_ENV: 'production',
|
|
41
|
+
PYTHONUNBUFFERED: 1,
|
|
42
|
+
PYTHONDONTWRITEBYTECODE: 1,
|
|
43
|
+
PYTHONIOENCODING: 'utf-8'
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
/** Local profile: same infra shape as docker with localhost hosts. */
|
|
47
|
+
const INFRA_ENV_DEFAULTS_LOCAL = Object.freeze({
|
|
48
|
+
DB_HOST: 'localhost',
|
|
49
|
+
DB_PORT: 5432,
|
|
50
|
+
REDIS_HOST: 'localhost',
|
|
51
|
+
REDIS_PORT: 6379,
|
|
52
|
+
NODE_ENV: 'development',
|
|
53
|
+
PYTHONUNBUFFERED: 1,
|
|
54
|
+
PYTHONDONTWRITEBYTECODE: 1,
|
|
55
|
+
PYTHONIOENCODING: 'utf-8'
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Default *_HOST / *_PORT / *_PUBLIC_PORT for known stack apps.
|
|
60
|
+
* Prefer application.yaml + url:// for URLs; these support ${VAR} interpolation until templates migrate.
|
|
61
|
+
*/
|
|
62
|
+
const APP_SERVICE_ENV_DEFAULTS_DOCKER = Object.freeze({
|
|
63
|
+
MISO_HOST: 'miso-controller',
|
|
64
|
+
MISO_PORT: 3000,
|
|
65
|
+
MISO_PUBLIC_PORT: 3000,
|
|
66
|
+
KEYCLOAK_HOST: 'keycloak',
|
|
67
|
+
KEYCLOAK_PORT: 8080,
|
|
68
|
+
KEYCLOAK_PUBLIC_PORT: 8082,
|
|
69
|
+
MORI_HOST: 'mori-controller',
|
|
70
|
+
MORI_PORT: 3004,
|
|
71
|
+
OPENWEBUI_HOST: 'openwebui',
|
|
72
|
+
OPENWEBUI_PORT: 3003,
|
|
73
|
+
FLOWISE_HOST: 'flowise',
|
|
74
|
+
FLOWISE_PORT: 3002,
|
|
75
|
+
DATAPLANE_HOST: 'dataplane',
|
|
76
|
+
DATAPLANE_PORT: 3001,
|
|
77
|
+
DATAPLANE_PUBLIC_PORT: 3001
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const APP_SERVICE_ENV_DEFAULTS_LOCAL = Object.freeze({
|
|
81
|
+
MISO_HOST: 'localhost',
|
|
82
|
+
MISO_PORT: 3010,
|
|
83
|
+
MISO_PUBLIC_PORT: 3010,
|
|
84
|
+
KEYCLOAK_HOST: 'localhost',
|
|
85
|
+
KEYCLOAK_PORT: 8082,
|
|
86
|
+
KEYCLOAK_PUBLIC_PORT: 8082,
|
|
87
|
+
MORI_HOST: 'localhost',
|
|
88
|
+
MORI_PORT: 3014,
|
|
89
|
+
OPENWEBUI_HOST: 'localhost',
|
|
90
|
+
OPENWEBUI_PORT: 3013,
|
|
91
|
+
FLOWISE_HOST: 'localhost',
|
|
92
|
+
FLOWISE_PORT: 3012,
|
|
93
|
+
DATAPLANE_HOST: 'localhost',
|
|
94
|
+
DATAPLANE_PORT: 3011,
|
|
95
|
+
DATAPLANE_PUBLIC_PORT: 3011
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @param {Record<string, unknown>} a
|
|
100
|
+
* @param {Record<string, unknown>} b
|
|
101
|
+
* @returns {Record<string, unknown>}
|
|
102
|
+
*/
|
|
103
|
+
function shallowMergeEnv(a, b) {
|
|
104
|
+
return { ...a, ...b };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Merged env-config shape (infra + static app fallbacks + per-app builder manifest overlay).
|
|
109
|
+
* @param {string|null|undefined} [projectRoot] - When omitted, uses paths getProjectRoot or process.cwd().
|
|
110
|
+
* @returns {Object}
|
|
111
|
+
*/
|
|
112
|
+
function buildMergedDefaultEnvConfig(projectRoot) {
|
|
113
|
+
const root = resolveProjectRootForEnvDefaults(projectRoot);
|
|
114
|
+
const overlay = buildAppServiceEnvOverlay(root);
|
|
115
|
+
return {
|
|
116
|
+
environments: {
|
|
117
|
+
docker: shallowMergeEnv(
|
|
118
|
+
shallowMergeEnv(
|
|
119
|
+
{ ...INFRA_ENV_DEFAULTS_DOCKER },
|
|
120
|
+
{ ...APP_SERVICE_ENV_DEFAULTS_DOCKER }
|
|
121
|
+
),
|
|
122
|
+
overlay.docker
|
|
123
|
+
),
|
|
124
|
+
local: shallowMergeEnv(
|
|
125
|
+
shallowMergeEnv(
|
|
126
|
+
{ ...INFRA_ENV_DEFAULTS_LOCAL },
|
|
127
|
+
{ ...APP_SERVICE_ENV_DEFAULTS_LOCAL }
|
|
128
|
+
),
|
|
129
|
+
overlay.local
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Deep clone of default env-config (docker/local hosts and ports).
|
|
137
|
+
* @param {string|null|undefined} [projectRoot] - Optional workspace root for builder/ scan.
|
|
138
|
+
* @returns {Object}
|
|
139
|
+
*/
|
|
140
|
+
function getDefaultEnvConfig(projectRoot) {
|
|
141
|
+
return JSON.parse(JSON.stringify(buildMergedDefaultEnvConfig(projectRoot)));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Infra-only defaults for declarative url:// resolution and registry fallbacks.
|
|
146
|
+
* Application manifests should set `port` / `frontDoorRouting`; these apply when omitted.
|
|
147
|
+
*/
|
|
148
|
+
const DECLARATIVE_URL_INFRA_DEFAULTS = Object.freeze({
|
|
149
|
+
manifestPortFallback: 3000,
|
|
150
|
+
frontDoorPatternWhenUnspecified: '/',
|
|
151
|
+
inactiveVdirPublicEnvReplacement: '/'
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
module.exports = {
|
|
155
|
+
getDefaultEnvConfig,
|
|
156
|
+
buildMergedDefaultEnvConfig,
|
|
157
|
+
INFRA_ENV_DEFAULTS_DOCKER,
|
|
158
|
+
INFRA_ENV_DEFAULTS_LOCAL,
|
|
159
|
+
APP_SERVICE_ENV_DEFAULTS_DOCKER,
|
|
160
|
+
APP_SERVICE_ENV_DEFAULTS_LOCAL,
|
|
161
|
+
DECLARATIVE_URL_INFRA_DEFAULTS
|
|
162
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared output for `aifabrix status`: title + configuration block.
|
|
3
|
+
* TLS/SSL (`infraTlsSslCell`) and `devNN` title match `dev-show-display.js`; environment, Traefik,
|
|
4
|
+
* and scoped-resources lines use uppercase ON/OFF-style labels for status output.
|
|
5
|
+
*
|
|
6
|
+
* @fileoverview Infra status CLI display helpers
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const config = require('../core/config');
|
|
14
|
+
const logger = require('./logger');
|
|
15
|
+
|
|
16
|
+
/** En dash for unset / empty values (same as dev-show-display). */
|
|
17
|
+
const EM = '\u2013';
|
|
18
|
+
const LABEL_W = 18;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {unknown} v
|
|
22
|
+
* @returns {boolean}
|
|
23
|
+
*/
|
|
24
|
+
function isUnset(v) {
|
|
25
|
+
return v === null || v === undefined || v === '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {unknown} v
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
function cell(v) {
|
|
33
|
+
return isUnset(v) ? EM : String(v);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {string} label
|
|
38
|
+
* @param {unknown} value
|
|
39
|
+
*/
|
|
40
|
+
function logPaddedFieldRow(label, value) {
|
|
41
|
+
logger.log(` ${label.padEnd(LABEL_W)} ${cell(value)}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {string|null|undefined} remoteUrl
|
|
46
|
+
* @returns {string}
|
|
47
|
+
*/
|
|
48
|
+
function hostFromRemoteUrl(remoteUrl) {
|
|
49
|
+
if (!remoteUrl || typeof remoteUrl !== 'string') {
|
|
50
|
+
return '';
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const u = new URL(remoteUrl.trim());
|
|
54
|
+
return u.hostname || '';
|
|
55
|
+
} catch {
|
|
56
|
+
return '';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {string} devIdStr
|
|
62
|
+
* @returns {string} e.g. dev02
|
|
63
|
+
*/
|
|
64
|
+
function devProfileHandle(devIdStr) {
|
|
65
|
+
const s = String(devIdStr);
|
|
66
|
+
if (/^[0-9]+$/.test(s)) {
|
|
67
|
+
return `dev${s.padStart(2, '0')}`;
|
|
68
|
+
}
|
|
69
|
+
return `dev${s}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Infra / compose TLS mode from ~/.aifabrix `tlsEnabled` (not Docker TLS verify).
|
|
74
|
+
* @param {boolean} tlsEnabled
|
|
75
|
+
* @returns {string}
|
|
76
|
+
*/
|
|
77
|
+
function infraTlsSslCell(tlsEnabled) {
|
|
78
|
+
return tlsEnabled ? 'ON 🔒' : 'OFF 🕐';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Traefik proxy row (`traefik: true` in config). Icons only (no ANSI color).
|
|
83
|
+
* @param {boolean} traefikEnabled
|
|
84
|
+
* @returns {string}
|
|
85
|
+
*/
|
|
86
|
+
function statusTraefikProxyCell(traefikEnabled) {
|
|
87
|
+
return traefikEnabled ? 'ON 🟢' : 'OFF 🟡';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Environment for status (uppercase).
|
|
92
|
+
* @param {unknown} environment
|
|
93
|
+
* @returns {string}
|
|
94
|
+
*/
|
|
95
|
+
function formatStatusEnvironment(environment) {
|
|
96
|
+
if (isUnset(environment)) {
|
|
97
|
+
return EM;
|
|
98
|
+
}
|
|
99
|
+
return String(environment).trim().toUpperCase();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Scoped resources for status: ON vs OFF (DEFAULT).
|
|
104
|
+
* @param {boolean} useScoped
|
|
105
|
+
* @returns {string}
|
|
106
|
+
*/
|
|
107
|
+
function statusScopedResourcesCell(useScoped) {
|
|
108
|
+
return useScoped ? 'ON' : 'OFF (DEFAULT)';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Single-line title for `aifabrix status` (same dev profile + remote host pattern as dev show).
|
|
113
|
+
* @param {string} devIdStr
|
|
114
|
+
* @param {string|null|undefined} remoteServer
|
|
115
|
+
* @returns {string}
|
|
116
|
+
*/
|
|
117
|
+
function formatInfraStatusTitleLine(devIdStr, remoteServer) {
|
|
118
|
+
const who = devProfileHandle(devIdStr);
|
|
119
|
+
const host = hostFromRemoteUrl(remoteServer);
|
|
120
|
+
if (host) {
|
|
121
|
+
return `📊 Infrastructure Status (${who} @ ${host})`;
|
|
122
|
+
}
|
|
123
|
+
return `📊 Infrastructure Status (${who})`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @param {{ remoteServer: string|null|undefined, tlsEnabled: boolean, environment: unknown, useScoped: boolean, traefikEnabled: boolean }} p
|
|
128
|
+
*/
|
|
129
|
+
function logInfraStatusConfigurationSummary(p) {
|
|
130
|
+
logger.log('⚙️ Configuration');
|
|
131
|
+
logPaddedFieldRow('Server', p.remoteServer);
|
|
132
|
+
logPaddedFieldRow('TLS/SSL', infraTlsSslCell(p.tlsEnabled));
|
|
133
|
+
logPaddedFieldRow('Traefik proxy', statusTraefikProxyCell(p.traefikEnabled));
|
|
134
|
+
logPaddedFieldRow('Environment', formatStatusEnvironment(p.environment));
|
|
135
|
+
logPaddedFieldRow('Scoped resources', statusScopedResourcesCell(p.useScoped));
|
|
136
|
+
logger.log('');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @returns {Promise<{ devIdStr: string, remoteServer: string|null|undefined, tlsEnabled: boolean, environment: unknown, useScoped: boolean, traefikEnabled: boolean }>}
|
|
141
|
+
*/
|
|
142
|
+
async function loadInfraStatusSummary() {
|
|
143
|
+
const [rawDevId, environment, tlsEnabled, remoteServer, useScoped, traefikEnabled] = await Promise.all([
|
|
144
|
+
config.getDeveloperId(),
|
|
145
|
+
config.getCurrentEnvironment(),
|
|
146
|
+
config.getTlsEnabled(),
|
|
147
|
+
config.getRemoteServer(),
|
|
148
|
+
config.getUseEnvironmentScopedResources(),
|
|
149
|
+
config.getTraefikEnabled()
|
|
150
|
+
]);
|
|
151
|
+
const devIdStr = rawDevId === null || rawDevId === undefined ? '0' : String(rawDevId);
|
|
152
|
+
return {
|
|
153
|
+
devIdStr,
|
|
154
|
+
environment,
|
|
155
|
+
tlsEnabled,
|
|
156
|
+
remoteServer,
|
|
157
|
+
useScoped,
|
|
158
|
+
traefikEnabled
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
module.exports = {
|
|
163
|
+
loadInfraStatusSummary,
|
|
164
|
+
formatInfraStatusTitleLine,
|
|
165
|
+
logInfraStatusConfigurationSummary,
|
|
166
|
+
logPaddedFieldRow
|
|
167
|
+
};
|