genbox 1.0.26 → 1.0.27

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/dist/api.js CHANGED
@@ -49,10 +49,26 @@ async function fetchApi(endpoint, options = {}) {
49
49
  if (token) {
50
50
  headers['Authorization'] = `Bearer ${token}`;
51
51
  }
52
- const response = await fetch(url, {
53
- ...options,
54
- headers,
55
- });
52
+ let response;
53
+ try {
54
+ response = await fetch(url, {
55
+ ...options,
56
+ headers,
57
+ });
58
+ }
59
+ catch (error) {
60
+ // Handle network-level errors (DNS, connection refused, timeout, etc.)
61
+ if (error.cause?.code === 'ECONNREFUSED') {
62
+ throw new Error(`Cannot connect to Genbox API at ${API_URL}. Is the server running?`);
63
+ }
64
+ if (error.cause?.code === 'ENOTFOUND') {
65
+ throw new Error(`Cannot resolve Genbox API host. Check your internet connection.`);
66
+ }
67
+ if (error.message?.includes('fetch failed')) {
68
+ throw new Error(`Cannot connect to Genbox API at ${API_URL}. Check your internet connection or try again later.`);
69
+ }
70
+ throw new Error(`Network error: ${error.message}`);
71
+ }
56
72
  if (!response.ok) {
57
73
  // Handle authentication errors with a friendly message
58
74
  if (response.status === 401) {
@@ -763,6 +763,14 @@ function buildPayload(resolved, config, publicKey, privateKey, configLoader) {
763
763
  gitToken: envVars.GIT_TOKEN,
764
764
  envVars: resolved.env,
765
765
  apps: resolved.apps.map(a => a.name),
766
+ appConfigs: resolved.apps.map(a => ({
767
+ name: a.name,
768
+ path: a.path.startsWith('/') ? a.path : `${resolved.repos[0]?.path || '/home/dev'}/${a.path}`,
769
+ type: a.type,
770
+ port: a.port,
771
+ framework: a.framework,
772
+ commands: a.commands,
773
+ })),
766
774
  infrastructure: resolved.infrastructure.map(i => ({
767
775
  name: i.name,
768
776
  type: i.type,
@@ -1012,35 +1012,59 @@ exports.initCommand = new commander_1.Command('init')
1012
1012
  * Create default profiles (sync version for non-interactive mode)
1013
1013
  */
1014
1014
  function createDefaultProfilesSync(scan, config) {
1015
- return createProfilesFromScan(scan);
1015
+ const definedEnvs = Object.keys(config.environments || {});
1016
+ return createProfilesFromScan(scan, definedEnvs);
1016
1017
  }
1017
1018
  async function createDefaultProfiles(scan, config) {
1018
- return createProfilesFromScan(scan);
1019
+ // Get defined environments to use in profiles
1020
+ const definedEnvs = Object.keys(config.environments || {});
1021
+ return createProfilesFromScan(scan, definedEnvs);
1019
1022
  }
1020
- function createProfilesFromScan(scan) {
1023
+ function createProfilesFromScan(scan, definedEnvironments = []) {
1021
1024
  const profiles = {};
1022
1025
  const frontendApps = scan.apps.filter(a => a.type === 'frontend');
1023
1026
  const backendApps = scan.apps.filter(a => a.type === 'backend' || a.type === 'api');
1024
1027
  const hasApi = scan.apps.some(a => a.name === 'api' || a.type === 'backend');
1028
+ // Determine which environment to use for remote connections
1029
+ // Priority: staging > production > first defined
1030
+ const remoteEnv = definedEnvironments.includes('staging')
1031
+ ? 'staging'
1032
+ : definedEnvironments.includes('production')
1033
+ ? 'production'
1034
+ : definedEnvironments[0];
1025
1035
  // Quick UI profiles for each frontend (v4: use default_connection instead of connect_to)
1026
- for (const frontend of frontendApps.slice(0, 3)) {
1027
- profiles[`${frontend.name}-quick`] = {
1028
- description: `${frontend.name} only, connected to staging`,
1029
- size: 'small',
1030
- apps: [frontend.name],
1031
- default_connection: 'staging',
1032
- };
1036
+ // Only create if we have a remote environment defined
1037
+ if (remoteEnv) {
1038
+ for (const frontend of frontendApps.slice(0, 3)) {
1039
+ profiles[`${frontend.name}-quick`] = {
1040
+ description: `${frontend.name} only, connected to ${remoteEnv}`,
1041
+ size: 'small',
1042
+ apps: [frontend.name],
1043
+ default_connection: remoteEnv,
1044
+ };
1045
+ }
1046
+ }
1047
+ else {
1048
+ // No remote environment - create local-only profiles
1049
+ for (const frontend of frontendApps.slice(0, 3)) {
1050
+ profiles[`${frontend.name}-local`] = {
1051
+ description: `${frontend.name} with local API`,
1052
+ size: 'medium',
1053
+ apps: [frontend.name, ...(hasApi ? ['api'] : [])],
1054
+ };
1055
+ }
1033
1056
  }
1034
- // Full local development
1057
+ // Full local development (with DB copy from available environment)
1035
1058
  if (hasApi && frontendApps.length > 0) {
1036
1059
  const primaryFrontend = frontendApps[0];
1060
+ const dbSource = remoteEnv || 'staging'; // Use defined env or default
1037
1061
  profiles[`${primaryFrontend.name}-full`] = {
1038
1062
  description: `${primaryFrontend.name} + local API + DB copy`,
1039
1063
  size: 'large',
1040
1064
  apps: [primaryFrontend.name, 'api'],
1041
1065
  database: {
1042
- mode: 'copy',
1043
- source: 'staging',
1066
+ mode: remoteEnv ? 'copy' : 'local', // Only copy if we have a source
1067
+ ...(remoteEnv && { source: dbSource }),
1044
1068
  },
1045
1069
  };
1046
1070
  }
@@ -1055,24 +1079,25 @@ function createProfilesFromScan(scan) {
1055
1079
  },
1056
1080
  };
1057
1081
  }
1058
- // All frontends + staging (v4: use default_connection)
1059
- if (frontendApps.length > 1) {
1060
- profiles['frontends-staging'] = {
1061
- description: 'All frontends with staging backend',
1082
+ // All frontends + remote backend (only if remote env defined)
1083
+ if (frontendApps.length > 1 && remoteEnv) {
1084
+ profiles[`frontends-${remoteEnv}`] = {
1085
+ description: `All frontends with ${remoteEnv} backend`,
1062
1086
  size: 'medium',
1063
1087
  apps: frontendApps.map(a => a.name),
1064
- default_connection: 'staging',
1088
+ default_connection: remoteEnv,
1065
1089
  };
1066
1090
  }
1067
1091
  // Full stack
1068
1092
  if (scan.apps.length > 1) {
1093
+ const dbSource = remoteEnv || 'staging';
1069
1094
  profiles['full-stack'] = {
1070
- description: 'Everything local with DB copy',
1095
+ description: 'Everything local' + (remoteEnv ? ' with DB copy' : ''),
1071
1096
  size: 'xl',
1072
1097
  apps: scan.apps.filter(a => a.type !== 'library').map(a => a.name),
1073
1098
  database: {
1074
- mode: 'copy',
1075
- source: 'staging',
1099
+ mode: remoteEnv ? 'copy' : 'local',
1100
+ ...(remoteEnv && { source: dbSource }),
1076
1101
  },
1077
1102
  };
1078
1103
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {