litestar-vite 0.1.1__py3-none-any.whl → 0.15.0rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. litestar_vite/__init__.py +54 -4
  2. litestar_vite/__metadata__.py +12 -7
  3. litestar_vite/_codegen/__init__.py +26 -0
  4. litestar_vite/_codegen/inertia.py +407 -0
  5. litestar_vite/_codegen/openapi.py +233 -0
  6. litestar_vite/_codegen/routes.py +653 -0
  7. litestar_vite/_codegen/ts.py +235 -0
  8. litestar_vite/_handler/__init__.py +8 -0
  9. litestar_vite/_handler/app.py +524 -0
  10. litestar_vite/_handler/routing.py +130 -0
  11. litestar_vite/cli.py +1147 -10
  12. litestar_vite/codegen.py +39 -0
  13. litestar_vite/commands.py +79 -0
  14. litestar_vite/config.py +1594 -70
  15. litestar_vite/deploy.py +355 -0
  16. litestar_vite/doctor.py +1179 -0
  17. litestar_vite/exceptions.py +78 -0
  18. litestar_vite/executor.py +316 -0
  19. litestar_vite/handler.py +9 -0
  20. litestar_vite/html_transform.py +426 -0
  21. litestar_vite/inertia/__init__.py +53 -0
  22. litestar_vite/inertia/_utils.py +114 -0
  23. litestar_vite/inertia/exception_handler.py +172 -0
  24. litestar_vite/inertia/helpers.py +1043 -0
  25. litestar_vite/inertia/middleware.py +54 -0
  26. litestar_vite/inertia/plugin.py +133 -0
  27. litestar_vite/inertia/request.py +286 -0
  28. litestar_vite/inertia/response.py +706 -0
  29. litestar_vite/inertia/types.py +316 -0
  30. litestar_vite/loader.py +462 -121
  31. litestar_vite/plugin.py +2160 -21
  32. litestar_vite/py.typed +0 -0
  33. litestar_vite/scaffolding/__init__.py +20 -0
  34. litestar_vite/scaffolding/generator.py +270 -0
  35. litestar_vite/scaffolding/templates.py +437 -0
  36. litestar_vite/templates/__init__.py +0 -0
  37. litestar_vite/templates/addons/tailwindcss/tailwind.css.j2 +1 -0
  38. litestar_vite/templates/angular/index.html.j2 +12 -0
  39. litestar_vite/templates/angular/openapi-ts.config.ts.j2 +18 -0
  40. litestar_vite/templates/angular/package.json.j2 +35 -0
  41. litestar_vite/templates/angular/src/app/app.component.css.j2 +3 -0
  42. litestar_vite/templates/angular/src/app/app.component.html.j2 +1 -0
  43. litestar_vite/templates/angular/src/app/app.component.ts.j2 +9 -0
  44. litestar_vite/templates/angular/src/app/app.config.ts.j2 +5 -0
  45. litestar_vite/templates/angular/src/main.ts.j2 +9 -0
  46. litestar_vite/templates/angular/src/styles.css.j2 +9 -0
  47. litestar_vite/templates/angular/tsconfig.app.json.j2 +34 -0
  48. litestar_vite/templates/angular/tsconfig.json.j2 +20 -0
  49. litestar_vite/templates/angular/vite.config.ts.j2 +21 -0
  50. litestar_vite/templates/angular-cli/.postcssrc.json.j2 +5 -0
  51. litestar_vite/templates/angular-cli/angular.json.j2 +36 -0
  52. litestar_vite/templates/angular-cli/openapi-ts.config.ts.j2 +18 -0
  53. litestar_vite/templates/angular-cli/package.json.j2 +27 -0
  54. litestar_vite/templates/angular-cli/proxy.conf.json.j2 +18 -0
  55. litestar_vite/templates/angular-cli/src/app/app.component.css.j2 +3 -0
  56. litestar_vite/templates/angular-cli/src/app/app.component.html.j2 +1 -0
  57. litestar_vite/templates/angular-cli/src/app/app.component.ts.j2 +9 -0
  58. litestar_vite/templates/angular-cli/src/app/app.config.ts.j2 +5 -0
  59. litestar_vite/templates/angular-cli/src/index.html.j2 +13 -0
  60. litestar_vite/templates/angular-cli/src/main.ts.j2 +6 -0
  61. litestar_vite/templates/angular-cli/src/styles.css.j2 +10 -0
  62. litestar_vite/templates/angular-cli/tailwind.config.js.j2 +4 -0
  63. litestar_vite/templates/angular-cli/tsconfig.app.json.j2 +16 -0
  64. litestar_vite/templates/angular-cli/tsconfig.json.j2 +26 -0
  65. litestar_vite/templates/angular-cli/tsconfig.spec.json.j2 +9 -0
  66. litestar_vite/templates/astro/astro.config.mjs.j2 +28 -0
  67. litestar_vite/templates/astro/openapi-ts.config.ts.j2 +15 -0
  68. litestar_vite/templates/astro/src/layouts/Layout.astro.j2 +63 -0
  69. litestar_vite/templates/astro/src/pages/index.astro.j2 +36 -0
  70. litestar_vite/templates/astro/src/styles/global.css.j2 +1 -0
  71. litestar_vite/templates/base/.gitignore.j2 +42 -0
  72. litestar_vite/templates/base/openapi-ts.config.ts.j2 +15 -0
  73. litestar_vite/templates/base/package.json.j2 +38 -0
  74. litestar_vite/templates/base/resources/vite-env.d.ts.j2 +1 -0
  75. litestar_vite/templates/base/tsconfig.json.j2 +37 -0
  76. litestar_vite/templates/htmx/src/main.js.j2 +8 -0
  77. litestar_vite/templates/htmx/templates/base.html.j2.j2 +56 -0
  78. litestar_vite/templates/htmx/templates/index.html.j2.j2 +13 -0
  79. litestar_vite/templates/htmx/vite.config.ts.j2 +40 -0
  80. litestar_vite/templates/nuxt/app.vue.j2 +29 -0
  81. litestar_vite/templates/nuxt/composables/useApi.ts.j2 +33 -0
  82. litestar_vite/templates/nuxt/nuxt.config.ts.j2 +31 -0
  83. litestar_vite/templates/nuxt/openapi-ts.config.ts.j2 +15 -0
  84. litestar_vite/templates/nuxt/pages/index.vue.j2 +54 -0
  85. litestar_vite/templates/react/index.html.j2 +13 -0
  86. litestar_vite/templates/react/src/App.css.j2 +56 -0
  87. litestar_vite/templates/react/src/App.tsx.j2 +19 -0
  88. litestar_vite/templates/react/src/main.tsx.j2 +10 -0
  89. litestar_vite/templates/react/vite.config.ts.j2 +39 -0
  90. litestar_vite/templates/react-inertia/index.html.j2 +14 -0
  91. litestar_vite/templates/react-inertia/package.json.j2 +46 -0
  92. litestar_vite/templates/react-inertia/resources/App.css.j2 +68 -0
  93. litestar_vite/templates/react-inertia/resources/main.tsx.j2 +17 -0
  94. litestar_vite/templates/react-inertia/resources/pages/Home.tsx.j2 +18 -0
  95. litestar_vite/templates/react-inertia/resources/ssr.tsx.j2 +19 -0
  96. litestar_vite/templates/react-inertia/vite.config.ts.j2 +59 -0
  97. litestar_vite/templates/react-router/index.html.j2 +12 -0
  98. litestar_vite/templates/react-router/src/App.css.j2 +17 -0
  99. litestar_vite/templates/react-router/src/App.tsx.j2 +7 -0
  100. litestar_vite/templates/react-router/src/main.tsx.j2 +10 -0
  101. litestar_vite/templates/react-router/vite.config.ts.j2 +39 -0
  102. litestar_vite/templates/react-tanstack/index.html.j2 +12 -0
  103. litestar_vite/templates/react-tanstack/openapi-ts.config.ts.j2 +18 -0
  104. litestar_vite/templates/react-tanstack/src/App.css.j2 +17 -0
  105. litestar_vite/templates/react-tanstack/src/main.tsx.j2 +21 -0
  106. litestar_vite/templates/react-tanstack/src/routeTree.gen.ts.j2 +7 -0
  107. litestar_vite/templates/react-tanstack/src/routes/__root.tsx.j2 +9 -0
  108. litestar_vite/templates/react-tanstack/src/routes/books.tsx.j2 +9 -0
  109. litestar_vite/templates/react-tanstack/src/routes/index.tsx.j2 +9 -0
  110. litestar_vite/templates/react-tanstack/vite.config.ts.j2 +39 -0
  111. litestar_vite/templates/svelte/index.html.j2 +13 -0
  112. litestar_vite/templates/svelte/src/App.svelte.j2 +30 -0
  113. litestar_vite/templates/svelte/src/app.css.j2 +45 -0
  114. litestar_vite/templates/svelte/src/main.ts.j2 +8 -0
  115. litestar_vite/templates/svelte/src/vite-env.d.ts.j2 +2 -0
  116. litestar_vite/templates/svelte/svelte.config.js.j2 +5 -0
  117. litestar_vite/templates/svelte/vite.config.ts.j2 +39 -0
  118. litestar_vite/templates/svelte-inertia/index.html.j2 +14 -0
  119. litestar_vite/templates/svelte-inertia/resources/app.css.j2 +21 -0
  120. litestar_vite/templates/svelte-inertia/resources/main.ts.j2 +11 -0
  121. litestar_vite/templates/svelte-inertia/resources/pages/Home.svelte.j2 +43 -0
  122. litestar_vite/templates/svelte-inertia/resources/vite-env.d.ts.j2 +2 -0
  123. litestar_vite/templates/svelte-inertia/svelte.config.js.j2 +5 -0
  124. litestar_vite/templates/svelte-inertia/vite.config.ts.j2 +37 -0
  125. litestar_vite/templates/sveltekit/openapi-ts.config.ts.j2 +15 -0
  126. litestar_vite/templates/sveltekit/src/app.css.j2 +40 -0
  127. litestar_vite/templates/sveltekit/src/app.html.j2 +12 -0
  128. litestar_vite/templates/sveltekit/src/hooks.server.ts.j2 +55 -0
  129. litestar_vite/templates/sveltekit/src/routes/+layout.svelte.j2 +12 -0
  130. litestar_vite/templates/sveltekit/src/routes/+page.svelte.j2 +34 -0
  131. litestar_vite/templates/sveltekit/svelte.config.js.j2 +12 -0
  132. litestar_vite/templates/sveltekit/tsconfig.json.j2 +14 -0
  133. litestar_vite/templates/sveltekit/vite.config.ts.j2 +31 -0
  134. litestar_vite/templates/vue/env.d.ts.j2 +7 -0
  135. litestar_vite/templates/vue/index.html.j2 +13 -0
  136. litestar_vite/templates/vue/src/App.vue.j2 +28 -0
  137. litestar_vite/templates/vue/src/main.ts.j2 +5 -0
  138. litestar_vite/templates/vue/src/style.css.j2 +45 -0
  139. litestar_vite/templates/vue/vite.config.ts.j2 +39 -0
  140. litestar_vite/templates/vue-inertia/env.d.ts.j2 +7 -0
  141. litestar_vite/templates/vue-inertia/index.html.j2 +14 -0
  142. litestar_vite/templates/vue-inertia/package.json.j2 +49 -0
  143. litestar_vite/templates/vue-inertia/resources/main.ts.j2 +18 -0
  144. litestar_vite/templates/vue-inertia/resources/pages/Home.vue.j2 +22 -0
  145. litestar_vite/templates/vue-inertia/resources/ssr.ts.j2 +21 -0
  146. litestar_vite/templates/vue-inertia/resources/style.css.j2 +21 -0
  147. litestar_vite/templates/vue-inertia/vite.config.ts.j2 +59 -0
  148. litestar_vite-0.15.0rc2.dist-info/METADATA +230 -0
  149. litestar_vite-0.15.0rc2.dist-info/RECORD +151 -0
  150. {litestar_vite-0.1.1.dist-info → litestar_vite-0.15.0rc2.dist-info}/WHEEL +1 -1
  151. litestar_vite/template_engine.py +0 -103
  152. litestar_vite-0.1.1.dist-info/METADATA +0 -68
  153. litestar_vite-0.1.1.dist-info/RECORD +0 -11
  154. {litestar_vite-0.1.1.dist-info → litestar_vite-0.15.0rc2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,233 @@
1
+ """OpenAPI integration helpers for code generation.
2
+
3
+ This module centralizes Litestar private OpenAPI API usage so that the rest of
4
+ the codegen logic can remain stable and easier to reason about.
5
+ """
6
+
7
+ import contextlib
8
+ from dataclasses import dataclass
9
+ from pathlib import Path
10
+ from typing import TYPE_CHECKING, Any, Protocol, cast
11
+
12
+ from litestar._openapi.datastructures import OpenAPIContext # pyright: ignore[reportPrivateUsage]
13
+ from litestar._openapi.schema_generation import SchemaCreator # pyright: ignore[reportPrivateUsage]
14
+ from litestar.handlers import HTTPRouteHandler
15
+ from litestar.openapi.spec import Reference, Schema
16
+ from litestar.response import Response as LitestarResponse
17
+ from litestar.response import Template
18
+ from litestar.response.base import ASGIResponse
19
+ from litestar.types.builtin_types import NoneType
20
+ from litestar.typing import FieldDefinition
21
+
22
+ if TYPE_CHECKING:
23
+ from litestar import Litestar
24
+ from litestar.dto import AbstractDTO
25
+
26
+
27
+ class _SchemaRegistryEntry(Protocol):
28
+ key: tuple[str, ...]
29
+
30
+
31
+ @dataclass(slots=True)
32
+ class OpenAPISupport:
33
+ """Best-effort access to Litestar OpenAPI internals.
34
+
35
+ Attributes:
36
+ openapi_schema: Exported OpenAPI schema dict (optional).
37
+ context: Litestar OpenAPIContext (optional).
38
+ schema_creator: Litestar SchemaCreator (optional).
39
+ """
40
+
41
+ openapi_schema: dict[str, Any] | None
42
+ context: OpenAPIContext | None
43
+ schema_creator: SchemaCreator | None
44
+
45
+ @classmethod
46
+ def from_app(cls, app: "Litestar", openapi_schema: dict[str, Any] | None) -> "OpenAPISupport":
47
+ """Create OpenAPISupport from a Litestar application.
48
+
49
+ Args:
50
+ app: Litestar application instance.
51
+ openapi_schema: Optional OpenAPI schema dict exported by Litestar.
52
+
53
+ Returns:
54
+ OpenAPISupport instance.
55
+ """
56
+ context, creator = try_create_openapi_context(app)
57
+ return cls(openapi_schema=openapi_schema, context=context, schema_creator=creator)
58
+
59
+ @property
60
+ def enabled(self) -> bool:
61
+ """Whether OpenAPI support is available.
62
+
63
+ Returns:
64
+ True if OpenAPI support is available, otherwise False.
65
+ """
66
+ return self.context is not None and self.schema_creator is not None
67
+
68
+
69
+ def try_create_openapi_context(app: "Litestar") -> tuple[OpenAPIContext | None, SchemaCreator | None]:
70
+ """Create OpenAPIContext and SchemaCreator if available.
71
+
72
+ This mirrors Litestar's internal OpenAPI setup but is tolerant of missing
73
+ configuration or internal API changes.
74
+
75
+ Args:
76
+ app: Litestar application instance.
77
+
78
+ Returns:
79
+ Tuple of (OpenAPIContext or None, SchemaCreator or None).
80
+ """
81
+ openapi_config = app.openapi_config
82
+ if openapi_config is None:
83
+ return None, None
84
+
85
+ with contextlib.suppress(AttributeError, TypeError, ValueError):
86
+ openapi_context = OpenAPIContext(
87
+ openapi_config=openapi_config, # pyright: ignore[reportUnknownMemberType]
88
+ plugins=app.plugins.openapi, # pyright: ignore[reportUnknownMemberType]
89
+ )
90
+ return openapi_context, SchemaCreator.from_openapi_context(openapi_context)
91
+
92
+ return None, None
93
+
94
+
95
+ def openapi_components_schemas(openapi_schema: dict[str, Any] | None) -> dict[str, Any]:
96
+ """Extract OpenAPI components.schemas dict as a concrete mapping.
97
+
98
+ Returns:
99
+ The components.schemas mapping, or an empty dict if unavailable.
100
+ """
101
+ if not isinstance(openapi_schema, dict):
102
+ return {}
103
+ components = openapi_schema.get("components")
104
+ if not isinstance(components, dict):
105
+ return {}
106
+ schemas = cast("dict[str, Any]", components).get("schemas")
107
+ if not isinstance(schemas, dict):
108
+ return {}
109
+ return cast("dict[str, Any]", schemas)
110
+
111
+
112
+ def merge_generated_components_into_openapi(
113
+ openapi_schema: dict[str, Any], generated_components: dict[str, Schema]
114
+ ) -> None:
115
+ """Merge generated component schemas into an OpenAPI document."""
116
+ components_any = openapi_schema.get("components")
117
+ if not isinstance(components_any, dict):
118
+ openapi_schema["components"] = {}
119
+ components_any = openapi_schema["components"]
120
+
121
+ components_dict = cast("dict[str, Any]", components_any)
122
+ schemas_any = components_dict.get("schemas")
123
+ if not isinstance(schemas_any, dict):
124
+ components_dict["schemas"] = {}
125
+ schemas_any = components_dict["schemas"]
126
+
127
+ schemas_dict = cast("dict[str, Any]", schemas_any)
128
+ for component_name, schema in generated_components.items():
129
+ if component_name not in schemas_dict:
130
+ schemas_dict[component_name] = schema.to_schema()
131
+
132
+
133
+ def build_schema_name_map(schema_registry: Any) -> dict[tuple[str, ...], str]:
134
+ """Build a mapping of schema registry keys to final component names.
135
+
136
+ Uses the same shortening and de-duplication logic as
137
+ ``SchemaRegistry.generate_components_schemas()``.
138
+
139
+ Args:
140
+ schema_registry: Litestar schema registry.
141
+
142
+ Returns:
143
+ Mapping of schema keys to component names.
144
+ """
145
+ name_map: dict[tuple[str, ...], str] = {}
146
+ try:
147
+ model_name_groups = schema_registry._model_name_groups
148
+ except AttributeError:
149
+ model_name_groups = {}
150
+ if not isinstance(model_name_groups, dict):
151
+ return name_map
152
+
153
+ groups_dict = cast("dict[str, Any]", model_name_groups)
154
+ for name, group_any in groups_dict.items():
155
+ group = cast("list[Any]", group_any)
156
+ if len(group) == 1:
157
+ registered_schema: _SchemaRegistryEntry = group[0]
158
+ name_map[registered_schema.key] = name
159
+ continue
160
+
161
+ full_keys: list[tuple[str, ...]] = []
162
+ for registered_schema_any in group:
163
+ entry_key: _SchemaRegistryEntry = registered_schema_any
164
+ full_keys.append(entry_key.key)
165
+
166
+ shortened_keys: list[tuple[str, ...]] = list(schema_registry.remove_common_prefix(full_keys))
167
+ names = ["_".join(k) for k in shortened_keys]
168
+
169
+ for name_, registered_schema_any in zip(names, group, strict=False):
170
+ entry_name: _SchemaRegistryEntry = registered_schema_any
171
+ name_map[entry_name.key] = name_
172
+
173
+ return name_map
174
+
175
+
176
+ def schema_name_from_ref(ref: str) -> str:
177
+ """Return the OpenAPI component name from a schema $ref string.
178
+
179
+ Returns:
180
+ The schema name part of the reference.
181
+ """
182
+ return ref.rsplit("/", maxsplit=1)[-1]
183
+
184
+
185
+ def resolve_page_props_field_definition(
186
+ handler: HTTPRouteHandler, schema_creator: SchemaCreator
187
+ ) -> tuple[FieldDefinition | None, Schema | Reference | None]:
188
+ """Resolve FieldDefinition and schema result for a handler's response.
189
+
190
+ Mirrors Litestar's response schema generation to ensure consistent schema registration.
191
+
192
+ Args:
193
+ handler: HTTP route handler.
194
+ schema_creator: Litestar SchemaCreator.
195
+
196
+ Returns:
197
+ Tuple of (FieldDefinition or None, Schema/Reference or None).
198
+ """
199
+ field_definition = handler.parsed_fn_signature.return_type
200
+
201
+ if field_definition.is_subclass_of((NoneType, ASGIResponse)):
202
+ return None, None
203
+
204
+ resolve_return_dto: Any = None
205
+ with contextlib.suppress(AttributeError):
206
+ resolve_return_dto = cast("Any", handler).resolve_return_dto
207
+ dto = resolve_return_dto() if callable(resolve_return_dto) else None
208
+ if dto is not None:
209
+ dto_t = cast("type[AbstractDTO[Any]]", dto)
210
+ result = dto_t.create_openapi_schema(
211
+ field_definition=field_definition, handler_id=handler.handler_id, schema_creator=schema_creator
212
+ )
213
+ return field_definition, result
214
+
215
+ if field_definition.is_subclass_of(Template):
216
+ resolved_field = FieldDefinition.from_annotation(str)
217
+ elif field_definition.is_subclass_of(LitestarResponse):
218
+ resolved_field = (
219
+ field_definition.inner_types[0] if field_definition.inner_types else FieldDefinition.from_annotation(Any)
220
+ )
221
+ else:
222
+ resolved_field = field_definition
223
+
224
+ return resolved_field, schema_creator.for_field_definition(resolved_field)
225
+
226
+
227
+ def to_root_path(root_dir: Path, path: Path) -> Path:
228
+ """Resolve a path relative to ``root_dir`` when it is not absolute.
229
+
230
+ Returns:
231
+ Absolute path.
232
+ """
233
+ return path if path.is_absolute() else (root_dir / path)