@aifabrix/builder 2.42.1 → 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 +2 -2
- 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 +157 -0
- package/integration/{hubspot → hubspot-test}/application.json +6 -6
- package/integration/{hubspot → hubspot-test}/create-hubspot.js +10 -10
- package/integration/hubspot-test/env.template +4 -0
- package/integration/hubspot-test/hubspot-test-datasource-company.json +138 -0
- package/integration/hubspot-test/hubspot-test-datasource-contact.json +146 -0
- package/integration/hubspot-test/hubspot-test-datasource-deal.json +146 -0
- package/integration/hubspot-test/hubspot-test-datasource-users.json +76 -0
- package/integration/{hubspot/hubspot-deploy.json → hubspot-test/hubspot-test-deploy.json} +201 -24
- package/integration/{hubspot/hubspot-system.json → hubspot-test/hubspot-test-system.json} +8 -7
- package/integration/hubspot-test/rbac.json +166 -0
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-hubspot-credential-real.yaml +3 -3
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-hubspot-env-vars.yaml +2 -2
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-add-datasource.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-credential-create.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-credential-select.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-known-platform.yaml +1 -1
- package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +2 -0
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-mode.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-openapi-file.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-openapi-url.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-source.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-dimension-array-test.yaml +1 -1
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +5 -0
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +5 -0
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-dimension-test.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-rbac-test.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-dataplane-down-tests.js +1 -7
- package/integration/{hubspot → hubspot-test}/test-dataplane-down.js +3 -3
- package/integration/{hubspot → hubspot-test}/test.js +137 -102
- package/integration/{hubspot → hubspot-test}/wizard-hubspot-e2e.yaml +2 -2
- package/integration/{hubspot → hubspot-test}/wizard-hubspot-platform.yaml +1 -1
- 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/service-users.api.js +111 -2
- package/lib/api/types/dev.types.js +4 -3
- package/lib/api/types/pipeline.types.js +8 -5
- package/lib/api/types/service-users.types.js +41 -0
- 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 +19 -8
- package/lib/app/rotate-secret.js +17 -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 +59 -123
- package/lib/cli/setup-app.test-commands.js +179 -0
- package/lib/cli/setup-auth.js +36 -14
- 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 +190 -103
- package/lib/cli/setup-environment.js +11 -20
- package/lib/cli/setup-external-system.js +62 -22
- package/lib/cli/setup-infra.js +139 -47
- package/lib/cli/setup-parameters.js +32 -0
- package/lib/cli/setup-secrets.js +147 -10
- package/lib/cli/setup-service-user.js +146 -20
- package/lib/cli/setup-utility.js +47 -19
- 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 +10 -14
- 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 +123 -71
- 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 +16 -10
- package/lib/commands/repair-rbac.js +25 -19
- package/lib/commands/repair.js +116 -32
- package/lib/commands/secrets-list.js +23 -12
- package/lib/commands/secrets-remove-all.js +220 -0
- package/lib/commands/secrets-remove.js +22 -13
- package/lib/commands/secrets-set.js +21 -12
- package/lib/commands/secrets-validate.js +20 -7
- package/lib/commands/secure.js +10 -9
- package/lib/commands/service-user.js +243 -13
- package/lib/commands/test-e2e-external.js +27 -1
- package/lib/commands/up-common.js +28 -2
- package/lib/commands/up-dataplane.js +31 -18
- 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 +16 -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 +59 -58
- package/lib/core/diff.js +3 -2
- package/lib/core/ensure-encryption-key.js +2 -4
- 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 +228 -42
- package/lib/core/templates-env.js +4 -3
- package/lib/core/templates.js +1 -1
- package/lib/datasource/abac-validator.js +148 -0
- package/lib/datasource/deploy.js +75 -53
- package/lib/datasource/field-reference-validator.js +77 -36
- package/lib/datasource/integration-context.js +63 -0
- package/lib/datasource/list.js +8 -7
- package/lib/datasource/log-viewer.js +252 -0
- package/lib/datasource/resolve-app.js +109 -0
- package/lib/datasource/test-e2e.js +95 -155
- package/lib/datasource/test-integration.js +121 -109
- 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 +162 -15
- 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 +104 -14
- 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-controller-manifest.js +3 -3
- package/lib/generator/external.js +23 -11
- package/lib/generator/helpers.js +71 -12
- package/lib/generator/index.js +8 -4
- package/lib/generator/split-readme.js +12 -7
- package/lib/generator/split-variables.js +2 -1
- package/lib/generator/split.js +46 -11
- package/lib/generator/wizard-readme.js +3 -3
- package/lib/generator/wizard.js +16 -13
- package/lib/infrastructure/compose.js +60 -6
- package/lib/infrastructure/helpers.js +238 -51
- package/lib/infrastructure/index.js +64 -37
- 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 +1201 -433
- 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-config-resolver.js +23 -1
- 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 +209 -6
- 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/credential-secrets-env.js +16 -1
- 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 +42 -11
- package/lib/utils/env-template.js +2 -2
- package/lib/utils/environment-scoped-resources.js +144 -0
- package/lib/utils/error-formatter.js +125 -9
- 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-env-template.js +180 -0
- package/lib/utils/external-readme.js +8 -1
- package/lib/utils/external-system-display.js +277 -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 +32 -14
- package/lib/utils/health-check-url.js +119 -0
- package/lib/utils/health-check.js +59 -25
- package/lib/utils/help-builder.js +14 -13
- 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 +29 -7
- package/lib/utils/paths.js +136 -48
- 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 +171 -51
- package/lib/utils/secrets-helpers.js +70 -59
- package/lib/utils/secrets-kv-scope.js +60 -0
- package/lib/utils/secrets-utils.js +35 -37
- package/lib/utils/secrets-validation.js +3 -1
- package/lib/utils/secrets-yaml-preserve.js +109 -0
- package/lib/utils/secure-file-permissions.js +91 -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 +37 -5
- 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 +78 -1
- package/lib/validation/datasource-warnings.js +56 -0
- package/lib/validation/env-template-auth.js +50 -2
- package/lib/validation/external-manifest-validator.js +35 -7
- package/lib/validation/validate-display.js +37 -31
- package/lib/validation/validate.js +9 -10
- package/lib/validation/validator-unresolved-placeholders.js +98 -0
- package/lib/validation/validator.js +32 -78
- package/lib/validation/wizard-config-validator.js +2 -1
- package/package.json +11 -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 +80 -18
- 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 +55 -14
- 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/env.template.hbs +22 -0
- 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/integration/hubspot/README.md +0 -102
- package/integration/hubspot/env.template +0 -4
- package/integration/hubspot/hubspot-datasource-company.json +0 -541
- package/integration/hubspot/hubspot-datasource-contact.json +0 -639
- package/integration/hubspot/hubspot-datasource-deal.json +0 -588
- package/integration/hubspot/hubspot-datasource-users.json +0 -116
- package/integration/hubspot/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
- package/lib/api/external-test.api.js +0 -111
- package/lib/schema/env-config.yaml +0 -43
- /package/integration/{hubspot → hubspot-test}/companies.json +0 -0
- /package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-app-name.yaml +0 -0
- /package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-missing-app.yaml +0 -0
- /package/integration/{hubspot → hubspot-test}/test-dataplane-down-helpers.js +0 -0
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grouped human-readable output for developer config (`dev show`, after `set-id` / `set-format`).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Dev show display (sections, remote gating, cert mismatch hints)
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 2.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const chalk = require('chalk');
|
|
14
|
+
const config = require('../core/config');
|
|
15
|
+
const devConfig = require('../utils/dev-config');
|
|
16
|
+
const logger = require('../utils/logger');
|
|
17
|
+
const paths = require('../utils/paths');
|
|
18
|
+
const { getUrlsLocalYamlPath } = require('../utils/urls-local-registry');
|
|
19
|
+
const {
|
|
20
|
+
getCertDir,
|
|
21
|
+
getCertValidNotAfter,
|
|
22
|
+
getCertSubjectDeveloperId,
|
|
23
|
+
developerIdsMatchNumeric
|
|
24
|
+
} = require('../utils/dev-cert-helper');
|
|
25
|
+
|
|
26
|
+
/** En dash for unset / empty values (readable empty state). */
|
|
27
|
+
const EM = '\u2013';
|
|
28
|
+
const LABEL_W = 18;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {unknown} v
|
|
32
|
+
* @returns {boolean}
|
|
33
|
+
*/
|
|
34
|
+
function isUnset(v) {
|
|
35
|
+
return v === null || v === undefined || v === '';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {unknown} v
|
|
40
|
+
* @returns {string}
|
|
41
|
+
*/
|
|
42
|
+
function cell(v) {
|
|
43
|
+
return isUnset(v) ? EM : String(v);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {string} label
|
|
48
|
+
* @param {unknown} value
|
|
49
|
+
*/
|
|
50
|
+
function logRow(label, value) {
|
|
51
|
+
logger.log(` ${label.padEnd(LABEL_W)} ${cell(value)}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {string|undefined|null} raw
|
|
56
|
+
* @returns {{ display: string|null, effective: string|null }}
|
|
57
|
+
*/
|
|
58
|
+
async function getSecretsDisplay(raw) {
|
|
59
|
+
let effective = null;
|
|
60
|
+
if (raw && typeof raw === 'string' && raw.trim()) {
|
|
61
|
+
try {
|
|
62
|
+
const remoteDevAuth = require('../utils/remote-dev-auth');
|
|
63
|
+
const resolved = await remoteDevAuth.resolveSharedSecretsEndpoint(raw);
|
|
64
|
+
if (typeof resolved === 'string' && resolved.trim() && resolverAndRawDiffer(resolved, raw)) {
|
|
65
|
+
effective = resolved.trim();
|
|
66
|
+
}
|
|
67
|
+
} catch {
|
|
68
|
+
// Show raw only
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const display =
|
|
72
|
+
raw && typeof raw === 'string' && raw.trim()
|
|
73
|
+
? raw.trim()
|
|
74
|
+
: null;
|
|
75
|
+
return { display, effective };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {string} resolved
|
|
80
|
+
* @param {string} raw
|
|
81
|
+
* @returns {boolean}
|
|
82
|
+
*/
|
|
83
|
+
function resolverAndRawDiffer(resolved, raw) {
|
|
84
|
+
return resolved.trim() !== raw.trim();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Prefer HTTPS(S) effective endpoint for display when present.
|
|
89
|
+
* @param {string|null} secretsMain
|
|
90
|
+
* @param {string|null} secretsEffective
|
|
91
|
+
* @returns {string|null}
|
|
92
|
+
*/
|
|
93
|
+
function secretsApiCell(secretsMain, secretsEffective) {
|
|
94
|
+
const eff = secretsEffective && String(secretsEffective).trim();
|
|
95
|
+
if (eff && /^https?:\/\//i.test(eff)) {
|
|
96
|
+
return eff;
|
|
97
|
+
}
|
|
98
|
+
if (secretsMain && String(secretsMain).trim()) {
|
|
99
|
+
return secretsMain.trim();
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Same directory as config.yaml / urls.local.yaml (nested ~/.aifabrix when AIFABRIX_HOME is $HOME).
|
|
106
|
+
* @returns {string}
|
|
107
|
+
*/
|
|
108
|
+
function resolveConfigDir() {
|
|
109
|
+
return paths.getConfigDirForPaths();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @param {string|null|undefined} user
|
|
114
|
+
* @param {string|null|undefined} host
|
|
115
|
+
* @returns {string|null}
|
|
116
|
+
*/
|
|
117
|
+
function formatSshLine(user, host) {
|
|
118
|
+
const u = user && String(user).trim() ? user : null;
|
|
119
|
+
const h = host && String(host).trim() ? host : null;
|
|
120
|
+
if (!u && !h) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
return `${u ?? EM}@${h ?? EM}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @param {boolean} dockerTlsSkipVerify
|
|
128
|
+
* @returns {string}
|
|
129
|
+
*/
|
|
130
|
+
function tlsVerifyCell(dockerTlsSkipVerify) {
|
|
131
|
+
return dockerTlsSkipVerify ? 'OFF' : 'ON 🔒';
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Infra / compose TLS mode from ~/.aifabrix `tlsEnabled` (not Docker TLS verify).
|
|
136
|
+
* @param {boolean} tlsEnabled
|
|
137
|
+
* @returns {string}
|
|
138
|
+
*/
|
|
139
|
+
function infraTlsSslCell(tlsEnabled) {
|
|
140
|
+
return tlsEnabled ? 'ON 🔒' : 'OFF 🕐';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @param {Date} d
|
|
145
|
+
* @returns {string} YYYY-MM-DD (local)
|
|
146
|
+
*/
|
|
147
|
+
function formatYmdLocal(d) {
|
|
148
|
+
const y = d.getFullYear();
|
|
149
|
+
const m = String(d.getMonth() + 1).padStart(2, '0');
|
|
150
|
+
const day = String(d.getDate()).padStart(2, '0');
|
|
151
|
+
return `${y}-${m}-${day}`;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @param {string|null|undefined} remoteUrl
|
|
156
|
+
* @returns {string}
|
|
157
|
+
*/
|
|
158
|
+
function hostFromRemoteUrl(remoteUrl) {
|
|
159
|
+
if (!remoteUrl || typeof remoteUrl !== 'string') {
|
|
160
|
+
return '';
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
const u = new URL(remoteUrl.trim());
|
|
164
|
+
return u.hostname || '';
|
|
165
|
+
} catch {
|
|
166
|
+
return '';
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @param {string} devIdStr
|
|
172
|
+
* @returns {string} e.g. dev02
|
|
173
|
+
*/
|
|
174
|
+
function devProfileHandle(devIdStr) {
|
|
175
|
+
const s = String(devIdStr);
|
|
176
|
+
if (/^[0-9]+$/.test(s)) {
|
|
177
|
+
return `dev${s.padStart(2, '0')}`;
|
|
178
|
+
}
|
|
179
|
+
return `dev${s}`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @param {string} devIdStr
|
|
184
|
+
* @param {boolean} hasRemote
|
|
185
|
+
* @param {string|null|undefined} remoteServer
|
|
186
|
+
* @returns {string}
|
|
187
|
+
*/
|
|
188
|
+
function buildHeaderLine(devIdStr, hasRemote, remoteServer) {
|
|
189
|
+
let line = '\n🔧 AI Fabrix • Developer Configuration';
|
|
190
|
+
if (hasRemote) {
|
|
191
|
+
const host = hostFromRemoteUrl(remoteServer);
|
|
192
|
+
const who = devProfileHandle(devIdStr);
|
|
193
|
+
line += host ? ` (${who} @ ${host})` : ` (${who})`;
|
|
194
|
+
}
|
|
195
|
+
return `${line}\n`;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* @param {string} certDir
|
|
200
|
+
* @param {string} devId
|
|
201
|
+
* @returns {{ status: string, mismatch: boolean, certDevDigits: string|null, notAfter: Date|null, daysRemaining: number|null }}
|
|
202
|
+
*/
|
|
203
|
+
function computeRemoteIdentity(certDir, devId) {
|
|
204
|
+
const certPath = path.join(certDir, 'cert.pem');
|
|
205
|
+
const certExists = fs.existsSync(certPath);
|
|
206
|
+
const notAfter = getCertValidNotAfter(certDir);
|
|
207
|
+
const certDevDigits = getCertSubjectDeveloperId(certDir);
|
|
208
|
+
|
|
209
|
+
let status;
|
|
210
|
+
if (!certExists) {
|
|
211
|
+
status = 'MISSING';
|
|
212
|
+
} else if (!notAfter) {
|
|
213
|
+
status = 'UNREADABLE';
|
|
214
|
+
} else if (notAfter.getTime() < Date.now()) {
|
|
215
|
+
status = 'EXPIRED';
|
|
216
|
+
} else {
|
|
217
|
+
status = 'VALID';
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const mismatch =
|
|
221
|
+
certExists &&
|
|
222
|
+
certDevDigits !== null &&
|
|
223
|
+
!developerIdsMatchNumeric(devId, certDevDigits);
|
|
224
|
+
|
|
225
|
+
let daysRemaining = null;
|
|
226
|
+
if (notAfter && notAfter.getTime() >= Date.now()) {
|
|
227
|
+
daysRemaining = Math.ceil((notAfter.getTime() - Date.now()) / 86400000);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return { status, mismatch, certDevDigits, notAfter, daysRemaining };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* @param {{ status: string, mismatch: boolean }} identity
|
|
235
|
+
* @returns {string}
|
|
236
|
+
*/
|
|
237
|
+
function formatCertificateStatus(identity) {
|
|
238
|
+
if (identity.status === 'VALID') {
|
|
239
|
+
return identity.mismatch ? 'VALID ⚠' : 'VALID ✔';
|
|
240
|
+
}
|
|
241
|
+
if (identity.status === 'EXPIRED') {
|
|
242
|
+
return 'EXPIRED';
|
|
243
|
+
}
|
|
244
|
+
if (identity.status === 'MISSING') {
|
|
245
|
+
return 'MISSING';
|
|
246
|
+
}
|
|
247
|
+
return 'UNREADABLE';
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @param {Date} notAfter
|
|
252
|
+
* @param {string} status
|
|
253
|
+
* @param {number|null} daysRemaining
|
|
254
|
+
* @returns {string|null}
|
|
255
|
+
*/
|
|
256
|
+
function formatExpiresLine(notAfter, status, daysRemaining) {
|
|
257
|
+
if (!notAfter) {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
const ymd = formatYmdLocal(notAfter);
|
|
261
|
+
if (status === 'EXPIRED') {
|
|
262
|
+
return `${ymd} (expired)`;
|
|
263
|
+
}
|
|
264
|
+
if (daysRemaining !== null) {
|
|
265
|
+
return `${ymd} (${daysRemaining} days)`;
|
|
266
|
+
}
|
|
267
|
+
return ymd;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* @param {string} devId
|
|
272
|
+
* @param {{ certDevDigits: string|null }} identity
|
|
273
|
+
*/
|
|
274
|
+
function logMismatchBlock(devId, identity) {
|
|
275
|
+
logger.log('');
|
|
276
|
+
logger.log(chalk.yellow('⚠ Developer mismatch'));
|
|
277
|
+
logRow('Config ID', devId);
|
|
278
|
+
const certShown = identity.certDevDigits;
|
|
279
|
+
logRow('Certificate ID', certShown);
|
|
280
|
+
logger.log('');
|
|
281
|
+
logger.log(' Fix:');
|
|
282
|
+
logger.log(` ${chalk.bold('af dev sync')}`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @param {string} devIdStr
|
|
287
|
+
* @param {boolean} hasRemote
|
|
288
|
+
* @param {object} remote
|
|
289
|
+
* @param {string} certDir
|
|
290
|
+
*/
|
|
291
|
+
function logRemoteAndIdentity(devIdStr, hasRemote, remote, certDir) {
|
|
292
|
+
if (!hasRemote) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
logger.log('');
|
|
296
|
+
logger.log('🌐 Remote');
|
|
297
|
+
logRow('Server', remote.server);
|
|
298
|
+
logRow('Docker', remote.dockerEndpoint);
|
|
299
|
+
logRow('SSH', formatSshLine(remote.syncSshUser, remote.syncSshHost));
|
|
300
|
+
logRow('TLS Verify', tlsVerifyCell(remote.dockerTlsSkip));
|
|
301
|
+
|
|
302
|
+
const identity = computeRemoteIdentity(certDir, devIdStr);
|
|
303
|
+
logger.log('');
|
|
304
|
+
logger.log('🔐 Identity');
|
|
305
|
+
logRow('Certificate', formatCertificateStatus(identity));
|
|
306
|
+
logRow('Developer ID', identity.certDevDigits);
|
|
307
|
+
const expiresShown = formatExpiresLine(identity.notAfter, identity.status, identity.daysRemaining);
|
|
308
|
+
if (expiresShown) {
|
|
309
|
+
logRow('Expires', expiresShown);
|
|
310
|
+
}
|
|
311
|
+
if (identity.mismatch) {
|
|
312
|
+
logMismatchBlock(devIdStr, identity);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* @param {object} ports
|
|
318
|
+
*/
|
|
319
|
+
function logPortsSection(ports) {
|
|
320
|
+
logger.log('');
|
|
321
|
+
logger.log('🚀 Ports');
|
|
322
|
+
logRow('App', ports.app);
|
|
323
|
+
logRow('Postgres', ports.postgres);
|
|
324
|
+
logRow('Redis', ports.redis);
|
|
325
|
+
logRow('pgAdmin', ports.pgadmin);
|
|
326
|
+
logRow('Redis Commander', ports.redisCommander);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* @param {object} p
|
|
331
|
+
*/
|
|
332
|
+
function logConfigurationSection(p) {
|
|
333
|
+
logger.log('');
|
|
334
|
+
logger.log('⚙️ Configuration');
|
|
335
|
+
logRow('TLS/SSL', infraTlsSslCell(p.tlsEnabled));
|
|
336
|
+
logRow('Environment', p.environment);
|
|
337
|
+
logRow('Controller', p.controller);
|
|
338
|
+
logRow('Format', p.formatVal);
|
|
339
|
+
logRow('Scoped resources', p.scopedResourcesLabel);
|
|
340
|
+
logRow('URLs registry', p.urlsLocalPath);
|
|
341
|
+
if (!p.hasRemote) {
|
|
342
|
+
const showRemoteFallback =
|
|
343
|
+
!isUnset(p.remoteServer) ||
|
|
344
|
+
!isUnset(p.dockerEndpoint) ||
|
|
345
|
+
!isUnset(p.syncSshUser) ||
|
|
346
|
+
!isUnset(p.syncSshHost) ||
|
|
347
|
+
p.dockerTlsSkip;
|
|
348
|
+
if (showRemoteFallback) {
|
|
349
|
+
logRow('Server', p.remoteServer);
|
|
350
|
+
logRow('Docker', p.dockerEndpoint);
|
|
351
|
+
logRow('SSH', formatSshLine(p.syncSshUser, p.syncSshHost));
|
|
352
|
+
logRow('TLS Verify', tlsVerifyCell(p.dockerTlsSkip));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* @param {string|null|undefined} homeResolved
|
|
359
|
+
* @param {string|null|undefined} workResolved
|
|
360
|
+
*/
|
|
361
|
+
function logPathsSection(homeResolved, workResolved) {
|
|
362
|
+
logger.log('');
|
|
363
|
+
logger.log('📁 Paths');
|
|
364
|
+
logRow('Home', homeResolved);
|
|
365
|
+
logRow('Work', workResolved);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* @param {string|null} secretsMain
|
|
370
|
+
* @param {string|null} secretsEffective
|
|
371
|
+
* @param {unknown} mutagenFolder
|
|
372
|
+
*/
|
|
373
|
+
function logIntegrationsSection(secretsMain, secretsEffective, mutagenFolder) {
|
|
374
|
+
logger.log('');
|
|
375
|
+
logger.log('🔗 Integrations');
|
|
376
|
+
logRow('Secrets API', secretsApiCell(secretsMain, secretsEffective));
|
|
377
|
+
logRow('Mutagen Folder', mutagenFolder);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Load all inputs for dev show (config, paths, secrets resolution).
|
|
382
|
+
* @param {string} devIdStr - Normalized developer id string
|
|
383
|
+
* @returns {Promise<object>} Bundle passed to {@link renderDevShow}
|
|
384
|
+
*/
|
|
385
|
+
async function loadDevShowData(devIdStr) {
|
|
386
|
+
const devIdNum = parseInt(devIdStr, 10);
|
|
387
|
+
const ports = devConfig.getDevPorts(Number.isNaN(devIdNum) ? 0 : devIdNum);
|
|
388
|
+
const [
|
|
389
|
+
environment, tlsEnabled, controller, formatRaw, useScoped, secretsRaw,
|
|
390
|
+
remoteServer, dockerEndpoint, dockerTlsSkipVerify, mutagenFolder, syncSshUser, syncSshHost
|
|
391
|
+
] = await Promise.all([
|
|
392
|
+
config.getCurrentEnvironment(), config.getTlsEnabled(), config.getControllerUrl(),
|
|
393
|
+
config.getFormat(), config.getUseEnvironmentScopedResources(), config.getAifabrixSecretsPath(),
|
|
394
|
+
config.getRemoteServer(), config.getDockerEndpoint(), config.getDockerTlsSkipVerify(),
|
|
395
|
+
config.getUserMutagenFolder(), config.getSyncSshUser(), config.getSyncSshHost()
|
|
396
|
+
]);
|
|
397
|
+
const urlsLocalPath = getUrlsLocalYamlPath();
|
|
398
|
+
const scopedResourcesLabel = useScoped ? 'on' : 'off (default)';
|
|
399
|
+
const workResolved = paths.getAifabrixWork();
|
|
400
|
+
const homeResolved = paths.getAifabrixHome();
|
|
401
|
+
const { display: secretsMain, effective: secretsEffective } = await getSecretsDisplay(secretsRaw);
|
|
402
|
+
const dockerTlsSkip = Boolean(dockerTlsSkipVerify);
|
|
403
|
+
const hasRemote = Boolean(remoteServer && String(remoteServer).trim());
|
|
404
|
+
const certDir = getCertDir(resolveConfigDir(), devIdStr);
|
|
405
|
+
return {
|
|
406
|
+
devIdStr,
|
|
407
|
+
ports,
|
|
408
|
+
environment,
|
|
409
|
+
tlsEnabled,
|
|
410
|
+
controller,
|
|
411
|
+
formatVal: formatRaw ?? null,
|
|
412
|
+
scopedResourcesLabel,
|
|
413
|
+
workResolved,
|
|
414
|
+
homeResolved,
|
|
415
|
+
secretsMain,
|
|
416
|
+
secretsEffective,
|
|
417
|
+
urlsLocalPath,
|
|
418
|
+
remoteServer,
|
|
419
|
+
dockerEndpoint,
|
|
420
|
+
dockerTlsSkip,
|
|
421
|
+
mutagenFolder,
|
|
422
|
+
syncSshUser,
|
|
423
|
+
syncSshHost,
|
|
424
|
+
hasRemote,
|
|
425
|
+
certDir
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* @param {object} data - Output of {@link loadDevShowData}
|
|
431
|
+
*/
|
|
432
|
+
function renderDevShow(data) {
|
|
433
|
+
logger.log(buildHeaderLine(data.devIdStr, data.hasRemote, data.remoteServer));
|
|
434
|
+
logger.log('👤 Developer');
|
|
435
|
+
logRow('ID', data.devIdStr);
|
|
436
|
+
logRemoteAndIdentity(data.devIdStr, data.hasRemote, {
|
|
437
|
+
server: data.remoteServer,
|
|
438
|
+
dockerEndpoint: data.dockerEndpoint,
|
|
439
|
+
dockerTlsSkip: data.dockerTlsSkip,
|
|
440
|
+
syncSshUser: data.syncSshUser,
|
|
441
|
+
syncSshHost: data.syncSshHost
|
|
442
|
+
}, data.certDir);
|
|
443
|
+
logPortsSection(data.ports);
|
|
444
|
+
logConfigurationSection({
|
|
445
|
+
environment: data.environment,
|
|
446
|
+
tlsEnabled: data.tlsEnabled,
|
|
447
|
+
controller: data.controller,
|
|
448
|
+
formatVal: data.formatVal,
|
|
449
|
+
scopedResourcesLabel: data.scopedResourcesLabel,
|
|
450
|
+
urlsLocalPath: data.urlsLocalPath,
|
|
451
|
+
hasRemote: data.hasRemote,
|
|
452
|
+
remoteServer: data.remoteServer,
|
|
453
|
+
dockerEndpoint: data.dockerEndpoint,
|
|
454
|
+
dockerTlsSkip: data.dockerTlsSkip,
|
|
455
|
+
syncSshUser: data.syncSshUser,
|
|
456
|
+
syncSshHost: data.syncSshHost
|
|
457
|
+
});
|
|
458
|
+
logPathsSection(data.homeResolved, data.workResolved);
|
|
459
|
+
logIntegrationsSection(data.secretsMain, data.secretsEffective, data.mutagenFolder);
|
|
460
|
+
logger.log('');
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Show ports, grouped config, optional remote + identity.
|
|
465
|
+
* @param {string} devId - Developer ID from config
|
|
466
|
+
* @returns {Promise<void>}
|
|
467
|
+
*/
|
|
468
|
+
async function displayDevConfig(devId) {
|
|
469
|
+
const devIdStr = devId === null || devId === undefined ? '0' : String(devId);
|
|
470
|
+
renderDevShow(await loadDevShowData(devIdStr));
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
module.exports = { displayDevConfig };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
3
|
* Login Credentials Handling
|
|
3
4
|
*
|
|
@@ -28,7 +29,7 @@ async function tryLoadCredentialsFromSecrets(appName) {
|
|
|
28
29
|
}
|
|
29
30
|
const credentials = await loadClientCredentials(appName);
|
|
30
31
|
if (!credentials) {
|
|
31
|
-
logger.log(chalk.yellow(
|
|
32
|
+
logger.log(chalk.yellow(`⚠ Credentials not found in secrets.local.yaml for app '${appName}'`));
|
|
32
33
|
logger.log(chalk.gray(` Looking for: '${appName}-client-idKeyVault' and '${appName}-client-secretKeyVault'`));
|
|
33
34
|
logger.log(chalk.gray(' Prompting for credentials...\n'));
|
|
34
35
|
}
|
|
@@ -143,7 +144,7 @@ function extractTokenData(response) {
|
|
|
143
144
|
const responseData = apiResponse.data || apiResponse;
|
|
144
145
|
|
|
145
146
|
if (!responseData || !responseData.token) {
|
|
146
|
-
logger.error(
|
|
147
|
+
logger.error(formatBlockingError('Invalid response: missing token'));
|
|
147
148
|
if (responseData) {
|
|
148
149
|
logger.error(chalk.gray(`Response structure: ${JSON.stringify(responseData, null, 2)}`));
|
|
149
150
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
3
|
* Login Device Code Flow Handling
|
|
3
4
|
*
|
|
@@ -84,7 +85,7 @@ async function saveTokenAndDisplaySuccess(controllerUrl, token, refreshToken, ex
|
|
|
84
85
|
if (envKey) {
|
|
85
86
|
await setCurrentEnvironment(envKey);
|
|
86
87
|
}
|
|
87
|
-
logger.log(
|
|
88
|
+
logger.log(formatSuccessParagraph('Successfully logged in!'));
|
|
88
89
|
logger.log(chalk.gray(`Controller: ${controllerUrl}`));
|
|
89
90
|
if (envKey) {
|
|
90
91
|
logger.log(chalk.gray(`Environment: ${envKey}`));
|
|
@@ -251,10 +252,10 @@ async function handleDeviceCodeLogin(controllerUrl, environment, online, scope)
|
|
|
251
252
|
} catch (deviceError) {
|
|
252
253
|
// Display formatted error if available (includes detailed validation info)
|
|
253
254
|
if (deviceError.formattedError) {
|
|
254
|
-
logger.error(chalk.red('\n
|
|
255
|
+
logger.error(chalk.red('\n✖ Device code flow failed:'));
|
|
255
256
|
logger.log(deviceError.formattedError);
|
|
256
257
|
} else {
|
|
257
|
-
logger.error(chalk.red(`\n
|
|
258
|
+
logger.error(chalk.red(`\n✖ Device code flow failed: ${deviceError.message}`));
|
|
258
259
|
}
|
|
259
260
|
process.exit(1);
|
|
260
261
|
}
|
package/lib/commands/login.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatBlockingError, formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
3
|
* AI Fabrix Builder - Login Command
|
|
3
4
|
*
|
|
@@ -26,7 +27,7 @@ const { resolveControllerUrl } = require('../utils/controller-url');
|
|
|
26
27
|
async function determineAuthMethod(method) {
|
|
27
28
|
if (method) {
|
|
28
29
|
if (method !== 'device' && method !== 'credentials') {
|
|
29
|
-
logger.error(
|
|
30
|
+
logger.error(formatBlockingError(`Invalid method: ${method}. Must be 'device' or 'credentials'`));
|
|
30
31
|
process.exit(1);
|
|
31
32
|
}
|
|
32
33
|
return method;
|
|
@@ -117,7 +118,7 @@ async function handleEnvironmentConfig(options) {
|
|
|
117
118
|
*/
|
|
118
119
|
function validateScopeOptions(method, options) {
|
|
119
120
|
if (method === 'credentials' && (options.online || options.scope)) {
|
|
120
|
-
logger.log(chalk.yellow('
|
|
121
|
+
logger.log(chalk.yellow('⚠ Warning: --online and --scope options are only available for device flow'));
|
|
121
122
|
logger.log(chalk.gray(' These options will be ignored for credentials method\n'));
|
|
122
123
|
}
|
|
123
124
|
}
|
|
@@ -133,7 +134,7 @@ function validateScopeOptions(method, options) {
|
|
|
133
134
|
*/
|
|
134
135
|
async function handleCredentialsLoginFlow(controllerUrl, environment, options) {
|
|
135
136
|
if (!options.app) {
|
|
136
|
-
logger.error(
|
|
137
|
+
logger.error(formatBlockingError('--app is required for credentials login method'));
|
|
137
138
|
process.exit(1);
|
|
138
139
|
}
|
|
139
140
|
const loginResult = await handleCredentialsLogin(controllerUrl, options.app, options.clientId, options.clientSecret);
|
|
@@ -169,7 +170,7 @@ async function handleLogin(options) {
|
|
|
169
170
|
return; // Early return for device flow (already saved config)
|
|
170
171
|
}
|
|
171
172
|
|
|
172
|
-
logger.log(
|
|
173
|
+
logger.log(formatSuccessParagraph('Successfully logged in!'));
|
|
173
174
|
logger.log(chalk.gray(`Controller: ${controllerUrl}`));
|
|
174
175
|
logger.log(chalk.gray(`Environment: ${environment}`));
|
|
175
176
|
if (options.app) {
|
package/lib/commands/logout.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatSuccessLine, formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
3
|
* AI Fabrix Builder - Logout Command
|
|
3
4
|
*
|
|
@@ -67,7 +68,7 @@ async function clearDeviceTokens(options) {
|
|
|
67
68
|
// Clear specific controller device token
|
|
68
69
|
const cleared = await clearDeviceToken(options.controller);
|
|
69
70
|
if (cleared) {
|
|
70
|
-
logger.log(
|
|
71
|
+
logger.log(formatSuccessLine(`Cleared device token for controller: ${options.controller}`));
|
|
71
72
|
return 1;
|
|
72
73
|
}
|
|
73
74
|
logger.log(chalk.gray(` No device token found for controller: ${options.controller}`));
|
|
@@ -78,7 +79,7 @@ async function clearDeviceTokens(options) {
|
|
|
78
79
|
// Clear all device tokens (only when no environment/app specified)
|
|
79
80
|
const cleared = await clearAllDeviceTokens();
|
|
80
81
|
if (cleared > 0) {
|
|
81
|
-
logger.log(
|
|
82
|
+
logger.log(formatSuccessLine(`Cleared ${cleared} device token(s)`));
|
|
82
83
|
} else {
|
|
83
84
|
logger.log(chalk.gray(' No device tokens found'));
|
|
84
85
|
}
|
|
@@ -99,7 +100,7 @@ async function clearClientTokens(options) {
|
|
|
99
100
|
// Clear specific app token in environment
|
|
100
101
|
const cleared = await clearClientToken(options.environment, options.app);
|
|
101
102
|
if (cleared) {
|
|
102
|
-
logger.log(
|
|
103
|
+
logger.log(formatSuccessLine(`Cleared client token for app '${options.app}' in environment '${options.environment}'`));
|
|
103
104
|
return 1;
|
|
104
105
|
}
|
|
105
106
|
logger.log(chalk.gray(` No client token found for app '${options.app}' in environment '${options.environment}'`));
|
|
@@ -110,7 +111,7 @@ async function clearClientTokens(options) {
|
|
|
110
111
|
// Clear all client tokens for environment
|
|
111
112
|
const cleared = await clearClientTokensForEnvironment(options.environment);
|
|
112
113
|
if (cleared > 0) {
|
|
113
|
-
logger.log(
|
|
114
|
+
logger.log(formatSuccessLine(`Cleared ${cleared} client token(s) for environment '${options.environment}'`));
|
|
114
115
|
} else {
|
|
115
116
|
logger.log(chalk.gray(` No client tokens found for environment '${options.environment}'`));
|
|
116
117
|
}
|
|
@@ -121,7 +122,7 @@ async function clearClientTokens(options) {
|
|
|
121
122
|
// Clear all client tokens (only when no specific options specified)
|
|
122
123
|
const cleared = await clearAllClientTokens();
|
|
123
124
|
if (cleared > 0) {
|
|
124
|
-
logger.log(
|
|
125
|
+
logger.log(formatSuccessLine(`Cleared ${cleared} client token(s)`));
|
|
125
126
|
} else {
|
|
126
127
|
logger.log(chalk.gray(' No client tokens found'));
|
|
127
128
|
}
|
|
@@ -168,10 +169,10 @@ async function handleLogout(options) {
|
|
|
168
169
|
// Summary
|
|
169
170
|
const totalCleared = deviceTokensCleared + clientTokensCleared;
|
|
170
171
|
if (totalCleared > 0) {
|
|
171
|
-
logger.log(
|
|
172
|
+
logger.log(formatSuccessParagraph('Successfully cleared tokens!'));
|
|
172
173
|
logger.log(chalk.gray(`Config file: ${configPath}\n`));
|
|
173
174
|
} else {
|
|
174
|
-
logger.log(chalk.yellow('\n
|
|
175
|
+
logger.log(chalk.yellow('\n⚠ No tokens found to clear'));
|
|
175
176
|
logger.log(chalk.gray(`Config file: ${configPath}\n`));
|
|
176
177
|
}
|
|
177
178
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const { formatBlockingError, formatSuccessLine } = require('../utils/cli-test-layout-chalk');
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview CLI handler: parameters validate (kv:// vs infra.parameter.yaml)
|
|
4
|
+
* @author AI Fabrix Team
|
|
5
|
+
* @version 2.0.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const logger = require('../utils/logger');
|
|
10
|
+
const pathsUtil = require('../utils/paths');
|
|
11
|
+
const {
|
|
12
|
+
getInfraParameterCatalog,
|
|
13
|
+
loadInfraParameterCatalog
|
|
14
|
+
} = require('../parameters/infra-parameter-catalog');
|
|
15
|
+
const {
|
|
16
|
+
validateWorkspaceKvRefsAgainstCatalog,
|
|
17
|
+
validateCatalogRequiredGenerators
|
|
18
|
+
} = require('../parameters/infra-parameter-validate');
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Run catalog + workspace kv:// validation.
|
|
22
|
+
* @param {Object} [options] - CLI options
|
|
23
|
+
* @returns {Promise<{ valid: boolean }>}
|
|
24
|
+
*/
|
|
25
|
+
async function handleParametersValidate(options = {}) {
|
|
26
|
+
let catalog;
|
|
27
|
+
try {
|
|
28
|
+
catalog = options.catalogPath
|
|
29
|
+
? loadInfraParameterCatalog(options.catalogPath)
|
|
30
|
+
: getInfraParameterCatalog();
|
|
31
|
+
} catch (e) {
|
|
32
|
+
logger.log(formatBlockingError(`Could not load infra parameter catalog: ${e.message}`));
|
|
33
|
+
return { valid: false };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const reqGen = validateCatalogRequiredGenerators(catalog.data);
|
|
37
|
+
if (!reqGen.valid) {
|
|
38
|
+
logger.log(formatBlockingError('Catalog requiredForLocal / generator issues:'));
|
|
39
|
+
reqGen.errors.forEach((err) => logger.log(chalk.yellow(` • ${err}`)));
|
|
40
|
+
return { valid: false };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const kv = validateWorkspaceKvRefsAgainstCatalog(catalog, pathsUtil);
|
|
44
|
+
if (!kv.valid) {
|
|
45
|
+
logger.log(formatBlockingError('env.template kv:// keys not covered by infra.parameter.yaml:'));
|
|
46
|
+
kv.errors.forEach((err) => logger.log(chalk.yellow(` • ${err}`)));
|
|
47
|
+
return { valid: false };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
logger.log(formatSuccessLine('parameters validate: catalog OK; workspace kv:// keys covered.'));
|
|
51
|
+
return { valid: true };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = { handleParametersValidate };
|