Commit 8df2a3a6 authored by Andreas Düren's avatar Andreas Düren
Browse files

Add browser compatibility fixes for URL constructor and Node.js functions

parent 192070ff
Loading
Loading
Loading
Loading
+123 −4
Original line number Diff line number Diff line
@@ -577,9 +577,14 @@ window.ENTE_CONFIG = {
    PUBLIC_ALBUMS_URL: 'https://${CLOUDRON_APP_FQDN}/public'
};

// Next.js environment variables - add NEXT_PUBLIC_BASE_URL to help with URL construction
// Add Node.js polyfills for browser environment
window.process = window.process || {};
window.process.env = window.process.env || {};
window.process.nextTick = window.process.nextTick || function(fn) { setTimeout(fn, 0); };
window.process.browser = true;
window.Buffer = window.Buffer || (function() { return { isBuffer: function() { return false; } }; })();

// Next.js environment variables
window.process.env.NEXT_PUBLIC_BASE_URL = 'https://${CLOUDRON_APP_FQDN}';
window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/api';
window.process.env.NEXT_PUBLIC_ENTE_PUBLIC_ALBUMS_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/public';
@@ -587,7 +592,8 @@ window.process.env.NEXT_PUBLIC_REACT_APP_ENTE_ENDPOINT = 'https://${CLOUDRON_APP
window.process.env.REACT_APP_ENTE_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/api';

// Add logging to help with debugging
console.log('Ente runtime config loaded from runtime-config.js');
console.log('Ente runtime config loaded from runtime-config.js with polyfills');
console.log('process.nextTick available:', !!window.process.nextTick);
console.log('BASE_URL:', window.process.env.NEXT_PUBLIC_BASE_URL);
console.log('API_URL (final):', window.ENTE_CONFIG.API_URL);
console.log('PUBLIC_ALBUMS_URL (final):', window.ENTE_CONFIG.PUBLIC_ALBUMS_URL);
@@ -596,6 +602,74 @@ EOF

chmod 644 /app/data/web/runtime-config.js

# Create a custom URL patch file to fix the URL constructor error
echo "==> Creating URL and SRP patch file"
cat << EOF > /app/data/web/ente-patches.js
(function() {
    // Save original URL constructor
    const originalURL = window.URL;
    
    // Create a patched URL constructor
    window.URL = function(url, base) {
        try {
            if (!url) {
                throw new Error('Invalid URL: URL cannot be empty');
            }
            
            // Fix relative URLs
            if (!url.match(/^https?:\/\//i)) {
                if (url.startsWith('/')) {
                    url = window.location.origin + url;
                } else {
                    url = window.location.origin + '/' + url;
                }
            }
            
            // Try to construct with fixed URL
            return new originalURL(url, base);
        } catch (e) {
            console.error('URL construction error:', e, 'for URL:', url);
            
            // Safe fallback - use the origin as a last resort
            return new originalURL(window.location.origin);
        }
    };
    
    // Patch the SRP implementation for browser compatibility
    if (window.process) {
        // Add any missing process methods
        window.process.nextTick = window.process.nextTick || function(fn) { 
            setTimeout(fn, 0); 
        };
    }
    
    // Add Buffer polyfill if needed
    if (!window.Buffer) {
        window.Buffer = {
            from: function(data, encoding) {
                if (typeof data === 'string') {
                    if (encoding === 'hex') {
                        return { 
                            data: data,
                            toString: function() { return data; }
                        };
                    }
                    return { 
                        data: data,
                        toString: function() { return data; }
                    };
                }
                return { data: data };
            },
            isBuffer: function() { return false; },
            alloc: function() { return {}; }
        };
    }
    
    console.log('Ente URL and SRP patches applied successfully');
})();
EOF

# Create the static HTML files with scripts pre-injected
for app_dir in photos accounts auth cast; do
    # Create directory for our modified files
@@ -613,7 +687,7 @@ for app_dir in photos accounts auth cast; do
        fi
        
        # Insert config scripts right after the opening head tag
        sed -i 's/<head>/<head>\n    <script src="\/config.js" type="text\/javascript"><\/script>\n    <script src="\/runtime-config.js" type="text\/javascript"><\/script>/' "/app/data/web/$app_dir/index.html"
        sed -i 's/<head>/<head>\n    <script src="\/polyfills.js" type="text\/javascript"><\/script>\n    <script src="\/config.js" type="text\/javascript"><\/script>\n    <script src="\/runtime-config.js" type="text\/javascript"><\/script>\n    <script src="\/ente-patches.js" type="text\/javascript"><\/script>/' "/app/data/web/$app_dir/index.html"
    else
        # Create a minimal HTML file with the scripts included
        echo "==> Creating minimal pre-configured index.html for $app_dir app with redirect"
@@ -621,8 +695,10 @@ for app_dir in photos accounts auth cast; do
<!DOCTYPE html>
<html>
<head>
    <script src="/polyfills.js" type="text/javascript"></script>
    <script src="/config.js" type="text/javascript"></script>
    <script src="/runtime-config.js" type="text/javascript"></script>
    <script src="/ente-patches.js" type="text/javascript"></script>
    <meta http-equiv="refresh" content="0;url=/app/web/$app_dir/index.html">
    <title>Ente $app_dir</title>
</head>
@@ -665,9 +741,14 @@ cat << EOF > /app/data/caddy/Caddyfile
                PUBLIC_ALBUMS_URL: 'https://${CLOUDRON_APP_FQDN}/public'
            };
            
            // Next.js environment variables
            // Add Node.js polyfills for browser environment
            window.process = window.process || {};
            window.process.env = window.process.env || {};
            window.process.nextTick = window.process.nextTick || function(fn) { setTimeout(fn, 0); };
            window.process.browser = true;
            window.Buffer = window.Buffer || (function() { return { isBuffer: function() { return false; } }; })();
            
            // Next.js environment variables
            window.process.env.NEXT_PUBLIC_BASE_URL = 'https://${CLOUDRON_APP_FQDN}';
            window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/api';
            window.process.env.NEXT_PUBLIC_ENTE_PUBLIC_ALBUMS_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/public';
@@ -675,6 +756,8 @@ cat << EOF > /app/data/caddy/Caddyfile
            window.process.env.REACT_APP_ENTE_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/api';
            
            // Make sure URLs are explicitly defined with full domain
            console.log('Node.js polyfills loaded');
            console.log('process.nextTick available:', !!window.process.nextTick);
            console.log('BASE_URL:', window.process.env.NEXT_PUBLIC_BASE_URL);
            console.log('Ente config loaded - API_URL:', window.ENTE_CONFIG.API_URL);
            console.log('Ente config loaded - PUBLIC_ALBUMS_URL:', window.ENTE_CONFIG.PUBLIC_ALBUMS_URL);
@@ -686,6 +769,35 @@ cat << EOF > /app/data/caddy/Caddyfile
        file_server
    }
    
    # Add before the root path section
    handle /polyfills.js {
        header Content-Type application/javascript
        respond "
            // Node.js polyfills for browsers
            window.process = window.process || {};
            window.process.env = window.process.env || {};
            window.process.nextTick = window.process.nextTick || function(fn) { setTimeout(fn, 0); };
            window.process.browser = true;
            
            // Buffer polyfill
            window.Buffer = window.Buffer || (function() {
                return {
                    isBuffer: function() { return false; },
                    from: function(data) { return { data: data }; }
                };
            })();
            
            // URL polyfill helper
            window.ensureValidURL = function(url) {
                if (!url) return 'https://${CLOUDRON_APP_FQDN}';
                if (url.startsWith('http://') || url.startsWith('https://')) return url;
                return 'https://${CLOUDRON_APP_FQDN}' + (url.startsWith('/') ? url : '/' + url);
            };
            
            console.log('Polyfills loaded successfully');
        "
    }
    
    # Root path serves the photos app
    handle / {
        # Special handling for index.html
@@ -838,6 +950,13 @@ cat << EOF > /app/data/caddy/Caddyfile
        uri strip_prefix /public
        reverse_proxy 0.0.0.0:$PUBLIC_ALBUMS_PORT
    }

    # Serve Ente client patches
    handle /ente-patches.js {
        header Content-Type application/javascript
        root * /app/data/web
        file_server
    }
}
EOF