genbox 1.0.24 → 1.0.26

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.
@@ -66,7 +66,9 @@ function createShowCommand() {
66
66
  const configLoader = new config_loader_1.ConfigLoader();
67
67
  const loadResult = await configLoader.load();
68
68
  if (!loadResult.found || !loadResult.config) {
69
- console.log(chalk_1.default.red('No genbox.yaml found in current directory or parent directories'));
69
+ console.log(chalk_1.default.red('Not a genbox project'));
70
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
71
+ console.log(chalk_1.default.dim('Run "genbox init" to initialize a new project.'));
70
72
  process.exit(1);
71
73
  }
72
74
  const config = loadResult.config;
@@ -87,7 +89,8 @@ function createDiffCommand() {
87
89
  const configLoader = new config_loader_1.ConfigLoader();
88
90
  const loadResult = await configLoader.load();
89
91
  if (!loadResult.found || !loadResult.config) {
90
- console.log(chalk_1.default.red('No genbox.yaml found'));
92
+ console.log(chalk_1.default.red('Not a genbox project'));
93
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
91
94
  process.exit(1);
92
95
  }
93
96
  const config = loadResult.config;
@@ -196,11 +196,16 @@ exports.createCommand = new commander_1.Command('create')
196
196
  // Load configuration
197
197
  const configLoader = new config_loader_1.ConfigLoader();
198
198
  const loadResult = await configLoader.load();
199
+ if (!loadResult.config) {
200
+ console.log(chalk_1.default.red('Not a genbox project'));
201
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
202
+ console.log(chalk_1.default.dim('Run "genbox init" to initialize a new project.'));
203
+ return;
204
+ }
199
205
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
200
- if (!loadResult.config || configVersion === 'unknown') {
201
- // Fall back to legacy v1/v2 handling
202
- const name = nameArg || await promptForName(options.yes);
203
- await createLegacy(name, options);
206
+ if (configVersion === 'unknown') {
207
+ console.log(chalk_1.default.red('Unknown config version'));
208
+ console.log(chalk_1.default.dim('Run "genbox init" to create a new configuration.'));
204
209
  return;
205
210
  }
206
211
  // Support both v3 and v4 configs
@@ -420,8 +425,12 @@ function displayResolvedConfig(resolved) {
420
425
  console.log(` • ${infra.name} (${infra.mode})`);
421
426
  }
422
427
  }
423
- console.log('');
424
- console.log(` ${chalk_1.default.bold('Database:')} ${resolved.database.mode}${resolved.database.source ? ` (from ${resolved.database.source})` : ''}`);
428
+ // Only show database info if there are backend apps
429
+ const hasBackendApps = resolved.apps.some(a => a.type === 'backend' || a.name === 'api');
430
+ if (hasBackendApps && resolved.database.mode !== 'none') {
431
+ console.log('');
432
+ console.log(` ${chalk_1.default.bold('Database:')} ${resolved.database.mode}${resolved.database.source ? ` (from ${resolved.database.source})` : ''}`);
433
+ }
425
434
  if (Object.keys(resolved.env).length > 0) {
426
435
  console.log('');
427
436
  console.log(` ${chalk_1.default.bold('Environment:')}`);
@@ -960,6 +960,26 @@ exports.initCommand = new commander_1.Command('init')
960
960
  console.log(chalk_1.default.dim(' Or use env var: CORS_ORIGINS=*.genbox.dev'));
961
961
  console.log('');
962
962
  console.log(chalk_1.default.red(' Without this, you will see CORS errors when accessing genbox environments.'));
963
+ // OAuth Configuration Instructions
964
+ console.log('');
965
+ console.log(chalk_1.default.yellow('=== OAuth Provider Configuration ==='));
966
+ console.log(chalk_1.default.white('If your app uses OAuth (Google, GitHub, etc.), add *.genbox.dev to allowed domains:'));
967
+ console.log('');
968
+ console.log(chalk_1.default.dim(' Google OAuth (console.cloud.google.com):'));
969
+ console.log(chalk_1.default.cyan(' Authorized JavaScript origins:'));
970
+ console.log(chalk_1.default.cyan(' https://*.genbox.dev'));
971
+ console.log(chalk_1.default.cyan(' Authorized redirect URIs:'));
972
+ console.log(chalk_1.default.cyan(' https://*.genbox.dev/api/auth/callback/google'));
973
+ console.log(chalk_1.default.cyan(' https://*.genbox.dev/auth/google/callback'));
974
+ console.log('');
975
+ console.log(chalk_1.default.dim(' GitHub OAuth (github.com/settings/developers):'));
976
+ console.log(chalk_1.default.cyan(' Authorization callback URL:'));
977
+ console.log(chalk_1.default.cyan(' https://*.genbox.dev/api/auth/callback/github'));
978
+ console.log('');
979
+ console.log(chalk_1.default.dim(' Other providers (Auth0, Clerk, etc.):'));
980
+ console.log(chalk_1.default.cyan(' Add *.genbox.dev to allowed callback URLs/origins'));
981
+ console.log('');
982
+ console.log(chalk_1.default.red(' Without this, OAuth flows will fail in genbox environments.'));
963
983
  }
964
984
  // Next steps
965
985
  console.log('');
@@ -967,14 +987,16 @@ exports.initCommand = new commander_1.Command('init')
967
987
  console.log(chalk_1.default.dim(` 1. Review and edit ${CONFIG_FILENAME}`));
968
988
  if (hasBackendApps && hasFrontendApps) {
969
989
  console.log(chalk_1.default.yellow(` 2. Add .genbox.dev to your backend CORS configuration`));
970
- console.log(chalk_1.default.dim(` 3. Update ${ENV_FILENAME} to use API URL variables where needed`));
971
- console.log(chalk_1.default.dim(` 4. Run 'genbox profiles' to see available profiles`));
972
- console.log(chalk_1.default.dim(` 5. Run 'genbox create <name> --profile <profile>' to create an environment`));
990
+ console.log(chalk_1.default.yellow(` 3. Add *.genbox.dev to OAuth providers (Google, GitHub, etc.) if using auth`));
991
+ console.log(chalk_1.default.dim(` 4. Update ${ENV_FILENAME} to use API URL variables where needed`));
992
+ console.log(chalk_1.default.dim(` 5. Run 'genbox profiles' to see available profiles`));
993
+ console.log(chalk_1.default.dim(` 6. Run 'genbox create <name> --profile <profile>' to create an environment`));
973
994
  }
974
995
  else {
975
996
  console.log(chalk_1.default.dim(` 2. Update ${ENV_FILENAME} to use API URL variables where needed`));
976
- console.log(chalk_1.default.dim(` 3. Run 'genbox profiles' to see available profiles`));
977
- console.log(chalk_1.default.dim(` 4. Run 'genbox create <name> --profile <profile>' to create an environment`));
997
+ console.log(chalk_1.default.dim(` 3. Add *.genbox.dev to OAuth providers if using auth`));
998
+ console.log(chalk_1.default.dim(` 4. Run 'genbox profiles' to see available profiles`));
999
+ console.log(chalk_1.default.dim(` 5. Run 'genbox create <name> --profile <profile>' to create an environment`));
978
1000
  }
979
1001
  }
980
1002
  catch (error) {
@@ -71,7 +71,8 @@ exports.migrateCommand = new commander_1.Command('migrate')
71
71
  const configLoader = new config_loader_1.ConfigLoader();
72
72
  const loadResult = await configLoader.load(cwd);
73
73
  if (!loadResult.found || !loadResult.config) {
74
- console.log(chalk_1.default.red('No genbox.yaml found. Nothing to migrate.'));
74
+ console.log(chalk_1.default.red('Not a genbox project'));
75
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
75
76
  process.exit(1);
76
77
  }
77
78
  const config = loadResult.config;
@@ -213,7 +214,8 @@ exports.deprecationsCommand = new commander_1.Command('deprecations')
213
214
  const configLoader = new config_loader_1.ConfigLoader();
214
215
  const loadResult = await configLoader.load(cwd);
215
216
  if (!loadResult.found || !loadResult.config) {
216
- console.log(chalk_1.default.red('No genbox.yaml found.'));
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.'));
217
219
  process.exit(1);
218
220
  }
219
221
  const deprecations = (0, migration_1.checkDeprecations)(loadResult.config);
@@ -53,8 +53,9 @@ exports.profilesCommand = new commander_1.Command('profiles')
53
53
  const configLoader = new config_loader_1.ConfigLoader();
54
54
  const loadResult = await configLoader.load();
55
55
  if (!loadResult.config) {
56
- console.log(chalk_1.default.yellow('No genbox.yaml found'));
57
- console.log(chalk_1.default.dim('Run "genbox init" to create a configuration'));
56
+ console.log(chalk_1.default.red('Not a genbox project'));
57
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
58
+ console.log(chalk_1.default.dim('Run "genbox init" to initialize a new project.'));
58
59
  return;
59
60
  }
60
61
  const version = (0, schema_v4_1.getConfigVersion)(loadResult.config);
@@ -113,12 +114,13 @@ exports.profilesCommand
113
114
  const configLoader = new config_loader_1.ConfigLoader();
114
115
  const loadResult = await configLoader.load();
115
116
  if (!loadResult.config) {
116
- console.log(chalk_1.default.yellow('No genbox.yaml found'));
117
+ console.log(chalk_1.default.red('Not a genbox project'));
118
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
117
119
  return;
118
120
  }
119
121
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
120
122
  if (configVersion === 'unknown') {
121
- console.log(chalk_1.default.yellow('Unknown config version'));
123
+ console.log(chalk_1.default.red('Unknown config version'));
122
124
  return;
123
125
  }
124
126
  const config = loadResult.config;
@@ -196,12 +198,13 @@ exports.profilesCommand
196
198
  const configLoader = new config_loader_1.ConfigLoader();
197
199
  const loadResult = await configLoader.load();
198
200
  if (!loadResult.config) {
199
- console.log(chalk_1.default.yellow('No genbox.yaml found'));
201
+ console.log(chalk_1.default.red('Not a genbox project'));
202
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
200
203
  return;
201
204
  }
202
205
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
203
206
  if (configVersion === 'unknown') {
204
- console.log(chalk_1.default.yellow('Unknown config version'));
207
+ console.log(chalk_1.default.red('Unknown config version'));
205
208
  return;
206
209
  }
207
210
  const config = loadResult.config;
@@ -318,12 +321,13 @@ exports.profilesCommand
318
321
  const configLoader = new config_loader_1.ConfigLoader();
319
322
  const loadResult = await configLoader.load();
320
323
  if (!loadResult.config) {
321
- console.log(chalk_1.default.yellow('No genbox.yaml found'));
324
+ console.log(chalk_1.default.red('Not a genbox project'));
325
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
322
326
  return;
323
327
  }
324
328
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
325
329
  if (configVersion === 'unknown') {
326
- console.log(chalk_1.default.yellow('Unknown config version'));
330
+ console.log(chalk_1.default.red('Unknown config version'));
327
331
  return;
328
332
  }
329
333
  const config = loadResult.config;
@@ -463,9 +463,15 @@ exports.rebuildCommand = new commander_1.Command('rebuild')
463
463
  // Load configuration
464
464
  const configLoader = new config_loader_1.ConfigLoader();
465
465
  const loadResult = await configLoader.load();
466
+ if (!loadResult.config) {
467
+ console.log(chalk_1.default.red('Not a genbox project'));
468
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
469
+ console.log(chalk_1.default.dim('Run "genbox init" to initialize a new project.'));
470
+ return;
471
+ }
466
472
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
467
- if (!loadResult.config || configVersion === 'unknown') {
468
- console.error(chalk_1.default.red('No valid genbox.yaml configuration found'));
473
+ if (configVersion === 'unknown') {
474
+ console.log(chalk_1.default.red('Unknown config version'));
469
475
  return;
470
476
  }
471
477
  const config = loadResult.config;
@@ -77,7 +77,9 @@ exports.resolveCommand = new commander_1.Command('resolve')
77
77
  const configLoader = new config_loader_1.ConfigLoader();
78
78
  const loadResult = await configLoader.load(cwd);
79
79
  if (!loadResult.found || !loadResult.config) {
80
- console.log(chalk_1.default.red('No genbox.yaml found. Run "genbox init" first.'));
80
+ console.log(chalk_1.default.red('Not a genbox project'));
81
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
82
+ console.log(chalk_1.default.dim('Run "genbox init" to initialize a new project.'));
81
83
  process.exit(1);
82
84
  }
83
85
  let config = loadResult.config;
@@ -153,7 +153,7 @@ async function validateGenboxConfig(cwd) {
153
153
  if (!loadResult.found || !loadResult.config) {
154
154
  errors.push({
155
155
  path: 'genbox.yaml',
156
- message: 'No genbox.yaml found. Run "genbox init" first.',
156
+ message: 'Not a genbox project. No genbox.yaml found in current directory.',
157
157
  severity: 'error',
158
158
  });
159
159
  return { valid: false, errors, warnings };
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  /**
3
- * Multi-Level Configuration Loader
3
+ * Configuration Loader
4
4
  *
5
- * Resolution order (highest priority first):
6
- * 1. CLI flags
7
- * 2. User profiles (~/.genbox/profiles.yaml)
8
- * 3. Project config (./genbox.yaml)
9
- * 4. Workspace config (../genbox.yaml)
10
- * 5. User defaults (~/.genbox/config.json)
5
+ * Loads genbox.yaml from the CURRENT directory only.
6
+ * No parent directory lookup - each project is self-contained.
7
+ *
8
+ * Additional sources (merged with project config):
9
+ * - User profiles (~/.genbox/profiles.yaml)
10
+ * - User defaults (~/.genbox/config.json)
11
11
  */
12
12
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
13
  if (k2 === undefined) k2 = k;
@@ -92,21 +92,13 @@ class ConfigLoader {
92
92
  async load(cwd = process.cwd()) {
93
93
  const sources = [];
94
94
  const warnings = [];
95
- // 1. Find and load workspace config (parent directories)
96
- const workspaceConfig = this.findWorkspaceConfig(cwd);
97
- if (workspaceConfig) {
98
- sources.push(workspaceConfig);
99
- }
100
- // 2. Load project config (current directory or git root)
95
+ // Load project config from current directory ONLY
101
96
  const projectConfig = this.loadProjectConfig(cwd);
102
97
  if (projectConfig) {
103
98
  sources.push(projectConfig);
104
99
  }
105
- // 3. Load user config
100
+ // Load user config (for user-level defaults and profiles)
106
101
  const userConfig = this.loadUserConfig();
107
- // Determine if this is a workspace setup
108
- const isWorkspace = workspaceConfig !== null &&
109
- (projectConfig === null || workspaceConfig.path !== projectConfig.path);
110
102
  // Merge configurations
111
103
  const mergedConfig = this.mergeConfigs(sources, userConfig);
112
104
  // Validate
@@ -115,56 +107,17 @@ class ConfigLoader {
115
107
  warnings.push(...validation.errors.map(e => e.message));
116
108
  }
117
109
  warnings.push(...validation.warnings.map(w => w.message));
118
- // Determine root directory
119
- const root = workspaceConfig?.path
120
- ? path.dirname(workspaceConfig.path)
121
- : projectConfig?.path
122
- ? path.dirname(projectConfig.path)
123
- : cwd;
110
+ // Root is current directory
111
+ const root = projectConfig?.path ? path.dirname(projectConfig.path) : cwd;
124
112
  return {
125
113
  found: sources.length > 0,
126
114
  config: sources.length > 0 ? mergedConfig : null,
127
115
  sources,
128
116
  warnings,
129
- isWorkspace,
117
+ isWorkspace: false,
130
118
  root,
131
119
  };
132
120
  }
133
- /**
134
- * Find workspace config by searching parent directories
135
- */
136
- findWorkspaceConfig(startDir) {
137
- let currentDir = path.resolve(startDir);
138
- const root = path.parse(currentDir).root;
139
- // Go up to 5 levels max
140
- for (let i = 0; i < 5; i++) {
141
- const parentDir = path.dirname(currentDir);
142
- // Stop at filesystem root
143
- if (parentDir === currentDir || parentDir === root) {
144
- break;
145
- }
146
- const configPath = path.join(parentDir, CONFIG_FILENAME);
147
- if (fs.existsSync(configPath)) {
148
- try {
149
- const content = fs.readFileSync(configPath, 'utf8');
150
- const config = yaml.load(content);
151
- // Check if it's a workspace config (has structure: 'workspace' or multiple repos)
152
- if (config.project?.structure === 'workspace' || config.repos) {
153
- return {
154
- type: 'workspace',
155
- path: configPath,
156
- config,
157
- };
158
- }
159
- }
160
- catch (err) {
161
- console.warn(`Warning: Could not parse ${configPath}:`, err);
162
- }
163
- }
164
- currentDir = parentDir;
165
- }
166
- return null;
167
- }
168
121
  /**
169
122
  * Load project config from current directory
170
123
  */
@@ -279,6 +232,10 @@ class ConfigLoader {
279
232
  }
280
233
  /**
281
234
  * Deep merge objects
235
+ *
236
+ * Special handling:
237
+ * - 'version' field is never overwritten (prevents v4 -> v1 downgrades)
238
+ * - Empty objects don't overwrite non-empty objects
282
239
  */
283
240
  deepMerge(target, source) {
284
241
  for (const key of Object.keys(source)) {
@@ -286,6 +243,21 @@ class ConfigLoader {
286
243
  const targetValue = target[key];
287
244
  if (sourceValue === undefined)
288
245
  continue;
246
+ // Never overwrite version field - workspace config takes precedence
247
+ if (key === 'version' && targetValue !== undefined)
248
+ continue;
249
+ // Don't overwrite non-empty objects with empty objects
250
+ if (typeof sourceValue === 'object' &&
251
+ sourceValue !== null &&
252
+ !Array.isArray(sourceValue) &&
253
+ Object.keys(sourceValue).length === 0 &&
254
+ typeof targetValue === 'object' &&
255
+ targetValue !== null &&
256
+ !Array.isArray(targetValue) &&
257
+ Object.keys(targetValue).length > 0) {
258
+ // Skip - don't let empty {} overwrite populated object
259
+ continue;
260
+ }
289
261
  if (typeof sourceValue === 'object' &&
290
262
  sourceValue !== null &&
291
263
  !Array.isArray(sourceValue) &&
@@ -520,33 +520,37 @@ class ProfileResolver {
520
520
  }
521
521
  }
522
522
  }
523
- // Add database URL
524
- if (database.mode === 'local') {
525
- env['MONGODB_URI'] = `mongodb://localhost:27017/${config.project.name}`;
526
- }
527
- else if (database.url) {
528
- env['MONGODB_URI'] = database.url;
529
- }
530
- // Add infrastructure URLs
531
- for (const infra of infrastructure) {
532
- if (infra.mode === 'local') {
533
- switch (infra.type) {
534
- case 'cache':
535
- env['REDIS_URL'] = `redis://localhost:${infra.port || 6379}`;
536
- break;
537
- case 'queue':
538
- env['RABBITMQ_URL'] = `amqp://localhost:${infra.port || 5672}`;
539
- break;
540
- }
523
+ // Only add database/infrastructure URLs if there are backend apps that need them
524
+ const hasBackendApps = apps.some(a => a.type === 'backend' || a.name === 'api');
525
+ if (hasBackendApps) {
526
+ // Add database URL
527
+ if (database.mode === 'local') {
528
+ env['MONGODB_URI'] = `mongodb://localhost:27017/${config.project.name}`;
541
529
  }
542
- else if (infra.url) {
543
- switch (infra.type) {
544
- case 'cache':
545
- env['REDIS_URL'] = infra.url;
546
- break;
547
- case 'queue':
548
- env['RABBITMQ_URL'] = infra.url;
549
- break;
530
+ else if (database.url) {
531
+ env['MONGODB_URI'] = database.url;
532
+ }
533
+ // Add infrastructure URLs
534
+ for (const infra of infrastructure) {
535
+ if (infra.mode === 'local') {
536
+ switch (infra.type) {
537
+ case 'cache':
538
+ env['REDIS_URL'] = `redis://localhost:${infra.port || 6379}`;
539
+ break;
540
+ case 'queue':
541
+ env['RABBITMQ_URL'] = `amqp://localhost:${infra.port || 5672}`;
542
+ break;
543
+ }
544
+ }
545
+ else if (infra.url) {
546
+ switch (infra.type) {
547
+ case 'cache':
548
+ env['REDIS_URL'] = infra.url;
549
+ break;
550
+ case 'queue':
551
+ env['RABBITMQ_URL'] = infra.url;
552
+ break;
553
+ }
550
554
  }
551
555
  }
552
556
  }
@@ -2,29 +2,95 @@
2
2
  /**
3
3
  * Random name generator for Genbox environments
4
4
  * Generates memorable names using adjective-noun combinations
5
+ * ~150 adjectives x ~150 nouns = ~22,500 unique combinations
5
6
  */
6
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.TOTAL_COMBINATIONS = void 0;
7
9
  exports.generateRandomName = generateRandomName;
8
10
  exports.generateNameSuggestions = generateNameSuggestions;
9
11
  const adjectives = [
10
- 'swift', 'calm', 'bold', 'keen', 'warm',
11
- 'cool', 'bright', 'quick', 'smart', 'fresh',
12
- 'wild', 'free', 'pure', 'soft', 'sharp',
13
- 'kind', 'brave', 'proud', 'fair', 'wise',
14
- 'gold', 'silver', 'azure', 'coral', 'amber',
15
- 'jade', 'ruby', 'pearl', 'ivory', 'onyx',
16
- 'misty', 'sunny', 'windy', 'rainy', 'snowy',
17
- 'lucky', 'happy', 'merry', 'jolly', 'lively',
12
+ // Colors & Shades
13
+ 'red', 'blue', 'green', 'gold', 'silver', 'bronze', 'copper', 'amber',
14
+ 'coral', 'ivory', 'onyx', 'jade', 'ruby', 'pearl', 'azure', 'cobalt',
15
+ 'crimson', 'scarlet', 'violet', 'indigo', 'teal', 'cyan', 'magenta',
16
+ 'golden', 'rusty', 'dusty', 'misty', 'frosty', 'snowy', 'icy',
17
+ // Weather & Nature
18
+ 'sunny', 'windy', 'rainy', 'stormy', 'cloudy', 'foggy', 'hazy',
19
+ 'balmy', 'breezy', 'dewy', 'humid', 'arid', 'polar', 'tropic',
20
+ // Temperature & Light
21
+ 'warm', 'cool', 'cold', 'hot', 'bright', 'dim', 'dark', 'light',
22
+ 'glowing', 'shiny', 'glossy', 'matte', 'vivid', 'pale', 'deep',
23
+ // Size & Shape
24
+ 'tiny', 'small', 'big', 'giant', 'vast', 'wide', 'narrow', 'tall',
25
+ 'short', 'long', 'round', 'flat', 'curved', 'steep', 'slim', 'broad',
26
+ // Speed & Movement
27
+ 'swift', 'quick', 'fast', 'rapid', 'slow', 'steady', 'still', 'calm',
28
+ 'wild', 'fierce', 'gentle', 'smooth', 'rough', 'bumpy', 'fluid',
29
+ // Character & Mood
30
+ 'bold', 'brave', 'keen', 'wise', 'smart', 'clever', 'witty', 'sharp',
31
+ 'kind', 'fair', 'proud', 'humble', 'noble', 'royal', 'grand', 'prime',
32
+ 'happy', 'merry', 'jolly', 'lively', 'peppy', 'zesty', 'perky', 'chirpy',
33
+ 'lucky', 'plucky', 'spunky', 'funky', 'groovy', 'snappy', 'zippy',
34
+ // Quality & State
35
+ 'fresh', 'crisp', 'clean', 'pure', 'clear', 'free', 'open', 'safe',
36
+ 'solid', 'stable', 'sturdy', 'strong', 'tough', 'hardy', 'robust',
37
+ 'sleek', 'slick', 'neat', 'tidy', 'trim', 'lean', 'fit', 'agile',
38
+ // Time & Age
39
+ 'new', 'young', 'early', 'late', 'ancient', 'modern', 'future', 'prime',
40
+ 'fresh', 'ripe', 'mature', 'seasoned', 'timely', 'eternal', 'lasting',
41
+ // Sound & Texture
42
+ 'silent', 'quiet', 'loud', 'sonic', 'soft', 'hard', 'dense', 'hollow',
43
+ 'fuzzy', 'fluffy', 'silky', 'velvet', 'smooth', 'grainy', 'sandy',
44
+ // Taste & Smell (abstract)
45
+ 'sweet', 'tangy', 'spicy', 'minty', 'zesty', 'savory', 'rich', 'mellow',
46
+ // Position & Direction
47
+ 'upper', 'lower', 'inner', 'outer', 'central', 'polar', 'lateral',
48
+ 'north', 'south', 'east', 'west', 'coastal', 'alpine', 'lunar', 'solar',
18
49
  ];
19
50
  const nouns = [
20
- 'fox', 'owl', 'wolf', 'hawk', 'bear',
21
- 'deer', 'hare', 'lynx', 'seal', 'dove',
22
- 'oak', 'pine', 'elm', 'ash', 'birch',
23
- 'maple', 'cedar', 'willow', 'sage', 'fern',
24
- 'river', 'lake', 'creek', 'brook', 'pond',
25
- 'peak', 'vale', 'ridge', 'cliff', 'mesa',
26
- 'moon', 'star', 'sun', 'cloud', 'wind',
27
- 'storm', 'frost', 'dawn', 'dusk', 'wave',
51
+ // Animals - Land
52
+ 'fox', 'wolf', 'bear', 'deer', 'elk', 'moose', 'hare', 'rabbit',
53
+ 'lynx', 'puma', 'tiger', 'lion', 'panther', 'jaguar', 'leopard',
54
+ 'horse', 'zebra', 'buffalo', 'bison', 'ox', 'ram', 'goat', 'sheep',
55
+ 'badger', 'otter', 'beaver', 'marten', 'ferret', 'mink', 'stoat',
56
+ 'squirrel', 'chipmunk', 'hedgehog', 'porcupine', 'armadillo',
57
+ // Animals - Birds
58
+ 'owl', 'hawk', 'eagle', 'falcon', 'raven', 'crow', 'jay', 'finch',
59
+ 'robin', 'sparrow', 'wren', 'lark', 'dove', 'pigeon', 'swan', 'crane',
60
+ 'heron', 'stork', 'pelican', 'albatross', 'condor', 'vulture', 'kite',
61
+ 'osprey', 'harrier', 'kestrel', 'merlin', 'shrike', 'oriole', 'thrush',
62
+ // Animals - Water
63
+ 'seal', 'walrus', 'whale', 'dolphin', 'shark', 'orca', 'salmon', 'trout',
64
+ 'bass', 'pike', 'perch', 'carp', 'tuna', 'marlin', 'barracuda',
65
+ 'squid', 'octopus', 'crab', 'lobster', 'shrimp', 'oyster', 'clam',
66
+ // Trees & Plants
67
+ 'oak', 'pine', 'elm', 'ash', 'birch', 'maple', 'cedar', 'spruce',
68
+ 'willow', 'poplar', 'aspen', 'alder', 'beech', 'cherry', 'walnut',
69
+ 'cypress', 'juniper', 'hemlock', 'sequoia', 'redwood', 'mahogany',
70
+ 'sage', 'fern', 'moss', 'ivy', 'vine', 'reed', 'bamboo', 'palm',
71
+ 'cactus', 'lotus', 'lily', 'rose', 'tulip', 'orchid', 'iris', 'daisy',
72
+ // Landforms & Geography
73
+ 'peak', 'summit', 'ridge', 'cliff', 'bluff', 'mesa', 'butte', 'dune',
74
+ 'vale', 'glen', 'dale', 'dell', 'gorge', 'canyon', 'ravine', 'gulch',
75
+ 'plain', 'prairie', 'meadow', 'field', 'grove', 'forest', 'jungle',
76
+ 'island', 'atoll', 'reef', 'cape', 'bay', 'cove', 'inlet', 'fjord',
77
+ // Water Bodies
78
+ 'river', 'stream', 'creek', 'brook', 'spring', 'falls', 'rapids',
79
+ 'lake', 'pond', 'pool', 'lagoon', 'marsh', 'swamp', 'delta', 'estuary',
80
+ 'ocean', 'sea', 'gulf', 'strait', 'channel', 'tide', 'wave', 'surf',
81
+ // Sky & Space
82
+ 'moon', 'sun', 'star', 'comet', 'meteor', 'nova', 'nebula', 'quasar',
83
+ 'cloud', 'storm', 'rain', 'snow', 'frost', 'hail', 'mist', 'fog',
84
+ 'wind', 'gale', 'breeze', 'gust', 'draft', 'zephyr', 'monsoon',
85
+ 'dawn', 'dusk', 'noon', 'night', 'twilight', 'aurora', 'eclipse',
86
+ // Stones & Minerals
87
+ 'stone', 'rock', 'boulder', 'pebble', 'gravel', 'sand', 'clay', 'chalk',
88
+ 'crystal', 'gem', 'diamond', 'emerald', 'sapphire', 'topaz', 'opal',
89
+ 'granite', 'marble', 'slate', 'quartz', 'flint', 'obsidian', 'basalt',
90
+ // Misc Nature
91
+ 'flame', 'ember', 'spark', 'blaze', 'torch', 'beacon', 'flare',
92
+ 'shadow', 'shade', 'glint', 'gleam', 'shimmer', 'glimmer', 'flash',
93
+ 'echo', 'whisper', 'murmur', 'rustle', 'ripple', 'rumble', 'thunder',
28
94
  ];
29
95
  function randomElement(array) {
30
96
  return array[Math.floor(Math.random() * array.length)];
@@ -39,12 +105,20 @@ function generateRandomName() {
39
105
  return `${adjective}-${noun}`;
40
106
  }
41
107
  /**
42
- * Generate multiple random name suggestions
108
+ * Generate multiple unique random name suggestions
43
109
  */
44
110
  function generateNameSuggestions(count = 3) {
45
111
  const names = new Set();
46
- while (names.size < count) {
112
+ // Prevent infinite loop if requesting more than possible combinations
113
+ const maxAttempts = count * 10;
114
+ let attempts = 0;
115
+ while (names.size < count && attempts < maxAttempts) {
47
116
  names.add(generateRandomName());
117
+ attempts++;
48
118
  }
49
119
  return Array.from(names);
50
120
  }
121
+ /**
122
+ * Total possible unique combinations
123
+ */
124
+ exports.TOTAL_COMBINATIONS = adjectives.length * nouns.length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.24",
3
+ "version": "1.0.26",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {