litestar-vite 0.13.0__py3-none-any.whl → 0.13.2__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.
Potentially problematic release.
This version of litestar-vite might be problematic. Click here for more details.
- litestar_vite/__init__.py +0 -2
- litestar_vite/__metadata__.py +0 -2
- litestar_vite/cli.py +33 -40
- litestar_vite/commands.py +48 -38
- litestar_vite/config.py +6 -7
- litestar_vite/inertia/_utils.py +53 -17
- litestar_vite/inertia/config.py +5 -7
- litestar_vite/inertia/exception_handler.py +22 -8
- litestar_vite/inertia/helpers.py +57 -61
- litestar_vite/inertia/middleware.py +4 -6
- litestar_vite/inertia/plugin.py +22 -9
- litestar_vite/inertia/request.py +58 -20
- litestar_vite/inertia/response.py +42 -40
- litestar_vite/inertia/routes.py +7 -9
- litestar_vite/inertia/types.py +6 -8
- litestar_vite/loader.py +95 -29
- litestar_vite/plugin.py +42 -38
- {litestar_vite-0.13.0.dist-info → litestar_vite-0.13.2.dist-info}/METADATA +3 -3
- litestar_vite-0.13.2.dist-info/RECORD +30 -0
- litestar_vite-0.13.0.dist-info/RECORD +0 -30
- {litestar_vite-0.13.0.dist-info → litestar_vite-0.13.2.dist-info}/WHEEL +0 -0
- {litestar_vite-0.13.0.dist-info → litestar_vite-0.13.2.dist-info}/licenses/LICENSE +0 -0
litestar_vite/__init__.py
CHANGED
litestar_vite/__metadata__.py
CHANGED
litestar_vite/cli.py
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
from pathlib import Path
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
2
|
+
from typing import TYPE_CHECKING, Optional
|
|
5
3
|
|
|
6
4
|
from click import Context, group, option
|
|
7
5
|
from click import Path as ClickPath
|
|
8
|
-
from litestar.cli._utils import
|
|
9
|
-
LitestarEnv,
|
|
10
|
-
LitestarGroup,
|
|
11
|
-
)
|
|
6
|
+
from litestar.cli._utils import LitestarEnv, LitestarGroup # pyright: ignore[reportPrivateImportUsage]
|
|
12
7
|
|
|
13
8
|
if TYPE_CHECKING:
|
|
14
9
|
from litestar import Litestar
|
|
@@ -89,18 +84,18 @@ def vite_group() -> None:
|
|
|
89
84
|
is_flag=True,
|
|
90
85
|
)
|
|
91
86
|
def vite_init(
|
|
92
|
-
ctx: Context,
|
|
93
|
-
vite_port: int
|
|
94
|
-
enable_ssr: bool
|
|
95
|
-
asset_url: str
|
|
96
|
-
root_path: Path
|
|
97
|
-
bundle_path: Path
|
|
98
|
-
resource_path: Path
|
|
99
|
-
public_path: Path
|
|
100
|
-
overwrite: bool,
|
|
101
|
-
verbose: bool,
|
|
102
|
-
no_prompt: bool,
|
|
103
|
-
no_install: bool,
|
|
87
|
+
ctx: "Context",
|
|
88
|
+
vite_port: "Optional[int]",
|
|
89
|
+
enable_ssr: "Optional[bool]",
|
|
90
|
+
asset_url: "Optional[str]",
|
|
91
|
+
root_path: "Optional[Path]",
|
|
92
|
+
bundle_path: "Optional[Path]",
|
|
93
|
+
resource_path: "Optional[Path]",
|
|
94
|
+
public_path: "Optional[Path]",
|
|
95
|
+
overwrite: "bool",
|
|
96
|
+
verbose: "bool",
|
|
97
|
+
no_prompt: "bool",
|
|
98
|
+
no_install: "bool",
|
|
104
99
|
) -> None: # sourcery skip: low-code-quality
|
|
105
100
|
"""Run vite build."""
|
|
106
101
|
import os
|
|
@@ -108,9 +103,7 @@ def vite_init(
|
|
|
108
103
|
from importlib.util import find_spec
|
|
109
104
|
from pathlib import Path
|
|
110
105
|
|
|
111
|
-
from litestar.cli._utils import
|
|
112
|
-
console,
|
|
113
|
-
)
|
|
106
|
+
from litestar.cli._utils import console # pyright: ignore[reportPrivateImportUsage]
|
|
114
107
|
from rich.prompt import Confirm
|
|
115
108
|
|
|
116
109
|
from litestar_vite import VitePlugin
|
|
@@ -175,7 +168,6 @@ def vite_init(
|
|
|
175
168
|
)
|
|
176
169
|
install_dir = os.environ.get("VIRTUAL_ENV", sys.prefix)
|
|
177
170
|
console.rule("[yellow]Starting Nodeenv installation process[/]", align="left")
|
|
178
|
-
console.print(f"Installing Node environment into {install_dir}")
|
|
179
171
|
execute_command(command_to_run=[nodeenv_command, install_dir, "--force", "--quiet"], cwd=root_path)
|
|
180
172
|
|
|
181
173
|
console.rule("[yellow]Starting package installation process[/]", align="left")
|
|
@@ -188,14 +180,14 @@ def vite_init(
|
|
|
188
180
|
help="Install frontend packages.",
|
|
189
181
|
)
|
|
190
182
|
@option("--verbose", type=bool, help="Enable verbose output.", default=False, is_flag=True)
|
|
191
|
-
def vite_install(app: Litestar, verbose: bool) -> None:
|
|
183
|
+
def vite_install(app: "Litestar", verbose: "bool") -> None:
|
|
192
184
|
"""Run vite build."""
|
|
193
185
|
import os
|
|
194
186
|
import sys
|
|
195
187
|
from importlib.util import find_spec
|
|
196
188
|
from pathlib import Path
|
|
197
189
|
|
|
198
|
-
from litestar.cli._utils import console
|
|
190
|
+
from litestar.cli._utils import console # pyright: ignore[reportPrivateImportUsage]
|
|
199
191
|
|
|
200
192
|
from litestar_vite.commands import execute_command
|
|
201
193
|
from litestar_vite.plugin import VitePlugin
|
|
@@ -213,7 +205,6 @@ def vite_install(app: Litestar, verbose: bool) -> None:
|
|
|
213
205
|
)
|
|
214
206
|
install_dir = os.environ.get("VIRTUAL_ENV", sys.prefix)
|
|
215
207
|
console.rule("[yellow]Starting Nodeenv installation process[/]", align="left")
|
|
216
|
-
console.print("Installing Node environment to %s:", install_dir)
|
|
217
208
|
execute_command(command_to_run=[nodeenv_command, install_dir, "--force", "--quiet"], cwd=plugin.config.root_dir)
|
|
218
209
|
|
|
219
210
|
console.rule("[yellow]Starting package installation process[/]", align="left")
|
|
@@ -226,11 +217,9 @@ def vite_install(app: Litestar, verbose: bool) -> None:
|
|
|
226
217
|
help="Building frontend assets with Vite.",
|
|
227
218
|
)
|
|
228
219
|
@option("--verbose", type=bool, help="Enable verbose output.", default=False, is_flag=True)
|
|
229
|
-
def vite_build(app: Litestar, verbose: bool) -> None:
|
|
220
|
+
def vite_build(app: "Litestar", verbose: "bool") -> None:
|
|
230
221
|
"""Run vite build."""
|
|
231
|
-
from litestar.cli._utils import
|
|
232
|
-
console,
|
|
233
|
-
)
|
|
222
|
+
from litestar.cli._utils import console # pyright: ignore[reportPrivateImportUsage]
|
|
234
223
|
|
|
235
224
|
from litestar_vite.commands import execute_command
|
|
236
225
|
from litestar_vite.plugin import VitePlugin, set_environment
|
|
@@ -253,11 +242,9 @@ def vite_build(app: Litestar, verbose: bool) -> None:
|
|
|
253
242
|
help="Serving frontend assets with Vite.",
|
|
254
243
|
)
|
|
255
244
|
@option("--verbose", type=bool, help="Enable verbose output.", default=False, is_flag=True)
|
|
256
|
-
def vite_serve(app: Litestar, verbose: bool) -> None:
|
|
245
|
+
def vite_serve(app: "Litestar", verbose: "bool") -> None:
|
|
257
246
|
"""Run vite serve."""
|
|
258
|
-
from litestar.cli._utils import
|
|
259
|
-
console,
|
|
260
|
-
)
|
|
247
|
+
from litestar.cli._utils import console # pyright: ignore[reportPrivateImportUsage]
|
|
261
248
|
|
|
262
249
|
from litestar_vite.commands import execute_command
|
|
263
250
|
from litestar_vite.plugin import VitePlugin, set_environment
|
|
@@ -289,13 +276,19 @@ def vite_serve(app: Litestar, verbose: bool) -> None:
|
|
|
289
276
|
show_default=True,
|
|
290
277
|
)
|
|
291
278
|
@option("--verbose", type=bool, help="Enable verbose output.", default=False, is_flag=True)
|
|
292
|
-
def generate_js_routes(app: Litestar, output: Path, verbose: bool) -> None:
|
|
293
|
-
"""Run vite serve.
|
|
279
|
+
def generate_js_routes(app: "Litestar", output: "Path", verbose: "bool") -> None:
|
|
280
|
+
"""Run vite serve.
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
app: The Litestar application instance.
|
|
284
|
+
output: The path to the output file.
|
|
285
|
+
verbose: Whether to enable verbose output.
|
|
286
|
+
|
|
287
|
+
Raises:
|
|
288
|
+
LitestarCLIException: If the output file cannot be written.
|
|
289
|
+
"""
|
|
294
290
|
import msgspec
|
|
295
|
-
from litestar.cli._utils import
|
|
296
|
-
LitestarCLIException,
|
|
297
|
-
console,
|
|
298
|
-
)
|
|
291
|
+
from litestar.cli._utils import LitestarCLIException, console # pyright: ignore[reportPrivateImportUsage]
|
|
299
292
|
from litestar.serialization import encode_json, get_serializer
|
|
300
293
|
|
|
301
294
|
from litestar_vite.plugin import VitePlugin, set_environment
|
litestar_vite/commands.py
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
import platform
|
|
4
2
|
import subprocess
|
|
3
|
+
from collections.abc import MutableMapping
|
|
5
4
|
from pathlib import Path
|
|
6
|
-
from typing import TYPE_CHECKING, Any,
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Optional, Union
|
|
7
6
|
|
|
8
7
|
if TYPE_CHECKING:
|
|
8
|
+
from collections.abc import MutableMapping
|
|
9
|
+
|
|
9
10
|
from jinja2 import Environment, Template
|
|
10
11
|
from litestar import Litestar
|
|
11
12
|
|
|
12
|
-
VITE_INIT_TEMPLATES: set[str] = {"package.json.j2", "tsconfig.json.j2", "vite.config.ts.j2"}
|
|
13
|
-
DEFAULT_RESOURCES: set[str] = {"styles.css.j2", "main.ts.j2"}
|
|
14
|
-
DEFAULT_DEV_DEPENDENCIES: dict[str, str] = {
|
|
15
|
-
"typescript": "^5.
|
|
16
|
-
"vite": "^6.
|
|
17
|
-
"litestar-vite-plugin": "^0.13.
|
|
18
|
-
"@types/node": "^22.
|
|
13
|
+
VITE_INIT_TEMPLATES: "set[str]" = {"package.json.j2", "tsconfig.json.j2", "vite.config.ts.j2"}
|
|
14
|
+
DEFAULT_RESOURCES: "set[str]" = {"styles.css.j2", "main.ts.j2"}
|
|
15
|
+
DEFAULT_DEV_DEPENDENCIES: "dict[str, str]" = {
|
|
16
|
+
"typescript": "^5.8.3",
|
|
17
|
+
"vite": "^6.3.5",
|
|
18
|
+
"litestar-vite-plugin": "^0.13.2",
|
|
19
|
+
"@types/node": "^22.15.3",
|
|
19
20
|
}
|
|
20
|
-
DEFAULT_DEPENDENCIES: dict[str, str] = {"axios": "^1.
|
|
21
|
+
DEFAULT_DEPENDENCIES: "dict[str, str]" = {"axios": "^1.9.0"}
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
def to_json(value: Any) -> str:
|
|
24
|
+
def to_json(value: "Any") -> str:
|
|
24
25
|
"""Serialize JSON field values.
|
|
25
26
|
|
|
26
27
|
Args:
|
|
@@ -35,15 +36,15 @@ def to_json(value: Any) -> str:
|
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
def init_vite(
|
|
38
|
-
app: Litestar,
|
|
39
|
-
root_path: Path,
|
|
40
|
-
resource_path: Path,
|
|
41
|
-
asset_url: str,
|
|
42
|
-
public_path: Path,
|
|
43
|
-
bundle_path: Path,
|
|
44
|
-
enable_ssr: bool,
|
|
39
|
+
app: "Litestar",
|
|
40
|
+
root_path: "Path",
|
|
41
|
+
resource_path: "Path",
|
|
42
|
+
asset_url: "str",
|
|
43
|
+
public_path: "Path",
|
|
44
|
+
bundle_path: "Path",
|
|
45
|
+
enable_ssr: "bool",
|
|
45
46
|
vite_port: int,
|
|
46
|
-
hot_file: Path,
|
|
47
|
+
hot_file: "Path",
|
|
47
48
|
litestar_port: int,
|
|
48
49
|
) -> None:
|
|
49
50
|
"""Initialize a new Vite project.
|
|
@@ -61,7 +62,7 @@ def init_vite(
|
|
|
61
62
|
litestar_port: Port for Litestar server.
|
|
62
63
|
"""
|
|
63
64
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
|
64
|
-
from litestar.cli._utils import console
|
|
65
|
+
from litestar.cli._utils import console # pyright: ignore[reportPrivateImportUsage]
|
|
65
66
|
from litestar.utils import module_loader
|
|
66
67
|
|
|
67
68
|
template_path = module_loader.module_to_os_path("litestar_vite.templates")
|
|
@@ -70,11 +71,11 @@ def init_vite(
|
|
|
70
71
|
autoescape=select_autoescape(),
|
|
71
72
|
)
|
|
72
73
|
|
|
73
|
-
enabled_templates: set[str] = VITE_INIT_TEMPLATES
|
|
74
|
-
enabled_resources: set[str] = DEFAULT_RESOURCES
|
|
75
|
-
dependencies: dict[str, str] = DEFAULT_DEPENDENCIES
|
|
76
|
-
dev_dependencies: dict[str, str] = DEFAULT_DEV_DEPENDENCIES
|
|
77
|
-
templates: dict[str, Template] = {
|
|
74
|
+
enabled_templates: "set[str]" = VITE_INIT_TEMPLATES
|
|
75
|
+
enabled_resources: "set[str]" = DEFAULT_RESOURCES
|
|
76
|
+
dependencies: "dict[str, str]" = DEFAULT_DEPENDENCIES
|
|
77
|
+
dev_dependencies: "dict[str, str]" = DEFAULT_DEV_DEPENDENCIES
|
|
78
|
+
templates: "dict[str, Template]" = {
|
|
78
79
|
template_name: get_template(environment=vite_template_env, name=template_name)
|
|
79
80
|
for template_name in enabled_templates
|
|
80
81
|
}
|
|
@@ -82,7 +83,7 @@ def init_vite(
|
|
|
82
83
|
# Prepare root_path
|
|
83
84
|
root_path.mkdir(parents=True, exist_ok=True)
|
|
84
85
|
for template_name, template in templates.items():
|
|
85
|
-
target_file_name = template_name
|
|
86
|
+
target_file_name = template_name.removesuffix(".j2")
|
|
86
87
|
target_file_path = root_path / target_file_name
|
|
87
88
|
with target_file_path.open(mode="w") as file:
|
|
88
89
|
console.print(f" * Writing {target_file_name} to {target_file_path!s}")
|
|
@@ -90,8 +91,7 @@ def init_vite(
|
|
|
90
91
|
file.write(
|
|
91
92
|
template.render(
|
|
92
93
|
entry_point=[
|
|
93
|
-
f"{resource_path!s}/{resource_name
|
|
94
|
-
for resource_name in enabled_resources
|
|
94
|
+
f"{resource_path!s}/{resource_name.removesuffix('.j2')}" for resource_name in enabled_resources
|
|
95
95
|
],
|
|
96
96
|
enable_ssr=enable_ssr,
|
|
97
97
|
asset_url=asset_url,
|
|
@@ -112,27 +112,37 @@ def init_vite(
|
|
|
112
112
|
(root_path / resource_path).mkdir(parents=True, exist_ok=True)
|
|
113
113
|
for resource_name in enabled_resources:
|
|
114
114
|
template = get_template(environment=vite_template_env, name=resource_name)
|
|
115
|
-
target_file_name = f"{resource_name
|
|
115
|
+
target_file_name = f"{resource_name.removesuffix('.j2')}"
|
|
116
116
|
target_file_path = root_path / resource_path / target_file_name
|
|
117
117
|
with target_file_path.open(mode="w") as file:
|
|
118
118
|
console.print(
|
|
119
|
-
f" * Writing {resource_name
|
|
119
|
+
f" * Writing {resource_name.removesuffix('.j2')} to {target_file_path!s}",
|
|
120
120
|
)
|
|
121
121
|
file.write(template.render())
|
|
122
122
|
console.print("[yellow]Vite initialization completed.[/]")
|
|
123
123
|
|
|
124
124
|
|
|
125
125
|
def get_template(
|
|
126
|
-
environment: Environment,
|
|
127
|
-
name: str
|
|
128
|
-
parent: str
|
|
129
|
-
globals: MutableMapping[str, Any]
|
|
130
|
-
) -> Template:
|
|
126
|
+
environment: "Environment",
|
|
127
|
+
name: "Union[str, Template]",
|
|
128
|
+
parent: "Optional[str]" = None,
|
|
129
|
+
globals: "Optional[MutableMapping[str, Any]]" = None, # noqa: A002
|
|
130
|
+
) -> "Template":
|
|
131
131
|
return environment.get_template(name=name, parent=parent, globals=globals)
|
|
132
132
|
|
|
133
133
|
|
|
134
|
-
def execute_command(
|
|
135
|
-
"""
|
|
134
|
+
def execute_command(
|
|
135
|
+
command_to_run: "list[str]", cwd: "Optional[Union[str, Path]]" = None
|
|
136
|
+
) -> "subprocess.CompletedProcess[bytes]":
|
|
137
|
+
"""Run Vite in a subprocess.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
command_to_run: The command to run.
|
|
141
|
+
cwd: The current working directory.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
The completed process.
|
|
145
|
+
"""
|
|
136
146
|
kwargs = {}
|
|
137
147
|
if cwd is not None:
|
|
138
148
|
kwargs["cwd"] = Path(cwd)
|
litestar_vite/config.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
import os
|
|
4
2
|
from dataclasses import dataclass, field
|
|
5
3
|
from pathlib import Path
|
|
4
|
+
from typing import Union
|
|
6
5
|
|
|
7
6
|
__all__ = ("ViteConfig",)
|
|
8
7
|
TRUE_VALUES = {"True", "true", "1", "yes", "Y", "T"}
|
|
@@ -17,17 +16,17 @@ class ViteConfig:
|
|
|
17
16
|
'plugins' key.
|
|
18
17
|
"""
|
|
19
18
|
|
|
20
|
-
bundle_dir: Path
|
|
19
|
+
bundle_dir: "Union[Path, str]" = field(default="public")
|
|
21
20
|
"""Location of the compiled assets from Vite.
|
|
22
21
|
|
|
23
22
|
The manifest file will also be found here.
|
|
24
23
|
"""
|
|
25
|
-
resource_dir: Path
|
|
24
|
+
resource_dir: "Union[Path, str]" = field(default="resources")
|
|
26
25
|
"""The directory where all typescript/javascript source are written.
|
|
27
26
|
|
|
28
27
|
In a standalone Vue or React application, this would be equivalent to the ``./src`` directory.
|
|
29
28
|
"""
|
|
30
|
-
public_dir: Path
|
|
29
|
+
public_dir: "Union[Path, str]" = field(default="public")
|
|
31
30
|
"""The optional public directory Vite serves assets from.
|
|
32
31
|
|
|
33
32
|
In a standalone Vue or React application, this would be equivalent to the ``./public`` directory.
|
|
@@ -45,9 +44,9 @@ class ViteConfig:
|
|
|
45
44
|
"""Enable HMR for Vite development server."""
|
|
46
45
|
ssr_enabled: bool = False
|
|
47
46
|
"""Enable SSR."""
|
|
48
|
-
ssr_output_dir: Path
|
|
47
|
+
ssr_output_dir: "Union[Path, str, None]" = None
|
|
49
48
|
"""SSR Output path"""
|
|
50
|
-
root_dir: Path
|
|
49
|
+
root_dir: "Union[Path, str, None]" = None
|
|
51
50
|
"""The is the base path to your application.
|
|
52
51
|
|
|
53
52
|
In a standalone Vue or React application, this would be equivalent to the top-level project folder containing the ``./src`` directory.
|
litestar_vite/inertia/_utils.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
from enum import Enum
|
|
4
2
|
from typing import TYPE_CHECKING, Any, Callable
|
|
5
3
|
|
|
@@ -18,43 +16,81 @@ class InertiaHeaders(str, Enum):
|
|
|
18
16
|
REFERER = "Referer"
|
|
19
17
|
|
|
20
18
|
|
|
21
|
-
def get_enabled_header(enabled: bool = True) -> dict[str, Any]:
|
|
22
|
-
"""True if inertia is enabled.
|
|
19
|
+
def get_enabled_header(enabled: bool = True) -> "dict[str, Any]":
|
|
20
|
+
"""True if inertia is enabled.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
enabled: Whether inertia is enabled.
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
The headers for inertia.
|
|
27
|
+
"""
|
|
23
28
|
|
|
24
29
|
return {InertiaHeaders.ENABLED.value: "true" if enabled else "false"}
|
|
25
30
|
|
|
26
31
|
|
|
27
|
-
def get_version_header(version: str) -> dict[str, Any]:
|
|
28
|
-
"""Return headers for change swap method response.
|
|
32
|
+
def get_version_header(version: str) -> "dict[str, Any]":
|
|
33
|
+
"""Return headers for change swap method response.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
version: The version of the inertia.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
The headers for inertia.
|
|
40
|
+
"""
|
|
29
41
|
return {InertiaHeaders.VERSION.value: version}
|
|
30
42
|
|
|
31
43
|
|
|
32
|
-
def get_partial_data_header(partial: str) -> dict[str, Any]:
|
|
33
|
-
"""Return headers for a partial data response.
|
|
44
|
+
def get_partial_data_header(partial: str) -> "dict[str, Any]":
|
|
45
|
+
"""Return headers for a partial data response.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
partial: The partial data.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
The headers for inertia.
|
|
52
|
+
"""
|
|
34
53
|
return {InertiaHeaders.PARTIAL_DATA.value: partial}
|
|
35
54
|
|
|
36
55
|
|
|
37
|
-
def get_partial_component_header(partial: str) -> dict[str, Any]:
|
|
38
|
-
"""Return headers for a partial data response.
|
|
56
|
+
def get_partial_component_header(partial: str) -> "dict[str, Any]":
|
|
57
|
+
"""Return headers for a partial data response.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
partial: The partial data.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
The headers for inertia.
|
|
64
|
+
"""
|
|
39
65
|
return {InertiaHeaders.PARTIAL_COMPONENT.value: partial}
|
|
40
66
|
|
|
41
67
|
|
|
42
|
-
def get_headers(inertia_headers: InertiaHeaderType) -> dict[str, Any]:
|
|
43
|
-
"""Return headers for Inertia responses.
|
|
68
|
+
def get_headers(inertia_headers: "InertiaHeaderType") -> "dict[str, Any]":
|
|
69
|
+
"""Return headers for Inertia responses.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
inertia_headers: The inertia headers.
|
|
73
|
+
|
|
74
|
+
Raises:
|
|
75
|
+
ValueError: If the inertia headers are None.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
The headers for inertia.
|
|
79
|
+
"""
|
|
44
80
|
if not inertia_headers:
|
|
45
81
|
msg = "Value for inertia_headers cannot be None."
|
|
46
82
|
raise ValueError(msg)
|
|
47
|
-
inertia_headers_dict: dict[str, Callable[..., dict[str, Any]]] = {
|
|
83
|
+
inertia_headers_dict: "dict[str, Callable[..., dict[str, Any]]]" = {
|
|
48
84
|
"enabled": get_enabled_header,
|
|
49
85
|
"partial_data": get_partial_data_header,
|
|
50
86
|
"partial_component": get_partial_component_header,
|
|
51
87
|
"version": get_version_header,
|
|
52
88
|
}
|
|
53
89
|
|
|
54
|
-
header: dict[str, Any] = {}
|
|
55
|
-
response: dict[str, Any]
|
|
56
|
-
key: str
|
|
57
|
-
value: Any
|
|
90
|
+
header: "dict[str, Any]" = {}
|
|
91
|
+
response: "dict[str, Any]"
|
|
92
|
+
key: "str"
|
|
93
|
+
value: "Any"
|
|
58
94
|
|
|
59
95
|
for key, value in inertia_headers.items():
|
|
60
96
|
if value is not None:
|
litestar_vite/inertia/config.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
from dataclasses import dataclass, field
|
|
4
|
-
from typing import Any
|
|
2
|
+
from typing import Any, Optional
|
|
5
3
|
|
|
6
4
|
__all__ = ("InertiaConfig",)
|
|
7
5
|
|
|
@@ -19,11 +17,11 @@ class InertiaConfig:
|
|
|
19
17
|
"""An identifier to use on routes to get the inertia component to render."""
|
|
20
18
|
exclude_from_js_routes_key: str = "exclude_from_routes"
|
|
21
19
|
"""An identifier to use on routes to exclude a route from the generated routes typescript file."""
|
|
22
|
-
redirect_unauthorized_to: str
|
|
20
|
+
redirect_unauthorized_to: "Optional[str]" = None
|
|
23
21
|
"""Optionally supply a path where unauthorized requests should redirect."""
|
|
24
|
-
redirect_404: str
|
|
22
|
+
redirect_404: "Optional[str]" = None
|
|
25
23
|
"""Optionally supply a path where 404 requests should redirect."""
|
|
26
|
-
extra_static_page_props: dict[str, Any] = field(default_factory=dict)
|
|
24
|
+
extra_static_page_props: "dict[str, Any]" = field(default_factory=dict) # pyright: ignore
|
|
27
25
|
"""A dictionary of values to automatically add in to page props on every response."""
|
|
28
|
-
extra_session_page_props: set[str] = field(default_factory=set)
|
|
26
|
+
extra_session_page_props: "set[str]" = field(default_factory=set) # pyright: ignore
|
|
29
27
|
"""A set of session keys for which the value automatically be added (if it exists) to the response."""
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
import re
|
|
4
2
|
from typing import TYPE_CHECKING, Any, cast
|
|
5
3
|
|
|
@@ -54,8 +52,16 @@ class _HTTPConflictException(HTTPException):
|
|
|
54
52
|
status_code: int = HTTP_409_CONFLICT
|
|
55
53
|
|
|
56
54
|
|
|
57
|
-
def exception_to_http_response(request: Request[UserT, AuthT, StateT], exc: Exception) -> Response[Any]:
|
|
58
|
-
"""Handler for all exceptions subclassed from HTTPException.
|
|
55
|
+
def exception_to_http_response(request: "Request[UserT, AuthT, StateT]", exc: "Exception") -> "Response[Any]":
|
|
56
|
+
"""Handler for all exceptions subclassed from HTTPException.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
request: The request object.
|
|
60
|
+
exc: The exception to handle.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
The response object.
|
|
64
|
+
"""
|
|
59
65
|
inertia_enabled = getattr(request, "inertia_enabled", False) or getattr(request, "is_inertia", False)
|
|
60
66
|
|
|
61
67
|
if not inertia_enabled:
|
|
@@ -65,14 +71,22 @@ def exception_to_http_response(request: Request[UserT, AuthT, StateT], exc: Exce
|
|
|
65
71
|
http_exc = _HTTPConflictException # type: ignore[assignment]
|
|
66
72
|
else:
|
|
67
73
|
http_exc = InternalServerException # type: ignore[assignment]
|
|
68
|
-
if request.app.debug and http_exc not in
|
|
74
|
+
if request.app.debug and http_exc not in {PermissionDeniedException, NotFoundError}:
|
|
69
75
|
return cast("Response[Any]", create_debug_response(request, exc))
|
|
70
76
|
return cast("Response[Any]", create_exception_response(request, http_exc(detail=str(exc.__cause__)))) # pyright: ignore[reportUnknownArgumentType]
|
|
71
77
|
return create_inertia_exception_response(request, exc)
|
|
72
78
|
|
|
73
79
|
|
|
74
|
-
def create_inertia_exception_response(request: Request[UserT, AuthT, StateT], exc: Exception) -> Response[Any]:
|
|
75
|
-
"""Create the inertia exception response
|
|
80
|
+
def create_inertia_exception_response(request: "Request[UserT, AuthT, StateT]", exc: "Exception") -> "Response[Any]":
|
|
81
|
+
"""Create the inertia exception response.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
request: The request object.
|
|
85
|
+
exc: The exception to handle.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
The response object.
|
|
89
|
+
"""
|
|
76
90
|
is_inertia = getattr(request, "is_inertia", False)
|
|
77
91
|
status_code = getattr(exc, "status_code", HTTP_500_INTERNAL_SERVER_ERROR)
|
|
78
92
|
preferred_type = MediaType.HTML if not is_inertia else MediaType.JSON
|
|
@@ -94,7 +108,7 @@ def create_inertia_exception_response(request: Request[UserT, AuthT, StateT], ex
|
|
|
94
108
|
match = FIELD_ERR_RE.search(error_detail)
|
|
95
109
|
field = match.group(1) if match else default_field
|
|
96
110
|
if isinstance(message, dict):
|
|
97
|
-
error(request, field, error_detail
|
|
111
|
+
error(request, field, error_detail or detail)
|
|
98
112
|
if status_code in {HTTP_422_UNPROCESSABLE_ENTITY, HTTP_400_BAD_REQUEST}:
|
|
99
113
|
return InertiaBack(request)
|
|
100
114
|
if isinstance(exc, PermissionDeniedException):
|