-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
513 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,8 +24,8 @@ | |
"**/*.d.ts", | ||
"resources/**/*.js" , | ||
"resources/**/*.ts" , | ||
|
||
|
||
"vite.config.ts" | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,4 +27,4 @@ | |
"resources/**/*.tsx", | ||
"resources/**/*.vue" | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
from __future__ import annotations | ||
|
||
from enum import Enum | ||
from typing import TYPE_CHECKING, Any, Callable | ||
|
||
if TYPE_CHECKING: | ||
from litestar_vite.inertia.types import InertiaHeaderType | ||
|
||
|
||
class InertiaHeaders(str, Enum): | ||
"""Enum for Inertia Headers""" | ||
|
||
ENABLED = "X-Inertia" | ||
VERSION = "X-Inertia-Version" | ||
PARTIAL_DATA = "X-Inertia-Partial-Data" | ||
PARTIAL_COMPONENT = "X-Inertia-Partial-Component" | ||
LOCATION = "X-Inertia-Location" | ||
|
||
|
||
def get_enabled_header(enabled: bool = True) -> dict[str, Any]: | ||
"""True if inertia is enabled.""" | ||
|
||
return {InertiaHeaders.ENABLED.value: enabled} | ||
|
||
|
||
def get_version_header(version: str) -> dict[str, Any]: | ||
"""Return headers for change swap method response.""" | ||
return {InertiaHeaders.VERSION.value: version} | ||
|
||
|
||
def get_partial_data_header(partial: str) -> dict[str, Any]: | ||
"""Return headers for a partial data response.""" | ||
return {InertiaHeaders.PARTIAL_DATA.value: partial} | ||
|
||
|
||
def get_partial_component_header(partial: str) -> dict[str, Any]: | ||
"""Return headers for a partial data response.""" | ||
return {InertiaHeaders.PARTIAL_COMPONENT.value: partial} | ||
|
||
|
||
def get_headers(inertia_headers: InertiaHeaderType) -> dict[str, Any]: | ||
"""Return headers for Inertia responses.""" | ||
if not inertia_headers: | ||
msg = "Value for inertia_headers cannot be None." | ||
raise ValueError(msg) | ||
inertia_headers_dict: dict[str, Callable] = { | ||
"enabled": get_enabled_header, | ||
"partial_data": get_partial_data_header, | ||
"partial_component": get_partial_component_header, | ||
"version": get_version_header, | ||
} | ||
|
||
header: dict[str, Any] = {} | ||
response: dict[str, Any] | ||
key: str | ||
value: Any | ||
|
||
for key, value in inertia_headers.items(): | ||
if value is not None: | ||
response = inertia_headers_dict[key](value) | ||
header.update(response) | ||
return header |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from __future__ import annotations | ||
|
||
from dataclasses import dataclass, field | ||
from typing import TYPE_CHECKING, Any, MutableMapping, TypeVar | ||
|
||
from litestar.template import TemplateEngineProtocol | ||
|
||
__all__ = ("InertiaConfig",) | ||
|
||
|
||
if TYPE_CHECKING: | ||
from pathlib import Path | ||
|
||
|
||
T = TypeVar("T", bound=TemplateEngineProtocol) | ||
|
||
|
||
@dataclass | ||
class InertiaConfig: | ||
"""Configuration for InertiaJS support.""" | ||
|
||
root_template: Path | ||
"""Name of the root template to use. | ||
This must be a path that is found by the Vite Plugin template config | ||
""" | ||
default_props: MutableMapping[str, Any] = field(default_factory=dict) | ||
"""The additional default props and their types you would like to include on a response.""" | ||
component_opt_key: str = "component" | ||
"""An identifier to use on routes to get the inertia component to render.""" |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
from __future__ import annotations | ||
|
||
from typing import TYPE_CHECKING | ||
|
||
from litestar.plugins import InitPluginProtocol | ||
|
||
from litestar_vite.inertia import InertiaResponse | ||
from litestar_vite.inertia.request import InertiaRequest | ||
|
||
if TYPE_CHECKING: | ||
from litestar.config.app import AppConfig | ||
|
||
from litestar_vite.inertia.config import InertiaConfig | ||
|
||
|
||
class InertiaPlugin(InitPluginProtocol): | ||
"""Inertia plugin.""" | ||
|
||
__slots__ = ("_config",) | ||
|
||
def __init__(self, config: InertiaConfig) -> None: | ||
"""Initialize ``Inertia``. | ||
Args: | ||
config: configure and start Vite. | ||
""" | ||
self._config = config | ||
|
||
def on_app_init(self, app_config: AppConfig) -> AppConfig: | ||
"""Configure application for use with Vite. | ||
Args: | ||
app_config: The :class:`AppConfig <.config.app.AppConfig>` instance. | ||
""" | ||
app_config.request_class = InertiaRequest | ||
app_config.response_class = InertiaResponse | ||
return app_config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
from __future__ import annotations | ||
|
||
from functools import cached_property | ||
from typing import TYPE_CHECKING | ||
from urllib.parse import unquote | ||
|
||
from litestar import Request | ||
from litestar.connection.base import ( | ||
AuthT, | ||
StateT, | ||
UserT, | ||
empty_receive, | ||
empty_send, | ||
) | ||
|
||
from litestar_vite.inertia._utils import InertiaHeaders | ||
|
||
__all__ = ("InertiaDetails", "InertiaRequest") | ||
|
||
|
||
if TYPE_CHECKING: | ||
from litestar.types import Receive, Scope, Send | ||
|
||
|
||
class InertiaDetails: | ||
"""InertiaDetails holds all the values sent by Inertia client in headers and provide convenient properties.""" | ||
|
||
def __init__(self, request: Request) -> None: | ||
"""Initialize :class:`InertiaDetails`""" | ||
self.request = request | ||
|
||
def _get_header_value(self, name: InertiaHeaders) -> str | None: | ||
"""Parse request header | ||
Check for uri encoded header and unquotes it in readable format. | ||
""" | ||
|
||
if value := self.request.headers.get(name.value.lower()): | ||
is_uri_encoded = self.request.headers.get(f"{name.value.lower()}-uri-autoencoded") == "true" | ||
return unquote(value) if is_uri_encoded else value | ||
return None | ||
|
||
def __bool__(self) -> bool: | ||
"""Check if request is sent by an Inertia client.""" | ||
return self._get_header_value(InertiaHeaders.ENABLED) == "true" | ||
|
||
@cached_property | ||
def partial_component(self) -> str | None: | ||
"""Partial Data Reload.""" | ||
return self._get_header_value(InertiaHeaders.PARTIAL_COMPONENT) | ||
|
||
@cached_property | ||
def partial_data(self) -> str | None: | ||
"""Partial Data Reload.""" | ||
return self._get_header_value(InertiaHeaders.PARTIAL_DATA) | ||
|
||
|
||
class InertiaRequest(Request[UserT, AuthT, StateT]): | ||
"""Inertia Request class to work with Inertia client.""" | ||
|
||
__slots__ = ( | ||
"_json", | ||
"_form", | ||
"_body", | ||
"_msgpack", | ||
"_content_type", | ||
"_accept", | ||
"_inertia", | ||
"is_connected", | ||
"is_inertia", | ||
) | ||
|
||
def __init__(self, scope: Scope, receive: Receive = empty_receive, send: Send = empty_send) -> None: | ||
"""Initialize :class:`InertiaRequest`""" | ||
super().__init__(scope=scope, receive=receive, send=send) | ||
self._inertia = InertiaDetails(self) | ||
|
||
@property | ||
def is_inertia(self) -> bool: | ||
"""Return the request method. | ||
Returns: | ||
The request :class:`Method <litestar.types.Method>` | ||
""" | ||
return bool(self._inertia) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
from __future__ import annotations | ||
|
||
from typing import Any, MutableMapping | ||
|
||
from litestar import Response | ||
from litestar.response import Template | ||
|
||
from litestar_vite.inertia._utils import get_headers | ||
from litestar_vite.inertia.types import InertiaHeaderType | ||
|
||
|
||
class InertiaJSON(Response): | ||
"""Inertia JSON Response""" | ||
|
||
def __init__(self, props: MutableMapping[str, Any] | None = None, **kwargs: Any) -> None: | ||
"""Set Status code to 200 and set headers.""" | ||
super().__init__(**kwargs) | ||
self._props = props | ||
self.headers.update( | ||
get_headers(InertiaHeaderType(enabled=True)), | ||
) | ||
|
||
|
||
class InertiaTemplate(Template): | ||
"""Inertia template wrapper""" | ||
|
||
def __init__( | ||
self, | ||
props: MutableMapping[str, Any] | None = None, | ||
**kwargs: Any, | ||
) -> None: | ||
"""Create InertiaTemplate response. | ||
Args: | ||
props: Dictionary or Prop type to serialize to JSON | ||
**kwargs: Additional arguments to pass to ``Template``. | ||
""" | ||
super().__init__(**kwargs) | ||
self._props = props | ||
self.headers.update( | ||
get_headers(InertiaHeaderType(enabled=True)), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
from __future__ import annotations | ||
|
||
from dataclasses import dataclass | ||
from typing import Generic, TypedDict, TypeVar | ||
|
||
__all__ = ( | ||
"InertiaHeaderType", | ||
"PageProps", | ||
) | ||
|
||
|
||
T = TypeVar("T") | ||
|
||
|
||
@dataclass | ||
class PageProps(Generic[T]): | ||
"""Inertia Page Props Type.""" | ||
|
||
component: str | ||
url: str | ||
version: str | ||
props: T | ||
|
||
|
||
@dataclass | ||
class InertiaProps(Generic[T]): | ||
"""Inertia Props Type.""" | ||
|
||
page: PageProps[T] | ||
|
||
|
||
class InertiaHeaderType(TypedDict, total=False): | ||
"""Type for hx_headers parameter in get_headers().""" | ||
|
||
enabled: bool | None | ||
version: str | None | ||
location: str | None | ||
partial_data: str | None | ||
partial_component: str | None |
Oops, something went wrong.