genbox 1.0.12 → 1.0.13

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.
@@ -0,0 +1,273 @@
1
+ "use strict";
2
+ /**
3
+ * Config Command
4
+ *
5
+ * Provides configuration inspection and debugging tools:
6
+ * - genbox config show - Show resolved configuration
7
+ * - genbox config show --explain - Show where each value comes from
8
+ * - genbox config diff <a> <b> - Compare two profiles
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || (function () {
27
+ var ownKeys = function(o) {
28
+ ownKeys = Object.getOwnPropertyNames || function (o) {
29
+ var ar = [];
30
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
+ return ar;
32
+ };
33
+ return ownKeys(o);
34
+ };
35
+ return function (mod) {
36
+ if (mod && mod.__esModule) return mod;
37
+ var result = {};
38
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
+ __setModuleDefault(result, mod);
40
+ return result;
41
+ };
42
+ })();
43
+ var __importDefault = (this && this.__importDefault) || function (mod) {
44
+ return (mod && mod.__esModule) ? mod : { "default": mod };
45
+ };
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.configCommand = void 0;
48
+ const commander_1 = require("commander");
49
+ const chalk_1 = __importDefault(require("chalk"));
50
+ const yaml = __importStar(require("js-yaml"));
51
+ const config_loader_1 = require("../config-loader");
52
+ const config_explainer_1 = require("../config-explainer");
53
+ exports.configCommand = new commander_1.Command('config')
54
+ .description('Inspect and debug configuration')
55
+ .addCommand(createShowCommand())
56
+ .addCommand(createDiffCommand());
57
+ function createShowCommand() {
58
+ return new commander_1.Command('show')
59
+ .description('Show resolved configuration')
60
+ .argument('[path]', 'Specific config path to show (e.g., apps.web, profiles.quick)')
61
+ .option('--explain', 'Show where each value comes from')
62
+ .option('--profile <profile>', 'Show configuration for a specific profile')
63
+ .option('--json', 'Output as JSON')
64
+ .option('--yaml', 'Output as YAML (default)')
65
+ .action(async (configPath, options) => {
66
+ const configLoader = new config_loader_1.ConfigLoader();
67
+ const loadResult = await configLoader.load();
68
+ if (!loadResult.found || !loadResult.config) {
69
+ console.log(chalk_1.default.red('No genbox.yaml found in current directory or parent directories'));
70
+ process.exit(1);
71
+ }
72
+ const config = loadResult.config;
73
+ if (options.explain) {
74
+ await showWithExplain(config, loadResult, configPath, options.profile);
75
+ }
76
+ else {
77
+ await showConfig(config, configPath, options);
78
+ }
79
+ });
80
+ }
81
+ function createDiffCommand() {
82
+ return new commander_1.Command('diff')
83
+ .description('Compare two profiles')
84
+ .argument('<profile1>', 'First profile name')
85
+ .argument('<profile2>', 'Second profile name')
86
+ .action(async (profile1, profile2) => {
87
+ const configLoader = new config_loader_1.ConfigLoader();
88
+ const loadResult = await configLoader.load();
89
+ if (!loadResult.found || !loadResult.config) {
90
+ console.log(chalk_1.default.red('No genbox.yaml found'));
91
+ process.exit(1);
92
+ }
93
+ const config = loadResult.config;
94
+ const p1 = configLoader.getProfile(config, profile1);
95
+ const p2 = configLoader.getProfile(config, profile2);
96
+ if (!p1) {
97
+ console.log(chalk_1.default.red(`Profile '${profile1}' not found`));
98
+ process.exit(1);
99
+ }
100
+ if (!p2) {
101
+ console.log(chalk_1.default.red(`Profile '${profile2}' not found`));
102
+ process.exit(1);
103
+ }
104
+ showProfileDiff(profile1, p1, profile2, p2, config);
105
+ });
106
+ }
107
+ async function showConfig(config, path, options) {
108
+ let data = config;
109
+ // If profile specified, show that profile's resolved config
110
+ if (options.profile) {
111
+ const configLoader = new config_loader_1.ConfigLoader();
112
+ const profile = configLoader.getProfile(config, options.profile);
113
+ if (!profile) {
114
+ console.log(chalk_1.default.red(`Profile '${options.profile}' not found`));
115
+ process.exit(1);
116
+ }
117
+ data = profile;
118
+ }
119
+ // Navigate to specific path if provided
120
+ if (path) {
121
+ const parts = path.split('.');
122
+ let current = data;
123
+ for (const part of parts) {
124
+ if (current && typeof current === 'object' && part in current) {
125
+ current = current[part];
126
+ }
127
+ else {
128
+ console.log(chalk_1.default.red(`Path '${path}' not found in configuration`));
129
+ process.exit(1);
130
+ }
131
+ }
132
+ data = current;
133
+ }
134
+ // Output
135
+ if (options.json) {
136
+ console.log(JSON.stringify(data, null, 2));
137
+ }
138
+ else {
139
+ console.log(yaml.dump(data, { lineWidth: 120, noRefs: true }));
140
+ }
141
+ }
142
+ async function showWithExplain(config, loadResult, path, profileName) {
143
+ const explainer = new config_explainer_1.ConfigExplainer(loadResult);
144
+ console.log(chalk_1.default.bold.cyan('\nšŸ“‹ Configuration Analysis\n'));
145
+ // Show sources
146
+ console.log(chalk_1.default.bold('Config Sources (priority order):'));
147
+ for (const source of loadResult.sources) {
148
+ const icon = source.type === 'workspace' ? 'šŸ¢' : source.type === 'project' ? 'šŸ“' : 'šŸ‘¤';
149
+ console.log(` ${icon} ${source.type}: ${source.path}`);
150
+ }
151
+ console.log();
152
+ // If path specified, show just that path
153
+ if (path) {
154
+ const explanation = explainer.explain(path, profileName);
155
+ printExplanation(path, explanation);
156
+ return;
157
+ }
158
+ // Show key configuration values with explanations
159
+ console.log(chalk_1.default.bold('Key Values:\n'));
160
+ // Project info
161
+ printExplanation('project.name', explainer.explain('project.name'));
162
+ printExplanation('project.structure', explainer.explain('project.structure'));
163
+ // Apps
164
+ if (config.apps) {
165
+ console.log(chalk_1.default.bold('\nApps:'));
166
+ for (const appName of Object.keys(config.apps)) {
167
+ console.log(chalk_1.default.cyan(`\n ${appName}:`));
168
+ printExplanation(` apps.${appName}.type`, explainer.explain(`apps.${appName}.type`), 4);
169
+ printExplanation(` apps.${appName}.port`, explainer.explain(`apps.${appName}.port`), 4);
170
+ printExplanation(` apps.${appName}.framework`, explainer.explain(`apps.${appName}.framework`), 4);
171
+ }
172
+ }
173
+ // Profiles
174
+ if (config.profiles && profileName) {
175
+ console.log(chalk_1.default.bold(`\nProfile '${profileName}':`));
176
+ printExplanation(' size', explainer.explain('size', profileName), 4);
177
+ printExplanation(' apps', explainer.explain('apps', profileName), 4);
178
+ printExplanation(' connect_to', explainer.explain('connect_to', profileName), 4);
179
+ printExplanation(' database.mode', explainer.explain('database.mode', profileName), 4);
180
+ }
181
+ // Defaults
182
+ if (config.defaults) {
183
+ console.log(chalk_1.default.bold('\nDefaults:'));
184
+ printExplanation(' defaults.size', explainer.explain('defaults.size'), 4);
185
+ printExplanation(' defaults.branch', explainer.explain('defaults.branch'), 4);
186
+ }
187
+ // Detection warnings
188
+ const warnings = explainer.getDetectionWarnings();
189
+ if (warnings.length > 0) {
190
+ console.log(chalk_1.default.bold.yellow('\nāš ļø Detection Warnings:\n'));
191
+ for (const warning of warnings) {
192
+ console.log(chalk_1.default.yellow(` • ${warning}`));
193
+ }
194
+ }
195
+ console.log();
196
+ }
197
+ function printExplanation(path, sources, indent = 0) {
198
+ const pad = ' '.repeat(indent);
199
+ if (sources.length === 0) {
200
+ console.log(`${pad}${chalk_1.default.dim(path)}: ${chalk_1.default.dim('(not set)')}`);
201
+ return;
202
+ }
203
+ const finalSource = sources.find(s => s.used) || sources[0];
204
+ const valueStr = formatValue(finalSource.value);
205
+ console.log(`${pad}${chalk_1.default.white(path)}: ${chalk_1.default.green(valueStr)}`);
206
+ for (const source of sources) {
207
+ const icon = source.used ? chalk_1.default.green('āœ“') : chalk_1.default.dim('ā—‹');
208
+ const sourceLabel = getSourceLabel(source);
209
+ const value = source.value !== undefined ? formatValue(source.value) : chalk_1.default.dim('(not set)');
210
+ if (source.used) {
211
+ console.log(`${pad} ${icon} ${sourceLabel}: ${value}`);
212
+ if (source.detectedFrom) {
213
+ console.log(`${pad} └─ ${chalk_1.default.dim(`detected from: ${source.detectedFrom}`)}`);
214
+ }
215
+ }
216
+ else {
217
+ console.log(`${pad} ${icon} ${chalk_1.default.dim(sourceLabel)}: ${chalk_1.default.dim(String(value))}`);
218
+ }
219
+ }
220
+ }
221
+ function getSourceLabel(source) {
222
+ switch (source.source) {
223
+ case 'cli':
224
+ return 'CLI flag';
225
+ case 'profile':
226
+ return `Profile '${source.profileName || 'unknown'}'`;
227
+ case 'project':
228
+ return 'genbox.yaml (explicit)';
229
+ case 'workspace':
230
+ return 'workspace genbox.yaml';
231
+ case 'detected':
232
+ return 'detected.yaml';
233
+ case 'default':
234
+ return 'schema default';
235
+ case 'inferred':
236
+ return 'inferred';
237
+ default:
238
+ return source.source;
239
+ }
240
+ }
241
+ function formatValue(value) {
242
+ if (value === undefined)
243
+ return '(undefined)';
244
+ if (value === null)
245
+ return '(null)';
246
+ if (Array.isArray(value))
247
+ return `[${value.join(', ')}]`;
248
+ if (typeof value === 'object')
249
+ return JSON.stringify(value);
250
+ return String(value);
251
+ }
252
+ function showProfileDiff(name1, profile1, name2, profile2, config) {
253
+ console.log(chalk_1.default.bold.cyan(`\nšŸ“Š Comparing profiles: ${name1} vs ${name2}\n`));
254
+ const allKeys = new Set([
255
+ ...Object.keys(profile1),
256
+ ...Object.keys(profile2),
257
+ ]);
258
+ let hasDiff = false;
259
+ for (const key of allKeys) {
260
+ const v1 = profile1[key];
261
+ const v2 = profile2[key];
262
+ if (JSON.stringify(v1) !== JSON.stringify(v2)) {
263
+ hasDiff = true;
264
+ console.log(chalk_1.default.bold(` ${key}:`));
265
+ console.log(chalk_1.default.red(` - ${name1}: ${formatValue(v1)}`));
266
+ console.log(chalk_1.default.green(` + ${name2}: ${formatValue(v2)}`));
267
+ console.log();
268
+ }
269
+ }
270
+ if (!hasDiff) {
271
+ console.log(chalk_1.default.dim(' No differences found'));
272
+ }
273
+ }
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ /**
3
+ * Migrate Command
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
14
+ */
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
49
+ return (mod && mod.__esModule) ? mod : { "default": mod };
50
+ };
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ exports.deprecationsCommand = exports.migrateCommand = void 0;
53
+ const commander_1 = require("commander");
54
+ 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
+ const config_loader_1 = require("../config-loader");
59
+ const migration_1 = require("../migration");
60
+ 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) => {
67
+ const cwd = process.cwd();
68
+ console.log(chalk_1.default.cyan('\nšŸ”„ Genbox Configuration Migration\n'));
69
+ try {
70
+ // Load current configuration
71
+ const configLoader = new config_loader_1.ConfigLoader();
72
+ const loadResult = await configLoader.load(cwd);
73
+ if (!loadResult.found || !loadResult.config) {
74
+ console.log(chalk_1.default.red('No genbox.yaml found. Nothing to migrate.'));
75
+ process.exit(1);
76
+ }
77
+ const config = loadResult.config;
78
+ // Check if migration is needed
79
+ if (!(0, migration_1.needsMigration)(config)) {
80
+ console.log(chalk_1.default.green('āœ“ Configuration is already at v4. No migration needed.'));
81
+ return;
82
+ }
83
+ // Show deprecation warnings
84
+ const deprecations = (0, migration_1.checkDeprecations)(config);
85
+ if (deprecations.length > 0) {
86
+ console.log(chalk_1.default.yellow.bold(`Found ${deprecations.length} deprecated patterns:\n`));
87
+ for (const dep of deprecations) {
88
+ console.log(chalk_1.default.yellow(` • ${dep.path}: ${dep.message}`));
89
+ console.log(chalk_1.default.dim(` → ${dep.suggestion}`));
90
+ }
91
+ console.log();
92
+ }
93
+ // Get migration summary
94
+ const summary = (0, migration_1.getMigrationSummary)(config);
95
+ console.log(chalk_1.default.bold('Migration Summary:\n'));
96
+ console.log(` Fields to migrate: ${summary.fieldsToMigrate}`);
97
+ console.log(` Deprecated patterns: ${summary.deprecatedPatterns}`);
98
+ if (summary.estimatedChanges.length > 0) {
99
+ console.log(chalk_1.default.bold('\n Changes to be made:'));
100
+ for (const change of summary.estimatedChanges) {
101
+ console.log(` • ${change}`);
102
+ }
103
+ }
104
+ // Perform migration
105
+ const result = (0, migration_1.migrateV3ToV4)(config);
106
+ if (options.json) {
107
+ console.log(JSON.stringify({
108
+ summary,
109
+ changes: result.changes,
110
+ warnings: result.warnings,
111
+ config: result.config,
112
+ }, null, 2));
113
+ return;
114
+ }
115
+ // Show detailed changes
116
+ console.log(chalk_1.default.bold('\nšŸ“ Detailed Changes:\n'));
117
+ for (const change of result.changes) {
118
+ const icon = change.type === 'add' ? '+' :
119
+ change.type === 'remove' ? '-' :
120
+ change.type === 'rename' ? '→' : '~';
121
+ const color = change.type === 'add' ? chalk_1.default.green :
122
+ change.type === 'remove' ? chalk_1.default.red :
123
+ chalk_1.default.yellow;
124
+ console.log(color(` ${icon} ${change.path}: ${change.description}`));
125
+ }
126
+ // Show warnings
127
+ if (result.warnings.length > 0) {
128
+ console.log(chalk_1.default.yellow.bold('\nāš ļø Warnings:\n'));
129
+ for (const warning of result.warnings) {
130
+ console.log(chalk_1.default.yellow(` • ${warning}`));
131
+ }
132
+ }
133
+ // Dry run stops here
134
+ if (options.dryRun) {
135
+ console.log(chalk_1.default.bold('\nšŸ“„ Migrated Configuration (preview):\n'));
136
+ console.log(chalk_1.default.dim('---'));
137
+ console.log(yaml.dump(result.config, { lineWidth: 120, noRefs: true }));
138
+ console.log(chalk_1.default.dim('---'));
139
+ console.log(chalk_1.default.cyan('\nThis was a dry run. No changes were made.'));
140
+ console.log('Run ' + chalk_1.default.bold('genbox migrate') + ' (without --dry-run) to apply changes.');
141
+ return;
142
+ }
143
+ // Confirm migration
144
+ if (!options.yes) {
145
+ console.log();
146
+ const confirmed = await (0, prompts_1.confirm)({
147
+ message: 'Apply these changes to genbox.yaml?',
148
+ default: true,
149
+ });
150
+ if (!confirmed) {
151
+ console.log(chalk_1.default.yellow('Migration cancelled.'));
152
+ return;
153
+ }
154
+ }
155
+ // Find the config file path
156
+ const projectSource = loadResult.sources.find(s => s.type === 'project');
157
+ if (!projectSource) {
158
+ console.log(chalk_1.default.red('Could not find project config file path.'));
159
+ process.exit(1);
160
+ }
161
+ const configPath = projectSource.path;
162
+ // Create backup
163
+ if (options.backup !== false) {
164
+ const backupPath = configPath.replace('.yaml', '.v3.yaml.bak');
165
+ fs.copyFileSync(configPath, backupPath);
166
+ console.log(chalk_1.default.dim(`\nBackup created: ${backupPath}`));
167
+ }
168
+ // Write migrated config
169
+ const migratedContent = yaml.dump(result.config, {
170
+ lineWidth: 120,
171
+ noRefs: true,
172
+ quotingType: '"',
173
+ forceQuotes: false,
174
+ });
175
+ // Add header comment
176
+ const header = `# Genbox Configuration v4
177
+ # Migrated from v3 on ${new Date().toISOString()}
178
+ # See: https://genbox.dev/docs/config-v4
179
+
180
+ `;
181
+ fs.writeFileSync(configPath, header + migratedContent);
182
+ console.log(chalk_1.default.green.bold('\nāœ“ Migration complete!'));
183
+ console.log(`\n Updated: ${configPath}`);
184
+ // Next steps
185
+ console.log(chalk_1.default.bold('\nšŸ“ Next steps:\n'));
186
+ console.log(' 1. Review the migrated configuration');
187
+ console.log(' 2. Run ' + chalk_1.default.cyan('genbox validate') + ' to check for issues');
188
+ console.log(' 3. Run ' + chalk_1.default.cyan('genbox scan') + ' to update detected.yaml');
189
+ console.log(' 4. Run ' + chalk_1.default.cyan('genbox resolve') + ' to verify resolution');
190
+ console.log();
191
+ // Show v4 benefits
192
+ console.log(chalk_1.default.bold('šŸŽ‰ v4 Benefits:\n'));
193
+ console.log(' • Explicit connections with ' + chalk_1.default.cyan('connects_to'));
194
+ console.log(' • Clear infrastructure with ' + chalk_1.default.cyan('provides'));
195
+ console.log(' • Opt-in detection with ' + chalk_1.default.cyan('$detect') + ' markers');
196
+ console.log(' • Strict mode for predictable behavior');
197
+ console.log();
198
+ }
199
+ catch (error) {
200
+ console.error(chalk_1.default.red('Migration failed:'), error);
201
+ process.exit(1);
202
+ }
203
+ });
204
+ /**
205
+ * Show deprecation warnings subcommand
206
+ */
207
+ exports.deprecationsCommand = new commander_1.Command('deprecations')
208
+ .description('Check for deprecated patterns in genbox.yaml')
209
+ .option('--json', 'Output as JSON')
210
+ .action(async (options) => {
211
+ const cwd = process.cwd();
212
+ try {
213
+ const configLoader = new config_loader_1.ConfigLoader();
214
+ const loadResult = await configLoader.load(cwd);
215
+ if (!loadResult.found || !loadResult.config) {
216
+ console.log(chalk_1.default.red('No genbox.yaml found.'));
217
+ process.exit(1);
218
+ }
219
+ const deprecations = (0, migration_1.checkDeprecations)(loadResult.config);
220
+ if (options.json) {
221
+ console.log(JSON.stringify(deprecations, null, 2));
222
+ return;
223
+ }
224
+ if (deprecations.length === 0) {
225
+ console.log(chalk_1.default.green('āœ“ No deprecated patterns found.'));
226
+ return;
227
+ }
228
+ console.log(chalk_1.default.yellow.bold(`\nFound ${deprecations.length} deprecated pattern(s):\n`));
229
+ for (const dep of deprecations) {
230
+ const icon = dep.severity === 'error' ? 'āœ—' : '⚠';
231
+ const color = dep.severity === 'error' ? chalk_1.default.red : chalk_1.default.yellow;
232
+ console.log(color(`${icon} ${dep.path}`));
233
+ console.log(` ${dep.message}`);
234
+ console.log(chalk_1.default.dim(` → ${dep.suggestion}`));
235
+ if (dep.autoMigrate) {
236
+ console.log(chalk_1.default.dim(' (can be auto-migrated)'));
237
+ }
238
+ console.log();
239
+ }
240
+ console.log(chalk_1.default.bold('Run ' + chalk_1.default.cyan('genbox migrate') + ' to fix these issues.\n'));
241
+ }
242
+ catch (error) {
243
+ console.error(chalk_1.default.red('Check failed:'), error);
244
+ process.exit(1);
245
+ }
246
+ });