vega-framework 0.1.34__tar.gz → 0.2.0__tar.gz
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.
- {vega_framework-0.1.34 → vega_framework-0.2.0}/PKG-INFO +10 -9
- {vega_framework-0.1.34 → vega_framework-0.2.0}/README.md +8 -7
- {vega_framework-0.1.34 → vega_framework-0.2.0}/pyproject.toml +28 -2
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/commands/add.py +9 -10
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/commands/init.py +9 -8
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/main.py +4 -4
- vega_framework-0.2.0/vega/cli/scaffolds/__init__.py +13 -0
- vega_framework-0.2.0/vega/cli/scaffolds/vega_web.py +109 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/__init__.py +34 -8
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/components.py +29 -13
- vega_framework-0.2.0/vega/cli/templates/web/app.py.j2 +15 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/health_route.py.j2 +2 -2
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/router.py.j2 +2 -2
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/routes_init_autodiscovery.py.j2 +2 -2
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/users_route.py.j2 +2 -2
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/discovery/routes.py +13 -13
- vega_framework-0.2.0/vega/web/__init__.py +100 -0
- vega_framework-0.2.0/vega/web/application.py +234 -0
- vega_framework-0.2.0/vega/web/builtin_middlewares.py +288 -0
- vega_framework-0.2.0/vega/web/exceptions.py +151 -0
- vega_framework-0.2.0/vega/web/middleware.py +185 -0
- vega_framework-0.2.0/vega/web/request.py +120 -0
- vega_framework-0.2.0/vega/web/response.py +220 -0
- vega_framework-0.2.0/vega/web/route_middleware.py +266 -0
- vega_framework-0.2.0/vega/web/router.py +350 -0
- vega_framework-0.2.0/vega/web/routing.py +347 -0
- vega_framework-0.1.34/vega/cli/scaffolds/__init__.py +0 -9
- vega_framework-0.1.34/vega/cli/templates/web/app.py.j2 +0 -15
- {vega_framework-0.1.34 → vega_framework-0.2.0}/LICENSE +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/__init__.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/__init__.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/commands/__init__.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/commands/generate.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/commands/migrate.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/commands/update.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/commands/web.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/scaffolds/fastapi.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/scaffolds/sqlalchemy.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/cli/command.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/cli/command_simple.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/cli/commands_init.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/domain/entity.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/domain/event.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/domain/event_handler.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/domain/interactor.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/domain/mediator.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/domain/repository_interface.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/domain/service_interface.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/infrastructure/model.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/infrastructure/repository_impl.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/infrastructure/service_impl.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/loader.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/project/.env.example +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/project/.gitignore +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/project/ARCHITECTURE.md.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/project/README.md.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/project/config.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/project/events_init.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/project/main.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/project/main_fastapi.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/project/main_standard.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/project/pyproject.toml.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/project/settings.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/sqlalchemy/alembic.ini.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/sqlalchemy/database_manager.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/sqlalchemy/env.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/sqlalchemy/script.py.mako +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/__init__.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/main.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/middleware.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/models_init.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/request_model.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/response_model.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/routes_init.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/templates/web/user_models.py.j2 +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/utils/__init__.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/utils/async_support.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/utils/messages.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/utils/naming.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/cli/utils/validators.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/di/__init__.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/di/container.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/di/decorators.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/di/errors.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/di/scope.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/discovery/__init__.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/discovery/commands.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/discovery/events.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/events/README.md +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/events/SYNTAX_GUIDE.md +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/events/__init__.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/events/bus.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/events/decorators.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/events/event.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/events/middleware.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/patterns/__init__.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/patterns/interactor.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/patterns/mediator.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/patterns/repository.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/patterns/service.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/settings/__init__.py +0 -0
- {vega_framework-0.1.34 → vega_framework-0.2.0}/vega/settings/base.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: vega-framework
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.2.0
|
4
4
|
Summary: Enterprise-ready Python framework that enforces Clean Architecture for building maintainable and scalable applications.
|
5
5
|
License: MIT
|
6
6
|
License-File: LICENSE
|
@@ -19,10 +19,10 @@ Classifier: Programming Language :: Python :: 3.14
|
|
19
19
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
20
20
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
21
21
|
Requires-Dist: click (>=8.0,<9.0)
|
22
|
-
Requires-Dist: fastapi (>=0.109,<0.110)
|
23
22
|
Requires-Dist: jinja2 (>=3.1,<4.0)
|
24
23
|
Requires-Dist: pydantic (>=2.0,<3.0)
|
25
24
|
Requires-Dist: pydantic-settings (>=2.0,<3.0)
|
25
|
+
Requires-Dist: starlette (>=0.37,<0.38)
|
26
26
|
Requires-Dist: toml (>=0.10,<0.11)
|
27
27
|
Requires-Dist: uvicorn (>=0.27,<0.28)
|
28
28
|
Project-URL: Documentation, https://vega-framework.readthedocs.io
|
@@ -43,7 +43,7 @@ Traditional Python frameworks show you **how to build** but don't enforce **how
|
|
43
43
|
- ✅ **Business Logic First** - Pure, testable, framework-independent
|
44
44
|
- ✅ **CLI Scaffolding** - Generate entire projects and components
|
45
45
|
- ✅ **Async Support** - Full async/await for CLI and web
|
46
|
-
- ✅ **
|
46
|
+
- ✅ **Vega Web (Starlette) & SQLAlchemy** - Built-in integrations when needed
|
47
47
|
|
48
48
|
**[Read the Philosophy →](docs/explanation/philosophy.md)** to understand why architecture matters.
|
49
49
|
|
@@ -152,7 +152,7 @@ container = Container({
|
|
152
152
|
|
153
153
|
```bash
|
154
154
|
vega init my-app # Create new project
|
155
|
-
vega init my-api --template
|
155
|
+
vega init my-api --template web # Create with Vega Web
|
156
156
|
vega doctor # Validate architecture
|
157
157
|
vega update # Update framework
|
158
158
|
```
|
@@ -169,7 +169,7 @@ vega generate interactor CreateProduct
|
|
169
169
|
vega generate mediator CheckoutWorkflow
|
170
170
|
|
171
171
|
# Presentation layer
|
172
|
-
vega generate router Product #
|
172
|
+
vega generate router Product # Vega Web (requires: vega add web)
|
173
173
|
vega generate command create-product # CLI
|
174
174
|
|
175
175
|
# Infrastructure
|
@@ -179,7 +179,7 @@ vega generate model Product # SQLAlchemy (requires: vega add db)
|
|
179
179
|
### Add Features
|
180
180
|
|
181
181
|
```bash
|
182
|
-
vega add web # Add
|
182
|
+
vega add web # Add Vega Web support
|
183
183
|
vega add sqlalchemy # Add database support
|
184
184
|
```
|
185
185
|
|
@@ -232,6 +232,7 @@ await UserCreated(user_id="123", email="test@test.com").publish()
|
|
232
232
|
- [Patterns](docs/explanation/patterns/interactor.md) - Interactor, Mediator, Repository, Service
|
233
233
|
|
234
234
|
### Guides
|
235
|
+
- [Use Vega Web](docs/how-to/use-vega-web.md) - Build HTTP APIs with Vega's router and middleware
|
235
236
|
- [Building Domain Layer](docs/how-to/build-domain-layer.md) - Business logic first
|
236
237
|
- [CLI Reference](docs/reference/cli/overview.md) - All CLI commands
|
237
238
|
- [Events System](docs/explanation/events/overview.md) - Event-driven architecture
|
@@ -268,7 +269,7 @@ my-app/
|
|
268
269
|
│ └── services/ # API integrations
|
269
270
|
├── presentation/ # User interfaces
|
270
271
|
│ ├── cli/ # CLI commands
|
271
|
-
│ └── web/ #
|
272
|
+
│ └── web/ # Vega Web routes
|
272
273
|
├── config.py # Dependency injection
|
273
274
|
├── settings.py # Configuration
|
274
275
|
└── main.py # Entry point
|
@@ -289,7 +290,7 @@ async def create_order(request: Request):
|
|
289
290
|
```
|
290
291
|
|
291
292
|
**Problems:**
|
292
|
-
- Can't test without
|
293
|
+
- Can't test without the web framework, database, and Stripe
|
293
294
|
- Can't reuse for CLI or other interfaces
|
294
295
|
- Business rules are unclear
|
295
296
|
- Tightly coupled to specific technologies
|
@@ -309,7 +310,7 @@ class PlaceOrder(Interactor[Order]):
|
|
309
310
|
await payment_service.charge(...)
|
310
311
|
return await order_repo.save(order)
|
311
312
|
|
312
|
-
# ✅
|
313
|
+
# ✅ Vega Web route (Presentation) - just wiring
|
313
314
|
@router.post("/orders")
|
314
315
|
async def create_order_api(request: CreateOrderRequest):
|
315
316
|
return await PlaceOrder(...)
|
@@ -11,7 +11,7 @@ Traditional Python frameworks show you **how to build** but don't enforce **how
|
|
11
11
|
- ✅ **Business Logic First** - Pure, testable, framework-independent
|
12
12
|
- ✅ **CLI Scaffolding** - Generate entire projects and components
|
13
13
|
- ✅ **Async Support** - Full async/await for CLI and web
|
14
|
-
- ✅ **
|
14
|
+
- ✅ **Vega Web (Starlette) & SQLAlchemy** - Built-in integrations when needed
|
15
15
|
|
16
16
|
**[Read the Philosophy →](docs/explanation/philosophy.md)** to understand why architecture matters.
|
17
17
|
|
@@ -120,7 +120,7 @@ container = Container({
|
|
120
120
|
|
121
121
|
```bash
|
122
122
|
vega init my-app # Create new project
|
123
|
-
vega init my-api --template
|
123
|
+
vega init my-api --template web # Create with Vega Web
|
124
124
|
vega doctor # Validate architecture
|
125
125
|
vega update # Update framework
|
126
126
|
```
|
@@ -137,7 +137,7 @@ vega generate interactor CreateProduct
|
|
137
137
|
vega generate mediator CheckoutWorkflow
|
138
138
|
|
139
139
|
# Presentation layer
|
140
|
-
vega generate router Product #
|
140
|
+
vega generate router Product # Vega Web (requires: vega add web)
|
141
141
|
vega generate command create-product # CLI
|
142
142
|
|
143
143
|
# Infrastructure
|
@@ -147,7 +147,7 @@ vega generate model Product # SQLAlchemy (requires: vega add db)
|
|
147
147
|
### Add Features
|
148
148
|
|
149
149
|
```bash
|
150
|
-
vega add web # Add
|
150
|
+
vega add web # Add Vega Web support
|
151
151
|
vega add sqlalchemy # Add database support
|
152
152
|
```
|
153
153
|
|
@@ -200,6 +200,7 @@ await UserCreated(user_id="123", email="test@test.com").publish()
|
|
200
200
|
- [Patterns](docs/explanation/patterns/interactor.md) - Interactor, Mediator, Repository, Service
|
201
201
|
|
202
202
|
### Guides
|
203
|
+
- [Use Vega Web](docs/how-to/use-vega-web.md) - Build HTTP APIs with Vega's router and middleware
|
203
204
|
- [Building Domain Layer](docs/how-to/build-domain-layer.md) - Business logic first
|
204
205
|
- [CLI Reference](docs/reference/cli/overview.md) - All CLI commands
|
205
206
|
- [Events System](docs/explanation/events/overview.md) - Event-driven architecture
|
@@ -236,7 +237,7 @@ my-app/
|
|
236
237
|
│ └── services/ # API integrations
|
237
238
|
├── presentation/ # User interfaces
|
238
239
|
│ ├── cli/ # CLI commands
|
239
|
-
│ └── web/ #
|
240
|
+
│ └── web/ # Vega Web routes
|
240
241
|
├── config.py # Dependency injection
|
241
242
|
├── settings.py # Configuration
|
242
243
|
└── main.py # Entry point
|
@@ -257,7 +258,7 @@ async def create_order(request: Request):
|
|
257
258
|
```
|
258
259
|
|
259
260
|
**Problems:**
|
260
|
-
- Can't test without
|
261
|
+
- Can't test without the web framework, database, and Stripe
|
261
262
|
- Can't reuse for CLI or other interfaces
|
262
263
|
- Business rules are unclear
|
263
264
|
- Tightly coupled to specific technologies
|
@@ -277,7 +278,7 @@ class PlaceOrder(Interactor[Order]):
|
|
277
278
|
await payment_service.charge(...)
|
278
279
|
return await order_repo.save(order)
|
279
280
|
|
280
|
-
# ✅
|
281
|
+
# ✅ Vega Web route (Presentation) - just wiring
|
281
282
|
@router.post("/orders")
|
282
283
|
async def create_order_api(request: CreateOrderRequest):
|
283
284
|
return await PlaceOrder(...)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "vega-framework"
|
3
|
-
version = "0.
|
3
|
+
version = "0.2.0"
|
4
4
|
description = "Enterprise-ready Python framework that enforces Clean Architecture for building maintainable and scalable applications."
|
5
5
|
authors = ["Roberto Ferro"]
|
6
6
|
license = "MIT"
|
@@ -43,7 +43,7 @@ click = "^8.0"
|
|
43
43
|
jinja2 = "^3.1"
|
44
44
|
toml = "^0.10"
|
45
45
|
uvicorn = "^0.27"
|
46
|
-
|
46
|
+
starlette = "^0.37"
|
47
47
|
|
48
48
|
[tool.poetry.group.dev.dependencies]
|
49
49
|
pytest = "^7.0"
|
@@ -53,6 +53,7 @@ black = "^23.0"
|
|
53
53
|
isort = "^5.0"
|
54
54
|
mypy = "^1.0"
|
55
55
|
ruff = "^0.1"
|
56
|
+
httpx = "^0.28.1"
|
56
57
|
|
57
58
|
[tool.poetry.scripts]
|
58
59
|
vega = "vega.cli.main:cli"
|
@@ -81,6 +82,31 @@ testpaths = ["tests"]
|
|
81
82
|
python_files = ["test_*.py"]
|
82
83
|
python_classes = ["Test*"]
|
83
84
|
python_functions = ["test_*"]
|
85
|
+
# Test markers
|
86
|
+
markers = [
|
87
|
+
"unit: Unit tests for individual components",
|
88
|
+
"functional: Functional tests for features and workflows",
|
89
|
+
"integration: Integration tests for component interactions",
|
90
|
+
"slow: Tests that take significant time to run",
|
91
|
+
"web: Web framework related tests",
|
92
|
+
"di: Dependency injection related tests",
|
93
|
+
"events: Event system related tests",
|
94
|
+
]
|
95
|
+
# Coverage settings
|
96
|
+
addopts = [
|
97
|
+
"--strict-markers",
|
98
|
+
"--tb=short",
|
99
|
+
"--cov=vega",
|
100
|
+
"--cov-report=term-missing",
|
101
|
+
"--cov-report=html:htmlcov",
|
102
|
+
"--cov-report=xml",
|
103
|
+
]
|
104
|
+
# Filter warnings
|
105
|
+
filterwarnings = [
|
106
|
+
"error",
|
107
|
+
"ignore::UserWarning",
|
108
|
+
"ignore::DeprecationWarning",
|
109
|
+
]
|
84
110
|
|
85
111
|
[tool.ruff]
|
86
112
|
line-length = 100
|
@@ -3,7 +3,7 @@ from pathlib import Path
|
|
3
3
|
|
4
4
|
import click
|
5
5
|
|
6
|
-
from vega.cli.scaffolds import
|
6
|
+
from vega.cli.scaffolds import create_vega_web_scaffold, create_sqlalchemy_scaffold
|
7
7
|
|
8
8
|
|
9
9
|
@click.command()
|
@@ -13,7 +13,7 @@ def add(feature: str, path: str):
|
|
13
13
|
"""Add features to an existing Vega project
|
14
14
|
|
15
15
|
Features:
|
16
|
-
web - Add
|
16
|
+
web - Add Vega Web scaffold to the project
|
17
17
|
sqlalchemy - Add SQLAlchemy database support (alias: db)
|
18
18
|
db - Alias for sqlalchemy
|
19
19
|
|
@@ -40,13 +40,13 @@ def add(feature: str, path: str):
|
|
40
40
|
|
41
41
|
|
42
42
|
def add_web_feature(project_path: Path, project_name: str):
|
43
|
-
"""Add
|
44
|
-
click.echo(f"\n[*] Adding
|
43
|
+
"""Add Vega Web scaffold to existing project"""
|
44
|
+
click.echo(f"\n[*] Adding Vega Web scaffold to: {click.style(project_name, fg='green', bold=True)}\n")
|
45
45
|
|
46
46
|
# Check if presentation/web already exists
|
47
47
|
web_dir = project_path / "presentation" / "web"
|
48
48
|
if web_dir.exists() and (web_dir / "main.py").exists():
|
49
|
-
click.echo(click.style("WARNING:
|
49
|
+
click.echo(click.style("WARNING: Web scaffold already exists!", fg='yellow'))
|
50
50
|
if not click.confirm("Do you want to overwrite existing files?"):
|
51
51
|
click.echo("Aborted.")
|
52
52
|
return
|
@@ -60,13 +60,12 @@ def add_web_feature(project_path: Path, project_name: str):
|
|
60
60
|
presentation_dir.mkdir(parents=True, exist_ok=True)
|
61
61
|
click.echo(f" + Created presentation/")
|
62
62
|
|
63
|
-
# Create
|
64
|
-
|
63
|
+
# Create Vega Web scaffold
|
64
|
+
create_vega_web_scaffold(project_path, project_name, overwrite=overwrite)
|
65
65
|
|
66
|
-
click.echo(f"\n{click.style('SUCCESS:
|
66
|
+
click.echo(f"\n{click.style('SUCCESS: Vega Web scaffold added!', fg='green', bold=True)}\n")
|
67
67
|
click.echo("Next steps:")
|
68
|
-
click.echo(" 1.
|
69
|
-
click.echo(" poetry add fastapi uvicorn[standard]")
|
68
|
+
click.echo(" 1. Dependencies are already included in vega-framework")
|
70
69
|
click.echo(" 2. Run the server:")
|
71
70
|
click.echo(" vega web run --reload")
|
72
71
|
click.echo(" 3. Visit http://localhost:8000/api/health/status")
|
@@ -5,7 +5,7 @@ from pathlib import Path
|
|
5
5
|
|
6
6
|
import click
|
7
7
|
|
8
|
-
from vega.cli.scaffolds import
|
8
|
+
from vega.cli.scaffolds import create_vega_web_scaffold
|
9
9
|
from vega.cli.templates.loader import render_template
|
10
10
|
import vega
|
11
11
|
|
@@ -104,14 +104,15 @@ def init_project(project_name: str, template: str, parent_path: str):
|
|
104
104
|
click.echo(f" + Created ARCHITECTURE.md")
|
105
105
|
|
106
106
|
# Create main.py based on template
|
107
|
-
|
108
|
-
|
109
|
-
|
107
|
+
# Support both "web" and "fastapi" (backward compat)
|
108
|
+
if template in ["web", "fastapi"]:
|
109
|
+
click.echo("\n[*] Adding Vega Web scaffold (presentation/web/)")
|
110
|
+
create_vega_web_scaffold(project_path, project_name)
|
110
111
|
|
111
|
-
# Create main.py for
|
112
|
+
# Create main.py for web project
|
112
113
|
main_content = render_template("main.py.j2", project_name=project_name, template="fastapi")
|
113
114
|
(project_path / "main.py").write_text(main_content)
|
114
|
-
click.echo(f" + Created main.py (
|
115
|
+
click.echo(f" + Created main.py (Vega Web entrypoint)")
|
115
116
|
else:
|
116
117
|
# Create standard main.py
|
117
118
|
main_content = render_template("main.py.j2", project_name=project_name, template="standard")
|
@@ -126,9 +127,9 @@ def init_project(project_name: str, template: str, parent_path: str):
|
|
126
127
|
click.echo(f" poetry install")
|
127
128
|
click.echo(f" cp .env.example .env")
|
128
129
|
|
129
|
-
if template
|
130
|
+
if template in ["web", "fastapi"]:
|
130
131
|
click.echo(f"\nRun commands:")
|
131
|
-
click.echo(f" vega web run # Start
|
132
|
+
click.echo(f" vega web run # Start Vega Web server (http://localhost:8000)")
|
132
133
|
click.echo(f" vega web run --reload # Start with auto-reload")
|
133
134
|
click.echo(f" python main.py hello # Run CLI command")
|
134
135
|
click.echo(f" python main.py --help # Show all commands")
|
@@ -34,7 +34,7 @@ def cli():
|
|
34
34
|
|
35
35
|
@cli.command()
|
36
36
|
@click.argument('project_name')
|
37
|
-
@click.option('--template', default='basic', help='Project template (basic,
|
37
|
+
@click.option('--template', default='basic', help='Project template (basic, web, ai-rag)')
|
38
38
|
@click.option('--path', default='.', help='Parent directory for project')
|
39
39
|
def init(project_name, template, path):
|
40
40
|
"""
|
@@ -49,7 +49,7 @@ def init(project_name, template, path):
|
|
49
49
|
|
50
50
|
Examples:
|
51
51
|
vega init my-app
|
52
|
-
vega init my-api --template=
|
52
|
+
vega init my-api --template=web
|
53
53
|
vega init my-ai --template=ai-rag --path=./projects
|
54
54
|
"""
|
55
55
|
init_project(project_name, template, path)
|
@@ -88,8 +88,8 @@ def generate(component_type, name, path, impl, request, response):
|
|
88
88
|
service - Service interface (domain layer)
|
89
89
|
interactor - Use case (business logic)
|
90
90
|
mediator - Workflow (orchestrates use cases)
|
91
|
-
router -
|
92
|
-
middleware -
|
91
|
+
router - Vega Web router (requires web module)
|
92
|
+
middleware - Vega Web middleware (requires web module)
|
93
93
|
webmodel - Pydantic request/response models (requires web module)
|
94
94
|
model - SQLAlchemy model (requires sqlalchemy module)
|
95
95
|
command - CLI command (async by default)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
"""Scaffolding helpers for Vega CLI."""
|
2
|
+
|
3
|
+
from .vega_web import create_vega_web_scaffold
|
4
|
+
from .sqlalchemy import create_sqlalchemy_scaffold
|
5
|
+
|
6
|
+
# Backward compatibility alias
|
7
|
+
create_fastapi_scaffold = create_vega_web_scaffold
|
8
|
+
|
9
|
+
__all__ = [
|
10
|
+
"create_vega_web_scaffold",
|
11
|
+
"create_fastapi_scaffold", # Deprecated: use create_vega_web_scaffold
|
12
|
+
"create_sqlalchemy_scaffold",
|
13
|
+
]
|
@@ -0,0 +1,109 @@
|
|
1
|
+
"""Vega Web scaffolding for new projects"""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from pathlib import Path
|
6
|
+
from typing import Callable, Iterable
|
7
|
+
|
8
|
+
import click
|
9
|
+
|
10
|
+
from vega.cli.templates import (
|
11
|
+
render_vega_app,
|
12
|
+
render_vega_health_route,
|
13
|
+
render_vega_main,
|
14
|
+
render_vega_routes_init_autodiscovery,
|
15
|
+
render_vega_user_route,
|
16
|
+
render_pydantic_models_init,
|
17
|
+
render_pydantic_user_models,
|
18
|
+
render_web_package_init,
|
19
|
+
)
|
20
|
+
|
21
|
+
|
22
|
+
def create_vega_web_scaffold(
|
23
|
+
project_root: Path,
|
24
|
+
project_name: str,
|
25
|
+
*,
|
26
|
+
overwrite: bool = False,
|
27
|
+
echo: Callable[[str], None] | None = None,
|
28
|
+
) -> list[Path]:
|
29
|
+
"""
|
30
|
+
Create Vega Web scaffolding under the project presentation/web/ directory.
|
31
|
+
|
32
|
+
This creates a complete web application structure using Vega's built-in
|
33
|
+
web framework (built on Starlette).
|
34
|
+
|
35
|
+
Args:
|
36
|
+
project_root: Root directory of the project
|
37
|
+
project_name: Name of the project
|
38
|
+
overwrite: Whether to overwrite existing files
|
39
|
+
echo: Function to print messages (defaults to click.echo)
|
40
|
+
|
41
|
+
Returns:
|
42
|
+
List of created file paths
|
43
|
+
"""
|
44
|
+
if echo is None:
|
45
|
+
echo = click.echo
|
46
|
+
|
47
|
+
created: list[Path] = []
|
48
|
+
web_dir = project_root / "presentation" / "web"
|
49
|
+
routes_dir = web_dir / "routes"
|
50
|
+
models_dir = web_dir / "models"
|
51
|
+
|
52
|
+
files: Iterable[tuple[Path, str]] = (
|
53
|
+
(web_dir / "__init__.py", render_web_package_init()),
|
54
|
+
(web_dir / "app.py", render_vega_app(project_name)),
|
55
|
+
(web_dir / "main.py", render_vega_main(project_name)),
|
56
|
+
(routes_dir / "__init__.py", render_vega_routes_init_autodiscovery()),
|
57
|
+
(routes_dir / "health.py", render_vega_health_route()),
|
58
|
+
(routes_dir / "users.py", render_vega_user_route()),
|
59
|
+
(models_dir / "__init__.py", render_pydantic_models_init()),
|
60
|
+
(models_dir / "user_models.py", render_pydantic_user_models()),
|
61
|
+
)
|
62
|
+
|
63
|
+
web_dir.mkdir(parents=True, exist_ok=True)
|
64
|
+
routes_dir.mkdir(parents=True, exist_ok=True)
|
65
|
+
models_dir.mkdir(parents=True, exist_ok=True)
|
66
|
+
|
67
|
+
for path, content in files:
|
68
|
+
rel_path = path.relative_to(project_root)
|
69
|
+
if path.exists() and not overwrite:
|
70
|
+
echo(
|
71
|
+
click.style(
|
72
|
+
f"WARNING: {rel_path} already exists. Skipping.",
|
73
|
+
fg="yellow",
|
74
|
+
)
|
75
|
+
)
|
76
|
+
continue
|
77
|
+
|
78
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
79
|
+
path.write_text(content, encoding="utf-8")
|
80
|
+
created.append(rel_path)
|
81
|
+
echo(f"+ Created {click.style(str(rel_path), fg='green')}")
|
82
|
+
|
83
|
+
echo("\n[TIP] Vega Web scaffold ready:")
|
84
|
+
echo(" 1. poetry install # sync dependencies (or poetry update)")
|
85
|
+
echo(" 2. poetry run vega web run --reload")
|
86
|
+
echo(" 3. Or: poetry run uvicorn presentation.web.main:app --reload")
|
87
|
+
|
88
|
+
return created
|
89
|
+
|
90
|
+
|
91
|
+
def _ensure_dependency_line(lines: list[str], name: str, spec: str) -> bool:
|
92
|
+
"""Insert dependency assignment into [tool.poetry.dependencies] if missing."""
|
93
|
+
header = "[tool.poetry.dependencies]"
|
94
|
+
try:
|
95
|
+
start = next(i for i, line in enumerate(lines) if line.strip() == header)
|
96
|
+
except StopIteration:
|
97
|
+
return False
|
98
|
+
|
99
|
+
end = start + 1
|
100
|
+
while end < len(lines) and not lines[end].startswith("["):
|
101
|
+
end += 1
|
102
|
+
|
103
|
+
block = lines[start + 1:end]
|
104
|
+
if any(line.strip().startswith(f"{name} =") for line in block):
|
105
|
+
return False
|
106
|
+
|
107
|
+
insertion = f"{name} = \"{spec}\"\n"
|
108
|
+
lines.insert(end, insertion)
|
109
|
+
return True
|
@@ -7,18 +7,32 @@ from .components import (
|
|
7
7
|
render_repository_interface,
|
8
8
|
render_service_interface,
|
9
9
|
render_web_package_init,
|
10
|
+
# New Vega Web functions
|
11
|
+
render_vega_app,
|
12
|
+
render_vega_routes_init,
|
13
|
+
render_vega_health_route,
|
14
|
+
render_vega_user_route,
|
15
|
+
render_vega_dependencies,
|
16
|
+
render_vega_main,
|
17
|
+
render_vega_project_main,
|
18
|
+
render_vega_router,
|
19
|
+
render_vega_middleware,
|
20
|
+
render_vega_routes_init_autodiscovery,
|
21
|
+
# Backward compatibility (deprecated)
|
10
22
|
render_fastapi_app,
|
11
23
|
render_fastapi_routes_init,
|
12
24
|
render_fastapi_health_route,
|
13
25
|
render_fastapi_user_route,
|
14
26
|
render_fastapi_dependencies,
|
15
27
|
render_fastapi_main,
|
16
|
-
render_standard_main,
|
17
28
|
render_fastapi_project_main,
|
18
|
-
render_pydantic_models_init,
|
19
|
-
render_pydantic_user_models,
|
20
29
|
render_fastapi_router,
|
21
30
|
render_fastapi_middleware,
|
31
|
+
render_fastapi_routes_init_autodiscovery,
|
32
|
+
# Common
|
33
|
+
render_standard_main,
|
34
|
+
render_pydantic_models_init,
|
35
|
+
render_pydantic_user_models,
|
22
36
|
render_database_manager,
|
23
37
|
render_alembic_ini,
|
24
38
|
render_alembic_env,
|
@@ -27,7 +41,6 @@ from .components import (
|
|
27
41
|
render_cli_command,
|
28
42
|
render_cli_command_simple,
|
29
43
|
render_cli_commands_init,
|
30
|
-
render_fastapi_routes_init_autodiscovery,
|
31
44
|
render_event,
|
32
45
|
render_event_handler,
|
33
46
|
render_events_init,
|
@@ -43,18 +56,32 @@ __all__ = [
|
|
43
56
|
"render_infrastructure_repository",
|
44
57
|
"render_infrastructure_service",
|
45
58
|
"render_web_package_init",
|
59
|
+
# Vega Web
|
60
|
+
"render_vega_app",
|
61
|
+
"render_vega_routes_init",
|
62
|
+
"render_vega_health_route",
|
63
|
+
"render_vega_user_route",
|
64
|
+
"render_vega_dependencies",
|
65
|
+
"render_vega_main",
|
66
|
+
"render_vega_project_main",
|
67
|
+
"render_vega_router",
|
68
|
+
"render_vega_middleware",
|
69
|
+
"render_vega_routes_init_autodiscovery",
|
70
|
+
# Backward compat (deprecated)
|
46
71
|
"render_fastapi_app",
|
47
72
|
"render_fastapi_routes_init",
|
48
73
|
"render_fastapi_health_route",
|
49
74
|
"render_fastapi_user_route",
|
50
75
|
"render_fastapi_dependencies",
|
51
76
|
"render_fastapi_main",
|
52
|
-
"render_standard_main",
|
53
77
|
"render_fastapi_project_main",
|
54
|
-
"render_pydantic_models_init",
|
55
|
-
"render_pydantic_user_models",
|
56
78
|
"render_fastapi_router",
|
57
79
|
"render_fastapi_middleware",
|
80
|
+
"render_fastapi_routes_init_autodiscovery",
|
81
|
+
# Common
|
82
|
+
"render_standard_main",
|
83
|
+
"render_pydantic_models_init",
|
84
|
+
"render_pydantic_user_models",
|
58
85
|
"render_database_manager",
|
59
86
|
"render_alembic_ini",
|
60
87
|
"render_alembic_env",
|
@@ -63,7 +90,6 @@ __all__ = [
|
|
63
90
|
"render_cli_command",
|
64
91
|
"render_cli_command_simple",
|
65
92
|
"render_cli_commands_init",
|
66
|
-
"render_fastapi_routes_init_autodiscovery",
|
67
93
|
"render_event",
|
68
94
|
"render_event_handler",
|
69
95
|
"render_events_init",
|
@@ -84,27 +84,27 @@ def render_web_package_init() -> str:
|
|
84
84
|
return render_template("__init__.py.j2", subfolder="web")
|
85
85
|
|
86
86
|
|
87
|
-
def
|
87
|
+
def render_vega_app(project_name: str) -> str:
|
88
88
|
"""Return the template for web/app.py"""
|
89
89
|
return render_template("app.py.j2", subfolder="web", project_name=project_name)
|
90
90
|
|
91
91
|
|
92
|
-
def
|
92
|
+
def render_vega_routes_init() -> str:
|
93
93
|
"""Return the template for web/routes/__init__.py"""
|
94
94
|
return render_template("routes_init.py.j2", subfolder="web")
|
95
95
|
|
96
96
|
|
97
|
-
def
|
97
|
+
def render_vega_health_route() -> str:
|
98
98
|
"""Return the template for web/routes/health.py"""
|
99
99
|
return render_template("health_route.py.j2", subfolder="web")
|
100
100
|
|
101
101
|
|
102
|
-
def
|
102
|
+
def render_vega_dependencies() -> str:
|
103
103
|
"""Return the template for web/dependencies.py"""
|
104
104
|
return render_template("dependencies.py.j2", subfolder="web")
|
105
105
|
|
106
106
|
|
107
|
-
def
|
107
|
+
def render_vega_main(project_name: str) -> str:
|
108
108
|
"""Return the template for presentation/web/main.py"""
|
109
109
|
return render_template("main.py.j2", subfolder="web", project_name=project_name)
|
110
110
|
|
@@ -116,8 +116,8 @@ def render_standard_main(project_name: str) -> str:
|
|
116
116
|
)
|
117
117
|
|
118
118
|
|
119
|
-
def
|
120
|
-
"""Return the template for main.py (
|
119
|
+
def render_vega_project_main(project_name: str) -> str:
|
120
|
+
"""Return the template for main.py (Vega Web project with Web and CLI)"""
|
121
121
|
return render_template(
|
122
122
|
"main_fastapi.py.j2", subfolder="project", project_name=project_name
|
123
123
|
)
|
@@ -133,13 +133,13 @@ def render_pydantic_user_models() -> str:
|
|
133
133
|
return render_template("user_models.py.j2", subfolder="web")
|
134
134
|
|
135
135
|
|
136
|
-
def
|
136
|
+
def render_vega_user_route() -> str:
|
137
137
|
"""Return the template for web/routes/users.py"""
|
138
138
|
return render_template("users_route.py.j2", subfolder="web")
|
139
139
|
|
140
140
|
|
141
|
-
def
|
142
|
-
"""Return the template for a
|
141
|
+
def render_vega_router(resource_name: str, resource_file: str, project_name: str) -> str:
|
142
|
+
"""Return the template for a Vega Web router"""
|
143
143
|
return render_template(
|
144
144
|
"router.py.j2",
|
145
145
|
subfolder="web",
|
@@ -149,8 +149,8 @@ def render_fastapi_router(resource_name: str, resource_file: str, project_name:
|
|
149
149
|
)
|
150
150
|
|
151
151
|
|
152
|
-
def
|
153
|
-
"""Return the template for a
|
152
|
+
def render_vega_middleware(class_name: str, file_name: str) -> str:
|
153
|
+
"""Return the template for a Vega Web middleware"""
|
154
154
|
return render_template(
|
155
155
|
"middleware.py.j2",
|
156
156
|
subfolder="web",
|
@@ -159,6 +159,18 @@ def render_fastapi_middleware(class_name: str, file_name: str) -> str:
|
|
159
159
|
)
|
160
160
|
|
161
161
|
|
162
|
+
# Backward compatibility aliases (deprecated)
|
163
|
+
render_fastapi_app = render_vega_app
|
164
|
+
render_fastapi_routes_init = render_vega_routes_init
|
165
|
+
render_fastapi_health_route = render_vega_health_route
|
166
|
+
render_fastapi_dependencies = render_vega_dependencies
|
167
|
+
render_fastapi_main = render_vega_main
|
168
|
+
render_fastapi_project_main = render_vega_project_main
|
169
|
+
render_fastapi_user_route = render_vega_user_route
|
170
|
+
render_fastapi_router = render_vega_router
|
171
|
+
render_fastapi_middleware = render_vega_middleware
|
172
|
+
|
173
|
+
|
162
174
|
def render_database_manager() -> str:
|
163
175
|
"""Return the template for database_manager.py"""
|
164
176
|
return render_template("database_manager.py.j2", subfolder="sqlalchemy")
|
@@ -244,11 +256,15 @@ def render_cli_commands_init() -> str:
|
|
244
256
|
return render_template("commands_init.py.j2", subfolder="cli")
|
245
257
|
|
246
258
|
|
247
|
-
def
|
259
|
+
def render_vega_routes_init_autodiscovery() -> str:
|
248
260
|
"""Return the template for web/routes/__init__.py with auto-discovery"""
|
249
261
|
return render_template("routes_init_autodiscovery.py.j2", subfolder="web")
|
250
262
|
|
251
263
|
|
264
|
+
# Backward compatibility alias
|
265
|
+
render_fastapi_routes_init_autodiscovery = render_vega_routes_init_autodiscovery
|
266
|
+
|
267
|
+
|
252
268
|
def render_event(class_name: str, fields: list[dict]) -> str:
|
253
269
|
"""Return the template for a domain event"""
|
254
270
|
return render_template(
|
@@ -0,0 +1,15 @@
|
|
1
|
+
"""Vega Web application factory for {{ project_name }}"""
|
2
|
+
from vega.web import VegaApp
|
3
|
+
|
4
|
+
from .routes import get_api_router
|
5
|
+
|
6
|
+
|
7
|
+
APP_TITLE = "{{ project_name.replace('-', ' ').replace('_', ' ').title() }}"
|
8
|
+
APP_VERSION = "0.1.0"
|
9
|
+
|
10
|
+
|
11
|
+
def create_app() -> VegaApp:
|
12
|
+
"""Create and configure Vega Web application"""
|
13
|
+
app = VegaApp(title=APP_TITLE, version=APP_VERSION)
|
14
|
+
app.include_router(get_api_router())
|
15
|
+
return app
|