vibetuner 2.7.0__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.

Files changed (52) hide show
  1. vibetuner/cli/__init__.py +13 -2
  2. vibetuner/cli/run.py +0 -1
  3. vibetuner/cli/scaffold.py +187 -0
  4. vibetuner/config.py +27 -11
  5. vibetuner/context.py +3 -0
  6. vibetuner/frontend/__init__.py +7 -2
  7. vibetuner/frontend/lifespan.py +12 -7
  8. vibetuner/frontend/middleware.py +3 -3
  9. vibetuner/frontend/routes/auth.py +19 -13
  10. vibetuner/frontend/routes/debug.py +1 -1
  11. vibetuner/frontend/routes/health.py +4 -0
  12. vibetuner/frontend/routes/user.py +1 -1
  13. vibetuner/mongo.py +1 -1
  14. vibetuner/paths.py +197 -80
  15. vibetuner/tasks/worker.py +1 -1
  16. vibetuner/templates/email/{default/magic_link.html.jinja → magic_link.html.jinja} +2 -1
  17. vibetuner/templates/frontend/base/favicons.html.jinja +1 -1
  18. vibetuner/templates/frontend/base/skeleton.html.jinja +5 -2
  19. vibetuner/templates/frontend/debug/collections.html.jinja +2 -0
  20. vibetuner/templates/frontend/debug/components/debug_nav.html.jinja +6 -6
  21. vibetuner/templates/frontend/debug/index.html.jinja +6 -4
  22. vibetuner/templates/frontend/debug/info.html.jinja +2 -0
  23. vibetuner/templates/frontend/debug/users.html.jinja +4 -2
  24. vibetuner/templates/frontend/debug/version.html.jinja +2 -0
  25. vibetuner/templates/frontend/email_sent.html.jinja +2 -1
  26. vibetuner/templates/frontend/index.html.jinja +1 -0
  27. vibetuner/templates/frontend/login.html.jinja +8 -3
  28. vibetuner/templates/frontend/user/edit.html.jinja +3 -2
  29. vibetuner/templates/frontend/user/profile.html.jinja +2 -1
  30. vibetuner/templates.py +9 -15
  31. vibetuner/versioning.py +1 -1
  32. vibetuner-2.18.1.dist-info/METADATA +241 -0
  33. vibetuner-2.18.1.dist-info/RECORD +72 -0
  34. {vibetuner-2.7.0.dist-info → vibetuner-2.18.1.dist-info}/WHEEL +1 -1
  35. vibetuner-2.18.1.dist-info/entry_points.txt +3 -0
  36. vibetuner/frontend/AGENTS.md +0 -113
  37. vibetuner/frontend/CLAUDE.md +0 -113
  38. vibetuner/models/AGENTS.md +0 -165
  39. vibetuner/models/CLAUDE.md +0 -165
  40. vibetuner/services/AGENTS.md +0 -104
  41. vibetuner/services/CLAUDE.md +0 -104
  42. vibetuner/tasks/AGENTS.md +0 -98
  43. vibetuner/tasks/CLAUDE.md +0 -98
  44. vibetuner/templates/email/AGENTS.md +0 -48
  45. vibetuner/templates/email/CLAUDE.md +0 -48
  46. vibetuner/templates/frontend/AGENTS.md +0 -74
  47. vibetuner/templates/frontend/CLAUDE.md +0 -74
  48. vibetuner/templates/markdown/AGENTS.md +0 -29
  49. vibetuner/templates/markdown/CLAUDE.md +0 -29
  50. vibetuner-2.7.0.dist-info/METADATA +0 -48
  51. vibetuner-2.7.0.dist-info/RECORD +0 -84
  52. /vibetuner/templates/email/{default/magic_link.txt.jinja → magic_link.txt.jinja} +0 -0
@@ -1,165 +0,0 @@
1
- # Core Models Module
2
-
3
- **IMMUTABLE SCAFFOLDING CODE** - These are the framework's core models that provide essential functionality.
4
-
5
- ## What's Here
6
-
7
- This module contains the scaffolding's core models:
8
-
9
- - **UserModel** - Base user model with authentication support
10
- - **OAuthAccountModel** - OAuth provider account linking
11
- - **EmailVerificationTokenModel** - Magic link authentication tokens
12
- - **BlobModel** - File storage and blob management
13
- - **Mixins** - Reusable model behaviors (TimeStampMixin, etc.)
14
- - **Types** - Common field types and validators
15
-
16
- ## Important Rules
17
-
18
- ⚠️ **DO NOT MODIFY** these core models directly.
19
-
20
- **For changes to core models:**
21
-
22
- - File an issue at `https://github.com/alltuner/scaffolding`
23
- - Core changes benefit all projects using the scaffolding
24
-
25
- **For your application models:**
26
-
27
- - Create them in `src/app/models/` instead
28
- - Import core models when needed: `from vibetuner.models import UserModel`
29
- - Use mixins from here: `from vibetuner.models.mixins import TimeStampMixin`
30
-
31
- ## User Model Pattern (for reference)
32
-
33
- Your application models in `src/app/models/` should follow this pattern:
34
-
35
- ```python
36
- from beanie import Document
37
- from pydantic import Field
38
- from vibetuner.models.mixins import TimeStampMixin
39
-
40
- class Product(Document, TimeStampMixin):
41
- name: str
42
- price: float = Field(gt=0)
43
- stock: int = Field(ge=0)
44
-
45
- class Settings:
46
- name = "products"
47
- indexes = ["name"]
48
- ```
49
-
50
- ## Available Mixins
51
-
52
- ### TimeStampMixin
53
-
54
- Automatic timestamps for all models:
55
-
56
- - `db_insert_dt` - Created at (UTC)
57
- - `db_update_dt` - Updated at (UTC)
58
- - Methods: `age()`, `age_in()`, `is_older_than()`
59
-
60
- Import in your app models:
61
-
62
- ```python
63
- from vibetuner.models.mixins import TimeStampMixin
64
- ```
65
-
66
- ## Queries
67
-
68
- ### Finding Documents
69
-
70
- ```python
71
- from beanie.operators import Eq, In, Gt, Lt
72
-
73
- # By ID (preferred method)
74
- product = await Product.get(product_id)
75
-
76
- # By field (use Beanie operators)
77
- product = await Product.find_one(Eq(Product.name, "Widget"))
78
- products = await Product.find(Lt(Product.price, 100)).to_list()
79
-
80
- # Multiple conditions
81
- results = await Product.find(
82
- Eq(Product.category, "electronics"),
83
- Gt(Product.price, 50)
84
- ).to_list()
85
-
86
- # With In operator
87
- products = await Product.find(
88
- In(Product.category, ["electronics", "gadgets"])
89
- ).to_list()
90
- ```
91
-
92
- ### Save/Delete
93
-
94
- ```python
95
- # Create
96
- product = Product(name="Widget", price=9.99, stock=100)
97
- await product.insert()
98
-
99
- # Update
100
- product.price = 19.99
101
- await product.save()
102
-
103
- # Delete
104
- await product.delete()
105
- ```
106
-
107
- ### Aggregation
108
-
109
- ```python
110
- results = await Product.aggregate([
111
- {"$match": {"price": {"$gt": 50}}},
112
- {"$group": {"_id": "$category", "total": {"$sum": 1}}}
113
- ]).to_list()
114
- ```
115
-
116
- ## Indexes
117
-
118
- ```python
119
- from pymongo import IndexModel, TEXT
120
-
121
- class Settings:
122
- indexes = [
123
- "field_name", # Simple index
124
- [("field1", 1), ("field2", -1)], # Compound index
125
- IndexModel([("text_field", TEXT)]) # Text search
126
- ]
127
- ```
128
-
129
- ## Relationships
130
-
131
- ```python
132
- from beanie import Link
133
-
134
- class Order(Document):
135
- user: Link[User]
136
- products: list[Link[Product]]
137
-
138
- # Fetch with relations
139
- order = await Order.get(order_id, fetch_links=True)
140
- print(order.user.email) # Automatically loaded
141
- ```
142
-
143
- ## Extending Core Models
144
-
145
- If you need to add fields to User or other core models:
146
-
147
- 1. **Option A**: File an issue at `https://github.com/alltuner/scaffolding` for widely useful fields
148
- 2. **Option B**: Create a related model in `src/app/models/` that links to the core model:
149
-
150
- ```python
151
- from beanie import Document, Link
152
- from vibetuner.models import UserModel
153
-
154
- class UserProfile(Document):
155
- user: Link[UserModel]
156
- bio: str
157
- avatar_url: str
158
-
159
- class Settings:
160
- name = "user_profiles"
161
- ```
162
-
163
- ## MongoDB MCP
164
-
165
- Claude Code has MongoDB MCP access for database operations, queries, and debugging.
@@ -1,165 +0,0 @@
1
- # Core Models Module
2
-
3
- **IMMUTABLE SCAFFOLDING CODE** - These are the framework's core models that provide essential functionality.
4
-
5
- ## What's Here
6
-
7
- This module contains the scaffolding's core models:
8
-
9
- - **UserModel** - Base user model with authentication support
10
- - **OAuthAccountModel** - OAuth provider account linking
11
- - **EmailVerificationTokenModel** - Magic link authentication tokens
12
- - **BlobModel** - File storage and blob management
13
- - **Mixins** - Reusable model behaviors (TimeStampMixin, etc.)
14
- - **Types** - Common field types and validators
15
-
16
- ## Important Rules
17
-
18
- ⚠️ **DO NOT MODIFY** these core models directly.
19
-
20
- **For changes to core models:**
21
-
22
- - File an issue at `https://github.com/alltuner/scaffolding`
23
- - Core changes benefit all projects using the scaffolding
24
-
25
- **For your application models:**
26
-
27
- - Create them in `src/app/models/` instead
28
- - Import core models when needed: `from vibetuner.models import UserModel`
29
- - Use mixins from here: `from vibetuner.models.mixins import TimeStampMixin`
30
-
31
- ## User Model Pattern (for reference)
32
-
33
- Your application models in `src/app/models/` should follow this pattern:
34
-
35
- ```python
36
- from beanie import Document
37
- from pydantic import Field
38
- from vibetuner.models.mixins import TimeStampMixin
39
-
40
- class Product(Document, TimeStampMixin):
41
- name: str
42
- price: float = Field(gt=0)
43
- stock: int = Field(ge=0)
44
-
45
- class Settings:
46
- name = "products"
47
- indexes = ["name"]
48
- ```
49
-
50
- ## Available Mixins
51
-
52
- ### TimeStampMixin
53
-
54
- Automatic timestamps for all models:
55
-
56
- - `db_insert_dt` - Created at (UTC)
57
- - `db_update_dt` - Updated at (UTC)
58
- - Methods: `age()`, `age_in()`, `is_older_than()`
59
-
60
- Import in your app models:
61
-
62
- ```python
63
- from vibetuner.models.mixins import TimeStampMixin
64
- ```
65
-
66
- ## Queries
67
-
68
- ### Finding Documents
69
-
70
- ```python
71
- from beanie.operators import Eq, In, Gt, Lt
72
-
73
- # By ID (preferred method)
74
- product = await Product.get(product_id)
75
-
76
- # By field (use Beanie operators)
77
- product = await Product.find_one(Eq(Product.name, "Widget"))
78
- products = await Product.find(Lt(Product.price, 100)).to_list()
79
-
80
- # Multiple conditions
81
- results = await Product.find(
82
- Eq(Product.category, "electronics"),
83
- Gt(Product.price, 50)
84
- ).to_list()
85
-
86
- # With In operator
87
- products = await Product.find(
88
- In(Product.category, ["electronics", "gadgets"])
89
- ).to_list()
90
- ```
91
-
92
- ### Save/Delete
93
-
94
- ```python
95
- # Create
96
- product = Product(name="Widget", price=9.99, stock=100)
97
- await product.insert()
98
-
99
- # Update
100
- product.price = 19.99
101
- await product.save()
102
-
103
- # Delete
104
- await product.delete()
105
- ```
106
-
107
- ### Aggregation
108
-
109
- ```python
110
- results = await Product.aggregate([
111
- {"$match": {"price": {"$gt": 50}}},
112
- {"$group": {"_id": "$category", "total": {"$sum": 1}}}
113
- ]).to_list()
114
- ```
115
-
116
- ## Indexes
117
-
118
- ```python
119
- from pymongo import IndexModel, TEXT
120
-
121
- class Settings:
122
- indexes = [
123
- "field_name", # Simple index
124
- [("field1", 1), ("field2", -1)], # Compound index
125
- IndexModel([("text_field", TEXT)]) # Text search
126
- ]
127
- ```
128
-
129
- ## Relationships
130
-
131
- ```python
132
- from beanie import Link
133
-
134
- class Order(Document):
135
- user: Link[User]
136
- products: list[Link[Product]]
137
-
138
- # Fetch with relations
139
- order = await Order.get(order_id, fetch_links=True)
140
- print(order.user.email) # Automatically loaded
141
- ```
142
-
143
- ## Extending Core Models
144
-
145
- If you need to add fields to User or other core models:
146
-
147
- 1. **Option A**: File an issue at `https://github.com/alltuner/scaffolding` for widely useful fields
148
- 2. **Option B**: Create a related model in `src/app/models/` that links to the core model:
149
-
150
- ```python
151
- from beanie import Document, Link
152
- from vibetuner.models import UserModel
153
-
154
- class UserProfile(Document):
155
- user: Link[UserModel]
156
- bio: str
157
- avatar_url: str
158
-
159
- class Settings:
160
- name = "user_profiles"
161
- ```
162
-
163
- ## MongoDB MCP
164
-
165
- Claude Code has MongoDB MCP access for database operations, queries, and debugging.
@@ -1,104 +0,0 @@
1
- # Core Services Module
2
-
3
- **IMMUTABLE SCAFFOLDING CODE** - These are the framework's core services that provide essential functionality.
4
-
5
- ## What's Here
6
-
7
- This module contains the scaffolding's core services:
8
-
9
- - **email.py** - Email sending via AWS SES
10
- - **blob.py** - File storage and blob management
11
-
12
- ## Important Rules
13
-
14
- ⚠️ **DO NOT MODIFY** these core services directly.
15
-
16
- **For changes to core services:**
17
-
18
- - File an issue at `https://github.com/alltuner/scaffolding`
19
- - Core changes benefit all projects using the scaffolding
20
-
21
- **For your application services:**
22
-
23
- - Create them in `src/app/services/` instead
24
- - Import core services when needed: `from vibetuner.services.email import send_email`
25
-
26
- ## User Service Pattern (for reference)
27
-
28
- Your application services in `src/app/services/` should follow this pattern:
29
-
30
- ```python
31
- from vibetuner.models import UserModel
32
-
33
- class NotificationService:
34
- async def send_notification(
35
- self,
36
- user: UserModel,
37
- message: str,
38
- priority: str = "normal"
39
- ) -> bool:
40
- # Implementation
41
- return True
42
-
43
- # Singleton
44
- notification_service = NotificationService()
45
- ```
46
-
47
- ## Using Core Services
48
-
49
- ### Email Service
50
-
51
- ```python
52
- from vibetuner.services.email import send_email
53
-
54
- await send_email(
55
- to_email="user@example.com",
56
- subject="Welcome",
57
- html_content="<h1>Welcome!</h1>",
58
- text_content="Welcome!"
59
- )
60
- ```
61
-
62
- ### Blob Service
63
-
64
- ```python
65
- from vibetuner.services.blob import blob_service
66
-
67
- # Upload file
68
- blob = await blob_service.upload(file_data, "image.png")
69
-
70
- # Get file URL
71
- url = await blob_service.get_url(blob.id)
72
- ```
73
-
74
- ## Creating Your Own Services
75
-
76
- Place your application services in `src/app/services/`:
77
-
78
- ```python
79
- # src/app/services/external_api.py
80
- import httpx
81
-
82
- async def call_api(api_url: str, api_key: str, data: dict) -> dict:
83
- async with httpx.AsyncClient() as client:
84
- response = await client.post(
85
- api_url,
86
- json=data,
87
- headers={"Authorization": f"Bearer {api_key}"}
88
- )
89
- response.raise_for_status()
90
- return response.json()
91
- ```
92
-
93
- ## Dependency Injection
94
-
95
- ```python
96
- from fastapi import Depends
97
-
98
- @router.post("/notify")
99
- async def notify(
100
- message: str,
101
- service=Depends(lambda: notification_service)
102
- ):
103
- await service.send_notification(user, message)
104
- ```
@@ -1,104 +0,0 @@
1
- # Core Services Module
2
-
3
- **IMMUTABLE SCAFFOLDING CODE** - These are the framework's core services that provide essential functionality.
4
-
5
- ## What's Here
6
-
7
- This module contains the scaffolding's core services:
8
-
9
- - **email.py** - Email sending via AWS SES
10
- - **blob.py** - File storage and blob management
11
-
12
- ## Important Rules
13
-
14
- ⚠️ **DO NOT MODIFY** these core services directly.
15
-
16
- **For changes to core services:**
17
-
18
- - File an issue at `https://github.com/alltuner/scaffolding`
19
- - Core changes benefit all projects using the scaffolding
20
-
21
- **For your application services:**
22
-
23
- - Create them in `src/app/services/` instead
24
- - Import core services when needed: `from vibetuner.services.email import send_email`
25
-
26
- ## User Service Pattern (for reference)
27
-
28
- Your application services in `src/app/services/` should follow this pattern:
29
-
30
- ```python
31
- from vibetuner.models import UserModel
32
-
33
- class NotificationService:
34
- async def send_notification(
35
- self,
36
- user: UserModel,
37
- message: str,
38
- priority: str = "normal"
39
- ) -> bool:
40
- # Implementation
41
- return True
42
-
43
- # Singleton
44
- notification_service = NotificationService()
45
- ```
46
-
47
- ## Using Core Services
48
-
49
- ### Email Service
50
-
51
- ```python
52
- from vibetuner.services.email import send_email
53
-
54
- await send_email(
55
- to_email="user@example.com",
56
- subject="Welcome",
57
- html_content="<h1>Welcome!</h1>",
58
- text_content="Welcome!"
59
- )
60
- ```
61
-
62
- ### Blob Service
63
-
64
- ```python
65
- from vibetuner.services.blob import blob_service
66
-
67
- # Upload file
68
- blob = await blob_service.upload(file_data, "image.png")
69
-
70
- # Get file URL
71
- url = await blob_service.get_url(blob.id)
72
- ```
73
-
74
- ## Creating Your Own Services
75
-
76
- Place your application services in `src/app/services/`:
77
-
78
- ```python
79
- # src/app/services/external_api.py
80
- import httpx
81
-
82
- async def call_api(api_url: str, api_key: str, data: dict) -> dict:
83
- async with httpx.AsyncClient() as client:
84
- response = await client.post(
85
- api_url,
86
- json=data,
87
- headers={"Authorization": f"Bearer {api_key}"}
88
- )
89
- response.raise_for_status()
90
- return response.json()
91
- ```
92
-
93
- ## Dependency Injection
94
-
95
- ```python
96
- from fastapi import Depends
97
-
98
- @router.post("/notify")
99
- async def notify(
100
- message: str,
101
- service=Depends(lambda: notification_service)
102
- ):
103
- await service.send_notification(user, message)
104
- ```
vibetuner/tasks/AGENTS.md DELETED
@@ -1,98 +0,0 @@
1
- # Core Tasks Module
2
-
3
- **IMMUTABLE SCAFFOLDING CODE** - This is the framework's core background task infrastructure.
4
-
5
- ## What's Here
6
-
7
- This module contains the scaffolding's core task components:
8
-
9
- - **worker.py** - Streaq worker setup and configuration
10
- - **context.py** - Task context management (DB, HTTP client, etc.)
11
- - ****init**.py** - Task infrastructure exports
12
-
13
- ## Important Rules
14
-
15
- ⚠️ **DO NOT MODIFY** these core task components directly.
16
-
17
- **For changes to core tasks:**
18
-
19
- - File an issue at `https://github.com/alltuner/scaffolding`
20
- - Core changes benefit all projects using the scaffolding
21
-
22
- **For your application tasks:**
23
-
24
- - Create them in `src/app/tasks/` instead
25
- - Import the worker from vibetuner: `from vibetuner.tasks.worker import worker`
26
-
27
- ## Quick Reference
28
-
29
- Tasks are only available if job queue was enabled during scaffolding.
30
-
31
- The worker is defined in `src/vibetuner/tasks/worker.py` and should be imported from there in your app tasks.
32
-
33
- ## User Task Pattern (for reference)
34
-
35
- Your application tasks in `src/app/tasks/` should follow this pattern:
36
-
37
- ```python
38
- # src/app/tasks/emails.py
39
- from vibetuner.models import UserModel
40
- from vibetuner.tasks.worker import worker
41
-
42
- @worker.task()
43
- async def send_welcome_email(user_id: str) -> dict[str, str]:
44
- """Example background job."""
45
-
46
- # Access context
47
- res = await worker.context.http_client.get(url)
48
-
49
- if user := await UserModel.get(user_id):
50
- # Perform side effects
51
- return {"status": "sent", "user": user.email}
52
- return {"status": "skipped"}
53
- ```
54
-
55
- ## Queueing Tasks
56
-
57
- ```python
58
- # In your routes: src/app/frontend/routes/auth.py
59
- from app.tasks.emails import send_welcome_email
60
-
61
- @router.post("/signup")
62
- async def signup(email: str):
63
- user = await create_user(email)
64
-
65
- task = await send_welcome_email.enqueue(user.id)
66
- # Optional: await task.result() or check task.id
67
-
68
- return {"status": "registered", "job_id": task.id}
69
- ```
70
-
71
- Note: Import your task functions from `src/app/tasks/` but the worker itself comes from `vibetuner.tasks.worker`.
72
-
73
- ## Worker Management
74
-
75
- ```bash
76
- just worker-dev # Run worker locally with auto-reload
77
- ```
78
-
79
- ## Task Registration
80
-
81
- Add new task modules at the end of `src/app/tasks/__init__.py`:
82
-
83
- ```python
84
- # src/app/tasks/__init__.py
85
- # Import your task modules so decorators register with worker
86
- from . import emails # noqa: F401
87
- from . import new_tasks # noqa: F401
88
- ```
89
-
90
- ## Monitoring
91
-
92
- ```python
93
- task = await send_digest_email.enqueue(account_id)
94
-
95
- status = await task.status()
96
- result = await task.result(timeout=30)
97
- await task.abort() # Cancel if needed
98
- ```