genbox 1.0.83 → 1.0.84

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.
@@ -728,7 +728,9 @@ function buildPayload(resolved, config, publicKey, privateKey, configLoader) {
728
728
  const files = [];
729
729
  // Track env files to move in setup script (staging approach to avoid blocking git clone)
730
730
  const envFilesToMove = [];
731
- // Send .env.genbox content to server for each app
731
+ // Send .env.genbox content to server for processing
732
+ // OPTIMIZATION: Instead of duplicating GLOBAL section for each app,
733
+ // send ONE .env.genbox file and let server extract app-specific content
732
734
  const envGenboxPath = path.join(process.cwd(), '.env.genbox');
733
735
  if (fs.existsSync(envGenboxPath)) {
734
736
  const rawEnvContent = fs.readFileSync(envGenboxPath, 'utf-8');
@@ -751,42 +753,77 @@ function buildPayload(resolved, config, publicKey, privateKey, configLoader) {
751
753
  if (connectTo && Object.keys(serviceUrlMap).length > 0) {
752
754
  console.log(chalk_1.default.dim(` Using ${connectTo} URLs for variable expansion`));
753
755
  }
754
- // Add env file for each app - filtered by selected apps only
755
- for (const app of resolved.apps) {
756
- const appPath = config.apps[app.name]?.path || app.name;
757
- const repoPath = resolved.repos.find(r => r.name === app.name)?.path ||
758
- (resolved.repos[0]?.path ? `${resolved.repos[0].path}/${appPath}` : `/home/dev/${config.project.name}/${appPath}`);
759
- // Check if this app has microservices (sections like api/gateway, api/auth)
760
- const servicesSections = Array.from(sections.keys()).filter(s => s.startsWith(`${app.name}/`));
761
- if (servicesSections.length > 0) {
762
- // App has microservices - create env file for each service
763
- for (const serviceSectionName of servicesSections) {
764
- const serviceName = serviceSectionName.split('/')[1];
765
- // Build service-specific env content (GLOBAL + service section)
766
- const serviceEnvContent = (0, utils_1.buildAppEnvContent)(sections, serviceSectionName, serviceUrlMap);
767
- const stagingName = `${app.name}-${serviceName}.env`;
768
- const targetPath = `${repoPath}/apps/${serviceName}/.env`;
756
+ // For projects with many apps, send ONE processed .env file to avoid duplicating GLOBAL
757
+ // This significantly reduces cloud-init size (Hetzner has 32KB limit)
758
+ if (resolved.apps.length > 3) {
759
+ // Send single .env.genbox with expansions applied, let server split into app files
760
+ let expandedEnvContent = rawEnvContent;
761
+ for (const [varName, value] of Object.entries(serviceUrlMap)) {
762
+ const pattern = new RegExp(`\\$\\{${varName}\\}`, 'g');
763
+ expandedEnvContent = expandedEnvContent.replace(pattern, value);
764
+ }
765
+ files.push({
766
+ path: '/home/dev/.env.genbox',
767
+ content: expandedEnvContent,
768
+ permissions: '0644',
769
+ });
770
+ // Track which apps need .env files (server will process)
771
+ for (const app of resolved.apps) {
772
+ const appPath = config.apps[app.name]?.path || app.name;
773
+ const repoPath = resolved.repos.find(r => r.name === app.name)?.path ||
774
+ (resolved.repos[0]?.path ? `${resolved.repos[0].path}/${appPath}` : `/home/dev/${config.project.name}/${appPath}`);
775
+ const servicesSections = Array.from(sections.keys()).filter(s => s.startsWith(`${app.name}/`));
776
+ if (servicesSections.length > 0) {
777
+ for (const serviceSectionName of servicesSections) {
778
+ const serviceName = serviceSectionName.split('/')[1];
779
+ envFilesToMove.push({
780
+ stagingName: serviceSectionName, // e.g., "api/gateway" - server will parse
781
+ targetPath: `${repoPath}/apps/${serviceName}/.env`,
782
+ });
783
+ }
784
+ }
785
+ else {
786
+ envFilesToMove.push({
787
+ stagingName: app.name,
788
+ targetPath: `${repoPath}/.env`,
789
+ });
790
+ }
791
+ }
792
+ }
793
+ else {
794
+ // For small projects, use the original per-app approach (simpler)
795
+ for (const app of resolved.apps) {
796
+ const appPath = config.apps[app.name]?.path || app.name;
797
+ const repoPath = resolved.repos.find(r => r.name === app.name)?.path ||
798
+ (resolved.repos[0]?.path ? `${resolved.repos[0].path}/${appPath}` : `/home/dev/${config.project.name}/${appPath}`);
799
+ const servicesSections = Array.from(sections.keys()).filter(s => s.startsWith(`${app.name}/`));
800
+ if (servicesSections.length > 0) {
801
+ for (const serviceSectionName of servicesSections) {
802
+ const serviceName = serviceSectionName.split('/')[1];
803
+ const serviceEnvContent = (0, utils_1.buildAppEnvContent)(sections, serviceSectionName, serviceUrlMap);
804
+ const stagingName = `${app.name}-${serviceName}.env`;
805
+ const targetPath = `${repoPath}/apps/${serviceName}/.env`;
806
+ files.push({
807
+ path: `/home/dev/.env-staging/${stagingName}`,
808
+ content: serviceEnvContent,
809
+ permissions: '0644',
810
+ });
811
+ envFilesToMove.push({ stagingName, targetPath });
812
+ }
813
+ }
814
+ else {
815
+ const appEnvContent = (0, utils_1.buildAppEnvContent)(sections, app.name, serviceUrlMap);
769
816
  files.push({
770
- path: `/home/dev/.env-staging/${stagingName}`,
771
- content: serviceEnvContent,
817
+ path: `/home/dev/.env-staging/${app.name}.env`,
818
+ content: appEnvContent,
772
819
  permissions: '0644',
773
820
  });
774
- envFilesToMove.push({ stagingName, targetPath });
821
+ envFilesToMove.push({
822
+ stagingName: `${app.name}.env`,
823
+ targetPath: `${repoPath}/.env`,
824
+ });
775
825
  }
776
826
  }
777
- else {
778
- // Regular app - build app-specific env content (GLOBAL + app section)
779
- const appEnvContent = (0, utils_1.buildAppEnvContent)(sections, app.name, serviceUrlMap);
780
- files.push({
781
- path: `/home/dev/.env-staging/${app.name}.env`,
782
- content: appEnvContent,
783
- permissions: '0644',
784
- });
785
- envFilesToMove.push({
786
- stagingName: `${app.name}.env`,
787
- targetPath: `${repoPath}/.env`,
788
- });
789
- }
790
827
  }
791
828
  }
792
829
  // Add setup script if generated
@@ -870,9 +907,45 @@ function generateSetupScript(resolved, config, envFilesToMove = []) {
870
907
  'set -e',
871
908
  '',
872
909
  ];
873
- // Move .env files from staging to their correct locations
874
- // This runs after git clone has completed
875
- if (envFilesToMove.length > 0) {
910
+ // Check if we're using the optimized single-file approach (for projects with many apps)
911
+ // or the legacy per-app staging approach
912
+ const useOptimizedEnv = resolved.apps.length > 3;
913
+ if (useOptimizedEnv && envFilesToMove.length > 0) {
914
+ // OPTIMIZED: Parse single .env.genbox and create app-specific .env files
915
+ lines.push('# Process .env.genbox and create app-specific .env files');
916
+ lines.push('if [ -f "/home/dev/.env.genbox" ]; then');
917
+ lines.push(' echo "Processing .env.genbox for app-specific .env files..."');
918
+ lines.push('');
919
+ lines.push(' # Function to extract section content');
920
+ lines.push(' extract_section() {');
921
+ lines.push(' local section="$1"');
922
+ lines.push(' local file="$2"');
923
+ lines.push(' awk -v section="$section" \'');
924
+ lines.push(' BEGIN { in_global=0; in_section=0; }');
925
+ lines.push(' /^# === GLOBAL ===/ { in_global=1; next }');
926
+ lines.push(' /^# === [^=]+ ===/ {');
927
+ lines.push(' in_global=0;');
928
+ lines.push(' if ($0 ~ "# === "section" ===") { in_section=1 }');
929
+ lines.push(' else { in_section=0 }');
930
+ lines.push(' next');
931
+ lines.push(' }');
932
+ lines.push(' in_global || in_section { print }');
933
+ lines.push(' \' "$file" | grep -v "^$" | head -n -1');
934
+ lines.push(' }');
935
+ lines.push('');
936
+ for (const { stagingName, targetPath } of envFilesToMove) {
937
+ lines.push(` # Create .env for ${stagingName}`);
938
+ lines.push(` mkdir -p "$(dirname "${targetPath}")"`);
939
+ lines.push(` extract_section "${stagingName}" /home/dev/.env.genbox > "${targetPath}"`);
940
+ lines.push(` echo " Created ${targetPath}"`);
941
+ }
942
+ lines.push('');
943
+ lines.push(' rm -f /home/dev/.env.genbox');
944
+ lines.push('fi');
945
+ lines.push('');
946
+ }
947
+ else if (envFilesToMove.length > 0) {
948
+ // LEGACY: Move pre-staged .env files
876
949
  lines.push('# Move .env files from staging to app directories');
877
950
  for (const { stagingName, targetPath } of envFilesToMove) {
878
951
  lines.push(`if [ -f "/home/dev/.env-staging/${stagingName}" ]; then`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.83",
3
+ "version": "1.0.84",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {