litestar-vite 0.1.1__py3-none-any.whl → 0.15.0__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/__init__.py +54 -4
- litestar_vite/__metadata__.py +12 -7
- litestar_vite/cli.py +1048 -10
- litestar_vite/codegen/__init__.py +48 -0
- litestar_vite/codegen/_export.py +229 -0
- litestar_vite/codegen/_inertia.py +619 -0
- litestar_vite/codegen/_openapi.py +280 -0
- litestar_vite/codegen/_routes.py +720 -0
- litestar_vite/codegen/_ts.py +235 -0
- litestar_vite/codegen/_utils.py +141 -0
- litestar_vite/commands.py +73 -0
- litestar_vite/config/__init__.py +997 -0
- litestar_vite/config/_constants.py +97 -0
- litestar_vite/config/_deploy.py +70 -0
- litestar_vite/config/_inertia.py +241 -0
- litestar_vite/config/_paths.py +63 -0
- litestar_vite/config/_runtime.py +235 -0
- litestar_vite/config/_spa.py +93 -0
- litestar_vite/config/_types.py +94 -0
- litestar_vite/deploy.py +366 -0
- litestar_vite/doctor.py +1181 -0
- litestar_vite/exceptions.py +78 -0
- litestar_vite/executor.py +360 -0
- litestar_vite/handler/__init__.py +9 -0
- litestar_vite/handler/_app.py +612 -0
- litestar_vite/handler/_routing.py +130 -0
- litestar_vite/html_transform.py +569 -0
- litestar_vite/inertia/__init__.py +77 -0
- litestar_vite/inertia/_utils.py +119 -0
- litestar_vite/inertia/exception_handler.py +178 -0
- litestar_vite/inertia/helpers.py +1571 -0
- litestar_vite/inertia/middleware.py +54 -0
- litestar_vite/inertia/plugin.py +199 -0
- litestar_vite/inertia/precognition.py +274 -0
- litestar_vite/inertia/request.py +334 -0
- litestar_vite/inertia/response.py +802 -0
- litestar_vite/inertia/types.py +335 -0
- litestar_vite/loader.py +464 -123
- litestar_vite/plugin/__init__.py +687 -0
- litestar_vite/plugin/_process.py +185 -0
- litestar_vite/plugin/_proxy.py +689 -0
- litestar_vite/plugin/_proxy_headers.py +244 -0
- litestar_vite/plugin/_static.py +37 -0
- litestar_vite/plugin/_utils.py +489 -0
- litestar_vite/py.typed +0 -0
- litestar_vite/scaffolding/__init__.py +20 -0
- litestar_vite/scaffolding/generator.py +270 -0
- litestar_vite/scaffolding/templates.py +437 -0
- litestar_vite/templates/__init__.py +0 -0
- litestar_vite/templates/addons/tailwindcss/tailwind.css.j2 +1 -0
- litestar_vite/templates/angular/index.html.j2 +12 -0
- litestar_vite/templates/angular/openapi-ts.config.ts.j2 +18 -0
- litestar_vite/templates/angular/package.json.j2 +36 -0
- litestar_vite/templates/angular/src/app/app.component.css.j2 +3 -0
- litestar_vite/templates/angular/src/app/app.component.html.j2 +1 -0
- litestar_vite/templates/angular/src/app/app.component.ts.j2 +9 -0
- litestar_vite/templates/angular/src/app/app.config.ts.j2 +5 -0
- litestar_vite/templates/angular/src/main.ts.j2 +9 -0
- litestar_vite/templates/angular/src/styles.css.j2 +9 -0
- litestar_vite/templates/angular/tsconfig.app.json.j2 +34 -0
- litestar_vite/templates/angular/tsconfig.json.j2 +20 -0
- litestar_vite/templates/angular/vite.config.ts.j2 +21 -0
- litestar_vite/templates/angular-cli/.postcssrc.json.j2 +5 -0
- litestar_vite/templates/angular-cli/angular.json.j2 +36 -0
- litestar_vite/templates/angular-cli/openapi-ts.config.ts.j2 +18 -0
- litestar_vite/templates/angular-cli/package.json.j2 +28 -0
- litestar_vite/templates/angular-cli/proxy.conf.json.j2 +18 -0
- litestar_vite/templates/angular-cli/src/app/app.component.css.j2 +3 -0
- litestar_vite/templates/angular-cli/src/app/app.component.html.j2 +1 -0
- litestar_vite/templates/angular-cli/src/app/app.component.ts.j2 +9 -0
- litestar_vite/templates/angular-cli/src/app/app.config.ts.j2 +5 -0
- litestar_vite/templates/angular-cli/src/index.html.j2 +13 -0
- litestar_vite/templates/angular-cli/src/main.ts.j2 +6 -0
- litestar_vite/templates/angular-cli/src/styles.css.j2 +10 -0
- litestar_vite/templates/angular-cli/tailwind.config.js.j2 +4 -0
- litestar_vite/templates/angular-cli/tsconfig.app.json.j2 +16 -0
- litestar_vite/templates/angular-cli/tsconfig.json.j2 +26 -0
- litestar_vite/templates/angular-cli/tsconfig.spec.json.j2 +9 -0
- litestar_vite/templates/astro/astro.config.mjs.j2 +28 -0
- litestar_vite/templates/astro/openapi-ts.config.ts.j2 +15 -0
- litestar_vite/templates/astro/src/layouts/Layout.astro.j2 +63 -0
- litestar_vite/templates/astro/src/pages/index.astro.j2 +36 -0
- litestar_vite/templates/astro/src/styles/global.css.j2 +1 -0
- litestar_vite/templates/base/.gitignore.j2 +42 -0
- litestar_vite/templates/base/openapi-ts.config.ts.j2 +15 -0
- litestar_vite/templates/base/package.json.j2 +39 -0
- litestar_vite/templates/base/resources/vite-env.d.ts.j2 +1 -0
- litestar_vite/templates/base/tsconfig.json.j2 +37 -0
- litestar_vite/templates/htmx/src/main.js.j2 +8 -0
- litestar_vite/templates/htmx/templates/base.html.j2.j2 +56 -0
- litestar_vite/templates/htmx/templates/index.html.j2.j2 +13 -0
- litestar_vite/templates/htmx/vite.config.ts.j2 +40 -0
- litestar_vite/templates/nuxt/app.vue.j2 +29 -0
- litestar_vite/templates/nuxt/composables/useApi.ts.j2 +33 -0
- litestar_vite/templates/nuxt/nuxt.config.ts.j2 +31 -0
- litestar_vite/templates/nuxt/openapi-ts.config.ts.j2 +15 -0
- litestar_vite/templates/nuxt/pages/index.vue.j2 +54 -0
- litestar_vite/templates/react/index.html.j2 +13 -0
- litestar_vite/templates/react/src/App.css.j2 +56 -0
- litestar_vite/templates/react/src/App.tsx.j2 +19 -0
- litestar_vite/templates/react/src/main.tsx.j2 +10 -0
- litestar_vite/templates/react/vite.config.ts.j2 +39 -0
- litestar_vite/templates/react-inertia/index.html.j2 +14 -0
- litestar_vite/templates/react-inertia/package.json.j2 +47 -0
- litestar_vite/templates/react-inertia/resources/App.css.j2 +68 -0
- litestar_vite/templates/react-inertia/resources/main.tsx.j2 +17 -0
- litestar_vite/templates/react-inertia/resources/pages/Home.tsx.j2 +18 -0
- litestar_vite/templates/react-inertia/resources/ssr.tsx.j2 +19 -0
- litestar_vite/templates/react-inertia/vite.config.ts.j2 +59 -0
- litestar_vite/templates/react-router/index.html.j2 +12 -0
- litestar_vite/templates/react-router/src/App.css.j2 +17 -0
- litestar_vite/templates/react-router/src/App.tsx.j2 +7 -0
- litestar_vite/templates/react-router/src/main.tsx.j2 +10 -0
- litestar_vite/templates/react-router/vite.config.ts.j2 +39 -0
- litestar_vite/templates/react-tanstack/index.html.j2 +12 -0
- litestar_vite/templates/react-tanstack/openapi-ts.config.ts.j2 +18 -0
- litestar_vite/templates/react-tanstack/src/App.css.j2 +17 -0
- litestar_vite/templates/react-tanstack/src/main.tsx.j2 +21 -0
- litestar_vite/templates/react-tanstack/src/routeTree.gen.ts.j2 +7 -0
- litestar_vite/templates/react-tanstack/src/routes/__root.tsx.j2 +9 -0
- litestar_vite/templates/react-tanstack/src/routes/books.tsx.j2 +9 -0
- litestar_vite/templates/react-tanstack/src/routes/index.tsx.j2 +9 -0
- litestar_vite/templates/react-tanstack/vite.config.ts.j2 +39 -0
- litestar_vite/templates/svelte/index.html.j2 +13 -0
- litestar_vite/templates/svelte/src/App.svelte.j2 +30 -0
- litestar_vite/templates/svelte/src/app.css.j2 +45 -0
- litestar_vite/templates/svelte/src/main.ts.j2 +8 -0
- litestar_vite/templates/svelte/src/vite-env.d.ts.j2 +2 -0
- litestar_vite/templates/svelte/svelte.config.js.j2 +5 -0
- litestar_vite/templates/svelte/vite.config.ts.j2 +39 -0
- litestar_vite/templates/svelte-inertia/index.html.j2 +14 -0
- litestar_vite/templates/svelte-inertia/resources/app.css.j2 +21 -0
- litestar_vite/templates/svelte-inertia/resources/main.ts.j2 +11 -0
- litestar_vite/templates/svelte-inertia/resources/pages/Home.svelte.j2 +43 -0
- litestar_vite/templates/svelte-inertia/resources/vite-env.d.ts.j2 +2 -0
- litestar_vite/templates/svelte-inertia/svelte.config.js.j2 +5 -0
- litestar_vite/templates/svelte-inertia/vite.config.ts.j2 +37 -0
- litestar_vite/templates/sveltekit/openapi-ts.config.ts.j2 +15 -0
- litestar_vite/templates/sveltekit/src/app.css.j2 +40 -0
- litestar_vite/templates/sveltekit/src/app.html.j2 +12 -0
- litestar_vite/templates/sveltekit/src/hooks.server.ts.j2 +55 -0
- litestar_vite/templates/sveltekit/src/routes/+layout.svelte.j2 +12 -0
- litestar_vite/templates/sveltekit/src/routes/+page.svelte.j2 +34 -0
- litestar_vite/templates/sveltekit/svelte.config.js.j2 +12 -0
- litestar_vite/templates/sveltekit/tsconfig.json.j2 +14 -0
- litestar_vite/templates/sveltekit/vite.config.ts.j2 +31 -0
- litestar_vite/templates/vue/env.d.ts.j2 +7 -0
- litestar_vite/templates/vue/index.html.j2 +13 -0
- litestar_vite/templates/vue/src/App.vue.j2 +28 -0
- litestar_vite/templates/vue/src/main.ts.j2 +5 -0
- litestar_vite/templates/vue/src/style.css.j2 +45 -0
- litestar_vite/templates/vue/vite.config.ts.j2 +39 -0
- litestar_vite/templates/vue-inertia/env.d.ts.j2 +7 -0
- litestar_vite/templates/vue-inertia/index.html.j2 +14 -0
- litestar_vite/templates/vue-inertia/package.json.j2 +50 -0
- litestar_vite/templates/vue-inertia/resources/main.ts.j2 +18 -0
- litestar_vite/templates/vue-inertia/resources/pages/Home.vue.j2 +22 -0
- litestar_vite/templates/vue-inertia/resources/ssr.ts.j2 +21 -0
- litestar_vite/templates/vue-inertia/resources/style.css.j2 +21 -0
- litestar_vite/templates/vue-inertia/vite.config.ts.j2 +59 -0
- litestar_vite-0.15.0.dist-info/METADATA +230 -0
- litestar_vite-0.15.0.dist-info/RECORD +164 -0
- {litestar_vite-0.1.1.dist-info → litestar_vite-0.15.0.dist-info}/WHEEL +1 -1
- litestar_vite/config.py +0 -100
- litestar_vite/plugin.py +0 -45
- litestar_vite/template_engine.py +0 -103
- litestar_vite-0.1.1.dist-info/METADATA +0 -68
- litestar_vite-0.1.1.dist-info/RECORD +0 -11
- {litestar_vite-0.1.1.dist-info → litestar_vite-0.15.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
"""Vite Plugin for Litestar.
|
|
2
|
+
|
|
3
|
+
This module provides the VitePlugin class for integrating Vite with Litestar.
|
|
4
|
+
The plugin handles:
|
|
5
|
+
|
|
6
|
+
- Static file serving configuration
|
|
7
|
+
- Jinja2 template callable registration
|
|
8
|
+
- Vite dev server process management
|
|
9
|
+
- Async asset loader initialization
|
|
10
|
+
- Development proxies for Vite HTTP and HMR WebSockets (with hop-by-hop header filtering)
|
|
11
|
+
|
|
12
|
+
Example::
|
|
13
|
+
|
|
14
|
+
from litestar import Litestar
|
|
15
|
+
from litestar_vite import VitePlugin, ViteConfig
|
|
16
|
+
|
|
17
|
+
app = Litestar(
|
|
18
|
+
plugins=[VitePlugin(config=ViteConfig(dev_mode=True))],
|
|
19
|
+
)
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import os
|
|
23
|
+
from contextlib import asynccontextmanager, contextmanager
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
26
|
+
|
|
27
|
+
import httpx
|
|
28
|
+
from litestar.exceptions import NotFoundException
|
|
29
|
+
from litestar.middleware import DefineMiddleware
|
|
30
|
+
from litestar.plugins import CLIPlugin, InitPluginProtocol
|
|
31
|
+
from litestar.static_files import create_static_files_router # pyright: ignore[reportUnknownVariableType]
|
|
32
|
+
|
|
33
|
+
from litestar_vite.config import JINJA_INSTALLED, TRUE_VALUES, ExternalDevServer
|
|
34
|
+
from litestar_vite.loader import ViteAssetLoader
|
|
35
|
+
from litestar_vite.plugin._process import ViteProcess
|
|
36
|
+
from litestar_vite.plugin._proxy import ViteProxyMiddleware, create_ssr_proxy_controller, create_vite_hmr_handler
|
|
37
|
+
from litestar_vite.plugin._proxy_headers import ProxyHeadersMiddleware, TrustedHosts
|
|
38
|
+
from litestar_vite.plugin._static import StaticFilesConfig
|
|
39
|
+
from litestar_vite.plugin._utils import (
|
|
40
|
+
create_proxy_client,
|
|
41
|
+
get_litestar_route_prefixes,
|
|
42
|
+
is_litestar_route,
|
|
43
|
+
is_non_serving_assets_cli,
|
|
44
|
+
log_fail,
|
|
45
|
+
log_info,
|
|
46
|
+
log_success,
|
|
47
|
+
log_warn,
|
|
48
|
+
pick_free_port,
|
|
49
|
+
resolve_litestar_version,
|
|
50
|
+
set_app_environment,
|
|
51
|
+
set_environment,
|
|
52
|
+
static_not_found_handler,
|
|
53
|
+
vite_not_found_handler,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
if TYPE_CHECKING:
|
|
57
|
+
from collections.abc import AsyncIterator, Iterator
|
|
58
|
+
|
|
59
|
+
from click import Group
|
|
60
|
+
from litestar import Litestar
|
|
61
|
+
from litestar.config.app import AppConfig
|
|
62
|
+
from litestar.types import ExceptionHandlersMap
|
|
63
|
+
|
|
64
|
+
from litestar_vite.config import ViteConfig
|
|
65
|
+
from litestar_vite.handler import AppHandler
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class VitePlugin(InitPluginProtocol, CLIPlugin):
|
|
69
|
+
"""Vite plugin for Litestar.
|
|
70
|
+
|
|
71
|
+
This plugin integrates Vite with Litestar, providing:
|
|
72
|
+
|
|
73
|
+
- Static file serving configuration
|
|
74
|
+
- Jinja2 template callables for asset tags
|
|
75
|
+
- Vite dev server process management
|
|
76
|
+
- Async asset loader initialization
|
|
77
|
+
|
|
78
|
+
Example::
|
|
79
|
+
|
|
80
|
+
from litestar import Litestar
|
|
81
|
+
from litestar_vite import VitePlugin, ViteConfig
|
|
82
|
+
|
|
83
|
+
app = Litestar(
|
|
84
|
+
plugins=[
|
|
85
|
+
VitePlugin(config=ViteConfig(dev_mode=True))
|
|
86
|
+
],
|
|
87
|
+
)
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
__slots__ = (
|
|
91
|
+
"_asset_loader",
|
|
92
|
+
"_config",
|
|
93
|
+
"_proxy_client",
|
|
94
|
+
"_proxy_target",
|
|
95
|
+
"_spa_handler",
|
|
96
|
+
"_static_files_config",
|
|
97
|
+
"_vite_process",
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
def __init__(
|
|
101
|
+
self,
|
|
102
|
+
config: "ViteConfig | None" = None,
|
|
103
|
+
asset_loader: "ViteAssetLoader | None" = None,
|
|
104
|
+
static_files_config: "StaticFilesConfig | None" = None,
|
|
105
|
+
) -> None:
|
|
106
|
+
"""Initialize the Vite plugin.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
config: Vite configuration. Defaults to ViteConfig() if not provided.
|
|
110
|
+
asset_loader: Optional pre-initialized asset loader.
|
|
111
|
+
static_files_config: Optional configuration for static file serving.
|
|
112
|
+
"""
|
|
113
|
+
from litestar_vite.config import ViteConfig
|
|
114
|
+
|
|
115
|
+
if config is None:
|
|
116
|
+
config = ViteConfig()
|
|
117
|
+
self._config = config
|
|
118
|
+
self._asset_loader = asset_loader
|
|
119
|
+
self._vite_process = ViteProcess(executor=config.executor)
|
|
120
|
+
self._static_files_config: dict[str, Any] = static_files_config.__dict__ if static_files_config else {}
|
|
121
|
+
self._proxy_target: "str | None" = None
|
|
122
|
+
self._proxy_client: "httpx.AsyncClient | None" = None
|
|
123
|
+
self._spa_handler: "AppHandler | None" = None
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def config(self) -> "ViteConfig":
|
|
127
|
+
"""Get the Vite configuration.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
The ViteConfig instance.
|
|
131
|
+
"""
|
|
132
|
+
return self._config
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def asset_loader(self) -> "ViteAssetLoader":
|
|
136
|
+
"""Get the asset loader instance.
|
|
137
|
+
|
|
138
|
+
Lazily initializes the loader if not already set.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
The ViteAssetLoader instance.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
if self._asset_loader is None:
|
|
145
|
+
self._asset_loader = ViteAssetLoader.initialize_loader(config=self._config)
|
|
146
|
+
return self._asset_loader
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def spa_handler(self) -> "AppHandler | None":
|
|
150
|
+
"""Return the configured SPA handler when SPA mode is enabled.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
The AppHandler instance, or None when SPA mode is disabled/not configured.
|
|
154
|
+
"""
|
|
155
|
+
return self._spa_handler
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def proxy_client(self) -> "httpx.AsyncClient | None":
|
|
159
|
+
"""Return the shared httpx.AsyncClient for proxy requests.
|
|
160
|
+
|
|
161
|
+
The client is initialized during app lifespan (dev mode only) and provides
|
|
162
|
+
connection pooling, TLS session reuse, and HTTP/2 multiplexing benefits.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
The shared AsyncClient instance, or None if not initialized or not in dev mode.
|
|
166
|
+
"""
|
|
167
|
+
return self._proxy_client
|
|
168
|
+
|
|
169
|
+
def _resolve_bundle_dir(self) -> Path:
|
|
170
|
+
"""Resolve the bundle directory to an absolute path.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
The absolute path to the bundle directory.
|
|
174
|
+
"""
|
|
175
|
+
bundle_dir = Path(self._config.bundle_dir)
|
|
176
|
+
if not bundle_dir.is_absolute():
|
|
177
|
+
return self._config.root_dir / bundle_dir
|
|
178
|
+
return bundle_dir
|
|
179
|
+
|
|
180
|
+
def _resolve_hotfile_path(self) -> Path:
|
|
181
|
+
"""Resolve the path to the hotfile.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
The absolute path to the hotfile.
|
|
185
|
+
"""
|
|
186
|
+
return self._resolve_bundle_dir() / self._config.hot_file
|
|
187
|
+
|
|
188
|
+
def _write_hotfile(self, content: str) -> None:
|
|
189
|
+
"""Write content to the hotfile.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
content: The content to write (usually the dev server URL).
|
|
193
|
+
"""
|
|
194
|
+
hotfile_path = self._resolve_hotfile_path()
|
|
195
|
+
hotfile_path.parent.mkdir(parents=True, exist_ok=True)
|
|
196
|
+
hotfile_path.write_text(content, encoding="utf-8")
|
|
197
|
+
|
|
198
|
+
def _resolve_dev_command(self) -> "list[str]":
|
|
199
|
+
"""Resolve the command to run for the dev server.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
The list of command arguments.
|
|
203
|
+
"""
|
|
204
|
+
ext = self._config.runtime.external_dev_server
|
|
205
|
+
if isinstance(ext, ExternalDevServer) and ext.enabled:
|
|
206
|
+
command = ext.command or self._config.executor.start_command
|
|
207
|
+
log_info(f"Starting external dev server: {' '.join(command)}")
|
|
208
|
+
return command
|
|
209
|
+
|
|
210
|
+
if self._config.hot_reload:
|
|
211
|
+
log_info("Starting Vite dev server (HMR enabled)")
|
|
212
|
+
return self._config.run_command
|
|
213
|
+
|
|
214
|
+
log_info("Starting Vite watch build process")
|
|
215
|
+
return self._config.build_watch_command
|
|
216
|
+
|
|
217
|
+
def _ensure_proxy_target(self) -> None:
|
|
218
|
+
"""Prepare proxy target URL and port for proxy modes (vite, proxy, ssr).
|
|
219
|
+
|
|
220
|
+
For all proxy modes in dev mode:
|
|
221
|
+
- Auto-selects a free port if VITE_PORT is not explicitly set
|
|
222
|
+
- Sets the port in runtime config for JS integrations to read
|
|
223
|
+
|
|
224
|
+
For 'vite' mode specifically:
|
|
225
|
+
- Forces loopback host unless VITE_ALLOW_REMOTE is set
|
|
226
|
+
- Sets _proxy_target directly (JS writes hotfile when server starts)
|
|
227
|
+
|
|
228
|
+
For 'proxy'/'ssr' modes:
|
|
229
|
+
- Port is written to .litestar.json for SSR framework to read
|
|
230
|
+
- SSR framework writes hotfile with actual URL when ready
|
|
231
|
+
- Proxy discovers target from hotfile at request time
|
|
232
|
+
"""
|
|
233
|
+
if not self._config.is_dev_mode:
|
|
234
|
+
return
|
|
235
|
+
|
|
236
|
+
if self._config.proxy_mode is None:
|
|
237
|
+
return
|
|
238
|
+
|
|
239
|
+
if os.getenv("VITE_PORT") is None and self._config.runtime.port == 5173:
|
|
240
|
+
self._config.runtime.port = pick_free_port()
|
|
241
|
+
|
|
242
|
+
if self._config.proxy_mode == "vite":
|
|
243
|
+
if self._proxy_target is not None:
|
|
244
|
+
return
|
|
245
|
+
if os.getenv("VITE_ALLOW_REMOTE", "False") not in TRUE_VALUES:
|
|
246
|
+
self._config.runtime.host = "127.0.0.1"
|
|
247
|
+
self._proxy_target = f"{self._config.protocol}://{self._config.host}:{self._config.port}"
|
|
248
|
+
|
|
249
|
+
def _configure_inertia(self, app_config: "AppConfig") -> "AppConfig":
|
|
250
|
+
"""Configure Inertia.js by registering an InertiaPlugin instance.
|
|
251
|
+
|
|
252
|
+
This is called automatically when `inertia` config is provided to ViteConfig.
|
|
253
|
+
Users can still use InertiaPlugin manually for more control.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
app_config: The Litestar application configuration.
|
|
257
|
+
|
|
258
|
+
Returns:
|
|
259
|
+
The modified application configuration.
|
|
260
|
+
"""
|
|
261
|
+
from litestar_vite.inertia.plugin import InertiaPlugin
|
|
262
|
+
|
|
263
|
+
inertia_plugin = InertiaPlugin(config=self._config.inertia) # type: ignore[arg-type]
|
|
264
|
+
app_config.plugins.append(inertia_plugin)
|
|
265
|
+
|
|
266
|
+
return app_config
|
|
267
|
+
|
|
268
|
+
def on_cli_init(self, cli: "Group") -> None:
|
|
269
|
+
"""Register CLI commands.
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
cli: The Click command group to add commands to.
|
|
273
|
+
"""
|
|
274
|
+
from litestar_vite.cli import vite_group
|
|
275
|
+
|
|
276
|
+
cli.add_command(vite_group)
|
|
277
|
+
|
|
278
|
+
def _configure_jinja_callables(self, app_config: "AppConfig") -> None:
|
|
279
|
+
"""Register Jinja2 template callables for Vite asset handling.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
app_config: The Litestar application configuration.
|
|
283
|
+
"""
|
|
284
|
+
from litestar.contrib.jinja import JinjaTemplateEngine
|
|
285
|
+
|
|
286
|
+
from litestar_vite.loader import render_asset_tag, render_hmr_client, render_routes, render_static_asset
|
|
287
|
+
|
|
288
|
+
template_config = app_config.template_config # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
|
|
289
|
+
if template_config and isinstance(
|
|
290
|
+
template_config.engine_instance, # pyright: ignore[reportUnknownMemberType]
|
|
291
|
+
JinjaTemplateEngine,
|
|
292
|
+
):
|
|
293
|
+
engine = template_config.engine_instance # pyright: ignore[reportUnknownMemberType]
|
|
294
|
+
engine.register_template_callable(key="vite_hmr", template_callable=render_hmr_client)
|
|
295
|
+
engine.register_template_callable(key="vite", template_callable=render_asset_tag)
|
|
296
|
+
engine.register_template_callable(key="vite_static", template_callable=render_static_asset)
|
|
297
|
+
engine.register_template_callable(key="vite_routes", template_callable=render_routes)
|
|
298
|
+
|
|
299
|
+
def _configure_static_files(self, app_config: "AppConfig") -> None:
|
|
300
|
+
"""Configure static file serving for Vite assets.
|
|
301
|
+
|
|
302
|
+
The static files router serves real files (JS, CSS, images). SPA fallback (serving
|
|
303
|
+
index.html for client-side routes) is handled by the AppHandler.
|
|
304
|
+
|
|
305
|
+
Args:
|
|
306
|
+
app_config: The Litestar application configuration.
|
|
307
|
+
"""
|
|
308
|
+
bundle_dir = self._resolve_bundle_dir()
|
|
309
|
+
|
|
310
|
+
resource_dir = Path(self._config.resource_dir)
|
|
311
|
+
if not resource_dir.is_absolute():
|
|
312
|
+
resource_dir = self._config.root_dir / resource_dir
|
|
313
|
+
|
|
314
|
+
static_dir = Path(self._config.static_dir)
|
|
315
|
+
if not static_dir.is_absolute():
|
|
316
|
+
static_dir = self._config.root_dir / static_dir
|
|
317
|
+
|
|
318
|
+
static_dirs = [bundle_dir, resource_dir]
|
|
319
|
+
if static_dir.exists() and static_dir != bundle_dir:
|
|
320
|
+
static_dirs.append(static_dir)
|
|
321
|
+
|
|
322
|
+
opt: dict[str, Any] = {}
|
|
323
|
+
if self._config.exclude_static_from_auth:
|
|
324
|
+
opt["exclude_from_auth"] = True
|
|
325
|
+
user_opt = self._static_files_config.get("opt", {})
|
|
326
|
+
if user_opt:
|
|
327
|
+
opt = {**opt, **user_opt}
|
|
328
|
+
|
|
329
|
+
base_config: dict[str, Any] = {
|
|
330
|
+
"directories": (static_dirs if self._config.is_dev_mode else [bundle_dir]),
|
|
331
|
+
"path": self._config.asset_url,
|
|
332
|
+
"name": "vite",
|
|
333
|
+
"html_mode": False,
|
|
334
|
+
"include_in_schema": False,
|
|
335
|
+
"opt": opt,
|
|
336
|
+
"exception_handlers": {NotFoundException: static_not_found_handler},
|
|
337
|
+
}
|
|
338
|
+
user_config = {k: v for k, v in self._static_files_config.items() if k != "opt"}
|
|
339
|
+
static_files_config: dict[str, Any] = {**base_config, **user_config}
|
|
340
|
+
app_config.route_handlers.append(create_static_files_router(**static_files_config))
|
|
341
|
+
|
|
342
|
+
def _configure_dev_proxy(self, app_config: "AppConfig") -> None:
|
|
343
|
+
"""Configure dev proxy middleware and handlers based on proxy_mode.
|
|
344
|
+
|
|
345
|
+
Args:
|
|
346
|
+
app_config: The Litestar application configuration.
|
|
347
|
+
"""
|
|
348
|
+
proxy_mode = self._config.proxy_mode
|
|
349
|
+
hotfile_path = self._resolve_hotfile_path()
|
|
350
|
+
|
|
351
|
+
if proxy_mode == "vite":
|
|
352
|
+
self._configure_vite_proxy(app_config, hotfile_path)
|
|
353
|
+
elif proxy_mode == "proxy":
|
|
354
|
+
self._configure_ssr_proxy(app_config, hotfile_path)
|
|
355
|
+
|
|
356
|
+
def _configure_vite_proxy(self, app_config: "AppConfig", hotfile_path: Path) -> None:
|
|
357
|
+
"""Configure Vite proxy mode (allow list).
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
app_config: The Litestar application configuration.
|
|
361
|
+
hotfile_path: Path to the hotfile.
|
|
362
|
+
"""
|
|
363
|
+
self._ensure_proxy_target()
|
|
364
|
+
app_config.middleware.append(
|
|
365
|
+
DefineMiddleware(
|
|
366
|
+
ViteProxyMiddleware,
|
|
367
|
+
hotfile_path=hotfile_path,
|
|
368
|
+
asset_url=self._config.asset_url,
|
|
369
|
+
resource_dir=self._config.resource_dir,
|
|
370
|
+
bundle_dir=self._config.bundle_dir,
|
|
371
|
+
root_dir=self._config.root_dir,
|
|
372
|
+
http2=self._config.http2,
|
|
373
|
+
plugin=self,
|
|
374
|
+
)
|
|
375
|
+
)
|
|
376
|
+
hmr_path = f"{self._config.asset_url.rstrip('/')}/vite-hmr"
|
|
377
|
+
app_config.route_handlers.append(
|
|
378
|
+
create_vite_hmr_handler(hotfile_path=hotfile_path, hmr_path=hmr_path, asset_url=self._config.asset_url)
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
def _configure_ssr_proxy(self, app_config: "AppConfig", hotfile_path: Path) -> None:
|
|
382
|
+
"""Configure SSR proxy mode (deny list).
|
|
383
|
+
|
|
384
|
+
Args:
|
|
385
|
+
app_config: The Litestar application configuration.
|
|
386
|
+
hotfile_path: Path to the hotfile.
|
|
387
|
+
"""
|
|
388
|
+
self._ensure_proxy_target()
|
|
389
|
+
external = self._config.external_dev_server
|
|
390
|
+
static_target = external.target if external else None
|
|
391
|
+
|
|
392
|
+
app_config.route_handlers.append(
|
|
393
|
+
create_ssr_proxy_controller(
|
|
394
|
+
target=static_target,
|
|
395
|
+
hotfile_path=hotfile_path if static_target is None else None,
|
|
396
|
+
http2=external.http2 if external else True,
|
|
397
|
+
plugin=self,
|
|
398
|
+
)
|
|
399
|
+
)
|
|
400
|
+
hmr_path = f"{self._config.asset_url.rstrip('/')}/vite-hmr"
|
|
401
|
+
app_config.route_handlers.append(
|
|
402
|
+
create_vite_hmr_handler(hotfile_path=hotfile_path, hmr_path=hmr_path, asset_url=self._config.asset_url)
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
def on_app_init(self, app_config: "AppConfig") -> "AppConfig":
|
|
406
|
+
"""Configure the Litestar application for Vite.
|
|
407
|
+
|
|
408
|
+
This method wires up supporting configuration for dev/prod operation:
|
|
409
|
+
|
|
410
|
+
- Adds types used by generated handlers to the signature namespace.
|
|
411
|
+
- Ensures a consistent NotFound handler for asset/proxy lookups.
|
|
412
|
+
- Registers optional Inertia and Jinja integrations.
|
|
413
|
+
- Configures static file routing when enabled.
|
|
414
|
+
- Configures dev proxy middleware based on proxy_mode.
|
|
415
|
+
- Creates/initializes the SPA handler where applicable and registers lifespans.
|
|
416
|
+
|
|
417
|
+
Args:
|
|
418
|
+
app_config: The Litestar application configuration.
|
|
419
|
+
|
|
420
|
+
Returns:
|
|
421
|
+
The modified application configuration.
|
|
422
|
+
"""
|
|
423
|
+
from litestar import Response
|
|
424
|
+
from litestar.connection import Request as LitestarRequest
|
|
425
|
+
|
|
426
|
+
app_config.signature_namespace["Response"] = Response
|
|
427
|
+
app_config.signature_namespace["Request"] = LitestarRequest
|
|
428
|
+
|
|
429
|
+
# Register proxy headers middleware FIRST if configured
|
|
430
|
+
# This must run before other middleware to ensure correct scheme/client in scope
|
|
431
|
+
if self._config.trusted_proxies is not None:
|
|
432
|
+
from litestar_vite.plugin._proxy_headers import ProxyHeadersMiddleware
|
|
433
|
+
|
|
434
|
+
app_config.middleware.insert(
|
|
435
|
+
0, # Insert at beginning for early processing
|
|
436
|
+
DefineMiddleware(ProxyHeadersMiddleware, trusted_hosts=self._config.trusted_proxies),
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
handlers: ExceptionHandlersMap = cast("ExceptionHandlersMap", app_config.exception_handlers or {}) # pyright: ignore
|
|
440
|
+
if NotFoundException not in handlers:
|
|
441
|
+
handlers[NotFoundException] = vite_not_found_handler
|
|
442
|
+
app_config.exception_handlers = handlers # pyright: ignore[reportUnknownMemberType]
|
|
443
|
+
|
|
444
|
+
if self._config.inertia is not None:
|
|
445
|
+
app_config = self._configure_inertia(app_config)
|
|
446
|
+
|
|
447
|
+
if JINJA_INSTALLED and self._config.mode in {"template", "htmx"}:
|
|
448
|
+
self._configure_jinja_callables(app_config)
|
|
449
|
+
|
|
450
|
+
skip_static = self._config.mode == "external" and self._config.is_dev_mode
|
|
451
|
+
if self._config.set_static_folders and not skip_static:
|
|
452
|
+
self._configure_static_files(app_config)
|
|
453
|
+
|
|
454
|
+
if self._config.is_dev_mode and self._config.proxy_mode is not None and not is_non_serving_assets_cli():
|
|
455
|
+
self._configure_dev_proxy(app_config)
|
|
456
|
+
|
|
457
|
+
use_spa_handler = self._config.spa_handler and self._config.mode in {"spa", "framework"}
|
|
458
|
+
use_spa_handler = use_spa_handler or (self._config.mode == "external" and not self._config.is_dev_mode)
|
|
459
|
+
if use_spa_handler:
|
|
460
|
+
from litestar_vite.handler import AppHandler
|
|
461
|
+
|
|
462
|
+
self._spa_handler = AppHandler(self._config)
|
|
463
|
+
app_config.route_handlers.append(self._spa_handler.create_route_handler())
|
|
464
|
+
elif self._config.mode == "hybrid":
|
|
465
|
+
from litestar_vite.handler import AppHandler
|
|
466
|
+
|
|
467
|
+
self._spa_handler = AppHandler(self._config)
|
|
468
|
+
|
|
469
|
+
app_config.lifespan.append(self.lifespan) # pyright: ignore[reportUnknownMemberType]
|
|
470
|
+
|
|
471
|
+
return app_config
|
|
472
|
+
|
|
473
|
+
def _check_health(self) -> None:
|
|
474
|
+
"""Check if the Vite dev server is running and ready.
|
|
475
|
+
|
|
476
|
+
Polls the dev server URL for up to 5 seconds.
|
|
477
|
+
"""
|
|
478
|
+
import time
|
|
479
|
+
|
|
480
|
+
url = f"{self._config.protocol}://{self._config.host}:{self._config.port}/__vite_ping"
|
|
481
|
+
for _ in range(50):
|
|
482
|
+
try:
|
|
483
|
+
httpx.get(url, timeout=0.1)
|
|
484
|
+
except httpx.HTTPError:
|
|
485
|
+
time.sleep(0.1)
|
|
486
|
+
else:
|
|
487
|
+
log_success("Vite dev server responded to health check")
|
|
488
|
+
return
|
|
489
|
+
log_fail("Vite server health check failed")
|
|
490
|
+
|
|
491
|
+
def _run_health_check(self) -> None:
|
|
492
|
+
"""Run the appropriate health check based on proxy mode."""
|
|
493
|
+
match self._config.proxy_mode:
|
|
494
|
+
case "proxy":
|
|
495
|
+
self._check_ssr_health(self._resolve_hotfile_path())
|
|
496
|
+
case _:
|
|
497
|
+
self._check_health()
|
|
498
|
+
|
|
499
|
+
def _check_ssr_health(self, hotfile_path: Path, timeout: float = 10.0) -> bool:
|
|
500
|
+
"""Wait for SSR framework to be ready via hotfile.
|
|
501
|
+
|
|
502
|
+
Polls intelligently for the hotfile and validates HTTP connectivity.
|
|
503
|
+
Exits early as soon as the server is confirmed ready.
|
|
504
|
+
|
|
505
|
+
Args:
|
|
506
|
+
hotfile_path: Path to the hotfile written by the SSR framework.
|
|
507
|
+
timeout: Maximum time to wait in seconds (default 10s).
|
|
508
|
+
|
|
509
|
+
Returns:
|
|
510
|
+
True if SSR server is ready, False if timeout reached.
|
|
511
|
+
"""
|
|
512
|
+
import time
|
|
513
|
+
|
|
514
|
+
start = time.time()
|
|
515
|
+
last_url = None
|
|
516
|
+
|
|
517
|
+
while time.time() - start < timeout:
|
|
518
|
+
if hotfile_path.exists():
|
|
519
|
+
try:
|
|
520
|
+
url = hotfile_path.read_text(encoding="utf-8").strip()
|
|
521
|
+
if url:
|
|
522
|
+
last_url = url
|
|
523
|
+
resp = httpx.get(url, timeout=0.5, follow_redirects=True)
|
|
524
|
+
if resp.status_code < 500:
|
|
525
|
+
log_success(f"SSR server ready at {url}")
|
|
526
|
+
return True
|
|
527
|
+
except OSError:
|
|
528
|
+
pass
|
|
529
|
+
except httpx.HTTPError:
|
|
530
|
+
pass
|
|
531
|
+
|
|
532
|
+
time.sleep(0.1)
|
|
533
|
+
|
|
534
|
+
if last_url:
|
|
535
|
+
log_fail(f"SSR server at {last_url} did not respond within {timeout}s")
|
|
536
|
+
else:
|
|
537
|
+
log_fail(f"SSR hotfile not found at {hotfile_path} within {timeout}s")
|
|
538
|
+
return False
|
|
539
|
+
|
|
540
|
+
def _export_types_sync(self, app: "Litestar") -> None:
|
|
541
|
+
"""Export type metadata synchronously on startup.
|
|
542
|
+
|
|
543
|
+
This exports OpenAPI schema, route metadata (JSON), typed routes (TypeScript),
|
|
544
|
+
and Inertia pages metadata when type generation is enabled. The Vite plugin
|
|
545
|
+
watches these files and triggers @hey-api/openapi-ts when they change.
|
|
546
|
+
|
|
547
|
+
Uses the shared `export_integration_assets` function to guarantee
|
|
548
|
+
byte-identical output between CLI and plugin.
|
|
549
|
+
|
|
550
|
+
Args:
|
|
551
|
+
app: The Litestar application instance.
|
|
552
|
+
"""
|
|
553
|
+
from litestar_vite.codegen import export_integration_assets
|
|
554
|
+
|
|
555
|
+
try:
|
|
556
|
+
result = export_integration_assets(app, self._config)
|
|
557
|
+
|
|
558
|
+
if result.exported_files:
|
|
559
|
+
log_success(f"Types exported → {', '.join(result.exported_files)}")
|
|
560
|
+
except (OSError, TypeError, ValueError, ImportError) as e: # pragma: no cover
|
|
561
|
+
log_warn(f"Type export failed: {e}")
|
|
562
|
+
|
|
563
|
+
@contextmanager
|
|
564
|
+
def server_lifespan(self, app: "Litestar") -> "Iterator[None]":
|
|
565
|
+
"""Server-level lifespan context manager (runs ONCE per server, before workers).
|
|
566
|
+
|
|
567
|
+
This is called by Litestar CLI before workers start. It handles:
|
|
568
|
+
- Environment variable setup (with logging)
|
|
569
|
+
- Vite dev server process start/stop (ONE instance for all workers)
|
|
570
|
+
- Type export on startup
|
|
571
|
+
|
|
572
|
+
Note: SPA handler and asset loader initialization happens in the per-worker
|
|
573
|
+
`lifespan` method, which is auto-registered in `on_app_init`.
|
|
574
|
+
|
|
575
|
+
Hotfile behavior: the hotfile is written before starting the dev server to ensure proxy
|
|
576
|
+
middleware and SPA handlers can resolve a target URL immediately on first request.
|
|
577
|
+
|
|
578
|
+
Args:
|
|
579
|
+
app: The Litestar application instance.
|
|
580
|
+
|
|
581
|
+
Yields:
|
|
582
|
+
None
|
|
583
|
+
"""
|
|
584
|
+
if self._config.is_dev_mode:
|
|
585
|
+
self._ensure_proxy_target()
|
|
586
|
+
|
|
587
|
+
if self._config.set_environment:
|
|
588
|
+
set_environment(config=self._config)
|
|
589
|
+
set_app_environment(app)
|
|
590
|
+
log_info("Applied Vite environment variables")
|
|
591
|
+
|
|
592
|
+
self._export_types_sync(app)
|
|
593
|
+
|
|
594
|
+
if self._config.is_dev_mode and self._config.runtime.start_dev_server:
|
|
595
|
+
ext = self._config.runtime.external_dev_server
|
|
596
|
+
is_external = isinstance(ext, ExternalDevServer) and ext.enabled
|
|
597
|
+
|
|
598
|
+
command_to_run = self._resolve_dev_command()
|
|
599
|
+
if is_external and isinstance(ext, ExternalDevServer) and ext.target:
|
|
600
|
+
self._write_hotfile(ext.target)
|
|
601
|
+
elif not is_external:
|
|
602
|
+
target_url = f"{self._config.protocol}://{self._config.host}:{self._config.port}"
|
|
603
|
+
self._write_hotfile(target_url)
|
|
604
|
+
|
|
605
|
+
try:
|
|
606
|
+
self._vite_process.start(command_to_run, self._config.root_dir)
|
|
607
|
+
log_success("Dev server process started")
|
|
608
|
+
if self._config.health_check and not is_external:
|
|
609
|
+
self._run_health_check()
|
|
610
|
+
yield
|
|
611
|
+
finally:
|
|
612
|
+
self._vite_process.stop()
|
|
613
|
+
log_info("Dev server process stopped.")
|
|
614
|
+
else:
|
|
615
|
+
yield
|
|
616
|
+
|
|
617
|
+
@asynccontextmanager
|
|
618
|
+
async def lifespan(self, app: "Litestar") -> "AsyncIterator[None]":
|
|
619
|
+
"""Worker-level lifespan context manager (runs per worker process).
|
|
620
|
+
|
|
621
|
+
This is auto-registered in `on_app_init` and handles per-worker initialization:
|
|
622
|
+
- Environment variable setup (silently - each worker needs process-local env vars)
|
|
623
|
+
- Shared proxy client initialization (dev mode only, for ViteProxyMiddleware/SSRProxyController)
|
|
624
|
+
- Asset loader initialization
|
|
625
|
+
- SPA handler initialization
|
|
626
|
+
- Route metadata injection
|
|
627
|
+
|
|
628
|
+
Note: The Vite dev server process is started in `server_lifespan`, which
|
|
629
|
+
runs ONCE per server before workers start.
|
|
630
|
+
|
|
631
|
+
Args:
|
|
632
|
+
app: The Litestar application instance.
|
|
633
|
+
|
|
634
|
+
Yields:
|
|
635
|
+
None
|
|
636
|
+
"""
|
|
637
|
+
from litestar_vite.loader import ViteAssetLoader
|
|
638
|
+
|
|
639
|
+
if self._config.set_environment:
|
|
640
|
+
set_environment(config=self._config)
|
|
641
|
+
set_app_environment(app)
|
|
642
|
+
|
|
643
|
+
# Initialize shared proxy client for ViteProxyMiddleware/SSRProxyController
|
|
644
|
+
# Uses connection pooling for better performance (HTTP/2 multiplexing, TLS reuse)
|
|
645
|
+
if self._config.is_dev_mode and self._config.proxy_mode is not None:
|
|
646
|
+
self._proxy_client = create_proxy_client(http2=self._config.http2)
|
|
647
|
+
|
|
648
|
+
if self._asset_loader is None:
|
|
649
|
+
self._asset_loader = ViteAssetLoader(config=self._config)
|
|
650
|
+
await self._asset_loader.initialize()
|
|
651
|
+
|
|
652
|
+
if self._spa_handler is not None and not self._spa_handler.is_initialized:
|
|
653
|
+
self._spa_handler.initialize_sync(vite_url=self._proxy_target)
|
|
654
|
+
log_success("SPA handler initialized")
|
|
655
|
+
|
|
656
|
+
is_ssr_mode = self._config.mode == "framework" or self._config.proxy_mode == "proxy"
|
|
657
|
+
if not self._config.is_dev_mode and not self._config.has_built_assets() and not is_ssr_mode:
|
|
658
|
+
log_warn(
|
|
659
|
+
"Vite dev server is disabled (dev_mode=False) but no index.html was found. "
|
|
660
|
+
"Run your front-end build or set VITE_DEV_MODE=1 to enable HMR."
|
|
661
|
+
)
|
|
662
|
+
|
|
663
|
+
try:
|
|
664
|
+
yield
|
|
665
|
+
finally:
|
|
666
|
+
if self._proxy_client is not None:
|
|
667
|
+
await self._proxy_client.aclose()
|
|
668
|
+
self._proxy_client = None
|
|
669
|
+
if self._spa_handler is not None:
|
|
670
|
+
await self._spa_handler.shutdown_async()
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
__all__ = (
|
|
674
|
+
"ProxyHeadersMiddleware",
|
|
675
|
+
"StaticFilesConfig",
|
|
676
|
+
"TrustedHosts",
|
|
677
|
+
"VitePlugin",
|
|
678
|
+
"ViteProcess",
|
|
679
|
+
"ViteProxyMiddleware",
|
|
680
|
+
"create_ssr_proxy_controller",
|
|
681
|
+
"create_vite_hmr_handler",
|
|
682
|
+
"get_litestar_route_prefixes",
|
|
683
|
+
"is_litestar_route",
|
|
684
|
+
"resolve_litestar_version",
|
|
685
|
+
"set_app_environment",
|
|
686
|
+
"set_environment",
|
|
687
|
+
)
|