vibetuner 2.14.1__py3-none-any.whl → 2.18.1__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 vibetuner might be problematic. Click here for more details.
- vibetuner/config.py +20 -9
- vibetuner/context.py +3 -0
- vibetuner/frontend/lifespan.py +12 -7
- vibetuner/frontend/middleware.py +2 -2
- vibetuner/frontend/routes/debug.py +1 -1
- vibetuner/frontend/routes/user.py +1 -1
- vibetuner/mongo.py +3 -3
- vibetuner/tasks/worker.py +1 -1
- vibetuner/templates/email/{default/magic_link.html.jinja → magic_link.html.jinja} +2 -1
- vibetuner/templates/frontend/base/favicons.html.jinja +1 -1
- vibetuner/templates/frontend/base/skeleton.html.jinja +5 -2
- vibetuner/templates/frontend/debug/collections.html.jinja +2 -0
- vibetuner/templates/frontend/debug/components/debug_nav.html.jinja +6 -6
- vibetuner/templates/frontend/debug/index.html.jinja +6 -4
- vibetuner/templates/frontend/debug/info.html.jinja +2 -0
- vibetuner/templates/frontend/debug/users.html.jinja +4 -2
- vibetuner/templates/frontend/debug/version.html.jinja +2 -0
- vibetuner/templates/frontend/email_sent.html.jinja +2 -1
- vibetuner/templates/frontend/index.html.jinja +1 -0
- vibetuner/templates/frontend/login.html.jinja +8 -3
- vibetuner/templates/frontend/user/edit.html.jinja +3 -2
- vibetuner/templates/frontend/user/profile.html.jinja +2 -1
- {vibetuner-2.14.1.dist-info → vibetuner-2.18.1.dist-info}/METADATA +20 -17
- {vibetuner-2.14.1.dist-info → vibetuner-2.18.1.dist-info}/RECORD +27 -41
- {vibetuner-2.14.1.dist-info → vibetuner-2.18.1.dist-info}/WHEEL +1 -1
- vibetuner/frontend/AGENTS.md +0 -113
- vibetuner/frontend/CLAUDE.md +0 -113
- vibetuner/models/AGENTS.md +0 -165
- vibetuner/models/CLAUDE.md +0 -165
- vibetuner/services/AGENTS.md +0 -104
- vibetuner/services/CLAUDE.md +0 -104
- vibetuner/tasks/AGENTS.md +0 -98
- vibetuner/tasks/CLAUDE.md +0 -98
- vibetuner/templates/email/AGENTS.md +0 -48
- vibetuner/templates/email/CLAUDE.md +0 -48
- vibetuner/templates/frontend/AGENTS.md +0 -74
- vibetuner/templates/frontend/CLAUDE.md +0 -74
- vibetuner/templates/markdown/AGENTS.md +0 -29
- vibetuner/templates/markdown/CLAUDE.md +0 -29
- /vibetuner/templates/email/{default/magic_link.txt.jinja → magic_link.txt.jinja} +0 -0
- {vibetuner-2.14.1.dist-info → vibetuner-2.18.1.dist-info}/entry_points.txt +0 -0
vibetuner/config.py
CHANGED
|
@@ -17,6 +17,8 @@ from pydantic import (
|
|
|
17
17
|
from pydantic_extra_types.language_code import LanguageAlpha2
|
|
18
18
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
19
19
|
|
|
20
|
+
from vibetuner.logging import logger
|
|
21
|
+
|
|
20
22
|
from .paths import config_vars as config_vars_path
|
|
21
23
|
from .versioning import version
|
|
22
24
|
|
|
@@ -32,12 +34,16 @@ def _load_project_config() -> "ProjectConfiguration":
|
|
|
32
34
|
)
|
|
33
35
|
if not config_vars_path.exists():
|
|
34
36
|
return ProjectConfiguration()
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
)
|
|
37
|
+
|
|
38
|
+
yaml_data = yaml.safe_load(config_vars_path.read_text(encoding="utf-8"))
|
|
39
|
+
return ProjectConfiguration(**yaml_data)
|
|
38
40
|
|
|
39
41
|
|
|
40
42
|
class ProjectConfiguration(BaseSettings):
|
|
43
|
+
@classmethod
|
|
44
|
+
def from_project_config(cls) -> "ProjectConfiguration":
|
|
45
|
+
return _load_project_config()
|
|
46
|
+
|
|
41
47
|
project_slug: str = "default_project"
|
|
42
48
|
project_name: str = "default_project"
|
|
43
49
|
|
|
@@ -47,9 +53,6 @@ class ProjectConfiguration(BaseSettings):
|
|
|
47
53
|
supported_languages: set[LanguageAlpha2] | None = None
|
|
48
54
|
default_language: LanguageAlpha2 = LanguageAlpha2("en")
|
|
49
55
|
|
|
50
|
-
mongodb_url: MongoDsn | None = None
|
|
51
|
-
redis_url: RedisDsn | None = None
|
|
52
|
-
|
|
53
56
|
# AWS Parameters
|
|
54
57
|
aws_default_region: str = "eu-central-1"
|
|
55
58
|
|
|
@@ -90,16 +93,20 @@ class ProjectConfiguration(BaseSettings):
|
|
|
90
93
|
)
|
|
91
94
|
return f"© {year_part}{f' {self.company_name}' if self.company_name else ''}"
|
|
92
95
|
|
|
93
|
-
model_config = SettingsConfigDict(extra="ignore")
|
|
96
|
+
model_config = SettingsConfigDict(case_sensitive=False, extra="ignore")
|
|
94
97
|
|
|
95
98
|
|
|
96
99
|
class CoreConfiguration(BaseSettings):
|
|
97
|
-
project: ProjectConfiguration
|
|
100
|
+
project: ProjectConfiguration = ProjectConfiguration.from_project_config()
|
|
98
101
|
|
|
99
102
|
debug: bool = False
|
|
100
103
|
version: str = version
|
|
101
104
|
session_key: SecretStr = SecretStr("ct-!secret-must-change-me")
|
|
102
105
|
|
|
106
|
+
# Database and Cache URLs
|
|
107
|
+
mongodb_url: MongoDsn = MongoDsn("mongodb://localhost:27017")
|
|
108
|
+
redis_url: RedisDsn = RedisDsn("redis://localhost:6379")
|
|
109
|
+
|
|
103
110
|
aws_access_key_id: SecretStr | None = None
|
|
104
111
|
aws_secret_access_key: SecretStr | None = None
|
|
105
112
|
|
|
@@ -130,4 +137,8 @@ class CoreConfiguration(BaseSettings):
|
|
|
130
137
|
)
|
|
131
138
|
|
|
132
139
|
|
|
133
|
-
settings = CoreConfiguration(
|
|
140
|
+
settings = CoreConfiguration()
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
logger.info("Configuration loaded for project: {}", settings.project.project_name)
|
|
144
|
+
logger.info("Configuration loaded for project: {}", settings.model_dump())
|
vibetuner/context.py
CHANGED
vibetuner/frontend/lifespan.py
CHANGED
|
@@ -2,25 +2,30 @@ from contextlib import asynccontextmanager
|
|
|
2
2
|
|
|
3
3
|
from fastapi import FastAPI
|
|
4
4
|
|
|
5
|
+
from vibetuner.context import ctx
|
|
6
|
+
from vibetuner.logging import logger
|
|
5
7
|
from vibetuner.mongo import init_models
|
|
6
8
|
|
|
7
|
-
from .context import ctx
|
|
8
9
|
from .hotreload import hotreload
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
@asynccontextmanager
|
|
12
|
-
async def
|
|
13
|
+
async def base_lifespan(app: FastAPI):
|
|
14
|
+
logger.info("Vibetuner frontend starting")
|
|
13
15
|
if ctx.DEBUG:
|
|
14
16
|
await hotreload.startup()
|
|
15
17
|
|
|
16
18
|
await init_models()
|
|
17
|
-
# Add below anything that should happen before startup
|
|
18
19
|
|
|
19
|
-
# Until here
|
|
20
20
|
yield
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# Until here
|
|
22
|
+
logger.info("Vibetuner frontend stopping")
|
|
25
23
|
if ctx.DEBUG:
|
|
26
24
|
await hotreload.shutdown()
|
|
25
|
+
logger.info("Vibetuner frontend stopped")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
from app.frontend.lifespan import lifespan # ty: ignore
|
|
30
|
+
except ImportError:
|
|
31
|
+
lifespan = base_lifespan
|
vibetuner/frontend/middleware.py
CHANGED
|
@@ -13,12 +13,12 @@ from starlette_babel import (
|
|
|
13
13
|
LocaleMiddleware,
|
|
14
14
|
get_translator,
|
|
15
15
|
)
|
|
16
|
-
from starlette_htmx.middleware import HtmxMiddleware
|
|
16
|
+
from starlette_htmx.middleware import HtmxMiddleware
|
|
17
17
|
|
|
18
18
|
from vibetuner.config import settings
|
|
19
|
+
from vibetuner.context import ctx
|
|
19
20
|
from vibetuner.paths import locales as locales_path
|
|
20
21
|
|
|
21
|
-
from .context import ctx
|
|
22
22
|
from .oauth import WebUser
|
|
23
23
|
|
|
24
24
|
|
|
@@ -10,10 +10,10 @@ from fastapi.responses import (
|
|
|
10
10
|
RedirectResponse,
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
+
from vibetuner.context import ctx
|
|
13
14
|
from vibetuner.models import UserModel
|
|
14
15
|
from vibetuner.models.registry import get_all_models
|
|
15
16
|
|
|
16
|
-
from ..context import ctx
|
|
17
17
|
from ..deps import MAGIC_COOKIE_NAME
|
|
18
18
|
from ..templates import render_template
|
|
19
19
|
|
|
@@ -3,9 +3,9 @@ from fastapi.responses import HTMLResponse, RedirectResponse
|
|
|
3
3
|
from pydantic_extra_types.language_code import LanguageAlpha2
|
|
4
4
|
from starlette.authentication import requires
|
|
5
5
|
|
|
6
|
+
from vibetuner.context import ctx
|
|
6
7
|
from vibetuner.models import UserModel
|
|
7
8
|
|
|
8
|
-
from ..context import ctx
|
|
9
9
|
from ..templates import render_template
|
|
10
10
|
|
|
11
11
|
|
vibetuner/mongo.py
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
from beanie import init_beanie
|
|
2
2
|
from pymongo import AsyncMongoClient
|
|
3
3
|
|
|
4
|
-
from .config import settings
|
|
5
|
-
from .models.registry import get_all_models
|
|
4
|
+
from vibetuner.config import settings
|
|
5
|
+
from vibetuner.models.registry import get_all_models
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
async def init_models() -> None:
|
|
9
9
|
"""Initialize MongoDB connection and register all Beanie models."""
|
|
10
10
|
|
|
11
11
|
client: AsyncMongoClient = AsyncMongoClient(
|
|
12
|
-
host=str(settings.
|
|
12
|
+
host=str(settings.mongodb_url),
|
|
13
13
|
compressors=["zstd"],
|
|
14
14
|
)
|
|
15
15
|
|
vibetuner/tasks/worker.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
{# djlint:off #}
|
|
1
2
|
<html>
|
|
2
3
|
<body>
|
|
3
|
-
<h2>Sign in to {{ project_name }}</h2>
|
|
4
4
|
<p>Click the link below to sign in to your account:</p>
|
|
5
5
|
<p>
|
|
6
6
|
<a href="{{ login_url }}"
|
|
@@ -14,3 +14,4 @@
|
|
|
14
14
|
<p>If you didn't request this, you can safely ignore this email.</p>
|
|
15
15
|
</body>
|
|
16
16
|
</html>
|
|
17
|
+
{# djlint:on #}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<link rel="manifest" href="{{ url_for(
|
|
1
|
+
<link rel="manifest" href="{{ url_for('site_webmanifest').path }}" />
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<meta name="description" content="{{ meta_description | default(
|
|
7
|
-
<meta name="keywords" content="{{ meta_keywords | default(
|
|
6
|
+
<meta name="description" content="{{ meta_description | default('') }}" />
|
|
7
|
+
<meta name="keywords" content="{{ meta_keywords | default('') }}" />
|
|
8
8
|
<meta name="color-scheme" content="light" />
|
|
9
9
|
<title>
|
|
10
10
|
{% block title %}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
{% endif %}
|
|
18
18
|
{% include "base/favicons.html.jinja" %}
|
|
19
19
|
{% include "base/opengraph.html.jinja" %}
|
|
20
|
+
|
|
20
21
|
{% block head %}
|
|
21
22
|
{% endblock head %}
|
|
22
23
|
</head>
|
|
@@ -26,6 +27,7 @@
|
|
|
26
27
|
{% block header %}
|
|
27
28
|
{% if not SKIP_HEADER %}
|
|
28
29
|
{% include "base/header.html.jinja" %}
|
|
30
|
+
|
|
29
31
|
{% endif %}
|
|
30
32
|
{% endblock header %}
|
|
31
33
|
{% block body %}
|
|
@@ -33,6 +35,7 @@
|
|
|
33
35
|
{% block footer %}
|
|
34
36
|
{% if not SKIP_FOOTER %}
|
|
35
37
|
{% include "base/footer.html.jinja" %}
|
|
38
|
+
|
|
36
39
|
{% endif %}
|
|
37
40
|
{% endblock footer %}
|
|
38
41
|
{% if DEBUG %}{{ hotreload.script(url_for('hot-reload') ) | safe }}{% endif %}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{% extends "base/skeleton.html.jinja" %}
|
|
2
|
+
|
|
2
3
|
{% block title %}
|
|
3
4
|
Database Collections Schema - Debug
|
|
4
5
|
{% endblock title %}
|
|
@@ -99,5 +100,6 @@
|
|
|
99
100
|
</div>
|
|
100
101
|
<!-- Debug Navigation Footer -->
|
|
101
102
|
{% include "debug/components/debug_nav.html.jinja" %}
|
|
103
|
+
|
|
102
104
|
</div>
|
|
103
105
|
{% endblock body %}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- Debug Navigation Component -->
|
|
2
2
|
<nav class="mt-8 pt-6 border-t border-base-200">
|
|
3
3
|
<div class="flex flex-wrap gap-4">
|
|
4
|
-
<a href="{{ url_for(
|
|
4
|
+
<a href="{{ url_for('debug_index') }}"
|
|
5
5
|
class="btn btn-outline btn-primary gap-2">
|
|
6
6
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
7
7
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z">
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
</svg>
|
|
12
12
|
Debug Home
|
|
13
13
|
</a>
|
|
14
|
-
<a href="{{ url_for(
|
|
14
|
+
<a href="{{ url_for('debug_info') }}"
|
|
15
15
|
class="btn btn-outline btn-primary gap-2">
|
|
16
16
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
17
17
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z">
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
</svg>
|
|
20
20
|
System Info
|
|
21
21
|
</a>
|
|
22
|
-
<a href="{{ url_for(
|
|
22
|
+
<a href="{{ url_for('debug_collections') }}"
|
|
23
23
|
class="btn btn-outline btn-primary gap-2">
|
|
24
24
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
25
25
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4">
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
</svg>
|
|
28
28
|
Collections
|
|
29
29
|
</a>
|
|
30
|
-
<a href="{{ url_for(
|
|
30
|
+
<a href="{{ url_for('debug_users') }}"
|
|
31
31
|
class="btn btn-outline btn-warning gap-2">
|
|
32
32
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
33
33
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z">
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
</svg>
|
|
36
36
|
User Impersonation
|
|
37
37
|
</a>
|
|
38
|
-
<a href="{{ url_for(
|
|
38
|
+
<a href="{{ url_for('debug_version') }}"
|
|
39
39
|
class="btn btn-outline btn-primary gap-2">
|
|
40
40
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
41
41
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z">
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
</svg>
|
|
44
44
|
Version
|
|
45
45
|
</a>
|
|
46
|
-
<a href="{{ url_for(
|
|
46
|
+
<a href="{{ url_for('health_ping') }}"
|
|
47
47
|
class="btn btn-outline btn-success gap-2">
|
|
48
48
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
49
49
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{% extends "base/skeleton.html.jinja" %}
|
|
2
|
+
|
|
2
3
|
{% block title %}
|
|
3
4
|
Debug Dashboard
|
|
4
5
|
{% endblock title %}
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
</h2>
|
|
24
25
|
<p class="text-base-content/70 mb-4">View application configuration, cookies, and runtime information</p>
|
|
25
26
|
<div class="card-actions justify-end">
|
|
26
|
-
<a href="{{ url_for(
|
|
27
|
+
<a href="{{ url_for('debug_info') }}" class="btn btn-primary btn-sm">View Details</a>
|
|
27
28
|
</div>
|
|
28
29
|
</div>
|
|
29
30
|
</div>
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
</h2>
|
|
40
41
|
<p class="text-base-content/70 mb-4">Explore MongoDB collections and their field schemas</p>
|
|
41
42
|
<div class="card-actions justify-end">
|
|
42
|
-
<a href="{{ url_for(
|
|
43
|
+
<a href="{{ url_for('debug_collections') }}"
|
|
43
44
|
class="btn btn-primary btn-sm">View Schemas</a>
|
|
44
45
|
</div>
|
|
45
46
|
</div>
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
</h2>
|
|
57
58
|
<p class="text-base-content/70 mb-4">Check application version and build information</p>
|
|
58
59
|
<div class="card-actions justify-end">
|
|
59
|
-
<a href="{{ url_for(
|
|
60
|
+
<a href="{{ url_for('debug_version') }}" class="btn btn-primary btn-sm">View Version</a>
|
|
60
61
|
</div>
|
|
61
62
|
</div>
|
|
62
63
|
</div>
|
|
@@ -72,12 +73,13 @@
|
|
|
72
73
|
</h2>
|
|
73
74
|
<p class="text-base-content/70 mb-4">Verify application health and API endpoint status</p>
|
|
74
75
|
<div class="card-actions justify-end">
|
|
75
|
-
<a href="{{ url_for(
|
|
76
|
+
<a href="{{ url_for('health_ping') }}" class="btn btn-success btn-sm">Check Health</a>
|
|
76
77
|
</div>
|
|
77
78
|
</div>
|
|
78
79
|
</div>
|
|
79
80
|
</div>
|
|
80
81
|
<!-- Debug Navigation Footer -->
|
|
81
82
|
{% include "debug/components/debug_nav.html.jinja" %}
|
|
83
|
+
|
|
82
84
|
</div>
|
|
83
85
|
{% endblock body %}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{% extends "base/skeleton.html.jinja" %}
|
|
2
|
+
|
|
2
3
|
{% block title %}
|
|
3
4
|
System Information - Debug
|
|
4
5
|
{% endblock title %}
|
|
@@ -252,5 +253,6 @@
|
|
|
252
253
|
</div>
|
|
253
254
|
<!-- Debug Navigation Footer -->
|
|
254
255
|
{% include "debug/components/debug_nav.html.jinja" %}
|
|
256
|
+
|
|
255
257
|
</div>
|
|
256
258
|
{% endblock body %}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{% extends "base/skeleton.html.jinja" %}
|
|
2
|
+
|
|
2
3
|
{% block title %}
|
|
3
4
|
Debug - User Impersonation
|
|
4
5
|
{% endblock title %}
|
|
@@ -36,7 +37,7 @@
|
|
|
36
37
|
User ID: <code>{{ current_user_id }}</code>
|
|
37
38
|
</p>
|
|
38
39
|
<div class="card-actions justify-end">
|
|
39
|
-
<form method="post" action="
|
|
40
|
+
<form method="post" action="{{ url_for('debug.stop_impersonation') }}">
|
|
40
41
|
<button type="submit" class="btn btn-secondary btn-sm">Stop Impersonation</button>
|
|
41
42
|
</form>
|
|
42
43
|
</div>
|
|
@@ -105,7 +106,7 @@
|
|
|
105
106
|
<td class="text-center">
|
|
106
107
|
{% if current_user_id != user.id|string %}
|
|
107
108
|
<form method="post"
|
|
108
|
-
action="
|
|
109
|
+
action="{{ url_for('debug.impersonate_user', user_id=user.id) }}"
|
|
109
110
|
class="inline">
|
|
110
111
|
<button type="submit" class="btn btn-outline btn-sm">Impersonate</button>
|
|
111
112
|
</form>
|
|
@@ -133,5 +134,6 @@
|
|
|
133
134
|
</div>
|
|
134
135
|
<!-- Debug Navigation Footer -->
|
|
135
136
|
{% include "debug/components/debug_nav.html.jinja" %}
|
|
137
|
+
|
|
136
138
|
</div>
|
|
137
139
|
{% endblock body %}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{% extends "base/skeleton.html.jinja" %}
|
|
2
|
+
|
|
2
3
|
{% block title %}
|
|
3
4
|
Version Information - Debug
|
|
4
5
|
{% endblock title %}
|
|
@@ -49,5 +50,6 @@
|
|
|
49
50
|
</div>
|
|
50
51
|
<!-- Debug Navigation Footer -->
|
|
51
52
|
{% include "debug/components/debug_nav.html.jinja" %}
|
|
53
|
+
|
|
52
54
|
</div>
|
|
53
55
|
{% endblock body %}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{% extends "base/skeleton.html.jinja" %}
|
|
2
|
+
|
|
2
3
|
{% block title %}
|
|
3
4
|
{{ _("Check Your Email") }}
|
|
4
5
|
{% endblock title %}
|
|
@@ -64,7 +65,7 @@
|
|
|
64
65
|
{{ _("Try Again") }}
|
|
65
66
|
</a>
|
|
66
67
|
<!-- Back to Home -->
|
|
67
|
-
<a href="{{ url_for(
|
|
68
|
+
<a href="{{ url_for('homepage') }}"
|
|
68
69
|
class="btn btn-ghost btn-block gap-2 text-base-content/70 hover:text-base-content transition-all duration-300">
|
|
69
70
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
70
71
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{% set BODY_CLASS = "min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100 flex flex-col justify-between" %}
|
|
2
2
|
{% extends "base/skeleton.html.jinja" %}
|
|
3
|
+
|
|
3
4
|
{% block body %}
|
|
4
5
|
<!-- Main Content -->
|
|
5
6
|
<div class="flex-1 flex items-center justify-center px-6">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{% extends "base/skeleton.html.jinja" %}
|
|
2
|
+
|
|
2
3
|
{% block title %}
|
|
3
4
|
{{ _("Sign In") }}
|
|
4
5
|
{% endblock title %}
|
|
@@ -15,7 +16,11 @@
|
|
|
15
16
|
{% if has_oauth and providers %}
|
|
16
17
|
<div class="space-y-3 mb-6">
|
|
17
18
|
{% for provider in providers %}
|
|
18
|
-
|
|
19
|
+
{% set login_url = url_for('login_with_' + provider) %}
|
|
20
|
+
{% if next %}
|
|
21
|
+
{% set login_url = login_url ~ '?next=' ~ next %}
|
|
22
|
+
{% endif %}
|
|
23
|
+
<a href="{{ login_url }}"
|
|
19
24
|
class="btn btn-outline btn-block justify-start gap-3 hover:btn-primary group transition-all duration-300 hover:scale-[1.02]">
|
|
20
25
|
<span>{{ _("Continue with %(provider)s") | format(provider=provider.title()) }}</span>
|
|
21
26
|
</a>
|
|
@@ -29,7 +34,7 @@
|
|
|
29
34
|
<div class="bg-base-200/50 rounded-2xl p-6 border border-base-300/50">
|
|
30
35
|
<form method="post"
|
|
31
36
|
class="space-y-4"
|
|
32
|
-
action="{{ url_for(
|
|
37
|
+
action="{{ url_for('send_magic_link') }}">
|
|
33
38
|
{% if next %}<input type="hidden" name="next" value="{{ next }}" />{% endif %}
|
|
34
39
|
<div class="form-control">
|
|
35
40
|
<label class="label" for="email">
|
|
@@ -40,7 +45,7 @@
|
|
|
40
45
|
id="email"
|
|
41
46
|
name="email"
|
|
42
47
|
class="input input-bordered w-full pr-12 focus:input-primary transition-all duration-300"
|
|
43
|
-
placeholder="{{ _(
|
|
48
|
+
placeholder="{{ _('Enter your email address') }}"
|
|
44
49
|
required
|
|
45
50
|
autocomplete="email" />
|
|
46
51
|
<div class="absolute inset-y-0 right-0 flex items-center pr-3">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{% extends "base/skeleton.html.jinja" %}
|
|
2
|
+
|
|
2
3
|
{% block title %}
|
|
3
4
|
{{ _("Edit Profile") }}
|
|
4
5
|
{% endblock title %}
|
|
@@ -13,7 +14,7 @@
|
|
|
13
14
|
</div>
|
|
14
15
|
<!-- Edit Form -->
|
|
15
16
|
<div class="bg-white shadow-lg rounded-lg p-6">
|
|
16
|
-
<form method="post" action="{{ url_for(
|
|
17
|
+
<form method="post" action="{{ url_for('user_edit_submit') }}">
|
|
17
18
|
<div class="space-y-6">
|
|
18
19
|
<!-- Name Field -->
|
|
19
20
|
<div>
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
</div>
|
|
56
57
|
<!-- Form Actions -->
|
|
57
58
|
<div class="flex justify-between items-center mt-8 pt-6 border-t border-gray-200">
|
|
58
|
-
<a href="{{ url_for(
|
|
59
|
+
<a href="{{ url_for('user_profile') }}" class="btn btn-ghost">{{ _("Cancel") }}</a>
|
|
59
60
|
<button type="submit" class="btn btn-primary">{{ _("Save Changes") }}</button>
|
|
60
61
|
</div>
|
|
61
62
|
</form>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{% extends "base/skeleton.html.jinja" %}
|
|
2
|
+
|
|
2
3
|
{% block title %}
|
|
3
4
|
{{ _("User Profile") }}
|
|
4
5
|
{% endblock title %}
|
|
@@ -108,7 +109,7 @@
|
|
|
108
109
|
hx-get="/user/edit"
|
|
109
110
|
hx-target="#main-content"
|
|
110
111
|
hx-swap="innerHTML">{{ _("Edit Profile") }}</button>
|
|
111
|
-
<a href="{{ url_for(
|
|
112
|
+
<a href="{{ url_for('auth_logout') }}" class="btn btn-outline btn-error">{{ _("Sign Out") }}</a>
|
|
112
113
|
</div>
|
|
113
114
|
</div>
|
|
114
115
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: vibetuner
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.18.1
|
|
4
4
|
Summary: Core Python framework and blessed dependencies for production-ready FastAPI + MongoDB + HTMX projects
|
|
5
5
|
Keywords: fastapi,mongodb,htmx,web-framework,scaffolding,oauth,background-jobs
|
|
6
6
|
Author: All Tuner Labs, S.L.
|
|
@@ -24,14 +24,14 @@ Requires-Dist: beanie[zstd]>=2.0.0
|
|
|
24
24
|
Requires-Dist: click>=8.3.0
|
|
25
25
|
Requires-Dist: copier>=9.10.3,<9.10.4
|
|
26
26
|
Requires-Dist: email-validator>=2.3.0
|
|
27
|
-
Requires-Dist: fastapi[standard-no-fastapi-cloud-cli]>=0.121.
|
|
27
|
+
Requires-Dist: fastapi[standard-no-fastapi-cloud-cli]>=0.121.1
|
|
28
28
|
Requires-Dist: granian[pname]>=2.5.7
|
|
29
29
|
Requires-Dist: httpx[http2]>=0.28.1
|
|
30
30
|
Requires-Dist: itsdangerous>=2.2.0
|
|
31
31
|
Requires-Dist: loguru>=0.7.3
|
|
32
32
|
Requires-Dist: pydantic[email]>=2.12.4
|
|
33
33
|
Requires-Dist: pydantic-extra-types[pycountry]>=2.10.6
|
|
34
|
-
Requires-Dist: pydantic-settings>=2.
|
|
34
|
+
Requires-Dist: pydantic-settings>=2.12.0
|
|
35
35
|
Requires-Dist: pyyaml>=6.0.3
|
|
36
36
|
Requires-Dist: redis[hiredis]>=7.0.1
|
|
37
37
|
Requires-Dist: rich>=14.2.0
|
|
@@ -44,24 +44,24 @@ Requires-Dist: babel>=2.17.0 ; extra == 'dev'
|
|
|
44
44
|
Requires-Dist: cloudflare>=4.3.1 ; extra == 'dev'
|
|
45
45
|
Requires-Dist: djlint>=1.36.4 ; extra == 'dev'
|
|
46
46
|
Requires-Dist: dunamai>=1.25.0 ; extra == 'dev'
|
|
47
|
-
Requires-Dist: gh-bin>=2.
|
|
47
|
+
Requires-Dist: gh-bin>=2.83.0 ; extra == 'dev'
|
|
48
48
|
Requires-Dist: granian[pname,reload]>=2.5.7 ; extra == 'dev'
|
|
49
49
|
Requires-Dist: just-bin>=1.43.0 ; extra == 'dev'
|
|
50
|
-
Requires-Dist: pre-commit>=4.
|
|
50
|
+
Requires-Dist: pre-commit>=4.4.0 ; extra == 'dev'
|
|
51
51
|
Requires-Dist: pysemver>=0.5.0 ; extra == 'dev'
|
|
52
|
-
Requires-Dist: ruff>=0.14.
|
|
53
|
-
Requires-Dist: rumdl>=0.0.
|
|
52
|
+
Requires-Dist: ruff>=0.14.4 ; extra == 'dev'
|
|
53
|
+
Requires-Dist: rumdl>=0.0.174 ; extra == 'dev'
|
|
54
54
|
Requires-Dist: semver>=3.0.4 ; extra == 'dev'
|
|
55
55
|
Requires-Dist: taplo>=0.9.3 ; extra == 'dev'
|
|
56
|
-
Requires-Dist: ty>=0.0.
|
|
56
|
+
Requires-Dist: ty>=0.0.1a26 ; extra == 'dev'
|
|
57
57
|
Requires-Dist: types-aioboto3[s3,ses]>=15.5.0 ; extra == 'dev'
|
|
58
58
|
Requires-Dist: types-authlib>=1.6.5.20251005 ; extra == 'dev'
|
|
59
59
|
Requires-Dist: types-pyyaml>=6.0.12.20250915 ; extra == 'dev'
|
|
60
60
|
Requires-Dist: uv-bump>=0.3.1 ; extra == 'dev'
|
|
61
61
|
Requires-Python: >=3.11
|
|
62
62
|
Project-URL: Changelog, https://github.com/alltuner/vibetuner/blob/main/CHANGELOG.md
|
|
63
|
-
Project-URL: Documentation, https://
|
|
64
|
-
Project-URL: Homepage, https://
|
|
63
|
+
Project-URL: Documentation, https://vibetuner.alltuner.com/
|
|
64
|
+
Project-URL: Homepage, https://vibetuner.alltuner.com/
|
|
65
65
|
Project-URL: Issues, https://github.com/alltuner/vibetuner/issues
|
|
66
66
|
Project-URL: Repository, https://github.com/alltuner/vibetuner
|
|
67
67
|
Provides-Extra: dev
|
|
@@ -69,13 +69,16 @@ Description-Content-Type: text/markdown
|
|
|
69
69
|
|
|
70
70
|
# vibetuner
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
Core Python framework and blessed dependencies for Vibetuner projects
|
|
73
73
|
|
|
74
|
-
This package provides the complete Python framework and curated dependency set for building modern
|
|
74
|
+
This package provides the complete Python framework and curated dependency set for building modern
|
|
75
|
+
web applications with Vibetuner. It includes everything from FastAPI and MongoDB integration to
|
|
76
|
+
authentication, background jobs, and CLI tools.
|
|
75
77
|
|
|
76
78
|
## What is Vibetuner?
|
|
77
79
|
|
|
78
|
-
Vibetuner is a production-ready scaffolding tool for FastAPI + MongoDB + HTMX web applications.
|
|
80
|
+
Vibetuner is a production-ready scaffolding tool for FastAPI + MongoDB + HTMX web applications.
|
|
81
|
+
This package (`vibetuner`) is the Python component that provides:
|
|
79
82
|
|
|
80
83
|
- Complete web application framework built on FastAPI
|
|
81
84
|
- MongoDB integration with Beanie ODM
|
|
@@ -84,7 +87,8 @@ Vibetuner is a production-ready scaffolding tool for FastAPI + MongoDB + HTMX we
|
|
|
84
87
|
- CLI framework with Typer
|
|
85
88
|
- Email services, blob storage, and more
|
|
86
89
|
|
|
87
|
-
**This package is designed to be used within projects generated by the Vibetuner scaffolding
|
|
90
|
+
**This package is designed to be used within projects generated by the Vibetuner scaffolding
|
|
91
|
+
tool.** For standalone use, you'll need to set up the project structure manually.
|
|
88
92
|
|
|
89
93
|
## Installation
|
|
90
94
|
|
|
@@ -172,7 +176,6 @@ vibetuner run prod worker
|
|
|
172
176
|
The `[dev]` extra includes all tools needed for development:
|
|
173
177
|
|
|
174
178
|
- **Ruff**: Fast linting and formatting
|
|
175
|
-
- **djlint**: Template linting
|
|
176
179
|
- **Babel**: i18n message extraction
|
|
177
180
|
- **pre-commit**: Git hooks
|
|
178
181
|
- **Type stubs**: For aioboto3, authlib, PyYAML
|
|
@@ -205,7 +208,7 @@ async def hello():
|
|
|
205
208
|
|
|
206
209
|
For complete documentation, guides, and examples, see the main Vibetuner repository:
|
|
207
210
|
|
|
208
|
-
**📖 [Vibetuner Documentation](https://
|
|
211
|
+
**📖 [Vibetuner Documentation](https://vibetuner.alltuner.com/)**
|
|
209
212
|
|
|
210
213
|
## Package Ecosystem
|
|
211
214
|
|
|
@@ -232,7 +235,7 @@ See [LICENSE](https://github.com/alltuner/vibetuner/blob/main/LICENSE) for detai
|
|
|
232
235
|
## Links
|
|
233
236
|
|
|
234
237
|
- **Main Repository**: <https://github.com/alltuner/vibetuner>
|
|
235
|
-
- **Documentation**: <https://
|
|
238
|
+
- **Documentation**: <https://vibetuner.alltuner.com/>
|
|
236
239
|
- **Issues**: <https://github.com/alltuner/vibetuner/issues>
|
|
237
240
|
- **PyPI**: <https://pypi.org/project/vibetuner/>
|
|
238
241
|
- **npm Package**: <https://www.npmjs.com/package/@alltuner/vibetuner>
|