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.
Files changed (169) hide show
  1. litestar_vite/__init__.py +54 -4
  2. litestar_vite/__metadata__.py +12 -7
  3. litestar_vite/cli.py +1048 -10
  4. litestar_vite/codegen/__init__.py +48 -0
  5. litestar_vite/codegen/_export.py +229 -0
  6. litestar_vite/codegen/_inertia.py +619 -0
  7. litestar_vite/codegen/_openapi.py +280 -0
  8. litestar_vite/codegen/_routes.py +720 -0
  9. litestar_vite/codegen/_ts.py +235 -0
  10. litestar_vite/codegen/_utils.py +141 -0
  11. litestar_vite/commands.py +73 -0
  12. litestar_vite/config/__init__.py +997 -0
  13. litestar_vite/config/_constants.py +97 -0
  14. litestar_vite/config/_deploy.py +70 -0
  15. litestar_vite/config/_inertia.py +241 -0
  16. litestar_vite/config/_paths.py +63 -0
  17. litestar_vite/config/_runtime.py +235 -0
  18. litestar_vite/config/_spa.py +93 -0
  19. litestar_vite/config/_types.py +94 -0
  20. litestar_vite/deploy.py +366 -0
  21. litestar_vite/doctor.py +1181 -0
  22. litestar_vite/exceptions.py +78 -0
  23. litestar_vite/executor.py +360 -0
  24. litestar_vite/handler/__init__.py +9 -0
  25. litestar_vite/handler/_app.py +612 -0
  26. litestar_vite/handler/_routing.py +130 -0
  27. litestar_vite/html_transform.py +569 -0
  28. litestar_vite/inertia/__init__.py +77 -0
  29. litestar_vite/inertia/_utils.py +119 -0
  30. litestar_vite/inertia/exception_handler.py +178 -0
  31. litestar_vite/inertia/helpers.py +1571 -0
  32. litestar_vite/inertia/middleware.py +54 -0
  33. litestar_vite/inertia/plugin.py +199 -0
  34. litestar_vite/inertia/precognition.py +274 -0
  35. litestar_vite/inertia/request.py +334 -0
  36. litestar_vite/inertia/response.py +802 -0
  37. litestar_vite/inertia/types.py +335 -0
  38. litestar_vite/loader.py +464 -123
  39. litestar_vite/plugin/__init__.py +687 -0
  40. litestar_vite/plugin/_process.py +185 -0
  41. litestar_vite/plugin/_proxy.py +689 -0
  42. litestar_vite/plugin/_proxy_headers.py +244 -0
  43. litestar_vite/plugin/_static.py +37 -0
  44. litestar_vite/plugin/_utils.py +489 -0
  45. litestar_vite/py.typed +0 -0
  46. litestar_vite/scaffolding/__init__.py +20 -0
  47. litestar_vite/scaffolding/generator.py +270 -0
  48. litestar_vite/scaffolding/templates.py +437 -0
  49. litestar_vite/templates/__init__.py +0 -0
  50. litestar_vite/templates/addons/tailwindcss/tailwind.css.j2 +1 -0
  51. litestar_vite/templates/angular/index.html.j2 +12 -0
  52. litestar_vite/templates/angular/openapi-ts.config.ts.j2 +18 -0
  53. litestar_vite/templates/angular/package.json.j2 +36 -0
  54. litestar_vite/templates/angular/src/app/app.component.css.j2 +3 -0
  55. litestar_vite/templates/angular/src/app/app.component.html.j2 +1 -0
  56. litestar_vite/templates/angular/src/app/app.component.ts.j2 +9 -0
  57. litestar_vite/templates/angular/src/app/app.config.ts.j2 +5 -0
  58. litestar_vite/templates/angular/src/main.ts.j2 +9 -0
  59. litestar_vite/templates/angular/src/styles.css.j2 +9 -0
  60. litestar_vite/templates/angular/tsconfig.app.json.j2 +34 -0
  61. litestar_vite/templates/angular/tsconfig.json.j2 +20 -0
  62. litestar_vite/templates/angular/vite.config.ts.j2 +21 -0
  63. litestar_vite/templates/angular-cli/.postcssrc.json.j2 +5 -0
  64. litestar_vite/templates/angular-cli/angular.json.j2 +36 -0
  65. litestar_vite/templates/angular-cli/openapi-ts.config.ts.j2 +18 -0
  66. litestar_vite/templates/angular-cli/package.json.j2 +28 -0
  67. litestar_vite/templates/angular-cli/proxy.conf.json.j2 +18 -0
  68. litestar_vite/templates/angular-cli/src/app/app.component.css.j2 +3 -0
  69. litestar_vite/templates/angular-cli/src/app/app.component.html.j2 +1 -0
  70. litestar_vite/templates/angular-cli/src/app/app.component.ts.j2 +9 -0
  71. litestar_vite/templates/angular-cli/src/app/app.config.ts.j2 +5 -0
  72. litestar_vite/templates/angular-cli/src/index.html.j2 +13 -0
  73. litestar_vite/templates/angular-cli/src/main.ts.j2 +6 -0
  74. litestar_vite/templates/angular-cli/src/styles.css.j2 +10 -0
  75. litestar_vite/templates/angular-cli/tailwind.config.js.j2 +4 -0
  76. litestar_vite/templates/angular-cli/tsconfig.app.json.j2 +16 -0
  77. litestar_vite/templates/angular-cli/tsconfig.json.j2 +26 -0
  78. litestar_vite/templates/angular-cli/tsconfig.spec.json.j2 +9 -0
  79. litestar_vite/templates/astro/astro.config.mjs.j2 +28 -0
  80. litestar_vite/templates/astro/openapi-ts.config.ts.j2 +15 -0
  81. litestar_vite/templates/astro/src/layouts/Layout.astro.j2 +63 -0
  82. litestar_vite/templates/astro/src/pages/index.astro.j2 +36 -0
  83. litestar_vite/templates/astro/src/styles/global.css.j2 +1 -0
  84. litestar_vite/templates/base/.gitignore.j2 +42 -0
  85. litestar_vite/templates/base/openapi-ts.config.ts.j2 +15 -0
  86. litestar_vite/templates/base/package.json.j2 +39 -0
  87. litestar_vite/templates/base/resources/vite-env.d.ts.j2 +1 -0
  88. litestar_vite/templates/base/tsconfig.json.j2 +37 -0
  89. litestar_vite/templates/htmx/src/main.js.j2 +8 -0
  90. litestar_vite/templates/htmx/templates/base.html.j2.j2 +56 -0
  91. litestar_vite/templates/htmx/templates/index.html.j2.j2 +13 -0
  92. litestar_vite/templates/htmx/vite.config.ts.j2 +40 -0
  93. litestar_vite/templates/nuxt/app.vue.j2 +29 -0
  94. litestar_vite/templates/nuxt/composables/useApi.ts.j2 +33 -0
  95. litestar_vite/templates/nuxt/nuxt.config.ts.j2 +31 -0
  96. litestar_vite/templates/nuxt/openapi-ts.config.ts.j2 +15 -0
  97. litestar_vite/templates/nuxt/pages/index.vue.j2 +54 -0
  98. litestar_vite/templates/react/index.html.j2 +13 -0
  99. litestar_vite/templates/react/src/App.css.j2 +56 -0
  100. litestar_vite/templates/react/src/App.tsx.j2 +19 -0
  101. litestar_vite/templates/react/src/main.tsx.j2 +10 -0
  102. litestar_vite/templates/react/vite.config.ts.j2 +39 -0
  103. litestar_vite/templates/react-inertia/index.html.j2 +14 -0
  104. litestar_vite/templates/react-inertia/package.json.j2 +47 -0
  105. litestar_vite/templates/react-inertia/resources/App.css.j2 +68 -0
  106. litestar_vite/templates/react-inertia/resources/main.tsx.j2 +17 -0
  107. litestar_vite/templates/react-inertia/resources/pages/Home.tsx.j2 +18 -0
  108. litestar_vite/templates/react-inertia/resources/ssr.tsx.j2 +19 -0
  109. litestar_vite/templates/react-inertia/vite.config.ts.j2 +59 -0
  110. litestar_vite/templates/react-router/index.html.j2 +12 -0
  111. litestar_vite/templates/react-router/src/App.css.j2 +17 -0
  112. litestar_vite/templates/react-router/src/App.tsx.j2 +7 -0
  113. litestar_vite/templates/react-router/src/main.tsx.j2 +10 -0
  114. litestar_vite/templates/react-router/vite.config.ts.j2 +39 -0
  115. litestar_vite/templates/react-tanstack/index.html.j2 +12 -0
  116. litestar_vite/templates/react-tanstack/openapi-ts.config.ts.j2 +18 -0
  117. litestar_vite/templates/react-tanstack/src/App.css.j2 +17 -0
  118. litestar_vite/templates/react-tanstack/src/main.tsx.j2 +21 -0
  119. litestar_vite/templates/react-tanstack/src/routeTree.gen.ts.j2 +7 -0
  120. litestar_vite/templates/react-tanstack/src/routes/__root.tsx.j2 +9 -0
  121. litestar_vite/templates/react-tanstack/src/routes/books.tsx.j2 +9 -0
  122. litestar_vite/templates/react-tanstack/src/routes/index.tsx.j2 +9 -0
  123. litestar_vite/templates/react-tanstack/vite.config.ts.j2 +39 -0
  124. litestar_vite/templates/svelte/index.html.j2 +13 -0
  125. litestar_vite/templates/svelte/src/App.svelte.j2 +30 -0
  126. litestar_vite/templates/svelte/src/app.css.j2 +45 -0
  127. litestar_vite/templates/svelte/src/main.ts.j2 +8 -0
  128. litestar_vite/templates/svelte/src/vite-env.d.ts.j2 +2 -0
  129. litestar_vite/templates/svelte/svelte.config.js.j2 +5 -0
  130. litestar_vite/templates/svelte/vite.config.ts.j2 +39 -0
  131. litestar_vite/templates/svelte-inertia/index.html.j2 +14 -0
  132. litestar_vite/templates/svelte-inertia/resources/app.css.j2 +21 -0
  133. litestar_vite/templates/svelte-inertia/resources/main.ts.j2 +11 -0
  134. litestar_vite/templates/svelte-inertia/resources/pages/Home.svelte.j2 +43 -0
  135. litestar_vite/templates/svelte-inertia/resources/vite-env.d.ts.j2 +2 -0
  136. litestar_vite/templates/svelte-inertia/svelte.config.js.j2 +5 -0
  137. litestar_vite/templates/svelte-inertia/vite.config.ts.j2 +37 -0
  138. litestar_vite/templates/sveltekit/openapi-ts.config.ts.j2 +15 -0
  139. litestar_vite/templates/sveltekit/src/app.css.j2 +40 -0
  140. litestar_vite/templates/sveltekit/src/app.html.j2 +12 -0
  141. litestar_vite/templates/sveltekit/src/hooks.server.ts.j2 +55 -0
  142. litestar_vite/templates/sveltekit/src/routes/+layout.svelte.j2 +12 -0
  143. litestar_vite/templates/sveltekit/src/routes/+page.svelte.j2 +34 -0
  144. litestar_vite/templates/sveltekit/svelte.config.js.j2 +12 -0
  145. litestar_vite/templates/sveltekit/tsconfig.json.j2 +14 -0
  146. litestar_vite/templates/sveltekit/vite.config.ts.j2 +31 -0
  147. litestar_vite/templates/vue/env.d.ts.j2 +7 -0
  148. litestar_vite/templates/vue/index.html.j2 +13 -0
  149. litestar_vite/templates/vue/src/App.vue.j2 +28 -0
  150. litestar_vite/templates/vue/src/main.ts.j2 +5 -0
  151. litestar_vite/templates/vue/src/style.css.j2 +45 -0
  152. litestar_vite/templates/vue/vite.config.ts.j2 +39 -0
  153. litestar_vite/templates/vue-inertia/env.d.ts.j2 +7 -0
  154. litestar_vite/templates/vue-inertia/index.html.j2 +14 -0
  155. litestar_vite/templates/vue-inertia/package.json.j2 +50 -0
  156. litestar_vite/templates/vue-inertia/resources/main.ts.j2 +18 -0
  157. litestar_vite/templates/vue-inertia/resources/pages/Home.vue.j2 +22 -0
  158. litestar_vite/templates/vue-inertia/resources/ssr.ts.j2 +21 -0
  159. litestar_vite/templates/vue-inertia/resources/style.css.j2 +21 -0
  160. litestar_vite/templates/vue-inertia/vite.config.ts.j2 +59 -0
  161. litestar_vite-0.15.0.dist-info/METADATA +230 -0
  162. litestar_vite-0.15.0.dist-info/RECORD +164 -0
  163. {litestar_vite-0.1.1.dist-info → litestar_vite-0.15.0.dist-info}/WHEEL +1 -1
  164. litestar_vite/config.py +0 -100
  165. litestar_vite/plugin.py +0 -45
  166. litestar_vite/template_engine.py +0 -103
  167. litestar_vite-0.1.1.dist-info/METADATA +0 -68
  168. litestar_vite-0.1.1.dist-info/RECORD +0 -11
  169. {litestar_vite-0.1.1.dist-info → litestar_vite-0.15.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,335 @@
1
+ """Inertia protocol types and serialization helpers.
2
+
3
+ This module defines the Python-side data structures for the Inertia.js protocol and provides
4
+ helpers to serialize dataclass instances into the camelCase shape expected by the client.
5
+ """
6
+
7
+ import re
8
+ from dataclasses import dataclass, field, fields, is_dataclass
9
+ from typing import Any, Generic, Literal, TypedDict, TypeVar, cast
10
+
11
+ __all__ = (
12
+ "DeferredPropsConfig",
13
+ "InertiaHeaderType",
14
+ "MergeStrategy",
15
+ "PageProps",
16
+ "ScrollPagination",
17
+ "ScrollPropsConfig",
18
+ "to_camel_case",
19
+ "to_inertia_dict",
20
+ )
21
+
22
+
23
+ T = TypeVar("T")
24
+
25
+ MergeStrategy = Literal["append", "prepend", "deep"]
26
+
27
+ _SNAKE_CASE_PATTERN = re.compile(r"_([a-z])")
28
+
29
+
30
+ def _empty_flash_factory() -> "dict[str, list[str]]":
31
+ """Return an empty flash dict with proper type annotation.
32
+
33
+ Returns:
34
+ Empty dict[str, list[str]] for flash messages.
35
+ """
36
+ return {}
37
+
38
+
39
+ def to_camel_case(snake_str: str) -> str:
40
+ """Convert snake_case string to camelCase.
41
+
42
+ Args:
43
+ snake_str: A snake_case string.
44
+
45
+ Returns:
46
+ The camelCase equivalent.
47
+
48
+ Examples:
49
+ >>> to_camel_case("encrypt_history")
50
+ 'encryptHistory'
51
+ >>> to_camel_case("deep_merge_props")
52
+ 'deepMergeProps'
53
+ """
54
+ return _SNAKE_CASE_PATTERN.sub(lambda m: m.group(1).upper(), snake_str)
55
+
56
+
57
+ def _is_dataclass_instance(value: Any) -> bool:
58
+ return is_dataclass(value) and not isinstance(value, type)
59
+
60
+
61
+ def _convert_value(value: Any) -> Any:
62
+ """Recursively convert a value for Inertia.js protocol.
63
+
64
+ Handles nested dataclasses, dicts, and lists without using asdict()
65
+ to avoid Python 3.10/3.11 bugs with dict[str, list[str]] types.
66
+
67
+ Returns:
68
+ The converted value.
69
+ """
70
+ if _is_dataclass_instance(value):
71
+ return to_inertia_dict(value)
72
+ if isinstance(value, dict):
73
+ return {k: _convert_value(v) for k, v in value.items()} # pyright: ignore[reportUnknownVariableType]
74
+ if isinstance(value, (list, tuple)):
75
+ return type(value)(_convert_value(v) for v in value) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
76
+ return value
77
+
78
+
79
+ def to_inertia_dict(obj: Any, required_fields: "set[str] | None" = None) -> dict[str, Any]:
80
+ """Convert a dataclass to a dict with camelCase keys for Inertia.js protocol.
81
+
82
+ Args:
83
+ obj: A dataclass instance.
84
+ required_fields: Set of field names that should always be included (even if None).
85
+
86
+ Returns:
87
+ A dictionary with camelCase keys, excluding None values for optional fields.
88
+
89
+ Note:
90
+ This function avoids using dataclasses.asdict() directly because of a bug
91
+ in Python 3.10/3.11 that fails when processing dict[str, list[str]] types.
92
+ See: https://github.com/python/cpython/issues/103000
93
+ """
94
+ if not _is_dataclass_instance(obj):
95
+ return cast("dict[str, Any]", obj)
96
+
97
+ required_fields = required_fields or set()
98
+ result: dict[str, Any] = {}
99
+
100
+ for dc_field in fields(obj):
101
+ field_name = dc_field.name
102
+ value = getattr(obj, field_name)
103
+ if value is None and field_name not in required_fields:
104
+ continue
105
+
106
+ value = _convert_value(value)
107
+ camel_key = to_camel_case(field_name)
108
+ result[camel_key] = value
109
+
110
+ return result
111
+
112
+
113
+ def _str_list_factory() -> list[str]:
114
+ """Factory function for empty string list (typed for pyright).
115
+
116
+ Returns:
117
+ An empty list.
118
+ """
119
+ return []
120
+
121
+
122
+ @dataclass
123
+ class DeferredPropsConfig:
124
+ """Configuration for deferred props (v2 feature).
125
+
126
+ Deferred props are loaded lazily after the initial page render.
127
+ This allows for faster initial page loads by deferring non-critical data.
128
+ """
129
+
130
+ group: str = "default"
131
+ props: list[str] = field(default_factory=_str_list_factory)
132
+
133
+
134
+ @dataclass
135
+ class ScrollPropsConfig:
136
+ """Configuration for infinite scroll (v2 feature)."""
137
+
138
+ page_name: str = "page"
139
+ previous_page: "int | None" = None
140
+ next_page: "int | None" = None
141
+ current_page: int = 1
142
+
143
+
144
+ @dataclass
145
+ class ScrollPagination(Generic[T]):
146
+ """Pagination container optimized for infinite scroll.
147
+
148
+ A generic pagination type that works seamlessly with Inertia's infinite
149
+ scroll feature. Can be constructed directly or created from any pagination
150
+ container using ``create_from()``.
151
+
152
+ Attributes:
153
+ items: The paginated items for the current page.
154
+ total: Total number of items across all pages.
155
+ limit: Maximum items per page (page size).
156
+ offset: Number of items skipped from the start.
157
+
158
+ Example::
159
+
160
+ from litestar_vite.inertia.types import ScrollPagination
161
+
162
+ Direct construction::
163
+
164
+ @get("/users", component="Users", infinite_scroll=True)
165
+ async def list_users() -> ScrollPagination[User]:
166
+ users = await fetch_users(limit=10, offset=0)
167
+ return ScrollPagination(items=users, total=100, limit=10, offset=0)
168
+
169
+ From an existing pagination container::
170
+
171
+ @get("/posts", component="Posts", infinite_scroll=True)
172
+ async def list_posts() -> ScrollPagination[Post]:
173
+ pagination = await repo.list_paginated(limit=10, offset=0)
174
+ return ScrollPagination.create_from(pagination)
175
+ """
176
+
177
+ items: list[T]
178
+ total: int
179
+ limit: int
180
+ offset: int
181
+
182
+ @classmethod
183
+ def create_from(cls, pagination: Any) -> "ScrollPagination[T]":
184
+ """Create from any pagination container (auto-detects type).
185
+
186
+ Supports OffsetPagination, ClassicPagination, and any custom pagination
187
+ class with standard pagination attributes.
188
+
189
+ Args:
190
+ pagination: Any pagination container with ``items`` attribute.
191
+
192
+ Returns:
193
+ A ScrollPagination instance with normalized offset-based metadata.
194
+
195
+ Example::
196
+
197
+ from litestar.pagination import OffsetPagination, ClassicPagination
198
+
199
+ From OffsetPagination::
200
+
201
+ offset_page = OffsetPagination(items=[...], limit=10, offset=20, total=100)
202
+ scroll = ScrollPagination.create_from(offset_page)
203
+
204
+ From ClassicPagination::
205
+
206
+ classic_page = ClassicPagination(items=[...], page_size=10, current_page=3, total_pages=10)
207
+ scroll = ScrollPagination.create_from(classic_page)
208
+ """
209
+ items = pagination.items
210
+ if meta := _extract_offset_pagination(pagination, items):
211
+ total, limit, offset = meta
212
+ return cls(items=items, total=total, limit=limit, offset=offset)
213
+ if meta := _extract_classic_pagination(pagination, items):
214
+ total, limit, offset = meta
215
+ return cls(items=items, total=total, limit=limit, offset=offset)
216
+ return cls(items=items, total=len(items), limit=len(items), offset=0)
217
+
218
+
219
+ def _extract_offset_pagination(pagination: Any, items: list[Any]) -> tuple[int, int, int] | None:
220
+ try:
221
+ limit = pagination.limit
222
+ offset = pagination.offset
223
+ except AttributeError:
224
+ return None
225
+
226
+ try:
227
+ total = pagination.total
228
+ except AttributeError:
229
+ total = len(items)
230
+
231
+ if not (isinstance(limit, int) and isinstance(offset, int) and isinstance(total, int)):
232
+ return None
233
+
234
+ return total, limit, offset
235
+
236
+
237
+ def _extract_classic_pagination(pagination: Any, items: list[Any]) -> tuple[int, int, int] | None:
238
+ try:
239
+ page_size = pagination.page_size
240
+ current_page = pagination.current_page
241
+ except AttributeError:
242
+ return None
243
+
244
+ try:
245
+ total_pages = pagination.total_pages
246
+ except AttributeError:
247
+ total_pages = 1
248
+
249
+ if not (isinstance(page_size, int) and isinstance(current_page, int) and isinstance(total_pages, int)):
250
+ return None
251
+
252
+ offset = (current_page - 1) * page_size
253
+ total = total_pages * page_size
254
+ return total, page_size, offset
255
+
256
+
257
+ @dataclass
258
+ class PageProps(Generic[T]):
259
+ """Inertia Page Props Type.
260
+
261
+ This represents the page object sent to the Inertia client.
262
+ See: https://inertiajs.com/the-protocol
263
+
264
+ Note: Field names use snake_case in Python but are serialized to camelCase
265
+ for the Inertia.js protocol using `to_inertia_dict()`.
266
+
267
+ Attributes:
268
+ component: JavaScript component name to render.
269
+ url: Current page URL.
270
+ version: Asset version identifier for cache busting.
271
+ props: Page data/props passed to the component.
272
+ encrypt_history: Whether to encrypt browser history state (v2).
273
+ clear_history: Whether to clear encrypted history state (v2).
274
+ merge_props: Props to append during navigation (v2).
275
+ prepend_props: Props to prepend during navigation (v2).
276
+ deep_merge_props: Props to deep merge during navigation (v2).
277
+ match_props_on: Keys for matching items during merge (v2).
278
+ deferred_props: Configuration for lazy-loaded props (v2).
279
+ scroll_props: Configuration for infinite scroll (v2).
280
+ flash: Flash messages as top-level property (v2.3+). Unlike props, flash
281
+ messages are NOT persisted in browser history state.
282
+ """
283
+
284
+ component: str
285
+ url: str
286
+ version: str
287
+ props: dict[str, Any]
288
+
289
+ encrypt_history: bool = False
290
+ clear_history: bool = False
291
+
292
+ merge_props: "list[str] | None" = None
293
+ prepend_props: "list[str] | None" = None
294
+ deep_merge_props: "list[str] | None" = None
295
+ match_props_on: "dict[str, list[str]] | None" = None
296
+
297
+ deferred_props: "dict[str, list[str]] | None" = None
298
+
299
+ # v2.2.20+ protocol: Props that should only be resolved once and cached client-side
300
+ once_props: "list[str] | None" = None
301
+
302
+ scroll_props: "ScrollPropsConfig | None" = None
303
+
304
+ # v2.3+ protocol: Flash messages at top level (not in props)
305
+ # This prevents flash from persisting in browser history state
306
+ # Always send {} for empty flash to support router.flash((current) => ({ ...current }))
307
+ flash: "dict[str, list[str]]" = field(default_factory=_empty_flash_factory)
308
+
309
+ def to_dict(self) -> dict[str, Any]:
310
+ """Convert to Inertia.js protocol format with camelCase keys.
311
+
312
+ Returns:
313
+ The Inertia protocol dictionary.
314
+ """
315
+ return to_inertia_dict(self, required_fields={"component", "url", "version", "props"})
316
+
317
+
318
+ @dataclass
319
+ class InertiaProps(Generic[T]):
320
+ """Inertia Props Type."""
321
+
322
+ page: PageProps[T]
323
+
324
+
325
+ class InertiaHeaderType(TypedDict, total=False):
326
+ """Type for inertia_headers parameter in get_headers()."""
327
+
328
+ enabled: "bool | None"
329
+ version: "str | None"
330
+ location: "str | None"
331
+ partial_data: "str | None"
332
+ partial_component: "str | None"
333
+ partial_except: "str | None"
334
+ reset: "str | None"
335
+ error_bag: "str | None"