Coverage for src / local_deep_research / web / utils / vite_helper.py: 100%
46 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-25 01:07 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-25 01:07 +0000
1"""
2Vite integration helper for Flask
3Handles development and production asset loading
4"""
6import json
7from pathlib import Path
8from markupsafe import Markup
11class ViteHelper:
12 """Helper class for Vite integration with Flask"""
14 def __init__(self, app=None):
15 self.app = app
16 self.manifest = None
17 self.is_dev = False
19 if app:
20 self.init_app(app)
22 def init_app(self, app):
23 """Initialize the helper with Flask app"""
24 self.app = app
25 self.is_dev = app.debug or app.config.get("VITE_DEV_MODE", False)
27 if not self.is_dev:
28 # Load manifest in production
29 self._load_manifest()
31 # Register template functions
32 app.jinja_env.globals["vite_asset"] = self.vite_asset
33 app.jinja_env.globals["vite_hmr"] = self.vite_hmr
35 def _load_manifest(self):
36 """Load Vite manifest file"""
37 static_dir = self.app.config.get("STATIC_DIR", "static")
38 manifest_path = Path(static_dir) / "dist" / ".vite" / "manifest.json"
40 if manifest_path.exists():
41 with open(manifest_path, "r") as f:
42 self.manifest = json.load(f)
43 else:
44 # Fallback if manifest doesn't exist yet
45 self.manifest = {}
47 def vite_hmr(self):
48 """Return HMR client script for development"""
49 if self.is_dev:
50 return Markup(
51 '<script type="module" src="http://localhost:5173/@vite/client"></script>'
52 )
53 return ""
55 def vite_asset(self, entry_point="js/app.js"):
56 """
57 Return appropriate script tags for the entry point
59 In development: Points to Vite dev server
60 In production: Uses manifest to get hashed filenames
61 """
62 if self.is_dev:
63 # Development mode - use Vite dev server
64 return Markup(
65 f'<script type="module" src="http://localhost:5173/{entry_point}"></script>'
66 )
68 # Production mode - use manifest
69 if not self.manifest:
70 # Fallback to CDN references if build hasn't run yet
71 return self._fallback_assets()
73 # Get the built file from manifest
74 if entry_point in self.manifest:
75 file_info = self.manifest[entry_point]
76 file_path = f"/static/dist/{file_info['file']}"
78 # Include CSS if present
79 css_tags = ""
80 if "css" in file_info:
81 for css_file in file_info["css"]:
82 css_tags += f'<link rel="stylesheet" href="/static/dist/{css_file}">\n'
84 # Include the main JS file
85 js_tag = f'<script type="module" src="{file_path}"></script>'
87 return Markup(css_tags + js_tag)
89 return self._fallback_assets()
91 def _fallback_assets(self):
92 """Fallback to existing script tags if build hasn't run"""
93 # This will be replaced once npm build is run
94 return Markup("""
95<!-- Vite build not found - run 'npm run build' to generate production assets -->
96<!-- Using existing static files as fallback -->
97 """)
100# Create global instance
101vite = ViteHelper()