#!/bin/bash # Cache-Busting Implementation Script # This script modifies server.js to add dynamic asset versioning set -e SERVER_FILE="/home/uroma/obsidian-web-interface/server.js" BACKUP_FILE="/home/uroma/obsidian-web-interface/server.js.backup-$(date +%s)" echo "[CACHE-BUSTING] Creating backup: $BACKUP_FILE" cp "$SERVER_FILE" "$BACKUP_FILE" echo "[CACHE-BUSTING] Applying cache-busting modifications to server.js..." # Use Python for more reliable file modification python3 << 'PYTHON_SCRIPT' import re server_file = "/home/uroma/obsidian-web-interface/server.js" with open(server_file, 'r') as f: content = f.read() # 1. Add cache-busting configuration after SESSION_SECRET line # Find the SESSION_SECRET line and add cache-busting config after it config_insertion = """const SESSION_SECRET = 'obsidian-web-secret-' + Math.random().toString(36).substring(2); // ============================================================ // CACHE-BUSTING CONFIGURATION // ============================================================ // Build timestamp forces browser to reload all assets on server restart const BUILD_TIMESTAMP = Date.now(); const ASSET_VERSION = `v=${BUILD_TIMESTAMP}`; console.log(`[CACHE-BUSTING] Build timestamp initialized: ${BUILD_TIMESTAMP}`); console.log(`[CACHE-BUSTING] All JavaScript files will be served with ?${ASSET_VERSION}`);""" # Replace the old SESSION_SECRET line and add cache-busting config content = re.sub( r"const SESSION_SECRET = 'obsidian-web-secret-\* \+ Math\.random\(\)\.toString\(36\)\.substring\(2\);", config_insertion, content ) # 2. Add cache-busting middleware import at the top after other requires # Find where the modules are required and add our middleware import_section = """const { db } = require('./services/database'); const app = express(); // Cache-busting middleware const cacheBustMiddleware = require('./cache-bust-middleware');""" content = re.sub( r"const \{ db \} = require\('\./services/database'\);\n\nconst app = express\(\);", import_section, content ) # 3. Add cache-busting middleware after session middleware session_middleware = """app.use(session({ secret: SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { secure: false, // Will work with both HTTP and HTTPS behind proxy sameSite: 'lax', httpOnly: true, maxAge: 24 * 60 * 60 * 1000 // 24 hours }, name: 'connect.sid' })); // Apply cache-busting middleware to HTML responses app.use(cacheBustMiddleware.createCacheBustingMiddleware(ASSET_VERSION));""" content = re.sub( r"app\.use\(session\(\{[^}]+\}\)\);", session_middleware, content, flags=re.DOTALL ) # 4. Enhance static file serving with stronger cache headers static_config = """// Serve static files (must come after specific routes) // CRITICAL: Disable ALL caching for JS files to prevent browser from serving stale code // Cache-busting via query parameters (ASSET_VERSION) ensures fresh content on every deploy app.use('/claude', express.static(path.join(__dirname, 'public'), { etag: false, lastModified: false, setHeaders: (res, filePath) => { // Disable caching for all JavaScript and CSS files if (filePath.endsWith('.js') || filePath.endsWith('.css')) { res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'); res.setHeader('Pragma', 'no-cache'); res.setHeader('Expires', '0'); res.removeHeader('ETag'); } } }));""" content = re.sub( r"// Serve static files \(must come after specific routes\)[^\n]+\n// Disable caching for JS files[^\n]+\napp\.use\('/claude', express\.static\(path\.join\(__dirname, 'public'\), \{[^}]+\}\);", static_config, content, flags=re.DOTALL ) with open(server_file, 'w') as f: f.write(content) print("[CACHE-BUSTING] Successfully applied all modifications") PYTHON_SCRIPT echo "[CACHE-BUSTING] Done! Restarting server..." echo "[CACHE-BUSTING] Original file backed up to: $BACKUP_FILE"