@aifabrix/builder 2.43.0 → 2.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/anchor-docs.mdc +15 -0
- package/README.md +1 -1
- package/anchor-docs/README.md +10 -0
- package/anchor-docs/_TEMPLATE +24 -0
- package/bin/aifabrix.js +13 -4
- package/integration/hubspot-test/README.md +31 -0
- package/integration/hubspot-test/create-hubspot.js +5 -5
- package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
- package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
- package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
- package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
- package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
- package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
- package/integration/hubspot-test/test-dataplane-down.js +3 -3
- package/integration/hubspot-test/test.js +35 -43
- package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
- package/integration/roundtrip-test-local/README.md +144 -0
- package/integration/roundtrip-test-local/application.yaml +13 -0
- package/integration/roundtrip-test-local/env.template +15 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
- package/integration/roundtrip-test-local2/README.md +144 -0
- package/integration/roundtrip-test-local2/application.yaml +13 -0
- package/integration/roundtrip-test-local2/env.template +15 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
- package/integration/test/wizard.yaml +8 -0
- package/jest.config.default.js +10 -0
- package/jest.config.integration.fixtures.js +22 -0
- package/jest.config.integration.js +21 -18
- package/jest.config.isolated.js +10 -0
- package/jest.projects.js +288 -0
- package/lib/api/datasources-core.api.js +3 -3
- package/lib/api/dev-mtls-request.js +110 -0
- package/lib/api/dev-server-https.js +145 -0
- package/lib/api/dev.api.js +133 -144
- package/lib/api/index.js +0 -1
- package/lib/api/pipeline.api.js +67 -20
- package/lib/api/types/dev.types.js +4 -3
- package/lib/api/types/pipeline.types.js +8 -5
- package/lib/api/types/validation-run.types.js +56 -0
- package/lib/api/validation-run.api.js +99 -0
- package/lib/api/validation-runner.js +99 -0
- package/lib/app/config.js +1 -1
- package/lib/app/deploy-status-display.js +2 -2
- package/lib/app/deploy.js +7 -6
- package/lib/app/display.js +2 -1
- package/lib/app/dockerfile.js +3 -2
- package/lib/app/down.js +2 -1
- package/lib/app/helpers.js +6 -5
- package/lib/app/index.js +27 -8
- package/lib/app/list.js +7 -6
- package/lib/app/push.js +4 -3
- package/lib/app/register.js +16 -7
- package/lib/app/rotate-secret.js +14 -13
- package/lib/app/run-container-start.js +184 -0
- package/lib/app/run-docker-fallback.js +108 -0
- package/lib/app/run-env-compose.js +30 -42
- package/lib/app/run-helpers.js +49 -126
- package/lib/app/run-infra-requirements.js +30 -0
- package/lib/app/run-resolve-image.js +21 -0
- package/lib/app/run.js +74 -21
- package/lib/app/show-display.js +1 -1
- package/lib/app/show.js +1 -1
- package/lib/build/index.js +13 -10
- package/lib/cli/index.js +2 -0
- package/lib/cli/setup-app.help.js +67 -0
- package/lib/cli/setup-app.js +57 -121
- package/lib/cli/setup-app.test-commands.js +179 -0
- package/lib/cli/setup-auth.js +19 -5
- package/lib/cli/setup-credential-deployment.js +22 -8
- package/lib/cli/setup-dev-path-commands.js +124 -0
- package/lib/cli/setup-dev.js +170 -113
- package/lib/cli/setup-environment.js +7 -1
- package/lib/cli/setup-external-system.js +62 -22
- package/lib/cli/setup-infra.js +126 -47
- package/lib/cli/setup-parameters.js +32 -0
- package/lib/cli/setup-secrets.js +106 -8
- package/lib/cli/setup-service-user.js +1 -1
- package/lib/cli/setup-utility.js +36 -20
- package/lib/commands/app-down.js +5 -7
- package/lib/commands/app-install.js +14 -7
- package/lib/commands/app-logs.js +13 -10
- package/lib/commands/app-shell.js +4 -1
- package/lib/commands/app-test.js +25 -19
- package/lib/commands/app.js +22 -10
- package/lib/commands/auth-config.js +6 -6
- package/lib/commands/auth-status.js +4 -3
- package/lib/commands/credential-env.js +4 -3
- package/lib/commands/credential-list.js +5 -4
- package/lib/commands/credential-push.js +4 -3
- package/lib/commands/datasource-unified-test-cli.js +495 -0
- package/lib/commands/datasource-unified-test-cli.options.js +149 -0
- package/lib/commands/datasource-validation-cli.js +129 -0
- package/lib/commands/datasource.js +105 -98
- package/lib/commands/deployment-list.js +6 -5
- package/lib/commands/dev-cli-handlers.js +122 -18
- package/lib/commands/dev-down.js +4 -3
- package/lib/commands/dev-init.js +231 -116
- package/lib/commands/dev-show-display.js +473 -0
- package/lib/commands/login-credentials.js +3 -2
- package/lib/commands/login-device.js +4 -3
- package/lib/commands/login.js +5 -4
- package/lib/commands/logout.js +8 -7
- package/lib/commands/parameters-validate.js +54 -0
- package/lib/commands/repair-datasource.js +314 -68
- package/lib/commands/repair-env-template.js +2 -2
- package/lib/commands/repair.js +21 -3
- package/lib/commands/secrets-list.js +23 -12
- package/lib/commands/secrets-remove-all.js +220 -0
- package/lib/commands/secrets-remove.js +21 -12
- package/lib/commands/secrets-set.js +21 -12
- package/lib/commands/secrets-validate.js +4 -4
- package/lib/commands/secure.js +10 -9
- package/lib/commands/service-user.js +26 -25
- package/lib/commands/test-e2e-external.js +27 -1
- package/lib/commands/up-common.js +3 -2
- package/lib/commands/up-dataplane.js +29 -16
- package/lib/commands/up-miso.js +19 -29
- package/lib/commands/upload.js +138 -39
- package/lib/commands/wizard-core-helpers.js +1 -1
- package/lib/commands/wizard-dataplane.js +4 -3
- package/lib/commands/wizard-helpers.js +3 -3
- package/lib/commands/wizard.js +2 -2
- package/lib/core/admin-secrets.js +14 -5
- package/lib/core/audit-logger.js +12 -4
- package/lib/core/config-attach-extensions.js +46 -0
- package/lib/core/config-runtime-paths.js +29 -0
- package/lib/core/config.js +55 -56
- package/lib/core/diff.js +3 -2
- package/lib/core/ensure-encryption-key.js +1 -1
- package/lib/core/secrets-ensure-infra.js +77 -0
- package/lib/core/secrets-ensure.js +120 -64
- package/lib/core/secrets-env-write.js +35 -7
- package/lib/core/secrets-infra-placeholder-sync.js +61 -0
- package/lib/core/secrets.js +200 -37
- package/lib/core/templates-env.js +4 -3
- package/lib/datasource/abac-validator.js +1 -10
- package/lib/datasource/deploy.js +75 -53
- package/lib/datasource/field-reference-validator.js +9 -6
- package/lib/datasource/integration-context.js +63 -0
- package/lib/datasource/list.js +8 -7
- package/lib/datasource/log-viewer.js +84 -53
- package/lib/datasource/resolve-app.js +4 -4
- package/lib/datasource/test-e2e.js +95 -146
- package/lib/datasource/test-integration.js +114 -122
- package/lib/datasource/unified-validation-run-body.js +65 -0
- package/lib/datasource/unified-validation-run-post.js +23 -0
- package/lib/datasource/unified-validation-run-resolve.js +43 -0
- package/lib/datasource/unified-validation-run.js +92 -0
- package/lib/datasource/validate.js +157 -13
- package/lib/deployment/deployer.js +4 -3
- package/lib/deployment/environment.js +7 -6
- package/lib/deployment/push.js +17 -8
- package/lib/external-system/delete.js +4 -3
- package/lib/external-system/deploy.js +131 -53
- package/lib/external-system/download-helpers.js +1 -1
- package/lib/external-system/download.js +7 -6
- package/lib/external-system/generator.js +92 -6
- package/lib/external-system/integration-test-dispatch.js +26 -0
- package/lib/external-system/test-execution.js +5 -1
- package/lib/external-system/test-helpers.js +0 -4
- package/lib/external-system/test-system-level-helpers.js +110 -0
- package/lib/external-system/test-system-level.js +83 -44
- package/lib/external-system/test.js +59 -8
- package/lib/generator/builders.js +23 -11
- package/lib/generator/deploy-manifest-azure-kv.js +81 -0
- package/lib/generator/external.js +16 -4
- package/lib/generator/helpers.js +58 -3
- package/lib/generator/index.js +4 -0
- package/lib/generator/split-readme.js +12 -7
- package/lib/generator/split-variables.js +2 -1
- package/lib/generator/split.js +1 -1
- package/lib/generator/wizard-readme.js +3 -3
- package/lib/generator/wizard.js +8 -8
- package/lib/infrastructure/compose.js +60 -6
- package/lib/infrastructure/helpers.js +201 -29
- package/lib/infrastructure/index.js +28 -17
- package/lib/infrastructure/services.js +21 -15
- package/lib/internal/fs-real-sync.js +104 -0
- package/lib/internal/node-fs.js +98 -0
- package/lib/parameters/database-secret-values.js +173 -0
- package/lib/parameters/infra-kv-discovery.js +121 -0
- package/lib/parameters/infra-parameter-catalog.js +458 -0
- package/lib/parameters/infra-parameter-validate.js +64 -0
- package/lib/schema/application-schema.json +37 -17
- package/lib/schema/datasource-test-run.schema.json +493 -0
- package/lib/schema/deployment-rules.yaml +102 -63
- package/lib/schema/external-datasource.schema.json +1200 -442
- package/lib/schema/external-system.schema.json +181 -5
- package/lib/schema/flag-map-validation-run.json +31 -0
- package/lib/schema/infra-parameter.schema.json +106 -0
- package/lib/schema/infra.parameter.yaml +421 -0
- package/lib/schema/type/credential-auth-templates.json +40 -0
- package/lib/schema/type/document-storage.json +213 -0
- package/lib/schema/type/message-service.json +123 -0
- package/lib/schema/type/vector-store.json +88 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
- package/lib/utils/api-error-handler.js +2 -2
- package/lib/utils/api.js +49 -14
- package/lib/utils/app-register-api.js +3 -2
- package/lib/utils/app-register-auth.js +1 -1
- package/lib/utils/app-register-config.js +4 -4
- package/lib/utils/app-register-display.js +3 -2
- package/lib/utils/app-register-validator.js +3 -2
- package/lib/utils/app-run-containers.js +26 -22
- package/lib/utils/app-scoped-config.js +31 -0
- package/lib/utils/app-service-env-from-builder.js +164 -0
- package/lib/utils/build-copy.js +1 -1
- package/lib/utils/build-helpers.js +20 -20
- package/lib/utils/build-resolve-image.js +165 -0
- package/lib/utils/cli-layout-chalk.js +8 -0
- package/lib/utils/cli-test-layout-chalk.js +267 -0
- package/lib/utils/cli-utils.js +88 -11
- package/lib/utils/compose-db-passwords.js +138 -0
- package/lib/utils/compose-generate-docker-compose.js +216 -0
- package/lib/utils/compose-generator.js +197 -291
- package/lib/utils/compose-miso-env.js +18 -0
- package/lib/utils/compose-traefik-ingress-base.js +158 -0
- package/lib/utils/config-paths.js +166 -7
- package/lib/utils/config-scoped-resources-preference.js +41 -0
- package/lib/utils/controller-deployment-outcome.js +68 -0
- package/lib/utils/credential-display.js +2 -2
- package/lib/utils/dataplane-pipeline-warning.js +4 -3
- package/lib/utils/datasource-test-run-capability-scope.js +43 -0
- package/lib/utils/datasource-test-run-debug-display.js +137 -0
- package/lib/utils/datasource-test-run-debug-slice.js +93 -0
- package/lib/utils/datasource-test-run-display.js +442 -0
- package/lib/utils/datasource-test-run-exit.js +58 -0
- package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
- package/lib/utils/datasource-test-run-report-version.js +51 -0
- package/lib/utils/datasource-test-run-schema-sync.js +59 -0
- package/lib/utils/datasource-test-run-tty-log.js +81 -0
- package/lib/utils/datasource-validation-watch.js +266 -0
- package/lib/utils/declarative-url-ports.js +47 -0
- package/lib/utils/derive-env-key-from-client-id.js +41 -0
- package/lib/utils/dev-ca-install.js +185 -23
- package/lib/utils/dev-cert-helper.js +266 -17
- package/lib/utils/dev-hosts-helper.js +307 -0
- package/lib/utils/dev-init-cert-hints.js +37 -0
- package/lib/utils/dev-init-health-messages.js +52 -0
- package/lib/utils/dev-init-resolve.js +86 -0
- package/lib/utils/dev-init-ssh-merge.js +65 -0
- package/lib/utils/dev-ssh-config-helper.js +196 -0
- package/lib/utils/dev-user-groups.js +93 -0
- package/lib/utils/docker-build.js +42 -17
- package/lib/utils/docker-exec.js +28 -0
- package/lib/utils/docker-manifest-public-port.js +116 -0
- package/lib/utils/docker-not-running-hint.js +52 -0
- package/lib/utils/docker.js +98 -11
- package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
- package/lib/utils/env-config-loader.js +10 -91
- package/lib/utils/env-copy.js +19 -10
- package/lib/utils/env-map.js +35 -8
- package/lib/utils/env-template.js +2 -2
- package/lib/utils/environment-scoped-resources.js +144 -0
- package/lib/utils/error-formatter.js +92 -13
- package/lib/utils/error-formatters/http-status-errors.js +6 -5
- package/lib/utils/error-formatters/network-errors.js +2 -1
- package/lib/utils/error-formatters/permission-errors.js +2 -1
- package/lib/utils/error-formatters/validation-errors.js +2 -1
- package/lib/utils/external-readme.js +8 -1
- package/lib/utils/external-system-display.js +234 -136
- package/lib/utils/external-system-local-test-tty.js +389 -0
- package/lib/utils/external-system-readiness-core.js +377 -0
- package/lib/utils/external-system-readiness-deploy-display.js +270 -0
- package/lib/utils/external-system-readiness-display-internals.js +150 -0
- package/lib/utils/external-system-readiness-display.js +186 -0
- package/lib/utils/external-system-test-helpers.js +24 -6
- package/lib/utils/external-system-validators.js +30 -12
- package/lib/utils/health-check-url.js +119 -0
- package/lib/utils/health-check.js +59 -25
- package/lib/utils/help-builder.js +11 -8
- package/lib/utils/image-version.js +4 -8
- package/lib/utils/infra-containers.js +4 -7
- package/lib/utils/infra-env-defaults.js +162 -0
- package/lib/utils/infra-status-display.js +167 -0
- package/lib/utils/infra-status.js +16 -8
- package/lib/utils/local-secrets.js +3 -4
- package/lib/utils/paths.js +134 -47
- package/lib/utils/port-resolver.js +10 -23
- package/lib/utils/redis-env-scope.js +62 -0
- package/lib/utils/register-aifabrix-shell-env.js +204 -0
- package/lib/utils/remote-builder-validation.js +99 -0
- package/lib/utils/remote-dev-auth.js +117 -21
- package/lib/utils/remote-docker-env.js +67 -15
- package/lib/utils/remote-secrets-loader.js +13 -4
- package/lib/utils/resolve-docker-image-ref.js +124 -0
- package/lib/utils/schema-loader.js +22 -9
- package/lib/utils/secrets-bash-kv.js +25 -0
- package/lib/utils/secrets-generator.js +169 -49
- package/lib/utils/secrets-helpers.js +70 -59
- package/lib/utils/secrets-kv-scope.js +60 -0
- package/lib/utils/secrets-utils.js +32 -38
- package/lib/utils/secrets-validation.js +3 -1
- package/lib/utils/secrets-yaml-preserve.js +109 -0
- package/lib/utils/ssh-key-helper.js +4 -2
- package/lib/utils/template-helpers.js +2 -2
- package/lib/utils/test-log-writer.js +3 -3
- package/lib/utils/token-manager.js +1 -2
- package/lib/utils/url-declarative-public-base.js +188 -0
- package/lib/utils/url-declarative-resolve-build.js +493 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
- package/lib/utils/url-declarative-resolve.js +220 -0
- package/lib/utils/url-declarative-token-parse.js +74 -0
- package/lib/utils/url-declarative-url-flags.js +50 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
- package/lib/utils/url-public-path-prefix.js +34 -0
- package/lib/utils/urls-local-registry.js +220 -0
- package/lib/utils/validation-report-tty-kit.js +77 -0
- package/lib/utils/validation-run-poll.js +89 -0
- package/lib/utils/validation-run-post-retry.js +73 -0
- package/lib/utils/validation-run-request.js +98 -0
- package/lib/utils/variable-transformer.js +21 -4
- package/lib/utils/yaml-preserve.js +33 -14
- package/lib/validation/datasource-warnings.js +56 -0
- package/lib/validation/env-template-auth.js +1 -1
- package/lib/validation/external-manifest-validator.js +27 -7
- package/lib/validation/validate-display.js +37 -31
- package/lib/validation/validate.js +4 -13
- package/lib/validation/validator-unresolved-placeholders.js +98 -0
- package/lib/validation/validator.js +22 -65
- package/lib/validation/wizard-config-validator.js +2 -1
- package/package.json +7 -3
- package/scripts/check-datasource-test-run-schema-sync.js +34 -0
- package/scripts/diagnose-cli.js +150 -0
- package/scripts/install-local.js +304 -55
- package/templates/README.md +15 -2
- package/templates/applications/dataplane/application.yaml +52 -2
- package/templates/applications/dataplane/env.template +75 -17
- package/templates/applications/dataplane/rbac.yaml +8 -0
- package/templates/applications/keycloak/application.yaml +9 -1
- package/templates/applications/keycloak/env.template +15 -6
- package/templates/applications/miso-controller/application.yaml +10 -2
- package/templates/applications/miso-controller/env.template +42 -12
- package/templates/applications/miso-controller/rbac.yaml +5 -0
- package/templates/external-system/README.md.hbs +20 -7
- package/templates/external-system/deploy.js.hbs +5 -5
- package/templates/external-system/external-datasource.yaml.hbs +197 -118
- package/templates/infra/compose.yaml.hbs +20 -4
- package/templates/python/docker-compose.hbs +16 -0
- package/templates/typescript/docker-compose.hbs +16 -0
- package/lib/api/external-test.api.js +0 -111
- package/lib/schema/env-config.yaml +0 -60
|
@@ -9,13 +9,10 @@
|
|
|
9
9
|
* @version 2.0.0
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
const { exec } = require('child_process');
|
|
13
|
-
const { promisify } = require('util');
|
|
14
12
|
const config = require('../core/config');
|
|
15
13
|
const devConfig = require('./dev-config');
|
|
16
14
|
const containerUtils = require('./infra-containers');
|
|
17
|
-
|
|
18
|
-
const execAsync = promisify(exec);
|
|
15
|
+
const { execWithDockerEnv } = require('./docker-exec');
|
|
19
16
|
|
|
20
17
|
/**
|
|
21
18
|
* Builds services config map from ports and config flags.
|
|
@@ -52,7 +49,7 @@ async function getServiceStatus(serviceName, serviceConfig, devId) {
|
|
|
52
49
|
try {
|
|
53
50
|
const containerName = await containerUtils.findContainer(serviceName, devId, { strict: true });
|
|
54
51
|
const rawStatus = containerName
|
|
55
|
-
? (await
|
|
52
|
+
? (await execWithDockerEnv(`docker inspect --format='{{.State.Status}}' ${containerName}`)).stdout.trim().replace(/['"]/g, '')
|
|
56
53
|
: 'not running';
|
|
57
54
|
return { status: rawStatus, port: serviceConfig.port, url: serviceConfig.url };
|
|
58
55
|
} catch {
|
|
@@ -107,6 +104,9 @@ function getInfraContainerNames(devIdNum, devId) {
|
|
|
107
104
|
/** Suffixes for init/helper containers to exclude from "Running Applications" (e.g. keycloak-db-init) */
|
|
108
105
|
const INIT_CONTAINER_SUFFIXES = ['-db-init', '-init'];
|
|
109
106
|
|
|
107
|
+
/** Names like aifabrix-dev02-postgres belong to isolated developer stacks, not legacy dev-0 mode */
|
|
108
|
+
const DEV_PREFIXED_CONTAINER = /^aifabrix-dev\d+-/;
|
|
109
|
+
|
|
110
110
|
/**
|
|
111
111
|
* Extracts app name from container name
|
|
112
112
|
* @param {string} containerName - Container name
|
|
@@ -115,6 +115,9 @@ const INIT_CONTAINER_SUFFIXES = ['-db-init', '-init'];
|
|
|
115
115
|
* @returns {string|null} App name or null if not matched
|
|
116
116
|
*/
|
|
117
117
|
function extractAppName(containerName, devIdNum, devId) {
|
|
118
|
+
if (devIdNum === 0 && DEV_PREFIXED_CONTAINER.test(containerName)) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
118
121
|
const pattern = devIdNum === 0 ? /^aifabrix-(.+)$/ : new RegExp(`^aifabrix-dev${devId}-(.+)$`);
|
|
119
122
|
const match = containerName.match(pattern);
|
|
120
123
|
if (!match) return null;
|
|
@@ -176,7 +179,7 @@ async function getAppStatus() {
|
|
|
176
179
|
try {
|
|
177
180
|
const devIdNum = parseInt(devId, 10);
|
|
178
181
|
const filterPattern = devIdNum === 0 ? 'aifabrix-' : `aifabrix-dev${devId}-`;
|
|
179
|
-
const { stdout } = await
|
|
182
|
+
const { stdout } = await execWithDockerEnv(`docker ps --filter "name=${filterPattern}" --format "{{.Names}}\t{{.Ports}}\t{{.Status}}"`);
|
|
180
183
|
const lines = stdout.trim().split('\n').filter(line => line.trim() !== '');
|
|
181
184
|
const infraContainers = getInfraContainerNames(devIdNum, devId);
|
|
182
185
|
for (const line of lines) {
|
|
@@ -211,9 +214,14 @@ async function listAppContainerNamesForDeveloper(devId, options = {}) {
|
|
|
211
214
|
const includeExited = !!options.includeExited;
|
|
212
215
|
try {
|
|
213
216
|
const allFlag = includeExited ? ' -a' : '';
|
|
214
|
-
const { stdout } = await
|
|
217
|
+
const { stdout } = await execWithDockerEnv(`docker ps${allFlag} --filter "name=${filterPattern}" --format "{{.Names}}"`);
|
|
215
218
|
const names = (stdout || '').trim().split('\n').filter(Boolean);
|
|
216
|
-
return names.filter(n =>
|
|
219
|
+
return names.filter(n => {
|
|
220
|
+
if (devIdNum === 0 && DEV_PREFIXED_CONTAINER.test(n)) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
return !infraContainers.includes(n);
|
|
224
|
+
});
|
|
217
225
|
} catch {
|
|
218
226
|
return [];
|
|
219
227
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Local Secrets Management Utilities
|
|
3
3
|
*
|
|
4
|
-
* Helper functions for managing local secrets in
|
|
4
|
+
* Helper functions for managing local secrets in getPrimaryUserSecretsLocalPath() (config dir)
|
|
5
5
|
*
|
|
6
6
|
* @fileoverview Local secrets management utilities
|
|
7
7
|
* @author AI Fabrix Team
|
|
@@ -36,8 +36,7 @@ async function resolveValueForWrite(key, value) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* Saves a secret to
|
|
40
|
-
* Uses paths.getAifabrixHome() to respect config.yaml aifabrix-home override
|
|
39
|
+
* Saves a secret to the primary user secrets file (getPrimaryUserSecretsLocalPath)
|
|
41
40
|
* Merges the key into the file (updates in place if key already exists, e.g. after rotate-secret).
|
|
42
41
|
* Encrypts the value when a secrets-encryption key is configured (except for the bootstrap key).
|
|
43
42
|
*
|
|
@@ -61,7 +60,7 @@ async function saveLocalSecret(key, value) {
|
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
const valueToWrite = await resolveValueForWrite(key, value);
|
|
64
|
-
const secretsPath =
|
|
63
|
+
const secretsPath = pathsUtil.getPrimaryUserSecretsLocalPath();
|
|
65
64
|
mergeSecretsIntoFile(secretsPath, { [key]: valueToWrite });
|
|
66
65
|
}
|
|
67
66
|
|
package/lib/utils/paths.js
CHANGED
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
const path = require('path');
|
|
13
13
|
const fs = require('fs');
|
|
14
14
|
const yaml = require('js-yaml');
|
|
15
|
+
const { nodeFs } = require('../internal/node-fs');
|
|
16
|
+
const {
|
|
17
|
+
getAifabrixRuntimeConfigDir,
|
|
18
|
+
resolveAifabrixHomeLikePath
|
|
19
|
+
} = require('./aifabrix-runtime-config-dir');
|
|
15
20
|
|
|
16
21
|
function safeHomedir() {
|
|
17
22
|
try {
|
|
@@ -29,30 +34,46 @@ function safeHomedir() {
|
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
/**
|
|
32
|
-
* Returns the path to the config directory (same
|
|
33
|
-
*
|
|
37
|
+
* Returns the path to the config directory (same as {@link getAifabrixRuntimeConfigDir} / config.js).
|
|
38
|
+
* When `AIFABRIX_HOME` is `$HOME` but `config.yaml` is only under `$HOME/.aifabrix/`, returns the latter.
|
|
34
39
|
* @returns {string} Absolute path to config directory
|
|
35
40
|
*/
|
|
36
41
|
function getConfigDirForPaths() {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
return getAifabrixRuntimeConfigDir();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* User-owned `secrets.local.yaml` beside effective `config.yaml` (see {@link getConfigDirForPaths}).
|
|
47
|
+
* When `AIFABRIX_HOME` is `$HOME` but config is only at `$HOME/.aifabrix/config.yaml`, uses that folder.
|
|
48
|
+
* Keeps `secret list` / `secret set` aligned with resolve merge (`loadPrimaryUserSecrets`).
|
|
49
|
+
*
|
|
50
|
+
* @returns {string} Absolute path to secrets.local.yaml
|
|
51
|
+
*/
|
|
52
|
+
function getPrimaryUserSecretsLocalPath() {
|
|
53
|
+
return path.join(getConfigDirForPaths(), 'secrets.local.yaml');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Directory for CLI system state next to `config.yaml`: `admin-secrets.env`, `infra/` or `infra-dev{id}/`,
|
|
58
|
+
* `audit.log`, etc. Unlike {@link getAifabrixHome}, this follows the resolved config directory (e.g.
|
|
59
|
+
* `~/.aifabrix` when config lives there even if `aifabrix-home` / `AIFABRIX_HOME` is `$HOME`).
|
|
60
|
+
*
|
|
61
|
+
* @returns {string} Absolute path (same as {@link getConfigDirForPaths})
|
|
62
|
+
*/
|
|
63
|
+
function getAifabrixSystemDir() {
|
|
64
|
+
return getConfigDirForPaths();
|
|
45
65
|
}
|
|
46
66
|
|
|
47
67
|
/**
|
|
48
68
|
* Returns the base AI Fabrix directory.
|
|
49
|
-
* Priority: AIFABRIX_HOME env → config.yaml `aifabrix-home`
|
|
69
|
+
* Priority: AIFABRIX_HOME env → config.yaml `aifabrix-home` → ~/.aifabrix.
|
|
70
|
+
* Builder-server SSH provisioning sets `aifabrix-home` to the user POSIX home; dev `.bashrc` exports AIFABRIX_HOME from that key (default $HOME).
|
|
50
71
|
*
|
|
51
72
|
* @returns {string} Absolute path to the AI Fabrix home directory
|
|
52
73
|
*/
|
|
53
74
|
function getAifabrixHome() {
|
|
54
75
|
if (process.env.AIFABRIX_HOME && typeof process.env.AIFABRIX_HOME === 'string') {
|
|
55
|
-
return
|
|
76
|
+
return resolveAifabrixHomeLikePath(process.env.AIFABRIX_HOME.trim());
|
|
56
77
|
}
|
|
57
78
|
const isTestEnv = process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID !== undefined;
|
|
58
79
|
if (!isTestEnv) {
|
|
@@ -64,7 +85,7 @@ function getAifabrixHome() {
|
|
|
64
85
|
const config = yaml.load(content) || {};
|
|
65
86
|
const homeOverride = config && typeof config['aifabrix-home'] === 'string' ? config['aifabrix-home'].trim() : '';
|
|
66
87
|
if (homeOverride) {
|
|
67
|
-
return
|
|
88
|
+
return resolveAifabrixHomeLikePath(homeOverride);
|
|
68
89
|
}
|
|
69
90
|
}
|
|
70
91
|
} catch {
|
|
@@ -74,6 +95,40 @@ function getAifabrixHome() {
|
|
|
74
95
|
return path.join(safeHomedir(), '.aifabrix');
|
|
75
96
|
}
|
|
76
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Default git / workspace root from env or config (optional; no fallback to aifabrix-home).
|
|
100
|
+
* Priority: AIFABRIX_WORK env (trim, resolve) → config.yaml `aifabrix-work` → null.
|
|
101
|
+
*
|
|
102
|
+
* @returns {string|null} Absolute path or null when unset
|
|
103
|
+
*/
|
|
104
|
+
function getAifabrixWork() {
|
|
105
|
+
if (process.env.AIFABRIX_WORK && typeof process.env.AIFABRIX_WORK === 'string') {
|
|
106
|
+
const t = process.env.AIFABRIX_WORK.trim();
|
|
107
|
+
if (t) {
|
|
108
|
+
return resolveAifabrixHomeLikePath(t);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const isTestEnv = process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID !== undefined;
|
|
112
|
+
if (!isTestEnv) {
|
|
113
|
+
try {
|
|
114
|
+
const configDir = getConfigDirForPaths();
|
|
115
|
+
const configPath = path.join(configDir, 'config.yaml');
|
|
116
|
+
if (fs.existsSync(configPath)) {
|
|
117
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
118
|
+
const config = yaml.load(content) || {};
|
|
119
|
+
const workOverride =
|
|
120
|
+
config && typeof config['aifabrix-work'] === 'string' ? config['aifabrix-work'].trim() : '';
|
|
121
|
+
if (workOverride) {
|
|
122
|
+
return resolveAifabrixHomeLikePath(workOverride);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch {
|
|
126
|
+
// ignore
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
77
132
|
// Cache project root to avoid repeated filesystem lookups
|
|
78
133
|
let cachedProjectRoot = null;
|
|
79
134
|
|
|
@@ -92,7 +147,8 @@ function clearProjectRootCache() {
|
|
|
92
147
|
*/
|
|
93
148
|
function hasPackageJson(dirPath) {
|
|
94
149
|
const packageJsonPath = path.join(dirPath, 'package.json');
|
|
95
|
-
|
|
150
|
+
// Real disk: Jest workers may retain jest.mock('fs') from other suites; project root must stay truthful.
|
|
151
|
+
return nodeFs().existsSync(packageJsonPath);
|
|
96
152
|
}
|
|
97
153
|
|
|
98
154
|
/**
|
|
@@ -215,22 +271,31 @@ function tryFindProjectRoot() {
|
|
|
215
271
|
}
|
|
216
272
|
|
|
217
273
|
function getProjectRoot() {
|
|
218
|
-
//
|
|
274
|
+
// Prefer global.PROJECT_ROOT whenever it is valid so tests that override it (or restore it)
|
|
275
|
+
// are not defeated by a stale cachedProjectRoot from an earlier call in the same Jest worker.
|
|
276
|
+
const globalRoot = checkGlobalProjectRoot();
|
|
277
|
+
if (globalRoot) {
|
|
278
|
+
cachedProjectRoot = globalRoot;
|
|
279
|
+
return globalRoot;
|
|
280
|
+
}
|
|
219
281
|
if (cachedProjectRoot && hasPackageJson(cachedProjectRoot)) {
|
|
220
282
|
return cachedProjectRoot;
|
|
221
283
|
}
|
|
222
|
-
|
|
223
284
|
return tryFindProjectRoot();
|
|
224
285
|
}
|
|
225
286
|
|
|
226
287
|
/**
|
|
227
|
-
* Returns the applications base directory.
|
|
288
|
+
* Returns the applications base directory next to effective `config.yaml` (same root as infra, secrets, audit).
|
|
289
|
+
* Dev 0: `<configDir>/applications`; non-zero dev: `<configDir>/applications-dev-{id}`.
|
|
290
|
+
* Uses {@link getAifabrixSystemDir}, not raw {@link getAifabrixHome}, so builder-server layouts with
|
|
291
|
+
* `AIFABRIX_HOME=$HOME` and config under `~/.aifabrix/` keep apps under `.aifabrix` (not `$HOME/applications-dev-*`).
|
|
292
|
+
*
|
|
228
293
|
* @param {number|string} developerId - Developer ID
|
|
229
294
|
* @returns {string} Absolute path to applications base directory
|
|
230
295
|
*/
|
|
231
296
|
function getApplicationsBaseDir(developerId) {
|
|
232
297
|
const idNum = typeof developerId === 'string' ? parseInt(developerId, 10) : developerId;
|
|
233
|
-
const base =
|
|
298
|
+
const base = getAifabrixSystemDir();
|
|
234
299
|
if (idNum === 0) {
|
|
235
300
|
return path.join(base, 'applications');
|
|
236
301
|
}
|
|
@@ -249,7 +314,8 @@ function getDevDirectory(appName, developerId) {
|
|
|
249
314
|
}
|
|
250
315
|
|
|
251
316
|
/**
|
|
252
|
-
* Gets the application path (builder or integration folder)
|
|
317
|
+
* Gets the application path (builder or integration folder).
|
|
318
|
+
* Matches getBuilderPath / getIntegrationPath: respects AIFABRIX_BUILDER_DIR and project-root vs cwd base.
|
|
253
319
|
* @param {string} appName - Application name
|
|
254
320
|
* @param {string} [appType] - Application type ('external' or other)
|
|
255
321
|
* @returns {string} Absolute path to application directory
|
|
@@ -258,9 +324,10 @@ function getAppPath(appName, appType) {
|
|
|
258
324
|
if (!appName || typeof appName !== 'string') {
|
|
259
325
|
throw new Error('App name is required and must be a string');
|
|
260
326
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
327
|
+
if (appType === 'external') {
|
|
328
|
+
return getIntegrationPath(appName);
|
|
329
|
+
}
|
|
330
|
+
return path.join(getBuilderRoot(), appName);
|
|
264
331
|
}
|
|
265
332
|
|
|
266
333
|
/**
|
|
@@ -299,28 +366,45 @@ function getBuilderRoot() {
|
|
|
299
366
|
return path.join(getIntegrationBuilderBaseDir(), 'builder');
|
|
300
367
|
}
|
|
301
368
|
|
|
369
|
+
/**
|
|
370
|
+
* True when name under root is a real directory (follows symlinks). False for broken symlinks, files, ENOENT.
|
|
371
|
+
* @param {string} root - Parent directory (must exist)
|
|
372
|
+
* @param {string} name - Entry from readdir
|
|
373
|
+
* @returns {boolean}
|
|
374
|
+
*/
|
|
375
|
+
function isAppSubdirSync(root, name) {
|
|
376
|
+
if (!name || name.startsWith('.')) return false;
|
|
377
|
+
const fullPath = path.join(root, name);
|
|
378
|
+
try {
|
|
379
|
+
const st = nodeFs().statSync(fullPath);
|
|
380
|
+
return Boolean(st && typeof st.isDirectory === 'function' && st.isDirectory());
|
|
381
|
+
} catch {
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
302
386
|
/**
|
|
303
387
|
* Lists app names (directories) under integration root. Excludes dot-prefixed entries.
|
|
304
388
|
* Returns [] if root does not exist.
|
|
305
389
|
* @returns {string[]} Sorted list of app directory names
|
|
306
390
|
*/
|
|
307
391
|
function listIntegrationAppNames() {
|
|
392
|
+
const disk = nodeFs();
|
|
308
393
|
const root = getIntegrationRoot();
|
|
309
|
-
if (!
|
|
394
|
+
if (!disk.existsSync(root)) {
|
|
395
|
+
return [];
|
|
396
|
+
}
|
|
397
|
+
let rootStat;
|
|
398
|
+
try {
|
|
399
|
+
rootStat = disk.statSync(root);
|
|
400
|
+
} catch {
|
|
310
401
|
return [];
|
|
311
402
|
}
|
|
312
|
-
|
|
313
|
-
if (!stat || typeof stat.isDirectory !== 'function' || !stat.isDirectory()) {
|
|
403
|
+
if (!rootStat || typeof rootStat.isDirectory !== 'function' || !rootStat.isDirectory()) {
|
|
314
404
|
return [];
|
|
315
405
|
}
|
|
316
|
-
const entries =
|
|
317
|
-
return entries
|
|
318
|
-
.filter(name => !name.startsWith('.'))
|
|
319
|
-
.filter(name => {
|
|
320
|
-
const fullPath = path.join(root, name);
|
|
321
|
-
return fs.statSync(fullPath).isDirectory();
|
|
322
|
-
})
|
|
323
|
-
.sort();
|
|
406
|
+
const entries = disk.readdirSync(root);
|
|
407
|
+
return entries.filter((name) => isAppSubdirSync(root, name)).sort();
|
|
324
408
|
}
|
|
325
409
|
|
|
326
410
|
/**
|
|
@@ -329,22 +413,22 @@ function listIntegrationAppNames() {
|
|
|
329
413
|
* @returns {string[]} Sorted list of app directory names
|
|
330
414
|
*/
|
|
331
415
|
function listBuilderAppNames() {
|
|
416
|
+
const disk = nodeFs();
|
|
332
417
|
const root = getBuilderRoot();
|
|
333
|
-
if (!
|
|
418
|
+
if (!disk.existsSync(root)) {
|
|
419
|
+
return [];
|
|
420
|
+
}
|
|
421
|
+
let rootStat;
|
|
422
|
+
try {
|
|
423
|
+
rootStat = disk.statSync(root);
|
|
424
|
+
} catch {
|
|
334
425
|
return [];
|
|
335
426
|
}
|
|
336
|
-
|
|
337
|
-
if (!stat || typeof stat.isDirectory !== 'function' || !stat.isDirectory()) {
|
|
427
|
+
if (!rootStat || typeof rootStat.isDirectory !== 'function' || !rootStat.isDirectory()) {
|
|
338
428
|
return [];
|
|
339
429
|
}
|
|
340
|
-
const entries =
|
|
341
|
-
return entries
|
|
342
|
-
.filter(name => !name.startsWith('.'))
|
|
343
|
-
.filter(name => {
|
|
344
|
-
const fullPath = path.join(root, name);
|
|
345
|
-
return fs.statSync(fullPath).isDirectory();
|
|
346
|
-
})
|
|
347
|
-
.sort();
|
|
430
|
+
const entries = disk.readdirSync(root);
|
|
431
|
+
return entries.filter((name) => isAppSubdirSync(root, name)).sort();
|
|
348
432
|
}
|
|
349
433
|
|
|
350
434
|
/**
|
|
@@ -387,7 +471,7 @@ function getBuilderPath(appName) {
|
|
|
387
471
|
? process.env.AIFABRIX_BUILDER_DIR.trim()
|
|
388
472
|
: null;
|
|
389
473
|
if (builderRoot) {
|
|
390
|
-
return path.join(builderRoot, appName);
|
|
474
|
+
return path.join(path.resolve(builderRoot), appName);
|
|
391
475
|
}
|
|
392
476
|
const base = getIntegrationBuilderBaseDir();
|
|
393
477
|
return path.join(base, 'builder', appName);
|
|
@@ -518,7 +602,7 @@ async function detectAppType(appName, _options = {}) {
|
|
|
518
602
|
|
|
519
603
|
/**
|
|
520
604
|
* Resolve-specific app path: prefer integration + env.template only (env-only mode).
|
|
521
|
-
* If integration/<
|
|
605
|
+
* If integration/<systemKey>/env.template exists, use that directory without requiring application.yaml.
|
|
522
606
|
* Otherwise fall back to detectAppType (integration or builder with full config).
|
|
523
607
|
*
|
|
524
608
|
* @param {string} appName - Application name
|
|
@@ -538,7 +622,7 @@ async function getResolveAppPath(appName) {
|
|
|
538
622
|
return { appPath: result.appPath, envOnly: false };
|
|
539
623
|
}
|
|
540
624
|
|
|
541
|
-
/** Resolve
|
|
625
|
+
/** Resolve app folder name when cwd is inside integration/<systemKey>/. */
|
|
542
626
|
function resolveIntegrationAppKeyFromCwd() {
|
|
543
627
|
const integrationNorm = path.resolve(path.join(getIntegrationBuilderBaseDir(), 'integration'));
|
|
544
628
|
const cwd = path.resolve(process.cwd());
|
|
@@ -548,7 +632,10 @@ function resolveIntegrationAppKeyFromCwd() {
|
|
|
548
632
|
|
|
549
633
|
module.exports = {
|
|
550
634
|
getAifabrixHome,
|
|
635
|
+
getAifabrixWork,
|
|
551
636
|
getConfigDirForPaths,
|
|
637
|
+
getAifabrixSystemDir,
|
|
638
|
+
getPrimaryUserSecretsLocalPath,
|
|
552
639
|
getApplicationsBaseDir,
|
|
553
640
|
getDevDirectory,
|
|
554
641
|
getAppPath,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Single source of truth for resolving application port from application config.
|
|
5
5
|
* Use getContainerPort for container/Docker/deployment/registration; use getLocalPort
|
|
6
|
-
* for local
|
|
6
|
+
* for manifest listen port (same as port; local host uses port+10+dev*100 in secrets-helpers).
|
|
7
7
|
*
|
|
8
8
|
* @fileoverview Port resolution from variables (port, build.containerPort)
|
|
9
9
|
* @author AI Fabrix Team
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
const fs = require('fs');
|
|
16
16
|
const yaml = require('js-yaml');
|
|
17
|
+
const { DECLARATIVE_URL_INFRA_DEFAULTS } = require('./infra-env-defaults');
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Resolve container port from variables object.
|
|
@@ -21,10 +22,10 @@ const yaml = require('js-yaml');
|
|
|
21
22
|
* When containerPort is empty or missing, main port is used (e.g. keycloak 8082:8080 vs miso 3000:3000).
|
|
22
23
|
*
|
|
23
24
|
* @param {Object} variables - Parsed application config (or subset with build, port)
|
|
24
|
-
* @param {number} [defaultPort
|
|
25
|
+
* @param {number} [defaultPort] - Default when neither build.containerPort nor port is set (infra fallback)
|
|
25
26
|
* @returns {number} Resolved container port
|
|
26
27
|
*/
|
|
27
|
-
function getContainerPort(variables, defaultPort =
|
|
28
|
+
function getContainerPort(variables, defaultPort = DECLARATIVE_URL_INFRA_DEFAULTS.manifestPortFallback) {
|
|
28
29
|
const v = variables || {};
|
|
29
30
|
const containerPort = v.build?.containerPort;
|
|
30
31
|
const useMain = containerPort === undefined || containerPort === null ||
|
|
@@ -36,20 +37,13 @@ function getContainerPort(variables, defaultPort = 3000) {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
|
-
* Resolve
|
|
40
|
-
* Precedence: build.localPort (when positive integer) → port → defaultPort.
|
|
41
|
-
* Used for env-copy, env-ports, getLocalPortFromPath, run compose host port.
|
|
42
|
-
*
|
|
40
|
+
* Resolve base application listen port (manifest `port` only; build.localPort removed).
|
|
43
41
|
* @param {Object} variables - Parsed application config
|
|
44
|
-
* @param {number} [defaultPort
|
|
45
|
-
* @returns {number}
|
|
42
|
+
* @param {number} [defaultPort] - Default when port is unset (infra fallback)
|
|
43
|
+
* @returns {number} Listen port
|
|
46
44
|
*/
|
|
47
|
-
function getLocalPort(variables, defaultPort =
|
|
45
|
+
function getLocalPort(variables, defaultPort = DECLARATIVE_URL_INFRA_DEFAULTS.manifestPortFallback) {
|
|
48
46
|
const v = variables || {};
|
|
49
|
-
const localPort = v.build?.localPort;
|
|
50
|
-
if (typeof localPort === 'number' && localPort > 0) {
|
|
51
|
-
return localPort;
|
|
52
|
-
}
|
|
53
47
|
return v.port ?? defaultPort;
|
|
54
48
|
}
|
|
55
49
|
|
|
@@ -94,22 +88,15 @@ function getContainerPortFromPath(variablesPath) {
|
|
|
94
88
|
}
|
|
95
89
|
|
|
96
90
|
/**
|
|
97
|
-
* Resolve
|
|
98
|
-
* Same rule as getLocalPort: build.localPort (when positive integer) → port.
|
|
99
|
-
* Returns null when file is missing or neither localPort nor port is set.
|
|
100
|
-
*
|
|
91
|
+
* Resolve manifest port from application config path.
|
|
101
92
|
* @param {string} variablesPath - Path to application config
|
|
102
|
-
* @returns {number|null}
|
|
93
|
+
* @returns {number|null} Port or null
|
|
103
94
|
*/
|
|
104
95
|
function getLocalPortFromPath(variablesPath) {
|
|
105
96
|
const v = loadVariablesFromPath(variablesPath);
|
|
106
97
|
if (!v) {
|
|
107
98
|
return null;
|
|
108
99
|
}
|
|
109
|
-
const localPort = v.build?.localPort;
|
|
110
|
-
if (typeof localPort === 'number' && localPort > 0) {
|
|
111
|
-
return localPort;
|
|
112
|
-
}
|
|
113
100
|
const p = v.port;
|
|
114
101
|
return (p !== undefined && p !== null) ? p : null;
|
|
115
102
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adjust Redis DB index in resolved .env content when environment-scoped resources are effective.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview REDIS_DB and redis:// URL path segment (plan 117)
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Set pathname /dbIndex for redis(s) URLs.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} urlStr - redis:// or rediss:// URL
|
|
15
|
+
* @param {number} dbIndex - logical DB (0–15 typical)
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
function setRedisUrlDbIndex(urlStr, dbIndex) {
|
|
19
|
+
if (!urlStr || typeof urlStr !== 'string') return urlStr;
|
|
20
|
+
try {
|
|
21
|
+
const u = new URL(urlStr.trim());
|
|
22
|
+
if (u.protocol !== 'redis:' && u.protocol !== 'rediss:') {
|
|
23
|
+
return urlStr;
|
|
24
|
+
}
|
|
25
|
+
u.pathname = `/${dbIndex}`;
|
|
26
|
+
return u.toString();
|
|
27
|
+
} catch {
|
|
28
|
+
return urlStr;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Apply Redis DB index to REDIS_DB= and REDIS_URL= lines when effective.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} content - .env text
|
|
36
|
+
* @param {number|null} dbIndex - from redisDbIndexForScopedRunEnv; skip if null
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
function applyRedisDbIndexToEnvContent(content, dbIndex) {
|
|
40
|
+
if (dbIndex === null || dbIndex === undefined || typeof content !== 'string') {
|
|
41
|
+
return content;
|
|
42
|
+
}
|
|
43
|
+
const lines = content.split('\n');
|
|
44
|
+
const out = lines.map((line) => {
|
|
45
|
+
const trimmed = line.trim();
|
|
46
|
+
if (!trimmed || trimmed.startsWith('#')) return line;
|
|
47
|
+
const eq = trimmed.indexOf('=');
|
|
48
|
+
if (eq <= 0) return line;
|
|
49
|
+
const key = trimmed.slice(0, eq).trim();
|
|
50
|
+
const value = trimmed.slice(eq + 1);
|
|
51
|
+
if (key === 'REDIS_DB') {
|
|
52
|
+
return `${key}=${dbIndex}`;
|
|
53
|
+
}
|
|
54
|
+
if (key === 'REDIS_URL' && value && !value.startsWith('kv://')) {
|
|
55
|
+
return `${key}=${setRedisUrlDbIndex(value, dbIndex)}`;
|
|
56
|
+
}
|
|
57
|
+
return line;
|
|
58
|
+
});
|
|
59
|
+
return out.join('\n');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = { applyRedisDbIndexToEnvContent, setRedisUrlDbIndex };
|