genbox 1.0.47 → 1.0.49

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.
@@ -2,49 +2,9 @@
2
2
  /**
3
3
  * Migrate Command
4
4
  *
5
- * Migrates genbox.yaml from v3 to v4 format:
6
- * - Shows what changes will be made
7
- * - Creates backup of original
8
- * - Applies migration
9
- *
10
- * Usage:
11
- * genbox migrate # Interactive migration
12
- * genbox migrate --dry-run # Show changes without applying
13
- * genbox migrate --yes # Skip confirmation
5
+ * Legacy command that now informs users to use genbox init instead.
6
+ * Only v4 configuration is supported.
14
7
  */
15
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
- if (k2 === undefined) k2 = k;
17
- var desc = Object.getOwnPropertyDescriptor(m, k);
18
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
- desc = { enumerable: true, get: function() { return m[k]; } };
20
- }
21
- Object.defineProperty(o, k2, desc);
22
- }) : (function(o, m, k, k2) {
23
- if (k2 === undefined) k2 = k;
24
- o[k2] = m[k];
25
- }));
26
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
- Object.defineProperty(o, "default", { enumerable: true, value: v });
28
- }) : function(o, v) {
29
- o["default"] = v;
30
- });
31
- var __importStar = (this && this.__importStar) || (function () {
32
- var ownKeys = function(o) {
33
- ownKeys = Object.getOwnPropertyNames || function (o) {
34
- var ar = [];
35
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
- return ar;
37
- };
38
- return ownKeys(o);
39
- };
40
- return function (mod) {
41
- if (mod && mod.__esModule) return mod;
42
- var result = {};
43
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
- __setModuleDefault(result, mod);
45
- return result;
46
- };
47
- })();
48
8
  var __importDefault = (this && this.__importDefault) || function (mod) {
49
9
  return (mod && mod.__esModule) ? mod : { "default": mod };
50
10
  };
@@ -52,197 +12,40 @@ Object.defineProperty(exports, "__esModule", { value: true });
52
12
  exports.deprecationsCommand = exports.migrateCommand = void 0;
53
13
  const commander_1 = require("commander");
54
14
  const chalk_1 = __importDefault(require("chalk"));
55
- const fs = __importStar(require("fs"));
56
- const yaml = __importStar(require("js-yaml"));
57
- const prompts_1 = require("@inquirer/prompts");
58
15
  const config_loader_1 = require("../config-loader");
59
- const migration_1 = require("../migration");
60
16
  exports.migrateCommand = new commander_1.Command('migrate')
61
- .description('Migrate genbox.yaml from v3 to v4 format')
62
- .option('--dry-run', 'Show changes without applying')
63
- .option('-y, --yes', 'Skip confirmation prompts')
64
- .option('--no-backup', 'Skip creating backup file')
65
- .option('--json', 'Output migration plan as JSON')
66
- .action(async (options) => {
17
+ .description('Migrate genbox.yaml (deprecated - only v4 is supported)')
18
+ .action(async () => {
67
19
  const cwd = process.cwd();
68
20
  console.log(chalk_1.default.cyan('\nšŸ”„ Genbox Configuration Migration\n'));
69
21
  try {
70
- // Load current configuration
71
22
  const configLoader = new config_loader_1.ConfigLoader();
72
23
  const loadResult = await configLoader.load(cwd);
73
- if (!loadResult.found || !loadResult.config) {
24
+ if (!loadResult.found) {
74
25
  console.log(chalk_1.default.red('Not a genbox project'));
75
26
  console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
27
+ console.log(chalk_1.default.dim('Run "genbox init" to initialize a new project.'));
76
28
  process.exit(1);
77
29
  }
78
- const config = loadResult.config;
79
- // Check if migration is needed
80
- if (!(0, migration_1.needsMigration)(config)) {
30
+ if (loadResult.config?.version === 4) {
81
31
  console.log(chalk_1.default.green('āœ“ Configuration is already at v4. No migration needed.'));
82
32
  return;
83
33
  }
84
- // Show deprecation warnings
85
- const deprecations = (0, migration_1.checkDeprecations)(config);
86
- if (deprecations.length > 0) {
87
- console.log(chalk_1.default.yellow.bold(`Found ${deprecations.length} deprecated patterns:\n`));
88
- for (const dep of deprecations) {
89
- console.log(chalk_1.default.yellow(` • ${dep.path}: ${dep.message}`));
90
- console.log(chalk_1.default.dim(` → ${dep.suggestion}`));
91
- }
92
- console.log();
93
- }
94
- // Get migration summary
95
- const summary = (0, migration_1.getMigrationSummary)(config);
96
- console.log(chalk_1.default.bold('Migration Summary:\n'));
97
- console.log(` Fields to migrate: ${summary.fieldsToMigrate}`);
98
- console.log(` Deprecated patterns: ${summary.deprecatedPatterns}`);
99
- if (summary.estimatedChanges.length > 0) {
100
- console.log(chalk_1.default.bold('\n Changes to be made:'));
101
- for (const change of summary.estimatedChanges) {
102
- console.log(` • ${change}`);
103
- }
104
- }
105
- // Perform migration
106
- const result = (0, migration_1.migrateV3ToV4)(config);
107
- if (options.json) {
108
- console.log(JSON.stringify({
109
- summary,
110
- changes: result.changes,
111
- warnings: result.warnings,
112
- config: result.config,
113
- }, null, 2));
114
- return;
115
- }
116
- // Show detailed changes
117
- console.log(chalk_1.default.bold('\nšŸ“ Detailed Changes:\n'));
118
- for (const change of result.changes) {
119
- const icon = change.type === 'add' ? '+' :
120
- change.type === 'remove' ? '-' :
121
- change.type === 'rename' ? '→' : '~';
122
- const color = change.type === 'add' ? chalk_1.default.green :
123
- change.type === 'remove' ? chalk_1.default.red :
124
- chalk_1.default.yellow;
125
- console.log(color(` ${icon} ${change.path}: ${change.description}`));
126
- }
127
- // Show warnings
128
- if (result.warnings.length > 0) {
129
- console.log(chalk_1.default.yellow.bold('\nāš ļø Warnings:\n'));
130
- for (const warning of result.warnings) {
131
- console.log(chalk_1.default.yellow(` • ${warning}`));
132
- }
133
- }
134
- // Dry run stops here
135
- if (options.dryRun) {
136
- console.log(chalk_1.default.bold('\nšŸ“„ Migrated Configuration (preview):\n'));
137
- console.log(chalk_1.default.dim('---'));
138
- console.log(yaml.dump(result.config, { lineWidth: 120, noRefs: true }));
139
- console.log(chalk_1.default.dim('---'));
140
- console.log(chalk_1.default.cyan('\nThis was a dry run. No changes were made.'));
141
- console.log('Run ' + chalk_1.default.bold('genbox migrate') + ' (without --dry-run) to apply changes.');
142
- return;
143
- }
144
- // Confirm migration
145
- if (!options.yes) {
146
- console.log();
147
- const confirmed = await (0, prompts_1.confirm)({
148
- message: 'Apply these changes to genbox.yaml?',
149
- default: true,
150
- });
151
- if (!confirmed) {
152
- console.log(chalk_1.default.yellow('Migration cancelled.'));
153
- return;
154
- }
155
- }
156
- // Find the config file path
157
- const projectSource = loadResult.sources.find(s => s.type === 'project');
158
- if (!projectSource) {
159
- console.log(chalk_1.default.red('Could not find project config file path.'));
160
- process.exit(1);
161
- }
162
- const configPath = projectSource.path;
163
- // Create backup
164
- if (options.backup !== false) {
165
- const backupPath = configPath.replace('.yaml', '.v3.yaml.bak');
166
- fs.copyFileSync(configPath, backupPath);
167
- console.log(chalk_1.default.dim(`\nBackup created: ${backupPath}`));
168
- }
169
- // Write migrated config
170
- const migratedContent = yaml.dump(result.config, {
171
- lineWidth: 120,
172
- noRefs: true,
173
- quotingType: '"',
174
- forceQuotes: false,
175
- });
176
- // Add header comment
177
- const header = `# Genbox Configuration v4
178
- # Migrated from v3 on ${new Date().toISOString()}
179
- # See: https://genbox.dev/docs/config-v4
180
-
181
- `;
182
- fs.writeFileSync(configPath, header + migratedContent);
183
- console.log(chalk_1.default.green.bold('\nāœ“ Migration complete!'));
184
- console.log(`\n Updated: ${configPath}`);
185
- // Next steps
186
- console.log(chalk_1.default.bold('\nšŸ“ Next steps:\n'));
187
- console.log(' 1. Review the migrated configuration');
188
- console.log(' 2. Run ' + chalk_1.default.cyan('genbox validate') + ' to check for issues');
189
- console.log(' 3. Run ' + chalk_1.default.cyan('genbox scan') + ' to update detected.yaml');
190
- console.log(' 4. Run ' + chalk_1.default.cyan('genbox resolve') + ' to verify resolution');
191
- console.log();
192
- // Show v4 benefits
193
- console.log(chalk_1.default.bold('šŸŽ‰ v4 Benefits:\n'));
194
- console.log(' • Explicit connections with ' + chalk_1.default.cyan('connects_to'));
195
- console.log(' • Clear infrastructure with ' + chalk_1.default.cyan('provides'));
196
- console.log(' • Opt-in detection with ' + chalk_1.default.cyan('$detect') + ' markers');
197
- console.log(' • Strict mode for predictable behavior');
198
- console.log();
34
+ // Old config version
35
+ console.log(chalk_1.default.yellow('āš ļø Legacy configuration detected.\n'));
36
+ console.log('Only v4 configuration format is supported.');
37
+ console.log('Please run ' + chalk_1.default.cyan('genbox init') + ' to create a new v4 configuration.\n');
38
+ console.log('Your existing configuration will be backed up automatically.');
199
39
  }
200
40
  catch (error) {
201
- console.error(chalk_1.default.red('Migration failed:'), error);
41
+ console.error(chalk_1.default.red('Error:'), error);
202
42
  process.exit(1);
203
43
  }
204
44
  });
205
- /**
206
- * Show deprecation warnings subcommand
207
- */
208
45
  exports.deprecationsCommand = new commander_1.Command('deprecations')
209
- .description('Check for deprecated patterns in genbox.yaml')
210
- .option('--json', 'Output as JSON')
211
- .action(async (options) => {
212
- const cwd = process.cwd();
213
- try {
214
- const configLoader = new config_loader_1.ConfigLoader();
215
- const loadResult = await configLoader.load(cwd);
216
- if (!loadResult.found || !loadResult.config) {
217
- console.log(chalk_1.default.red('Not a genbox project'));
218
- console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
219
- process.exit(1);
220
- }
221
- const deprecations = (0, migration_1.checkDeprecations)(loadResult.config);
222
- if (options.json) {
223
- console.log(JSON.stringify(deprecations, null, 2));
224
- return;
225
- }
226
- if (deprecations.length === 0) {
227
- console.log(chalk_1.default.green('āœ“ No deprecated patterns found.'));
228
- return;
229
- }
230
- console.log(chalk_1.default.yellow.bold(`\nFound ${deprecations.length} deprecated pattern(s):\n`));
231
- for (const dep of deprecations) {
232
- const icon = dep.severity === 'error' ? 'āœ—' : '⚠';
233
- const color = dep.severity === 'error' ? chalk_1.default.red : chalk_1.default.yellow;
234
- console.log(color(`${icon} ${dep.path}`));
235
- console.log(` ${dep.message}`);
236
- console.log(chalk_1.default.dim(` → ${dep.suggestion}`));
237
- if (dep.autoMigrate) {
238
- console.log(chalk_1.default.dim(' (can be auto-migrated)'));
239
- }
240
- console.log();
241
- }
242
- console.log(chalk_1.default.bold('Run ' + chalk_1.default.cyan('genbox migrate') + ' to fix these issues.\n'));
243
- }
244
- catch (error) {
245
- console.error(chalk_1.default.red('Check failed:'), error);
246
- process.exit(1);
247
- }
46
+ .description('Check for deprecated patterns (deprecated - only v4 is supported)')
47
+ .action(async () => {
48
+ console.log(chalk_1.default.yellow('\nāš ļø This command is deprecated.\n'));
49
+ console.log('Only v4 configuration format is supported.');
50
+ console.log('Run ' + chalk_1.default.cyan('genbox validate') + ' to check your v4 configuration.\n');
248
51
  });
@@ -58,7 +58,7 @@ exports.profilesCommand = new commander_1.Command('profiles')
58
58
  return;
59
59
  }
60
60
  const version = (0, schema_v4_1.getConfigVersion)(loadResult.config);
61
- if (version === 'unknown') {
61
+ if (version === 'invalid') {
62
62
  console.log(chalk_1.default.yellow('Unknown config version'));
63
63
  console.log(chalk_1.default.dim('Run "genbox init" to create a v4 configuration'));
64
64
  return;
@@ -118,7 +118,7 @@ exports.profilesCommand
118
118
  return;
119
119
  }
120
120
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
121
- if (configVersion === 'unknown') {
121
+ if (configVersion === 'invalid') {
122
122
  console.log(chalk_1.default.red('Unknown config version'));
123
123
  return;
124
124
  }
@@ -174,12 +174,6 @@ exports.profilesCommand
174
174
  }
175
175
  }
176
176
  }
177
- else if (v3Profile.infrastructure) {
178
- console.log(` ${chalk_1.default.bold('Infrastructure:')}`);
179
- for (const [name, mode] of Object.entries(v3Profile.infrastructure)) {
180
- console.log(` ${name}: ${mode}`);
181
- }
182
- }
183
177
  console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
184
178
  console.log('');
185
179
  console.log(chalk_1.default.dim(`Use: genbox create <name> --profile ${name}`));
@@ -202,7 +196,7 @@ exports.profilesCommand
202
196
  return;
203
197
  }
204
198
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
205
- if (configVersion === 'unknown') {
199
+ if (configVersion === 'invalid') {
206
200
  console.log(chalk_1.default.red('Unknown config version'));
207
201
  return;
208
202
  }
@@ -271,7 +265,7 @@ exports.profilesCommand
271
265
  description: description || undefined,
272
266
  size: size,
273
267
  apps: selectedApps,
274
- connect_to: connectTo !== 'local' ? connectTo : undefined,
268
+ default_connection: connectTo !== 'local' ? connectTo : undefined,
275
269
  database: dbMode !== 'none' ? {
276
270
  mode: dbMode.startsWith('copy') ? 'copy' : dbMode.startsWith('remote') ? 'remote' : 'local',
277
271
  source: dbMode.includes('staging') ? 'staging' : dbMode.includes('production') ? 'production' : undefined,
@@ -310,7 +304,7 @@ exports.profilesCommand
310
304
  return;
311
305
  }
312
306
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
313
- if (configVersion === 'unknown') {
307
+ if (configVersion === 'invalid') {
314
308
  console.log(chalk_1.default.red('Unknown config version'));
315
309
  return;
316
310
  }
@@ -45,6 +45,19 @@ const path = __importStar(require("path"));
45
45
  const os = __importStar(require("os"));
46
46
  const config_loader_1 = require("../config-loader");
47
47
  const api_1 = require("../api");
48
+ const DETECTED_DIR = '.genbox';
49
+ const PROJECT_CACHE_FILENAME = 'project.json';
50
+ /**
51
+ * Save project ID and info to local cache
52
+ */
53
+ function saveProjectCache(rootDir, cache) {
54
+ const genboxDir = path.join(rootDir, DETECTED_DIR);
55
+ if (!fs.existsSync(genboxDir)) {
56
+ fs.mkdirSync(genboxDir, { recursive: true });
57
+ }
58
+ const cachePath = path.join(genboxDir, PROJECT_CACHE_FILENAME);
59
+ fs.writeFileSync(cachePath, JSON.stringify(cache, null, 2));
60
+ }
48
61
  function getPrivateSshKey() {
49
62
  const home = os.homedir();
50
63
  const potentialKeys = [
@@ -58,6 +71,28 @@ function getPrivateSshKey() {
58
71
  }
59
72
  return undefined;
60
73
  }
74
+ /**
75
+ * Convert GenboxConfig to ProjectSyncPayload
76
+ */
77
+ function configToSyncPayload(config, envVars, privateKey) {
78
+ return {
79
+ name: config.project.name,
80
+ version: config.version,
81
+ project: config.project,
82
+ apps: config.apps,
83
+ provides: config.provides,
84
+ environments: config.environments,
85
+ profiles: config.profiles,
86
+ defaults: config.defaults,
87
+ repos: config.repos,
88
+ hooks: config.hooks,
89
+ scripts: config.scripts,
90
+ strict: config.strict,
91
+ git_auth: config.git_auth,
92
+ envVars,
93
+ privateKey,
94
+ };
95
+ }
61
96
  function buildLegacyPayload(config, envVars) {
62
97
  return {
63
98
  name: config.project_name,
@@ -98,7 +133,7 @@ function displayV3Summary(config, envVars, payload) {
98
133
  }
99
134
  }
100
135
  // Display infrastructure
101
- const infraNames = Object.keys(config.infrastructure || {});
136
+ const infraNames = Object.keys(config.provides || {});
102
137
  if (infraNames.length > 0) {
103
138
  console.log(` ${chalk_1.default.bold('Infra:')} ${infraNames.join(', ')}`);
104
139
  }
@@ -169,18 +204,20 @@ exports.pushCommand = new commander_1.Command('push')
169
204
  process.exit(1);
170
205
  }
171
206
  const config = loadResult.config;
172
- const isV3 = config?.version === '3.0';
207
+ const isV4 = config?.version === 4;
173
208
  // Load env vars
174
209
  const envVars = configLoader.loadEnvVars(process.cwd());
175
210
  console.log(chalk_1.default.blue('Preparing workspace configuration...'));
176
211
  console.log('');
177
- // Build appropriate payload based on version
212
+ // Build payload (v4 only)
178
213
  let payload;
179
- if (isV3) {
214
+ if (isV4) {
180
215
  payload = buildV3Payload(config, envVars);
181
216
  }
182
217
  else {
183
- payload = buildLegacyPayload(config, envVars);
218
+ console.log(chalk_1.default.red('Error: Only version 4 configuration is supported.'));
219
+ console.log(chalk_1.default.dim('Run "genbox init" to create a v4 configuration.'));
220
+ process.exit(1);
184
221
  }
185
222
  // Process files to upload (for both versions)
186
223
  const configAny = config;
@@ -212,13 +249,8 @@ exports.pushCommand = new commander_1.Command('push')
212
249
  console.log(chalk_1.default.yellow('Warning: No SSH private key found in ~/.ssh/'));
213
250
  }
214
251
  }
215
- // Display appropriate summary
216
- if (isV3) {
217
- displayV3Summary(config, envVars, payload);
218
- }
219
- else {
220
- displayLegacySummary(payload);
221
- }
252
+ // Display summary
253
+ displayV3Summary(config, envVars, payload);
222
254
  console.log('');
223
255
  // Dry run mode
224
256
  if (options.dryRun) {
@@ -235,29 +267,35 @@ exports.pushCommand = new commander_1.Command('push')
235
267
  console.log(JSON.stringify(previewPayload, null, 2));
236
268
  return;
237
269
  }
238
- // Upload to server
239
- const spinner = (0, ora_1.default)('Uploading workspace configuration...').start();
270
+ // Upload to server using the new projects endpoint
271
+ const spinner = (0, ora_1.default)('Syncing project configuration...').start();
240
272
  try {
241
- const result = await (0, api_1.fetchApi)('/workspaces', {
242
- method: 'PUT',
243
- body: JSON.stringify(payload),
273
+ const v4Config = config;
274
+ const syncPayload = configToSyncPayload(v4Config, envVars, options.includeKey ? payload.privateKey : undefined);
275
+ const result = await (0, api_1.syncProject)(syncPayload);
276
+ // Save project cache locally
277
+ saveProjectCache(process.cwd(), {
278
+ _id: result._id,
279
+ name: result.name,
280
+ lastSyncedAt: new Date().toISOString(),
281
+ action: result.action,
244
282
  });
245
- spinner.succeed(chalk_1.default.green('Workspace configuration uploaded successfully!'));
283
+ spinner.succeed(chalk_1.default.green(`Project synced successfully (${result.action})!`));
284
+ if (result.changes && result.changes.length > 0) {
285
+ console.log(chalk_1.default.dim(` Changes: ${result.changes.join(', ')}`));
286
+ }
246
287
  console.log('');
247
288
  console.log(chalk_1.default.dim('Your configuration is now available in the cloud.'));
248
289
  console.log(chalk_1.default.dim('Team members can run "genbox create <name>" to provision environments.'));
249
- if (isV3) {
250
- const v3Config = config;
251
- const profileNames = Object.keys(v3Config.profiles || {});
252
- if (profileNames.length > 0) {
253
- console.log('');
254
- console.log(chalk_1.default.dim('Available profiles:'));
255
- for (const name of profileNames.slice(0, 5)) {
256
- console.log(chalk_1.default.dim(` genbox create <name> --profile ${name}`));
257
- }
258
- if (profileNames.length > 5) {
259
- console.log(chalk_1.default.dim(` ... and ${profileNames.length - 5} more`));
260
- }
290
+ const profileNames = Object.keys(v4Config.profiles || {});
291
+ if (profileNames.length > 0) {
292
+ console.log('');
293
+ console.log(chalk_1.default.dim('Available profiles:'));
294
+ for (const name of profileNames.slice(0, 5)) {
295
+ console.log(chalk_1.default.dim(` genbox create <name> --profile ${name}`));
296
+ }
297
+ if (profileNames.length > 5) {
298
+ console.log(chalk_1.default.dim(` ... and ${profileNames.length - 5} more`));
261
299
  }
262
300
  }
263
301
  if (Object.keys(envVars).length === 0) {
@@ -268,11 +306,11 @@ exports.pushCommand = new commander_1.Command('push')
268
306
  }
269
307
  }
270
308
  catch (error) {
271
- spinner.fail(chalk_1.default.red('Failed to upload workspace configuration'));
309
+ spinner.fail(chalk_1.default.red('Failed to sync project configuration'));
272
310
  console.error(chalk_1.default.red(`Error: ${error.message}`));
273
311
  if (error instanceof api_1.AuthenticationError || error.message.includes('401') || error.message.includes('Unauthorized')) {
274
312
  console.log('');
275
- console.log(chalk_1.default.yellow('You need to be logged in to push workspace configuration.'));
313
+ console.log(chalk_1.default.yellow('You need to be logged in to push project configuration.'));
276
314
  console.log(chalk_1.default.dim('Run "genbox login" to authenticate.'));
277
315
  }
278
316
  }
@@ -176,13 +176,8 @@ function buildRebuildPayload(resolved, config, publicKey, privateKey, configLoad
176
176
  // Build services map
177
177
  const services = {};
178
178
  for (const app of resolved.apps) {
179
- if (app.services) {
180
- for (const [name, svc] of Object.entries(app.services)) {
181
- services[name] = { port: svc.port, healthcheck: svc.healthcheck };
182
- }
183
- }
184
- else if (app.port) {
185
- services[app.name] = { port: app.port };
179
+ if (app.port) {
180
+ services[app.name] = { port: app.port, healthcheck: app.healthcheck };
186
181
  }
187
182
  }
188
183
  // Build files bundle
@@ -470,7 +465,7 @@ exports.rebuildCommand = new commander_1.Command('rebuild')
470
465
  return;
471
466
  }
472
467
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
473
- if (configVersion === 'unknown') {
468
+ if (configVersion === 'invalid') {
474
469
  console.log(chalk_1.default.red('Unknown config version'));
475
470
  return;
476
471
  }
@@ -249,12 +249,12 @@ function validateSchema(config, errors, warnings) {
249
249
  suggestion: 'Add "version: 3" at the top of genbox.yaml',
250
250
  });
251
251
  }
252
- else if (config.version !== '3.0' && config.version !== 3 && config.version !== 4) {
253
- warnings.push({
252
+ else if (config.version !== 4) {
253
+ errors.push({
254
254
  path: 'version',
255
- message: `Version ${config.version} may not be fully supported`,
256
- severity: 'warning',
257
- suggestion: 'Consider upgrading to version 3 or 4',
255
+ message: `Version ${config.version} is not supported`,
256
+ severity: 'error',
257
+ suggestion: 'Only version 4 is supported. Run "genbox init" to create a v4 configuration.',
258
258
  });
259
259
  }
260
260
  if (!config.project?.name) {
@@ -316,8 +316,8 @@ function validateReferences(config, errors, _warnings) {
316
316
  }
317
317
  }
318
318
  // Validate connect_to references
319
- if (profile.connect_to) {
320
- for (const [appName, connections] of Object.entries(profile.connect_to)) {
319
+ if (profile.default_connection) {
320
+ for (const [appName, connections] of Object.entries(profile.default_connection)) {
321
321
  if (!appNames.has(appName)) {
322
322
  errors.push({
323
323
  path: `profiles.${profileName}.connect_to.${appName}`,
@@ -328,7 +328,7 @@ function validateReferences(config, errors, _warnings) {
328
328
  // Validate connection targets
329
329
  for (const [targetName] of Object.entries(connections || {})) {
330
330
  // Infrastructure names are in the infrastructure section (it's a Record, not array)
331
- const infraNames = new Set(Object.keys(config.infrastructure || {}));
331
+ const infraNames = new Set(Object.keys(config.provides || {}));
332
332
  if (!appNames.has(targetName) && !infraNames.has(targetName)) {
333
333
  errors.push({
334
334
  path: `profiles.${profileName}.connect_to.${appName}.${targetName}`,
@@ -372,11 +372,11 @@ function validateProfiles(config, errors, warnings) {
372
372
  }
373
373
  function validateDependencies(config, errors, warnings) {
374
374
  const appNames = new Set(Object.keys(config.apps || {}));
375
- const infraNames = new Set(Object.keys(config.infrastructure || {}));
375
+ const infraNames = new Set(Object.keys(config.provides || {}));
376
376
  // Check app dependencies
377
377
  for (const [appName, appConfig] of Object.entries(config.apps || {})) {
378
- if (appConfig.dependencies) {
379
- for (const depName of Object.keys(appConfig.dependencies)) {
378
+ if (appConfig.connects_to) {
379
+ for (const depName of Object.keys(appConfig.connects_to)) {
380
380
  if (!infraNames.has(depName) && !appNames.has(depName)) {
381
381
  errors.push({
382
382
  path: `apps.${appName}.dependencies.${depName}`,
@@ -391,7 +391,7 @@ function validateDependencies(config, errors, warnings) {
391
391
  // Check for circular dependencies
392
392
  const appDeps = new Map();
393
393
  for (const [appName, appConfig] of Object.entries(config.apps || {})) {
394
- const deps = Object.keys(appConfig.dependencies || {}).filter(d => appNames.has(d));
394
+ const deps = Object.keys(appConfig.connects_to || {}).filter(d => appNames.has(d));
395
395
  appDeps.set(appName, deps);
396
396
  }
397
397
  for (const appName of appNames) {
@@ -407,7 +407,7 @@ function validateDependencies(config, errors, warnings) {
407
407
  }
408
408
  // Warn about apps with no dependencies defined
409
409
  for (const [appName, appConfig] of Object.entries(config.apps || {})) {
410
- if (!appConfig.dependencies || Object.keys(appConfig.dependencies).length === 0) {
410
+ if (!appConfig.connects_to || Object.keys(appConfig.connects_to).length === 0) {
411
411
  if (appConfig.type === 'backend' || appConfig.type === 'worker') {
412
412
  warnings.push({
413
413
  path: `apps.${appName}.dependencies`,
@@ -258,7 +258,7 @@ class ConfigExplainer {
258
258
  const mappings = {
259
259
  'size': 'size',
260
260
  'apps': 'apps',
261
- 'connect_to': 'connect_to',
261
+ 'default_connection': 'default_connection',
262
262
  'database.mode': 'database',
263
263
  'branch': 'branch',
264
264
  };