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 +20 -4
- package/dist/commands/create.js +8 -0
- package/dist/commands/init.js +46 -21
- package/package.json +1 -1
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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) {
|
package/dist/commands/create.js
CHANGED
|
@@ -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,
|
package/dist/commands/init.js
CHANGED
|
@@ -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
|
-
|
|
1015
|
+
const definedEnvs = Object.keys(config.environments || {});
|
|
1016
|
+
return createProfilesFromScan(scan, definedEnvs);
|
|
1016
1017
|
}
|
|
1017
1018
|
async function createDefaultProfiles(scan, config) {
|
|
1018
|
-
|
|
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
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
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:
|
|
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 +
|
|
1059
|
-
if (frontendApps.length > 1) {
|
|
1060
|
-
profiles[
|
|
1061
|
-
description:
|
|
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:
|
|
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:
|
|
1099
|
+
mode: remoteEnv ? 'copy' : 'local',
|
|
1100
|
+
...(remoteEnv && { source: dbSource }),
|
|
1076
1101
|
},
|
|
1077
1102
|
};
|
|
1078
1103
|
}
|