@aifabrix/builder 2.0.6 → 2.0.8

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/lib/app-run.js CHANGED
@@ -281,11 +281,11 @@ async function startContainer(appName, composePath, port, config = null) {
281
281
  await execAsync(`docker-compose -f "${composePath}" up -d`, { env });
282
282
  logger.log(chalk.green(`✓ Container aifabrix-${appName} started`));
283
283
 
284
- // Wait for health check - detect actual mapped port from Docker
285
- // Don't pass port so waitForHealthCheck will auto-detect it from container
284
+ // Wait for health check using host port
285
+ // Port is the host port (CLI --port or config.port, NOT localPort)
286
286
  const healthCheckPath = config?.healthCheck?.path || '/health';
287
287
  logger.log(chalk.blue(`Waiting for application to be healthy at http://localhost:${port}${healthCheckPath}...`));
288
- await waitForHealthCheck(appName, 90, null, config);
288
+ await waitForHealthCheck(appName, 90, port, config);
289
289
  }
290
290
 
291
291
  /**
@@ -343,7 +343,8 @@ async function runApp(appName, options = {}) {
343
343
  }
344
344
 
345
345
  // Check port availability
346
- const port = options.port || config.build?.localPort || config.port || 3000;
346
+ // Host port: CLI --port if provided, otherwise port from variables.yaml (NOT localPort)
347
+ const port = options.port || config.port || 3000;
347
348
  const portAvailable = await checkPortAvailable(port);
348
349
  if (!portAvailable) {
349
350
  throw new Error(`Port ${port} is already in use. Try --port <alternative>`);
package/lib/secrets.js CHANGED
@@ -173,6 +173,8 @@ function loadEnvTemplate(templatePath) {
173
173
 
174
174
  /**
175
175
  * Processes environment variables and copies to output path if needed
176
+ * Updates PORT variable to use localPort if available (only when copying to envOutputPath)
177
+ * When .env stays in builder folder, uses port (container port)
176
178
  * @function processEnvVariables
177
179
  * @param {string} envPath - Path to generated .env file
178
180
  * @param {string} variablesPath - Path to variables.yaml
@@ -204,7 +206,18 @@ function processEnvVariables(envPath, variablesPath) {
204
206
  fs.mkdirSync(outputDir, { recursive: true });
205
207
  }
206
208
 
207
- fs.copyFileSync(envPath, outputPath);
209
+ // Read the .env file content
210
+ let envContent = fs.readFileSync(envPath, 'utf8');
211
+
212
+ // Update PORT variable: use localPort ONLY when copying to envOutputPath (outside builder folder)
213
+ // When .env stays in builder folder, it uses port (container port)
214
+ const portToUse = variables.build?.localPort || variables.port || 3000;
215
+
216
+ // Replace PORT line (handles PORT=value format, with or without spaces)
217
+ envContent = envContent.replace(/^PORT\s*=\s*.*$/m, `PORT=${portToUse}`);
218
+
219
+ // Write updated content to output path
220
+ fs.writeFileSync(outputPath, envContent, { mode: 0o600 });
208
221
  logger.log(chalk.green(`✓ Copied .env to: ${variables.build.envOutputPath}`));
209
222
  }
210
223
 
@@ -244,6 +257,22 @@ async function generateEnvFile(appName, secretsPath, environment = 'local', forc
244
257
  const resolved = await resolveKvReferences(template, secrets, environment, resolvedSecretsPath);
245
258
 
246
259
  fs.writeFileSync(envPath, resolved, { mode: 0o600 });
260
+
261
+ // Update PORT variable in container .env file to use port (from variables.yaml)
262
+ // Note: containerPort is ONLY used for Docker Compose port mapping, NOT for PORT env variable
263
+ // The application inside container listens on PORT env variable, which should be 'port' from variables.yaml
264
+ if (fs.existsSync(variablesPath)) {
265
+ const variablesContent = fs.readFileSync(variablesPath, 'utf8');
266
+ const variables = yaml.load(variablesContent);
267
+ const port = variables.port || 3000;
268
+
269
+ // Update PORT in container .env file to use port (NOT containerPort, NOT localPort)
270
+ let envContent = fs.readFileSync(envPath, 'utf8');
271
+ envContent = envContent.replace(/^PORT\s*=\s*.*$/m, `PORT=${port}`);
272
+ fs.writeFileSync(envPath, envContent, { mode: 0o600 });
273
+ }
274
+
275
+ // Process and copy to envOutputPath if configured (uses localPort for copied file)
247
276
  processEnvVariables(envPath, variablesPath);
248
277
 
249
278
  return envPath;
@@ -110,20 +110,18 @@ function buildServiceConfig(appName, config, port) {
110
110
  // Container port: build.containerPort > config.port
111
111
  const containerPortValue = config.build?.containerPort || config.port || port;
112
112
 
113
- // Host port logic:
114
- // - If containerPort is specified: use options.port or build.localPort
115
- // - If containerPort is NOT specified: use options.port if provided, otherwise config.port (same as container port)
116
- const hostPort = config.build?.containerPort
117
- ? (port || config.build?.localPort || config.port || 3000) // If containerPort exists, use options.port or localPort
118
- : (port !== config.port ? port : config.port || port); // If no containerPort, use options.port if different, else config.port
113
+ // Host port: use port parameter (already calculated from CLI --port or config.port in generateDockerCompose)
114
+ // Note: build.localPort is ONLY used for .env file PORT variable (for local PC dev), NOT for Docker Compose
115
+ const hostPort = port;
119
116
 
120
117
  return {
121
118
  app: buildAppConfig(appName, config),
122
119
  image: buildImageConfig(config, appName),
123
120
  port: containerPortValue, // Container port (for health check and template)
124
- containerPort: config.build?.containerPort || null, // Explicit containerPort if specified, null otherwise
121
+ containerPort: containerPortValue, // Container port (always set, equals containerPort if exists, else port)
122
+ hostPort: hostPort, // Host port (options.port if provided, else config.port)
125
123
  build: {
126
- localPort: hostPort // Host port
124
+ localPort: config.build?.localPort || null // Only used for .env file PORT variable, not for Docker Compose
127
125
  },
128
126
  healthCheck: buildHealthCheckConfig(config),
129
127
  ...buildRequiresConfig(config)
@@ -167,8 +165,9 @@ async function generateDockerCompose(appName, config, options) {
167
165
  const language = config.build?.language || config.language || 'typescript';
168
166
  const template = loadDockerComposeTemplate(language);
169
167
 
170
- // Determine port: use options.port if provided, otherwise use config.port (ignore build.localPort when no containerPort)
171
- const port = options.port || (config.build?.containerPort ? config.build?.localPort : null) || config.port || 3000;
168
+ // Use options.port if provided, otherwise use config.port
169
+ // (localPort will be handled in buildServiceConfig)
170
+ const port = options.port || config.port || 3000;
172
171
 
173
172
  const serviceConfig = buildServiceConfig(appName, config, port);
174
173
  const volumesConfig = buildVolumesConfig(appName);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aifabrix/builder",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
4
  "description": "AI Fabrix Local Fabric & Deployment SDK",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -9,11 +9,7 @@ services:
9
9
  env_file:
10
10
  - {{envFile}}
11
11
  ports:
12
- {{#if containerPort}}
13
- - "{{build.localPort}}:{{containerPort}}"
14
- {{else}}
15
- - "{{build.localPort}}:{{port}}"
16
- {{/if}}
12
+ - "{{hostPort}}:{{containerPort}}"
17
13
  networks:
18
14
  - infra_aifabrix-network
19
15
  {{#if requiresStorage}}
@@ -9,11 +9,7 @@ services:
9
9
  env_file:
10
10
  - {{envFile}}
11
11
  ports:
12
- {{#if containerPort}}
13
- - "{{build.localPort}}:{{containerPort}}"
14
- {{else}}
15
- - "{{build.localPort}}:{{port}}"
16
- {{/if}}
12
+ - "{{hostPort}}:{{containerPort}}"
17
13
  networks:
18
14
  - infra_aifabrix-network
19
15
  {{#if requiresStorage}}