@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,129 @@
|
|
|
1
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Shared CLI handling for unified validation (DatasourceTestRun + exit matrix).
|
|
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 { computeExitCodeFromDatasourceTestRun, exitCodeForPollTimeout } = require('../utils/datasource-test-run-exit');
|
|
11
|
+
const { analyzeCapabilityScope } = require('../utils/datasource-test-run-capability-scope');
|
|
12
|
+
const ttyLog = require('../utils/datasource-test-run-tty-log');
|
|
13
|
+
const { logEnvelopeForInteractiveCli } = ttyLog;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Build unified CLI result from integration test return shape.
|
|
17
|
+
* @param {Object} r - runDatasourceTestIntegration result
|
|
18
|
+
* @returns {{ envelope: Object|null, apiError: Object|null, pollTimedOut: boolean, incompleteNoAsync: boolean }}
|
|
19
|
+
*/
|
|
20
|
+
function unifiedCliResultFromIntegrationReturn(r) {
|
|
21
|
+
const meta = r.runMeta || {};
|
|
22
|
+
return {
|
|
23
|
+
apiError: meta.apiError || null,
|
|
24
|
+
pollTimedOut: meta.pollTimedOut === true,
|
|
25
|
+
incompleteNoAsync: meta.incompleteNoAsync === true,
|
|
26
|
+
envelope: r.datasourceTestRun || null
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function logApiError(apiError) {
|
|
31
|
+
logger.error(
|
|
32
|
+
formatBlockingError('Dataplane request failed:'),
|
|
33
|
+
apiError.formattedError || apiError.error || 'Request failed'
|
|
34
|
+
);
|
|
35
|
+
if (apiError.status) {
|
|
36
|
+
logger.error(chalk.gray(` HTTP ${apiError.status}`));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Print unified validation outcome and return exit code (plan §3.14 watch — no process.exit).
|
|
42
|
+
* @param {Object} result - From runUnifiedDatasourceValidation
|
|
43
|
+
* @param {Object} options - CLI flags
|
|
44
|
+
* @returns {number}
|
|
45
|
+
*/
|
|
46
|
+
function finalizeUnifiedValidationResult(result, options = {}) {
|
|
47
|
+
if (result.apiError) {
|
|
48
|
+
logApiError(result.apiError);
|
|
49
|
+
return 3;
|
|
50
|
+
}
|
|
51
|
+
if (result.pollTimedOut) {
|
|
52
|
+
logger.error(formatBlockingError('Report incomplete: timeout'));
|
|
53
|
+
return exitCodeForPollTimeout(result.envelope);
|
|
54
|
+
}
|
|
55
|
+
if (result.incompleteNoAsync) {
|
|
56
|
+
logger.error(
|
|
57
|
+
chalk.red(
|
|
58
|
+
'✖ Report incomplete: async polling disabled (--no-async) but server returned partial/minimal report.'
|
|
59
|
+
)
|
|
60
|
+
);
|
|
61
|
+
return 3;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const envelope = result.envelope;
|
|
65
|
+
logEnvelopeForInteractiveCli(envelope, options);
|
|
66
|
+
|
|
67
|
+
let exitCode = computeExitCodeFromDatasourceTestRun(envelope, {
|
|
68
|
+
warningsAsErrors: options.warningsAsErrors === true,
|
|
69
|
+
requireCert: options.requireCert === true
|
|
70
|
+
});
|
|
71
|
+
const scope = analyzeCapabilityScope(envelope, options.requestedCapabilityKey);
|
|
72
|
+
if (options.strictCapabilityScope === true && scope.violated) {
|
|
73
|
+
exitCode = Math.max(exitCode, 1);
|
|
74
|
+
}
|
|
75
|
+
if (
|
|
76
|
+
exitCode === 2 &&
|
|
77
|
+
options.requireCert &&
|
|
78
|
+
!envelope.certificate
|
|
79
|
+
) {
|
|
80
|
+
logger.error(formatBlockingError('Certification not returned; cannot verify.'));
|
|
81
|
+
}
|
|
82
|
+
return exitCode;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Handle unified validation result: logs, stdout JSON, process.exit.
|
|
87
|
+
* @param {Object} result - From runUnifiedDatasourceValidation
|
|
88
|
+
* @param {Object} options - CLI flags
|
|
89
|
+
* @returns {void} Exits process
|
|
90
|
+
*/
|
|
91
|
+
function exitFromUnifiedValidationResult(result, options = {}) {
|
|
92
|
+
process.exit(finalizeUnifiedValidationResult(result, options));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Compute exit code after integration CLI display (no process.exit; plan §3.14 watch).
|
|
97
|
+
* @param {Object} integrationResult - From runDatasourceTestIntegration
|
|
98
|
+
* @param {Object} [exitOpts]
|
|
99
|
+
* @returns {number}
|
|
100
|
+
*/
|
|
101
|
+
function finalizeAfterIntegrationDisplay(integrationResult, exitOpts = {}) {
|
|
102
|
+
const env = integrationResult.datasourceTestRun;
|
|
103
|
+
if (!env) {
|
|
104
|
+
return integrationResult.success ? 0 : 1;
|
|
105
|
+
}
|
|
106
|
+
return computeExitCodeFromDatasourceTestRun(env, {
|
|
107
|
+
warningsAsErrors: exitOpts.warningsAsErrors === true,
|
|
108
|
+
requireCert: exitOpts.requireCert === true
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Exit after integration CLI when not using raw unified output modes.
|
|
114
|
+
* @param {Object} integrationResult - From runDatasourceTestIntegration
|
|
115
|
+
* @param {Object} [exitOpts]
|
|
116
|
+
*/
|
|
117
|
+
function exitAfterIntegrationDisplay(integrationResult, exitOpts = {}) {
|
|
118
|
+
process.exit(finalizeAfterIntegrationDisplay(integrationResult, exitOpts));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = {
|
|
122
|
+
exitFromUnifiedValidationResult,
|
|
123
|
+
finalizeUnifiedValidationResult,
|
|
124
|
+
emitReportVersionDiagnostics: ttyLog.emitReportVersionDiagnostics,
|
|
125
|
+
emitCapabilityScopeDiagnostics: ttyLog.emitCapabilityScopeDiagnostics,
|
|
126
|
+
unifiedCliResultFromIntegrationReturn,
|
|
127
|
+
finalizeAfterIntegrationDisplay,
|
|
128
|
+
exitAfterIntegrationDisplay
|
|
129
|
+
};
|
|
@@ -1,39 +1,103 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AI Fabrix Builder - Datasource Commands
|
|
3
3
|
*
|
|
4
|
-
* Handles datasource validation, listing, comparison, and
|
|
5
|
-
*
|
|
4
|
+
* Handles datasource validation, listing, comparison, deployment, and online validation runs.
|
|
5
|
+
* Subcommands `test`, `test-integration`, and `test-e2e` call the dataplane unified validation API; permissions are summarized in `docs/commands/permissions.md`.
|
|
6
6
|
*
|
|
7
7
|
* @fileoverview Datasource management commands for AI Fabrix Builder
|
|
8
8
|
* @author AI Fabrix Team
|
|
9
9
|
* @version 2.0.0
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
const path = require('path');
|
|
12
13
|
const chalk = require('chalk');
|
|
13
14
|
const logger = require('../utils/logger');
|
|
15
|
+
const { sectionTitle, headerKeyValue, metadata, formatSuccessLine, formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
14
16
|
const { validateDatasourceFile } = require('../datasource/validate');
|
|
15
17
|
const { listDatasources } = require('../datasource/list');
|
|
16
18
|
const { compareDatasources } = require('../datasource/diff');
|
|
17
19
|
const { deployDatasource } = require('../datasource/deploy');
|
|
18
|
-
const {
|
|
19
|
-
const {
|
|
20
|
-
|
|
20
|
+
const { runLogViewer } = require('../datasource/log-viewer');
|
|
21
|
+
const {
|
|
22
|
+
setupDatasourceTestCommand,
|
|
23
|
+
setupDatasourceTestIntegrationCommand,
|
|
24
|
+
setupDatasourceTestE2ECommand
|
|
25
|
+
} = require('./datasource-unified-test-cli');
|
|
26
|
+
|
|
27
|
+
const DATASOURCE_HELP_AFTER = `
|
|
28
|
+
Subcommands:
|
|
29
|
+
validate <file-or-key> Validate datasource JSON (path or datasource key under integration/<app>/)
|
|
30
|
+
list List datasources (env from config)
|
|
31
|
+
upload <file-or-key> Deploy one datasource JSON to the dataplane (path or key; systemKey in file)
|
|
32
|
+
diff Compare two datasource JSON files
|
|
33
|
+
test <key> Structural/policy validation via unified dataplane API (DatasourceTestRun)
|
|
34
|
+
test-integration / test-e2e Integration or E2E run via the same unified validation API
|
|
35
|
+
log-integration / log-e2e Show saved test logs
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
const DATASOURCE_VALIDATE_HELP_AFTER = `
|
|
39
|
+
Examples:
|
|
40
|
+
$ aifabrix datasource validate test-e2e-hubspot-users
|
|
41
|
+
$ aifabrix datasource validate integration/myapp/myapp-datasource-contacts.json
|
|
42
|
+
$ aifabrix datasource validate ./test-e2e-hubspot-datasource-users.json
|
|
43
|
+
$ aifabrix datasource validate /path/to/system-datasource-entity.json
|
|
44
|
+
$ af ds validate ../integration/hubspot/hubspot-datasource-deals.json
|
|
45
|
+
`;
|
|
46
|
+
|
|
47
|
+
const DATASOURCE_UPLOAD_HELP_AFTER = `
|
|
48
|
+
Examples:
|
|
49
|
+
$ aifabrix datasource upload test-e2e-hubspot-users
|
|
50
|
+
$ aifabrix datasource upload integration/myapp/myapp-datasource-contacts.json
|
|
51
|
+
$ aifabrix datasource upload ./test-e2e-hubspot-datasource-users.json
|
|
52
|
+
$ aifabrix datasource upload /path/to/system-datasource-entity.json
|
|
53
|
+
$ af ds upload ../integration/hubspot/hubspot-datasource-deals.json
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* TTY layout for local datasource JSON validation (aligned with cli-test-layout-chalk).
|
|
58
|
+
* @param {{ valid: boolean, errors: string[], resolvedPath: string }} result
|
|
59
|
+
* @param {string} trimmed - original CLI argument
|
|
60
|
+
* @param {boolean} showMapping - show Key + File when key resolved to a path
|
|
61
|
+
*/
|
|
62
|
+
function logDatasourceValidateOutcome(result, trimmed, showMapping) {
|
|
63
|
+
logger.log('');
|
|
64
|
+
logger.log(sectionTitle('Datasource validation'));
|
|
65
|
+
logger.log(metadata('Offline — JSON schema and integration wiring'));
|
|
66
|
+
logger.log('');
|
|
67
|
+
if (!result.valid) {
|
|
68
|
+
logger.log(headerKeyValue('File:', result.resolvedPath));
|
|
69
|
+
logger.log('');
|
|
70
|
+
logger.log(formatBlockingError('Datasource file has errors:'));
|
|
71
|
+
result.errors.forEach(error => logger.log(chalk.red(` • ${error}`)));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (showMapping) {
|
|
75
|
+
logger.log(headerKeyValue('Key:', trimmed));
|
|
76
|
+
logger.log(headerKeyValue('File:', result.resolvedPath));
|
|
77
|
+
} else {
|
|
78
|
+
logger.log(headerKeyValue('File:', result.resolvedPath));
|
|
79
|
+
}
|
|
80
|
+
logger.log('');
|
|
81
|
+
logger.log(formatSuccessLine('Datasource file is valid.'));
|
|
82
|
+
}
|
|
21
83
|
|
|
22
84
|
function setupDatasourceValidateCommand(datasource) {
|
|
23
|
-
datasource.command('validate <file>')
|
|
24
|
-
.description('Validate
|
|
25
|
-
.
|
|
85
|
+
datasource.command('validate <file-or-key>')
|
|
86
|
+
.description('Validate datasource JSON (file path or datasource key under integration/<app>/)')
|
|
87
|
+
.addHelpText('after', DATASOURCE_VALIDATE_HELP_AFTER)
|
|
88
|
+
.action(async(fileOrKey) => {
|
|
26
89
|
try {
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
90
|
+
const trimmed = fileOrKey.trim();
|
|
91
|
+
const result = await validateDatasourceFile(trimmed);
|
|
92
|
+
const resolvedPath = result.resolvedPath;
|
|
93
|
+
const argResolved = path.resolve(trimmed);
|
|
94
|
+
const showMapping = resolvedPath && argResolved !== resolvedPath && trimmed !== resolvedPath;
|
|
95
|
+
logDatasourceValidateOutcome(result, trimmed, showMapping);
|
|
96
|
+
if (!result.valid) {
|
|
33
97
|
process.exit(1);
|
|
34
98
|
}
|
|
35
99
|
} catch (error) {
|
|
36
|
-
logger.error(
|
|
100
|
+
logger.error(formatBlockingError('Validation failed:'), error.message);
|
|
37
101
|
process.exit(1);
|
|
38
102
|
}
|
|
39
103
|
});
|
|
@@ -41,12 +105,12 @@ function setupDatasourceValidateCommand(datasource) {
|
|
|
41
105
|
|
|
42
106
|
function setupDatasourceListCommand(datasource) {
|
|
43
107
|
datasource.command('list')
|
|
44
|
-
.description('List datasources
|
|
108
|
+
.description('List datasources for environment in config')
|
|
45
109
|
.action(async() => {
|
|
46
110
|
try {
|
|
47
111
|
await listDatasources({});
|
|
48
112
|
} catch (error) {
|
|
49
|
-
logger.error(
|
|
113
|
+
logger.error(formatBlockingError('Failed to list datasources:'), error.message);
|
|
50
114
|
process.exit(1);
|
|
51
115
|
}
|
|
52
116
|
});
|
|
@@ -54,91 +118,70 @@ function setupDatasourceListCommand(datasource) {
|
|
|
54
118
|
|
|
55
119
|
function setupDatasourceDiffCommand(datasource) {
|
|
56
120
|
datasource.command('diff <file1> <file2>')
|
|
57
|
-
.description('
|
|
121
|
+
.description('Diff two datasource JSON files')
|
|
58
122
|
.action(async(file1, file2) => {
|
|
59
123
|
try {
|
|
60
124
|
await compareDatasources(file1, file2);
|
|
61
125
|
} catch (error) {
|
|
62
|
-
logger.error(
|
|
126
|
+
logger.error(formatBlockingError('Diff failed:'), error.message);
|
|
63
127
|
process.exit(1);
|
|
64
128
|
}
|
|
65
129
|
});
|
|
66
130
|
}
|
|
67
131
|
|
|
68
132
|
function setupDatasourceUploadCommand(datasource) {
|
|
69
|
-
datasource.command('upload <
|
|
70
|
-
.description('
|
|
71
|
-
.
|
|
133
|
+
datasource.command('upload <file-or-key>')
|
|
134
|
+
.description('Deploy datasource JSON to dataplane (file path or datasource key under integration/<app>/)')
|
|
135
|
+
.addHelpText('after', DATASOURCE_UPLOAD_HELP_AFTER)
|
|
136
|
+
.action(async(fileOrKey, options) => {
|
|
72
137
|
try {
|
|
73
|
-
await deployDatasource(
|
|
138
|
+
await deployDatasource(fileOrKey, options);
|
|
74
139
|
} catch (error) {
|
|
75
|
-
logger.error(
|
|
140
|
+
logger.error(formatBlockingError('Upload failed:'), error.message);
|
|
76
141
|
process.exit(1);
|
|
77
142
|
}
|
|
78
143
|
});
|
|
79
144
|
}
|
|
80
145
|
|
|
81
|
-
function
|
|
82
|
-
datasource.command('
|
|
83
|
-
.description('
|
|
84
|
-
.option(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
.option('--
|
|
146
|
+
function setupDatasourceLogE2ECommand(datasource) {
|
|
147
|
+
datasource.command('log-e2e <datasourceKey>')
|
|
148
|
+
.description('Show E2E test log (latest or --file)')
|
|
149
|
+
.option(
|
|
150
|
+
'-a, --app <app>',
|
|
151
|
+
'Integration folder name (optional: resolve from cwd or datasource key if single match)'
|
|
152
|
+
)
|
|
153
|
+
.option('-f, --file <path>', 'Path to log file (default: latest in app logs folder)')
|
|
89
154
|
.action(async(datasourceKey, options) => {
|
|
90
155
|
try {
|
|
91
|
-
|
|
156
|
+
await runLogViewer(datasourceKey, {
|
|
92
157
|
app: options.app,
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
debug: options.debug,
|
|
96
|
-
timeout: options.timeout
|
|
158
|
+
file: options.file,
|
|
159
|
+
logType: 'test-e2e'
|
|
97
160
|
});
|
|
98
|
-
displayIntegrationTestResults({
|
|
99
|
-
systemKey: result.systemKey || 'unknown',
|
|
100
|
-
datasourceResults: [result],
|
|
101
|
-
success: result.success
|
|
102
|
-
}, options.verbose);
|
|
103
|
-
if (!result.success) process.exit(1);
|
|
104
161
|
} catch (error) {
|
|
105
|
-
logger.error(
|
|
162
|
+
logger.error(formatBlockingError('log-e2e failed:'), error.message);
|
|
106
163
|
process.exit(1);
|
|
107
164
|
}
|
|
108
165
|
});
|
|
109
166
|
}
|
|
110
167
|
|
|
111
|
-
function
|
|
112
|
-
datasource.command('
|
|
113
|
-
.description('
|
|
114
|
-
.option(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
.option('--
|
|
119
|
-
.option('--record-id <id>', 'Record ID for test (body recordId)')
|
|
120
|
-
.option('--no-cleanup', 'Disable cleanup after test (body cleanup: false)')
|
|
121
|
-
.option('--primary-key-value <value|@path>', 'Primary key value or path to JSON file (e.g. @pk.json) for body primaryKeyValue')
|
|
122
|
-
.option('--no-async', 'Use sync mode (no polling); single POST, no asyncRun')
|
|
168
|
+
function setupDatasourceLogIntegrationCommand(datasource) {
|
|
169
|
+
datasource.command('log-integration <datasourceKey>')
|
|
170
|
+
.description('Show integration test log (latest or --file)')
|
|
171
|
+
.option(
|
|
172
|
+
'-a, --app <app>',
|
|
173
|
+
'Integration folder name (optional: resolve from cwd or datasource key if single match)'
|
|
174
|
+
)
|
|
175
|
+
.option('-f, --file <path>', 'Path to log file (default: latest in app logs folder)')
|
|
123
176
|
.action(async(datasourceKey, options) => {
|
|
124
177
|
try {
|
|
125
|
-
|
|
178
|
+
await runLogViewer(datasourceKey, {
|
|
126
179
|
app: options.app,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
verbose: options.verbose,
|
|
130
|
-
async: options.async !== false,
|
|
131
|
-
testCrud: options.testCrud,
|
|
132
|
-
recordId: options.recordId,
|
|
133
|
-
cleanup: options.cleanup,
|
|
134
|
-
primaryKeyValue: options.primaryKeyValue
|
|
180
|
+
file: options.file,
|
|
181
|
+
logType: 'test-integration'
|
|
135
182
|
});
|
|
136
|
-
displayE2EResults(data, options.verbose);
|
|
137
|
-
const steps = data.steps || data.completedActions || [];
|
|
138
|
-
const failed = data.success === false || steps.some(s => s.success === false || s.error);
|
|
139
|
-
if (failed) process.exit(1);
|
|
140
183
|
} catch (error) {
|
|
141
|
-
logger.error(
|
|
184
|
+
logger.error(formatBlockingError('log-integration failed:'), error.message);
|
|
142
185
|
process.exit(1);
|
|
143
186
|
}
|
|
144
187
|
});
|
|
@@ -149,13 +192,22 @@ function setupDatasourceTestE2ECommand(datasource) {
|
|
|
149
192
|
* @param {Command} program - Commander program instance
|
|
150
193
|
*/
|
|
151
194
|
function setupDatasourceCommands(program) {
|
|
152
|
-
const datasource = program
|
|
195
|
+
const datasource = program
|
|
196
|
+
.command('datasource')
|
|
197
|
+
.description('Datasource JSON: validate, list, deploy, test, logs')
|
|
198
|
+
.addHelpText('after', DATASOURCE_HELP_AFTER);
|
|
199
|
+
if (typeof datasource.alias === 'function') {
|
|
200
|
+
datasource.alias('ds');
|
|
201
|
+
}
|
|
153
202
|
setupDatasourceValidateCommand(datasource);
|
|
154
203
|
setupDatasourceListCommand(datasource);
|
|
155
204
|
setupDatasourceDiffCommand(datasource);
|
|
156
205
|
setupDatasourceUploadCommand(datasource);
|
|
206
|
+
setupDatasourceTestCommand(datasource);
|
|
157
207
|
setupDatasourceTestIntegrationCommand(datasource);
|
|
158
208
|
setupDatasourceTestE2ECommand(datasource);
|
|
209
|
+
setupDatasourceLogE2ECommand(datasource);
|
|
210
|
+
setupDatasourceLogIntegrationCommand(datasource);
|
|
159
211
|
}
|
|
160
212
|
|
|
161
213
|
module.exports = { setupDatasourceCommands };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
3
|
* Deployment list commands – list deployments for environment or for an app
|
|
3
4
|
* Uses GET .../deployments and GET .../applications/{appKey}/deployments.
|
|
@@ -97,7 +98,7 @@ async function runDeploymentList(options = {}) {
|
|
|
97
98
|
);
|
|
98
99
|
displayDeploymentList(extractDeployments(response), environment, authResult.controllerUrl);
|
|
99
100
|
} catch (error) {
|
|
100
|
-
logger.error(
|
|
101
|
+
logger.error(formatBlockingError(`Failed to list deployments: ${error.message}`));
|
|
101
102
|
process.exit(1);
|
|
102
103
|
}
|
|
103
104
|
}
|
|
@@ -133,13 +134,13 @@ function displayAppDeploymentList(deployments, appKey, environment, controllerUr
|
|
|
133
134
|
async function resolveDeploymentListContext(options) {
|
|
134
135
|
const controllerUrl = options.controller || (await resolveControllerUrl());
|
|
135
136
|
if (!controllerUrl) {
|
|
136
|
-
logger.error(
|
|
137
|
+
logger.error(formatBlockingError('Controller URL is required. Run "aifabrix login" first.'));
|
|
137
138
|
process.exit(1);
|
|
138
139
|
}
|
|
139
140
|
const environment = options.environment || (await resolveEnvironment());
|
|
140
141
|
const authResult = await getDeploymentListAuth(controllerUrl);
|
|
141
142
|
if (!authResult || !authResult.token) {
|
|
142
|
-
logger.error(
|
|
143
|
+
logger.error(formatBlockingError(`No authentication token for controller: ${controllerUrl}`));
|
|
143
144
|
logger.error(chalk.gray('Run: aifabrix login'));
|
|
144
145
|
process.exit(1);
|
|
145
146
|
}
|
|
@@ -158,7 +159,7 @@ async function resolveDeploymentListContext(options) {
|
|
|
158
159
|
*/
|
|
159
160
|
async function runAppDeploymentList(appKey, options = {}) {
|
|
160
161
|
if (!appKey || typeof appKey !== 'string') {
|
|
161
|
-
logger.error(
|
|
162
|
+
logger.error(formatBlockingError('Application key is required.'));
|
|
162
163
|
process.exit(1);
|
|
163
164
|
return;
|
|
164
165
|
}
|
|
@@ -180,7 +181,7 @@ async function runAppDeploymentList(appKey, options = {}) {
|
|
|
180
181
|
authResult.controllerUrl
|
|
181
182
|
);
|
|
182
183
|
} catch (error) {
|
|
183
|
-
logger.error(
|
|
184
|
+
logger.error(formatBlockingError(`Failed to list deployments for ${appKey}: ${error.message}`));
|
|
184
185
|
process.exit(1);
|
|
185
186
|
}
|
|
186
187
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
3
|
* @fileoverview CLI action handlers for dev list/add/update/pin/delete (remote Builder Server)
|
|
3
4
|
* @author AI Fabrix Team
|
|
@@ -9,6 +10,12 @@ const config = require('../core/config');
|
|
|
9
10
|
const logger = require('../utils/logger');
|
|
10
11
|
const devApi = require('../api/dev.api');
|
|
11
12
|
const { getRemoteDevAuth } = require('../utils/remote-dev-auth');
|
|
13
|
+
const { isValidIpv4 } = require('../utils/dev-hosts-helper');
|
|
14
|
+
const {
|
|
15
|
+
parseDevGroupsOption,
|
|
16
|
+
validateDevGroups,
|
|
17
|
+
augmentDevUserGroupsServerError
|
|
18
|
+
} = require('../utils/dev-user-groups');
|
|
12
19
|
|
|
13
20
|
const REMOTE_NOT_CONFIGURED_MSG = 'Remote server is not configured. Set remote-server and run "aifabrix dev init" first.';
|
|
14
21
|
|
|
@@ -39,7 +46,7 @@ async function handleDevList() {
|
|
|
39
46
|
logger.log(chalk.yellow(REMOTE_NOT_CONFIGURED_MSG));
|
|
40
47
|
return;
|
|
41
48
|
}
|
|
42
|
-
const users = await devApi.listUsers(auth.serverUrl, auth.clientCertPem);
|
|
49
|
+
const users = await devApi.listUsers(auth.serverUrl, auth.clientCertPem, auth.serverCaPem || undefined);
|
|
43
50
|
if (users.length === 0) {
|
|
44
51
|
logger.log(chalk.gray('No developers registered.'));
|
|
45
52
|
return;
|
|
@@ -71,14 +78,23 @@ async function handleDevList() {
|
|
|
71
78
|
async function handleDevAdd(options) {
|
|
72
79
|
const auth = await getRemoteDevAuth();
|
|
73
80
|
if (!auth) throw new Error(REMOTE_NOT_CONFIGURED_MSG);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
let groups = parseDevGroupsOption(
|
|
82
|
+
options.groups !== undefined && options.groups !== null ? options.groups : 'developer'
|
|
83
|
+
);
|
|
84
|
+
if (groups.length === 0) groups = ['developer'];
|
|
85
|
+
validateDevGroups(groups);
|
|
86
|
+
try {
|
|
87
|
+
const user = await devApi.createUser(auth.serverUrl, auth.clientCertPem, {
|
|
88
|
+
developerId: options.developerId,
|
|
89
|
+
name: options.name,
|
|
90
|
+
email: options.email,
|
|
91
|
+
groups
|
|
92
|
+
}, auth.serverCaPem || undefined);
|
|
93
|
+
logger.log(formatSuccessLine(`Developer ${user.id} created. Use "aifabrix dev pin ${user.id}" to create a PIN for onboarding.`));
|
|
94
|
+
} catch (err) {
|
|
95
|
+
augmentDevUserGroupsServerError(err, groups);
|
|
96
|
+
throw err;
|
|
97
|
+
}
|
|
82
98
|
}
|
|
83
99
|
|
|
84
100
|
/**
|
|
@@ -95,27 +111,115 @@ async function handleDevUpdate(developerId, options) {
|
|
|
95
111
|
const body = {};
|
|
96
112
|
if (options.name) body.name = options.name;
|
|
97
113
|
if (options.email) body.email = options.email;
|
|
98
|
-
if (options.groups)
|
|
114
|
+
if (options.groups) {
|
|
115
|
+
const groups = parseDevGroupsOption(options.groups);
|
|
116
|
+
if (groups.length === 0) {
|
|
117
|
+
throw new Error('--groups must list at least one valid group');
|
|
118
|
+
}
|
|
119
|
+
validateDevGroups(groups);
|
|
120
|
+
body.groups = groups;
|
|
121
|
+
}
|
|
99
122
|
if (Object.keys(body).length === 0) {
|
|
100
123
|
throw new Error('Provide at least one of --name, --email, --groups');
|
|
101
124
|
}
|
|
102
|
-
|
|
103
|
-
|
|
125
|
+
try {
|
|
126
|
+
await devApi.updateUser(auth.serverUrl, auth.clientCertPem, id, body, auth.serverCaPem || undefined);
|
|
127
|
+
logger.log(formatSuccessLine(`Developer ${id} updated.`));
|
|
128
|
+
} catch (err) {
|
|
129
|
+
augmentDevUserGroupsServerError(err, body.groups);
|
|
130
|
+
throw err;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function logPinHostsVariantLines(baseInit, id, hostsIp) {
|
|
135
|
+
logger.log(
|
|
136
|
+
chalk.cyan('2) Hosts file / administrator')
|
|
137
|
+
+ chalk.gray(
|
|
138
|
+
' — use when the hostname does not resolve and your organisation does not publish DNS for it. '
|
|
139
|
+
+ 'Run in an elevated terminal so the hosts file can be updated, or add the entry manually:'
|
|
140
|
+
)
|
|
141
|
+
);
|
|
142
|
+
if (hostsIp) {
|
|
143
|
+
logger.log(` ${baseInit} --add-hosts --hosts-ip ${hostsIp}`);
|
|
144
|
+
} else {
|
|
145
|
+
logger.log(` ${baseInit} --add-hosts --hosts-ip <server-LAN-IPv4>`);
|
|
146
|
+
logger.log(
|
|
147
|
+
chalk.gray(
|
|
148
|
+
` Replace <server-LAN-IPv4> with the Builder Server IPv4, or re-run: aifabrix dev pin ${id} --hosts-ip <ip>`
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Log copy-paste dev init commands for the developer (standard vs hosts-file).
|
|
156
|
+
* @param {Object} p
|
|
157
|
+
* @param {string} p.id - Developer ID
|
|
158
|
+
* @param {string} p.serverUrl - Builder Server base URL
|
|
159
|
+
* @param {string} p.pin - One-time PIN
|
|
160
|
+
* @param {string} p.expiresAt - PIN expiry (API string)
|
|
161
|
+
* @param {string} [p.hostsIp] - Optional IPv4 for the hosts variant
|
|
162
|
+
* @returns {void}
|
|
163
|
+
*/
|
|
164
|
+
function logDevPinShareInstructions(p) {
|
|
165
|
+
const { id, serverUrl, pin, expiresAt, hostsIp } = p;
|
|
166
|
+
const baseInit = `aifabrix dev init --developer-id ${id} --server ${serverUrl} --pin ${pin}`;
|
|
167
|
+
const pinOnly = `aifabrix dev init --pin ${pin}`;
|
|
168
|
+
logger.log(formatSuccessLine(`PIN created for ${id}, expires ${expiresAt}.`));
|
|
169
|
+
logger.log('');
|
|
170
|
+
logger.log(
|
|
171
|
+
chalk.bold('Share with the developer — they run one command (the PIN is one-time):')
|
|
172
|
+
);
|
|
173
|
+
logger.log('');
|
|
174
|
+
logger.log(
|
|
175
|
+
chalk.cyan('1) Standard')
|
|
176
|
+
+ chalk.gray(' — use when this machine can resolve the server hostname (DNS or hosts already set):')
|
|
177
|
+
);
|
|
178
|
+
logger.log(` ${baseInit}`);
|
|
179
|
+
logger.log('');
|
|
180
|
+
logPinHostsVariantLines(baseInit, id, hostsIp);
|
|
181
|
+
logger.log('');
|
|
182
|
+
logger.log(
|
|
183
|
+
chalk.cyan('3) Config already has remote-server + developer-id')
|
|
184
|
+
+ chalk.gray(
|
|
185
|
+
' — e.g. second machine / SSH session after settings were merged; same onboarding, PIN only:'
|
|
186
|
+
)
|
|
187
|
+
);
|
|
188
|
+
logger.log(` ${pinOnly}`);
|
|
189
|
+
logger.log('');
|
|
104
190
|
}
|
|
105
191
|
|
|
106
192
|
/**
|
|
107
193
|
* Handle dev pin – create/regenerate PIN (remote only).
|
|
108
194
|
* @param {string} [developerId] - Developer ID (optional; uses config if omitted)
|
|
195
|
+
* @param {Object} [options] - Commander options
|
|
196
|
+
* @param {string} [options.hostsIp] - From --hosts-ip (embeds IPv4 in the hosts variant)
|
|
109
197
|
* @returns {Promise<void>}
|
|
110
198
|
*/
|
|
111
|
-
async function handleDevPin(developerId) {
|
|
199
|
+
async function handleDevPin(developerId, options = {}) {
|
|
112
200
|
const auth = await getRemoteDevAuth();
|
|
113
201
|
if (!auth) throw new Error(REMOTE_NOT_CONFIGURED_MSG);
|
|
114
202
|
const id = developerId || await config.getDeveloperId();
|
|
115
203
|
if (!id) throw new Error('developerId is required (argument or set developer-id in config)');
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
204
|
+
const rawHostsIp = options.hostsIp ?? options['hosts-ip'];
|
|
205
|
+
let hostsIp = '';
|
|
206
|
+
if (rawHostsIp !== undefined && rawHostsIp !== null) {
|
|
207
|
+
const trimmed = String(rawHostsIp).trim();
|
|
208
|
+
if (trimmed !== '') {
|
|
209
|
+
if (!isValidIpv4(trimmed)) {
|
|
210
|
+
throw new Error('Invalid --hosts-ip (use an IPv4 address, e.g. 192.168.1.25)');
|
|
211
|
+
}
|
|
212
|
+
hostsIp = trimmed;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const res = await devApi.createPin(auth.serverUrl, auth.clientCertPem, id, auth.serverCaPem || undefined);
|
|
216
|
+
logDevPinShareInstructions({
|
|
217
|
+
id,
|
|
218
|
+
serverUrl: auth.serverUrl,
|
|
219
|
+
pin: res.pin,
|
|
220
|
+
expiresAt: res.expiresAt,
|
|
221
|
+
hostsIp: hostsIp || undefined
|
|
222
|
+
});
|
|
119
223
|
}
|
|
120
224
|
|
|
121
225
|
/**
|
|
@@ -128,8 +232,8 @@ async function handleDevDelete(developerId) {
|
|
|
128
232
|
if (!auth) throw new Error(REMOTE_NOT_CONFIGURED_MSG);
|
|
129
233
|
const id = developerId;
|
|
130
234
|
if (!id) throw new Error('Developer ID is required (positional argument or --developer-id).');
|
|
131
|
-
await devApi.deleteUser(auth.serverUrl, auth.clientCertPem, id);
|
|
132
|
-
logger.log(
|
|
235
|
+
await devApi.deleteUser(auth.serverUrl, auth.clientCertPem, id, auth.serverCaPem || undefined);
|
|
236
|
+
logger.log(formatSuccessLine(`Developer ${id} removed.`));
|
|
133
237
|
}
|
|
134
238
|
|
|
135
239
|
module.exports = {
|