litestar-vite 0.15.0__py3-none-any.whl → 0.15.0rc2__py3-none-any.whl
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.
- litestar_vite/_codegen/__init__.py +26 -0
- litestar_vite/_codegen/inertia.py +407 -0
- litestar_vite/{codegen/_openapi.py → _codegen/openapi.py} +11 -58
- litestar_vite/{codegen/_routes.py → _codegen/routes.py} +43 -110
- litestar_vite/{codegen/_ts.py → _codegen/ts.py} +19 -19
- litestar_vite/_handler/__init__.py +8 -0
- litestar_vite/{handler/_app.py → _handler/app.py} +29 -117
- litestar_vite/cli.py +254 -155
- litestar_vite/codegen.py +39 -0
- litestar_vite/commands.py +6 -0
- litestar_vite/{config/__init__.py → config.py} +726 -99
- litestar_vite/deploy.py +3 -14
- litestar_vite/doctor.py +6 -8
- litestar_vite/executor.py +1 -45
- litestar_vite/handler.py +9 -0
- litestar_vite/html_transform.py +5 -148
- litestar_vite/inertia/__init__.py +0 -24
- litestar_vite/inertia/_utils.py +0 -5
- litestar_vite/inertia/exception_handler.py +16 -22
- litestar_vite/inertia/helpers.py +18 -546
- litestar_vite/inertia/plugin.py +11 -77
- litestar_vite/inertia/request.py +0 -48
- litestar_vite/inertia/response.py +17 -113
- litestar_vite/inertia/types.py +0 -19
- litestar_vite/loader.py +7 -7
- litestar_vite/plugin.py +2184 -0
- litestar_vite/templates/angular/package.json.j2 +1 -2
- litestar_vite/templates/angular-cli/package.json.j2 +1 -2
- litestar_vite/templates/base/package.json.j2 +1 -2
- litestar_vite/templates/react-inertia/package.json.j2 +1 -2
- litestar_vite/templates/vue-inertia/package.json.j2 +1 -2
- {litestar_vite-0.15.0.dist-info → litestar_vite-0.15.0rc2.dist-info}/METADATA +5 -5
- {litestar_vite-0.15.0.dist-info → litestar_vite-0.15.0rc2.dist-info}/RECORD +36 -49
- litestar_vite/codegen/__init__.py +0 -48
- litestar_vite/codegen/_export.py +0 -229
- litestar_vite/codegen/_inertia.py +0 -619
- litestar_vite/codegen/_utils.py +0 -141
- litestar_vite/config/_constants.py +0 -97
- litestar_vite/config/_deploy.py +0 -70
- litestar_vite/config/_inertia.py +0 -241
- litestar_vite/config/_paths.py +0 -63
- litestar_vite/config/_runtime.py +0 -235
- litestar_vite/config/_spa.py +0 -93
- litestar_vite/config/_types.py +0 -94
- litestar_vite/handler/__init__.py +0 -9
- litestar_vite/inertia/precognition.py +0 -274
- litestar_vite/plugin/__init__.py +0 -687
- litestar_vite/plugin/_process.py +0 -185
- litestar_vite/plugin/_proxy.py +0 -689
- litestar_vite/plugin/_proxy_headers.py +0 -244
- litestar_vite/plugin/_static.py +0 -37
- litestar_vite/plugin/_utils.py +0 -489
- /litestar_vite/{handler/_routing.py → _handler/routing.py} +0 -0
- {litestar_vite-0.15.0.dist-info → litestar_vite-0.15.0rc2.dist-info}/WHEEL +0 -0
- {litestar_vite-0.15.0.dist-info → litestar_vite-0.15.0rc2.dist-info}/licenses/LICENSE +0 -0
|
@@ -18,15 +18,8 @@ from litestar import get
|
|
|
18
18
|
from litestar.exceptions import ImproperlyConfiguredException, SerializationException
|
|
19
19
|
from litestar.serialization import decode_json, encode_json
|
|
20
20
|
|
|
21
|
-
from litestar_vite.
|
|
22
|
-
from litestar_vite.
|
|
23
|
-
from litestar_vite.html_transform import (
|
|
24
|
-
inject_head_script,
|
|
25
|
-
inject_page_script,
|
|
26
|
-
inject_vite_dev_scripts,
|
|
27
|
-
set_data_attribute,
|
|
28
|
-
transform_asset_urls,
|
|
29
|
-
)
|
|
21
|
+
from litestar_vite._handler.routing import spa_handler_dev, spa_handler_prod
|
|
22
|
+
from litestar_vite.html_transform import inject_head_script, set_data_attribute, transform_asset_urls
|
|
30
23
|
|
|
31
24
|
if TYPE_CHECKING:
|
|
32
25
|
from litestar.connection import Request
|
|
@@ -164,29 +157,25 @@ class AppHandler:
|
|
|
164
157
|
|
|
165
158
|
if self._spa_config.inject_csrf and csrf_token:
|
|
166
159
|
script = f'window.{self._spa_config.csrf_var_name} = "{csrf_token}";'
|
|
167
|
-
html = inject_head_script(html, script, escape=False
|
|
160
|
+
html = inject_head_script(html, script, escape=False)
|
|
168
161
|
|
|
169
162
|
if page_data is not None:
|
|
170
163
|
json_data = encode_json(page_data).decode("utf-8")
|
|
171
|
-
|
|
172
|
-
inertia = self._config.inertia
|
|
173
|
-
use_script_element = isinstance(inertia, InertiaConfig) and inertia.use_script_element
|
|
174
|
-
if use_script_element:
|
|
175
|
-
# v2.3+ Inertia protocol: Use script element for better performance (~37% smaller)
|
|
176
|
-
html = inject_page_script(html, json_data, nonce=self._config.csp_nonce)
|
|
177
|
-
else:
|
|
178
|
-
# Legacy: Use data-page attribute
|
|
179
|
-
html = set_data_attribute(html, self._spa_config.app_selector, "data-page", json_data)
|
|
164
|
+
html = set_data_attribute(html, self._spa_config.app_selector, "data-page", json_data)
|
|
180
165
|
|
|
181
166
|
return html
|
|
182
167
|
|
|
183
168
|
async def _load_index_html_async(self) -> None:
|
|
184
|
-
"""Load and cache index.html asynchronously.
|
|
169
|
+
"""Load and cache index.html asynchronously.
|
|
170
|
+
|
|
171
|
+
Raises:
|
|
172
|
+
ImproperlyConfiguredException: If index.html cannot be located.
|
|
173
|
+
"""
|
|
185
174
|
resolved_path: Path | None = None
|
|
186
175
|
for candidate in self._config.candidate_index_html_paths():
|
|
187
|
-
candidate_path =
|
|
188
|
-
if
|
|
189
|
-
resolved_path =
|
|
176
|
+
candidate_path = Path(candidate)
|
|
177
|
+
if candidate_path.exists():
|
|
178
|
+
resolved_path = candidate_path
|
|
190
179
|
break
|
|
191
180
|
|
|
192
181
|
if resolved_path is None:
|
|
@@ -200,7 +189,11 @@ class AppHandler:
|
|
|
200
189
|
self._cached_bytes = html.encode("utf-8")
|
|
201
190
|
|
|
202
191
|
def _load_index_html_sync(self) -> None:
|
|
203
|
-
"""Load and cache index.html synchronously.
|
|
192
|
+
"""Load and cache index.html synchronously.
|
|
193
|
+
|
|
194
|
+
Raises:
|
|
195
|
+
ImproperlyConfiguredException: If index.html cannot be located.
|
|
196
|
+
"""
|
|
204
197
|
resolved_path: Path | None = None
|
|
205
198
|
for candidate in self._config.candidate_index_html_paths():
|
|
206
199
|
candidate_path = Path(candidate)
|
|
@@ -293,92 +286,10 @@ class AppHandler:
|
|
|
293
286
|
"""
|
|
294
287
|
if not self._manifest:
|
|
295
288
|
return html
|
|
296
|
-
return transform_asset_urls(
|
|
297
|
-
|
|
298
|
-
def _inject_dev_scripts(self, html: str) -> str:
|
|
299
|
-
"""Inject Vite dev scripts for hybrid mode HTML served by Litestar.
|
|
300
|
-
|
|
301
|
-
Returns:
|
|
302
|
-
The HTML with Vite dev scripts injected.
|
|
303
|
-
"""
|
|
304
|
-
resource_dir = self._config.resource_dir
|
|
305
|
-
try:
|
|
306
|
-
resource_dir_str = str(resource_dir.relative_to(self._config.root_dir))
|
|
307
|
-
except ValueError:
|
|
308
|
-
resource_dir_str = resource_dir.name
|
|
309
|
-
return inject_vite_dev_scripts(
|
|
310
|
-
html,
|
|
311
|
-
"",
|
|
312
|
-
asset_url=self._config.asset_url,
|
|
313
|
-
is_react=self._config.is_react,
|
|
314
|
-
csp_nonce=self._config.csp_nonce,
|
|
315
|
-
resource_dir=resource_dir_str,
|
|
289
|
+
return transform_asset_urls(
|
|
290
|
+
html, self._manifest, asset_url=self._config.asset_url, base_url=self._config.base_url
|
|
316
291
|
)
|
|
317
292
|
|
|
318
|
-
async def _transform_html_with_vite(self, html: str, url: str) -> str:
|
|
319
|
-
"""Transform HTML using the Vite dev server pipeline.
|
|
320
|
-
|
|
321
|
-
Returns:
|
|
322
|
-
The transformed HTML.
|
|
323
|
-
"""
|
|
324
|
-
if self._http_client is None or self._vite_url is None:
|
|
325
|
-
msg = "HTTP client not initialized. Ensure initialize_async() was called for dev mode."
|
|
326
|
-
raise ImproperlyConfiguredException(msg)
|
|
327
|
-
endpoint = f"{self._vite_url.rstrip('/')}/__litestar__/transform-index"
|
|
328
|
-
response = await self._http_client.post(endpoint, json={"url": url, "html": html}, timeout=5.0)
|
|
329
|
-
response.raise_for_status()
|
|
330
|
-
return response.text
|
|
331
|
-
|
|
332
|
-
def _transform_html_with_vite_sync(self, html: str, url: str) -> str:
|
|
333
|
-
"""Transform HTML using the Vite dev server pipeline (sync).
|
|
334
|
-
|
|
335
|
-
Returns:
|
|
336
|
-
The transformed HTML.
|
|
337
|
-
"""
|
|
338
|
-
if self._http_client_sync is None or self._vite_url is None:
|
|
339
|
-
msg = "HTTP client not initialized. Ensure initialize_sync() was called for dev mode."
|
|
340
|
-
raise ImproperlyConfiguredException(msg)
|
|
341
|
-
endpoint = f"{self._vite_url.rstrip('/')}/__litestar__/transform-index"
|
|
342
|
-
response = self._http_client_sync.post(endpoint, json={"url": url, "html": html}, timeout=5.0)
|
|
343
|
-
response.raise_for_status()
|
|
344
|
-
return response.text
|
|
345
|
-
|
|
346
|
-
async def _get_dev_html(self, request: "Request[Any, Any, Any]") -> str:
|
|
347
|
-
"""Resolve dev HTML for SPA or hybrid modes.
|
|
348
|
-
|
|
349
|
-
Returns:
|
|
350
|
-
The HTML to serve in development.
|
|
351
|
-
"""
|
|
352
|
-
if self._config.mode == "hybrid":
|
|
353
|
-
if self._cached_html is None:
|
|
354
|
-
await self._load_index_html_async()
|
|
355
|
-
base_html = self._cached_html or ""
|
|
356
|
-
request_url = request.url.path or "/"
|
|
357
|
-
try:
|
|
358
|
-
return await self._transform_html_with_vite(base_html, request_url)
|
|
359
|
-
except Exception as exc: # noqa: BLE001
|
|
360
|
-
logger.warning("Falling back to manual Vite script injection: %s", exc)
|
|
361
|
-
return self._inject_dev_scripts(base_html)
|
|
362
|
-
return await self._proxy_to_dev_server(request)
|
|
363
|
-
|
|
364
|
-
def _get_dev_html_sync(self, page_url: str | None = None) -> str:
|
|
365
|
-
"""Resolve dev HTML synchronously for SPA or hybrid modes.
|
|
366
|
-
|
|
367
|
-
Returns:
|
|
368
|
-
The HTML to serve in development.
|
|
369
|
-
"""
|
|
370
|
-
if self._config.mode == "hybrid":
|
|
371
|
-
if self._cached_html is None:
|
|
372
|
-
self._load_index_html_sync()
|
|
373
|
-
base_html = self._cached_html or ""
|
|
374
|
-
request_url = page_url or "/"
|
|
375
|
-
try:
|
|
376
|
-
return self._transform_html_with_vite_sync(base_html, request_url)
|
|
377
|
-
except Exception as exc: # noqa: BLE001
|
|
378
|
-
logger.warning("Falling back to manual Vite script injection: %s", exc)
|
|
379
|
-
return self._inject_dev_scripts(base_html)
|
|
380
|
-
return self._proxy_to_dev_server_sync()
|
|
381
|
-
|
|
382
293
|
def _get_csrf_token(self, request: "Request[Any, Any, Any]") -> "str | None":
|
|
383
294
|
"""Extract CSRF token from the request scope.
|
|
384
295
|
|
|
@@ -415,7 +326,7 @@ class AppHandler:
|
|
|
415
326
|
csrf_token = self._get_csrf_token(request) if needs_csrf else None
|
|
416
327
|
|
|
417
328
|
if self._config.is_dev_mode and self._config.hot_reload:
|
|
418
|
-
html = await self.
|
|
329
|
+
html = await self._proxy_to_dev_server(request)
|
|
419
330
|
if needs_transform:
|
|
420
331
|
html = self._transform_html(html, page_data, csrf_token)
|
|
421
332
|
return html
|
|
@@ -448,6 +359,9 @@ class AppHandler:
|
|
|
448
359
|
|
|
449
360
|
Returns:
|
|
450
361
|
The rendered HTML.
|
|
362
|
+
|
|
363
|
+
Raises:
|
|
364
|
+
ImproperlyConfiguredException: If dev-mode HTTP clients are not initialized or Vite URL is unresolved.
|
|
451
365
|
"""
|
|
452
366
|
if not self._initialized:
|
|
453
367
|
logger.warning(
|
|
@@ -459,16 +373,11 @@ class AppHandler:
|
|
|
459
373
|
needs_transform = self._spa_config is not None or page_data is not None
|
|
460
374
|
if not needs_transform:
|
|
461
375
|
if self._config.is_dev_mode and self._config.hot_reload:
|
|
462
|
-
return self.
|
|
376
|
+
return self._proxy_to_dev_server_sync()
|
|
463
377
|
return self._cached_html or ""
|
|
464
378
|
|
|
465
379
|
if self._config.is_dev_mode and self._config.hot_reload:
|
|
466
|
-
|
|
467
|
-
if page_data is not None:
|
|
468
|
-
url_value = page_data.get("url")
|
|
469
|
-
if isinstance(url_value, str) and url_value:
|
|
470
|
-
page_url = url_value
|
|
471
|
-
html = self._get_dev_html_sync(page_url)
|
|
380
|
+
html = self._proxy_to_dev_server_sync()
|
|
472
381
|
return self._transform_html(html, page_data, csrf_token)
|
|
473
382
|
|
|
474
383
|
base_html = self._cached_html or ""
|
|
@@ -478,7 +387,10 @@ class AppHandler:
|
|
|
478
387
|
"""Get cached index.html bytes (production).
|
|
479
388
|
|
|
480
389
|
Returns:
|
|
481
|
-
Cached HTML bytes.
|
|
390
|
+
Cached HTML bytes.
|
|
391
|
+
|
|
392
|
+
Raises:
|
|
393
|
+
ImproperlyConfiguredException: If index.html cannot be located.
|
|
482
394
|
"""
|
|
483
395
|
if not self._initialized:
|
|
484
396
|
logger.warning(
|