genbox 1.0.93 → 1.0.95

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.
@@ -54,10 +54,10 @@ const db_utils_1 = require("../db-utils");
54
54
  const utils_1 = require("../utils");
55
55
  // Credits consumed per hour for each size (matches API billing.config.ts)
56
56
  const CREDITS_PER_HOUR = {
57
- cx22: 1,
58
- cx32: 2,
59
- cx42: 4,
60
- cx52: 8,
57
+ cx23: 1,
58
+ cx33: 2,
59
+ cx43: 4,
60
+ cx53: 8,
61
61
  small: 1,
62
62
  medium: 2,
63
63
  large: 4,
@@ -194,9 +194,10 @@ function convertScanToDetected(scan, root) {
194
194
  framework: app.framework,
195
195
  framework_source: app.framework ? 'package.json dependencies' : undefined,
196
196
  commands: app.scripts ? {
197
- dev: app.scripts.dev,
198
- build: app.scripts.build,
199
- start: app.scripts.start,
197
+ // Use script NAMES (not raw commands) - PM2 runs `pnpm run <name>`
198
+ dev: app.scripts.dev ? 'dev' : undefined,
199
+ build: app.scripts.build ? 'build' : undefined,
200
+ start: app.scripts.start ? 'start' : undefined,
200
201
  } : undefined,
201
202
  dependencies: app.dependencies,
202
203
  git: appGit,
@@ -214,6 +215,7 @@ function convertScanToDetected(scan, root) {
214
215
  image: db.image || 'unknown',
215
216
  port: db.ports?.[0]?.host || 0,
216
217
  source: db.sourceFile || 'docker-compose.yml',
218
+ ...(db.replicaSet && { replicaSet: db.replicaSet }),
217
219
  });
218
220
  }
219
221
  for (const cache of scan.compose.caches || []) {
@@ -1337,11 +1339,16 @@ function generateConfig(detected, settings, repos, environments, profiles) {
1337
1339
  const provides = {};
1338
1340
  if (detected.infrastructure) {
1339
1341
  for (const infra of detected.infrastructure) {
1340
- provides[infra.name] = {
1342
+ const providerConfig = {
1341
1343
  type: infra.type,
1342
1344
  image: infra.image,
1343
1345
  port: infra.port,
1344
1346
  };
1347
+ // Include replicaSet for MongoDB if detected
1348
+ if (infra.replicaSet) {
1349
+ providerConfig.replicaSet = infra.replicaSet;
1350
+ }
1351
+ provides[infra.name] = providerConfig;
1345
1352
  }
1346
1353
  }
1347
1354
  // Build defaults
@@ -98,8 +98,8 @@ class ProfileResolver {
98
98
  // Step 3: Resolve dependencies
99
99
  const { apps, infrastructure, dependencyWarnings } = await this.resolveDependencies(config, selectedApps, options, profile);
100
100
  warnings.push(...dependencyWarnings);
101
- // Step 4: Determine database mode
102
- const database = await this.resolveDatabaseMode(config, options, profile);
101
+ // Step 4: Determine database mode (pass infrastructure for replicaSet detection)
102
+ const database = await this.resolveDatabaseMode(config, options, profile, infrastructure);
103
103
  // Step 5: Determine size
104
104
  const size = options.size || profile.size || this.inferSize(apps, infrastructure);
105
105
  // Step 6: Build resolved config
@@ -320,7 +320,7 @@ class ProfileResolver {
320
320
  /**
321
321
  * Resolve database mode
322
322
  */
323
- async resolveDatabaseMode(config, options, profile) {
323
+ async resolveDatabaseMode(config, options, profile, infrastructure) {
324
324
  // Load env vars from .env.genbox (where init stores MongoDB URLs)
325
325
  const envVars = this.configLoader.loadEnvVars(process.cwd());
326
326
  // Helper to get MongoDB URL from .env.genbox
@@ -335,6 +335,9 @@ class ProfileResolver {
335
335
  // Custom environments: {NAME}_MONGODB_URL
336
336
  return envVars[`${source.toUpperCase()}_MONGODB_URL`];
337
337
  };
338
+ // Extract replicaSet from MongoDB infrastructure config if present
339
+ const mongoInfra = infrastructure.find(i => i.type === 'database' && i.image?.toLowerCase().includes('mongo'));
340
+ const replicaSet = mongoInfra?.replicaSet;
338
341
  // CLI flag takes precedence
339
342
  if (options.db) {
340
343
  // Normalize 'fresh' to 'local' (fresh is the UI name, local is internal)
@@ -344,6 +347,7 @@ class ProfileResolver {
344
347
  mode: dbMode,
345
348
  source,
346
349
  url: dbMode === 'copy' ? getMongoUrl(source) : undefined,
350
+ replicaSet,
347
351
  };
348
352
  }
349
353
  // Profile setting
@@ -354,6 +358,7 @@ class ProfileResolver {
354
358
  url: profile.database.mode === 'copy' && profile.database.source
355
359
  ? getMongoUrl(profile.database.source)
356
360
  : undefined,
361
+ replicaSet,
357
362
  };
358
363
  }
359
364
  // If default_connection is set, use remote
@@ -365,11 +370,13 @@ class ProfileResolver {
365
370
  mode: 'remote',
366
371
  source: profileConnection,
367
372
  url: mongoUrl,
373
+ replicaSet,
368
374
  };
369
375
  }
370
376
  // Interactive mode
371
377
  if (!options.yes) {
372
- return await this.selectDatabaseModeInteractive(config);
378
+ const interactiveResult = await this.selectDatabaseModeInteractive(config);
379
+ return { ...interactiveResult, replicaSet };
373
380
  }
374
381
  // Default
375
382
  const defaultMode = config.defaults?.database?.mode || 'local';
@@ -378,6 +385,7 @@ class ProfileResolver {
378
385
  mode: defaultMode,
379
386
  source: defaultSource,
380
387
  url: defaultMode === 'copy' && defaultSource ? getMongoUrl(defaultSource) : undefined,
388
+ replicaSet,
381
389
  };
382
390
  }
383
391
  /**
@@ -194,21 +194,46 @@ class ComposeParser {
194
194
  return files;
195
195
  }
196
196
  normalizeService(name, config, root, composeDir, sourceFile) {
197
+ const command = this.normalizeCommand(config.command);
198
+ const environment = this.normalizeEnvironment(config.environment);
199
+ const image = config.image;
197
200
  return {
198
201
  name,
199
- image: config.image,
202
+ image,
200
203
  build: this.normalizeBuild(config.build, root, composeDir),
201
204
  ports: this.normalizePorts(config.ports),
202
- environment: this.normalizeEnvironment(config.environment),
205
+ environment,
203
206
  envFile: this.normalizeEnvFile(config.env_file),
204
207
  dependsOn: this.normalizeDependsOn(config.depends_on),
205
208
  volumes: this.normalizeVolumes(config.volumes),
206
209
  healthcheck: this.normalizeHealthcheck(config.healthcheck),
207
- command: this.normalizeCommand(config.command),
210
+ command,
208
211
  labels: this.normalizeLabels(config.labels),
209
212
  sourceFile,
213
+ replicaSet: this.detectReplicaSet(image, command, environment),
210
214
  };
211
215
  }
216
+ /**
217
+ * Detect MongoDB replica set configuration from command or environment
218
+ */
219
+ detectReplicaSet(image, command, environment) {
220
+ // Only check MongoDB services
221
+ if (!image || !DATABASE_PATTERNS[0].test(image)) {
222
+ return undefined;
223
+ }
224
+ // Check command for --replSet flag
225
+ if (command) {
226
+ const replSetMatch = command.match(/--replSet[=\s]+(\S+)/);
227
+ if (replSetMatch) {
228
+ return replSetMatch[1];
229
+ }
230
+ }
231
+ // Check environment for MONGO_REPLICA_SET
232
+ if (environment.MONGO_REPLICA_SET) {
233
+ return environment.MONGO_REPLICA_SET;
234
+ }
235
+ return undefined;
236
+ }
212
237
  normalizeBuild(build, root, composeDir) {
213
238
  if (!build)
214
239
  return undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.93",
3
+ "version": "1.0.95",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {