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,235 @@
1
+ """TypeScript conversion helpers for code generation."""
2
+
3
+ import re
4
+ from pathlib import PurePosixPath
5
+ from typing import Any, cast
6
+
7
+ _PATH_PARAM_TYPE_PATTERN = re.compile(r"\{([^:}]+):[^}]+\}")
8
+
9
+ _OPENAPI_STRING_FORMAT_TO_TS_ALIAS: dict[str, str] = {
10
+ "uuid": "UUID",
11
+ "date-time": "DateTime",
12
+ "date": "DateOnly",
13
+ "time": "TimeOnly",
14
+ "duration": "Duration",
15
+ "email": "Email",
16
+ "idn-email": "Email",
17
+ "uri": "URI",
18
+ "url": "URI",
19
+ "iri": "URI",
20
+ "iri-reference": "URI",
21
+ "uri-reference": "URI",
22
+ "uri-template": "URI",
23
+ "ipv4": "IPv4",
24
+ "ipv6": "IPv6",
25
+ }
26
+
27
+
28
+ def normalize_path(path: str) -> str:
29
+ """Normalize route path to use {param} syntax.
30
+
31
+ Returns:
32
+ Normalized path string.
33
+ """
34
+ if not path or path == "/":
35
+ return path
36
+ return _PATH_PARAM_TYPE_PATTERN.sub(r"{\1}", str(PurePosixPath(path)))
37
+
38
+
39
+ def ts_type_from_openapi(schema_dict: dict[str, Any]) -> str:
40
+ """Convert an OpenAPI schema dict to a TypeScript type string.
41
+
42
+ This function is intentionally lightweight and mirrors the historical
43
+ behavior used in this project's unit tests (OpenAPI 3.1 union types,
44
+ oneOf nullable patterns, etc.). It is not a full OpenAPI-to-TypeScript
45
+ compiler.
46
+
47
+ Returns:
48
+ A TypeScript type expression string.
49
+ """
50
+ if not schema_dict:
51
+ return "any"
52
+
53
+ ref = schema_dict.get("$ref")
54
+ if isinstance(ref, str) and ref:
55
+ return ref.split("/")[-1]
56
+
57
+ if "anyOf" in schema_dict and isinstance(schema_dict["anyOf"], list) and schema_dict["anyOf"]:
58
+ schemas = cast("list[Any]", schema_dict["anyOf"])
59
+ union = {_ts_type_from_subschema(s) for s in schemas}
60
+ return _join_union(union)
61
+
62
+ result = "any"
63
+ match schema_dict:
64
+ case {"const": const} if const is not None:
65
+ result = "any" if const is False else _ts_literal(const)
66
+ case {"enum": enum} if isinstance(enum, list) and enum:
67
+ enum_values = cast("list[Any]", enum)
68
+ result = " | ".join(_ts_literal(v) for v in enum_values)
69
+ case {"oneOf": one_of} if isinstance(one_of, list) and one_of:
70
+ schemas = cast("list[Any]", one_of)
71
+ union = {_ts_type_from_subschema(s) for s in schemas}
72
+ result = _join_union(union)
73
+ case {"allOf": all_of} if isinstance(all_of, list) and all_of:
74
+ schemas = cast("list[Any]", all_of)
75
+ parts = [_wrap_union_for_intersection(_ts_type_from_subschema(s)) for s in schemas]
76
+ parts = [p for p in parts if p and p != "any"]
77
+ result = " & ".join(parts) if parts else "any"
78
+ case {"type": list()}:
79
+ type_entries_list: list[Any] = schema_dict["type"]
80
+ parts = [_ts_type_from_openapi_type_entry(t, schema_dict) for t in type_entries_list if isinstance(t, str)]
81
+ result = _join_union(set(parts)) if parts else "any"
82
+ case {"type": str() as schema_type}:
83
+ result = _ts_type_from_openapi_type_entry(schema_type, schema_dict)
84
+ case _:
85
+ pass
86
+
87
+ return result
88
+
89
+
90
+ def python_type_to_typescript(py_type: str, *, fallback: str = "unknown") -> tuple[str, bool]:
91
+ """Convert a Python typing string representation into a TS type and optionality flag.
92
+
93
+ Returns:
94
+ A tuple of the TypeScript type string and a boolean indicating if the type is optional.
95
+ """
96
+ if not py_type:
97
+ return fallback, False
98
+
99
+ normalized = py_type.replace("typing.", "").replace("types.", "")
100
+ optional = "None" in normalized or "NoneType" in normalized or "Optional[" in normalized
101
+
102
+ normalized = normalized.replace("NoneType", "None").replace("None", "null")
103
+
104
+ mapping: dict[str, str] = {
105
+ "str": "string",
106
+ "int": "number",
107
+ "float": "number",
108
+ "bool": "boolean",
109
+ "dict": "Record<string, unknown>",
110
+ "Dict": "Record<string, unknown>",
111
+ "list": f"{fallback}[]",
112
+ "List": f"{fallback}[]",
113
+ "tuple": f"{fallback}[]",
114
+ "Tuple": f"{fallback}[]",
115
+ "set": f"{fallback}[]",
116
+ "Set": f"{fallback}[]",
117
+ "Any": fallback,
118
+ "unknown": "unknown",
119
+ "null": "null",
120
+ }
121
+
122
+ for k, v in mapping.items():
123
+ if normalized == k:
124
+ return v, optional
125
+
126
+ return normalized, optional
127
+
128
+
129
+ def collect_ref_names(schema_dict: Any) -> set[str]:
130
+ """Collect referenced component names from an OpenAPI schema dict.
131
+
132
+ Returns:
133
+ A set of referenced component names.
134
+ """
135
+ refs: set[str] = set()
136
+ if isinstance(schema_dict, dict):
137
+ schema_dict_t = cast("dict[str, Any]", schema_dict)
138
+ ref_any = schema_dict_t.get("$ref")
139
+ if isinstance(ref_any, str) and ref_any.startswith("#/components/schemas/"):
140
+ refs.add(ref_any.split("/")[-1])
141
+ for v in schema_dict_t.values():
142
+ refs.update(collect_ref_names(v))
143
+ elif isinstance(schema_dict, list):
144
+ for item in cast("list[Any]", schema_dict):
145
+ refs.update(collect_ref_names(item))
146
+ return refs
147
+
148
+
149
+ def _ts_type_from_subschema(schema: Any) -> str:
150
+ if isinstance(schema, dict):
151
+ return ts_type_from_openapi(cast("dict[str, Any]", schema))
152
+ return "any"
153
+
154
+
155
+ def _ts_type_from_openapi_type_entry(type_name: str, schema_dict: dict[str, Any]) -> str:
156
+ primitive_types: dict[str, str] = {
157
+ "string": "string",
158
+ "integer": "number",
159
+ "number": "number",
160
+ "boolean": "boolean",
161
+ "null": "null",
162
+ }
163
+
164
+ result = primitive_types.get(type_name, "any")
165
+ if type_name == "string":
166
+ fmt = schema_dict.get("format")
167
+ if isinstance(fmt, str) and fmt:
168
+ result = _OPENAPI_STRING_FORMAT_TO_TS_ALIAS.get(fmt, result)
169
+ if type_name == "array":
170
+ items = schema_dict.get("items")
171
+ item_type = _ts_type_from_subschema(items) if isinstance(items, dict) else "unknown"
172
+ result = f"{_wrap_for_array(item_type)}[]"
173
+ elif type_name == "object":
174
+ properties = schema_dict.get("properties")
175
+ if not isinstance(properties, dict) or not properties:
176
+ result = "{}"
177
+ else:
178
+ required_list = schema_dict.get("required")
179
+ required: set[str] = set()
180
+ if isinstance(required_list, list):
181
+ required = {v for v in cast("list[Any]", required_list) if isinstance(v, str)}
182
+
183
+ lines: list[str] = ["{"]
184
+ for name, prop_schema in cast("dict[str, Any]", properties).items():
185
+ ts_type = _ts_type_from_subschema(prop_schema)
186
+ optional = "" if name in required else "?"
187
+ lines.append(f" {name}{optional}: {ts_type};")
188
+ lines.append("}")
189
+ result = "\n".join(lines)
190
+
191
+ return result
192
+
193
+
194
+ def _wrap_for_array(type_expr: str) -> str:
195
+ expr = type_expr.strip()
196
+ if not expr:
197
+ return "unknown"
198
+ if expr.startswith("(") and expr.endswith(")"):
199
+ return expr
200
+ # Parenthesize unions/intersections so `(A | B)[]` / `(A & B)[]` is emitted correctly.
201
+ if " | " in expr or (" & " in expr and not expr.startswith("{")):
202
+ return f"({expr})"
203
+ return expr
204
+
205
+
206
+ def _wrap_union_for_intersection(type_expr: str) -> str:
207
+ expr = type_expr.strip()
208
+ if not expr:
209
+ return "any"
210
+ if expr.startswith("(") and expr.endswith(")"):
211
+ return expr
212
+ if " | " in expr:
213
+ return f"({expr})"
214
+ return expr
215
+
216
+
217
+ def _join_union(types: set[str]) -> str:
218
+ if not types:
219
+ return "any"
220
+ if len(types) == 1:
221
+ return next(iter(types))
222
+ return " | ".join(sorted(types))
223
+
224
+
225
+ def _ts_literal(value: Any) -> str:
226
+ if value is None:
227
+ return "null"
228
+ if isinstance(value, bool):
229
+ return "true" if value else "false"
230
+ if isinstance(value, int | float):
231
+ return str(value)
232
+ if isinstance(value, str):
233
+ escaped = value.replace("\\\\", "\\\\\\\\").replace('"', '\\"')
234
+ return f'"{escaped}"'
235
+ return "any"
@@ -0,0 +1,8 @@
1
+ """Internal SPA handler implementation.
2
+
3
+ The public API is exposed via :mod:`litestar_vite.handler`.
4
+ """
5
+
6
+ from litestar_vite._handler.app import AppHandler
7
+
8
+ __all__ = ("AppHandler",)