|
1 | 1 | # FastStack |
2 | 2 |
|
3 | | -Hybrid FastAPI framework — runtime core + CLI generator. |
| 3 | +**Hybrid FastAPI framework — runtime core + CLI generator.** |
4 | 4 |
|
5 | | -FastStack is a pip-installable framework that combines a thin runtime core (`faststack_core`) with a CLI generator (`faststack`) to scaffold production-ready async FastAPI projects from YAML entity definitions. |
| 5 | +[](https://github.com/manavgup/faststack/actions/workflows/ci.yml) |
| 6 | +[](https://github.com/manavgup/faststack/actions/workflows/lint.yml) |
| 7 | +[](https://www.python.org/downloads/) |
| 8 | +[](LICENSE) |
6 | 9 |
|
7 | | -## Status |
| 10 | +--- |
8 | 11 |
|
9 | | -Under active development. See the [design plan](docs/design/fastapi-generator-plan.md) and [implementation plan](docs/implementation/v1-implementation-plan.md). |
| 12 | +## What is FastStack? |
| 13 | + |
| 14 | +FastStack scaffolds **production-ready async FastAPI projects** from YAML entity definitions. Define your entities once, get a complete API with models, schemas, repositories, services, routers, dependency injection, and tests — all wired together and ready to run. |
| 15 | + |
| 16 | +Unlike one-shot project generators, FastStack is a **hybrid framework** (like Django): |
| 17 | + |
| 18 | +- **`faststack_core`** — a pip-installable runtime library with base classes, middleware, structured logging, and RFC 7807 error handling that generated projects import |
| 19 | +- **`faststack` CLI** — scaffolds projects and entities, regenerates derived files when models change |
| 20 | + |
| 21 | +## Features |
| 22 | + |
| 23 | +- **YAML-driven code generation** — define entities, get 9 files per entity (model, schema, repo, service, router, factory, fakes, unit tests, integration tests) |
| 24 | +- **Async-first** — all repos/services use `AsyncSession`, no sync support |
| 25 | +- **Protocol-based repositories** — structural typing with in-memory fakes for testing (no mocks) |
| 26 | +- **Dependency injection** — auto-generated `dependencies.py` with `Depends()` wiring |
| 27 | +- **RFC 7807 errors** — standardized problem-detail error responses |
| 28 | +- **Lifecycle hooks** — `before_create`, `after_create`, etc. on every service |
| 29 | +- **Structured logging** — JSON + console dual-format, sensitive data masking, correlation IDs |
| 30 | +- **Security middleware** — CORS, HSTS, X-Frame-Options, request logging |
| 31 | +- **File ownership model** — REGENERATABLE files (schemas, fakes) vs PRESERVED files (models, services) so you can customize without losing changes on regeneration |
| 32 | +- **Health checks** — `/health` and `/health/detailed` out of the box |
| 33 | +- **Complete test suite** — generated unit tests (fake repos) + integration tests (AsyncClient with DI overrides) |
| 34 | + |
| 35 | +## Quick Start |
| 36 | + |
| 37 | +### Install |
| 38 | + |
| 39 | +```bash |
| 40 | +git clone https://github.com/manavgup/faststack.git |
| 41 | +cd faststack |
| 42 | +make install-dev |
| 43 | +``` |
| 44 | + |
| 45 | +### Create a Project |
| 46 | + |
| 47 | +Define your entities in YAML: |
| 48 | + |
| 49 | +```yaml |
| 50 | +# entities.yaml |
| 51 | +entities: |
| 52 | + User: |
| 53 | + base: AuditedEntity |
| 54 | + fields: |
| 55 | + email: {type: string, required: true, unique: true} |
| 56 | + name: {type: string, required: true} |
| 57 | + role: {type: enum, values: [admin, editor, viewer], default: '"viewer"'} |
| 58 | + searchable: [email, name] |
| 59 | + |
| 60 | + Post: |
| 61 | + base: AuditedEntity |
| 62 | + fields: |
| 63 | + title: {type: string, required: true} |
| 64 | + content: {type: text} |
| 65 | + status: {type: enum, values: [draft, published, archived], default: '"draft"'} |
| 66 | + user_id: {type: uuid, references: User} |
| 67 | + searchable: [title] |
| 68 | +``` |
| 69 | +
|
| 70 | +Scaffold the project: |
| 71 | +
|
| 72 | +```bash |
| 73 | +poetry run faststack init my-blog --entities entities.yaml |
| 74 | +cd my-blog |
| 75 | +``` |
| 76 | + |
| 77 | +This generates a complete project: |
| 78 | + |
| 79 | +``` |
| 80 | +my-blog/ |
| 81 | +├── app/ |
| 82 | +│ ├── main.py # FastAPI app with all routers registered |
| 83 | +│ ├── config.py # Settings from environment variables |
| 84 | +│ ├── api/ |
| 85 | +│ │ ├── dependencies.py # DI providers (get_db_session, get_*_service) |
| 86 | +│ │ └── routes/ # Wired CRUD routers per entity |
| 87 | +│ ├── models/ # SQLAlchemy 2.0 models |
| 88 | +│ ├── schemas/ # Pydantic v2 Create/Update/Response schemas |
| 89 | +│ ├── repositories/ # SqlAlchemyRepository subclasses |
| 90 | +│ └── services/ # CrudService subclasses with lifecycle hooks |
| 91 | +├── tests/ |
| 92 | +│ ├── unit/ # Service tests with fake repositories |
| 93 | +│ │ └── fakes/ # In-memory repos (Protocol-based) |
| 94 | +│ ├── integration/ # API tests with AsyncClient + DI overrides |
| 95 | +│ │ └── conftest.py # Shared client fixture |
| 96 | +│ └── factories/ # Polyfactory test data generators |
| 97 | +├── alembic/ # Database migrations |
| 98 | +├── pyproject.toml |
| 99 | +├── Dockerfile |
| 100 | +└── docker-compose.yml |
| 101 | +``` |
| 102 | + |
| 103 | +### Add More Entities |
| 104 | + |
| 105 | +```bash |
| 106 | +# From YAML |
| 107 | +poetry run faststack add-entity Comment --from-yaml entities.yaml |
| 108 | + |
| 109 | +# Inline |
| 110 | +poetry run faststack add-entity Tag --fields "label:string:required,color:string" |
| 111 | + |
| 112 | +# Check status |
| 113 | +poetry run faststack list |
| 114 | +``` |
| 115 | + |
| 116 | +### Regenerate After Model Changes |
| 117 | + |
| 118 | +Edit a model file, then regenerate derived files (schemas, fakes, factories): |
| 119 | + |
| 120 | +```bash |
| 121 | +poetry run faststack generate Post # Single entity |
| 122 | +poetry run faststack generate --all # All entities |
| 123 | +``` |
| 124 | + |
| 125 | +Only REGENERATABLE files are overwritten. Your models, services, routers, and tests are preserved. |
| 126 | + |
| 127 | +## Supported Types |
| 128 | + |
| 129 | +| YAML Type | SQLAlchemy | Pydantic | Example | |
| 130 | +|-----------|-----------|----------|---------| |
| 131 | +| `string` | `String(255)` | `str` | `name: {type: string}` | |
| 132 | +| `text` | `Text` | `str` | `bio: {type: text}` | |
| 133 | +| `integer` | `Integer` | `int` | `count: {type: integer}` | |
| 134 | +| `float` | `Float` | `float` | `score: {type: float}` | |
| 135 | +| `boolean` | `Boolean` | `bool` | `active: {type: boolean}` | |
| 136 | +| `datetime` | `DateTime` | `datetime` | `expires_at: {type: datetime}` | |
| 137 | +| `date` | `Date` | `date` | `born_on: {type: date}` | |
| 138 | +| `uuid` | `UUID` | `UUID` | `ref_id: {type: uuid}` | |
| 139 | +| `decimal` | `Numeric(10,2)` | `Decimal` | `price: {type: decimal}` | |
| 140 | +| `json` | `JSON` | `dict` | `config: {type: json}` | |
| 141 | +| `jsonb` | `JSON` | `dict` | `metadata: {type: jsonb}` | |
| 142 | +| `enum` | `Enum` | `Literal[...]` | `role: {type: enum, values: [a, b]}` | |
| 143 | +| `array` | `ARRAY` | `list` | `tags: {type: array, items: string}` | |
| 144 | + |
| 145 | +Foreign keys: `user_id: {type: uuid, references: User}` with optional `on_delete: cascade|set_null|restrict`. |
| 146 | + |
| 147 | +## Entity Base Classes |
| 148 | + |
| 149 | +| Base | Fields | |
| 150 | +|------|--------| |
| 151 | +| `Entity` | `id` (UUID primary key) | |
| 152 | +| `AuditedEntity` | + `created_at`, `updated_at`, `created_by`, `updated_by` | |
| 153 | +| `SoftDeleteEntity` | + `is_deleted`, `deleted_at`, `deleted_by` | |
| 154 | +| `FullAuditedEntity` | All of the above | |
| 155 | + |
| 156 | +## Development |
| 157 | + |
| 158 | +```bash |
| 159 | +make install-dev # Full dev setup (venv + deps + pre-commit hooks) |
| 160 | +make check # Lint + typecheck + tests with 85% coverage (CI gate) |
| 161 | +make test-unit # Fast — core + template tests only |
| 162 | +make test-e2e # End-to-end scaffold validation |
| 163 | +make format # Auto-format with ruff + black |
| 164 | +make help # All available targets |
| 165 | +``` |
| 166 | + |
| 167 | +See [DEVELOPING.md](DEVELOPING.md) for project structure and how code generation works. |
| 168 | + |
| 169 | +## Testing |
| 170 | + |
| 171 | +393 tests at 90% coverage. See [TESTING.md](TESTING.md) for details. |
| 172 | + |
| 173 | +```bash |
| 174 | +make test # All tests + coverage gate |
| 175 | +make test-unit # 175 unit tests |
| 176 | +make test-integration # 162 CLI integration tests |
| 177 | +make test-e2e # 6 end-to-end tests |
| 178 | +make coverage # HTML report → htmlcov/index.html |
| 179 | +``` |
| 180 | + |
| 181 | +## Contributing |
| 182 | + |
| 183 | +See [CONTRIBUTING.md](CONTRIBUTING.md) for workflow, code standards, and PR process. |
| 184 | + |
| 185 | +## Architecture |
| 186 | + |
| 187 | +- **Design plan:** [`docs/design/fastapi-generator-plan.md`](docs/design/fastapi-generator-plan.md) |
| 188 | +- **Implementation plan:** [`docs/implementation/v1-implementation-plan.md`](docs/implementation/v1-implementation-plan.md) |
| 189 | +- **Architecture decisions:** [`docs/architecture/adr/`](docs/architecture/adr/) |
| 190 | + |
| 191 | +## License |
| 192 | + |
| 193 | +MIT |
0 commit comments