fastapi-templatekit 0.1.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.
- fastapi_templatekit-0.1.0/LICENSE +21 -0
- fastapi_templatekit-0.1.0/PKG-INFO +163 -0
- fastapi_templatekit-0.1.0/README.md +154 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/__init__.py +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/cli.py +33 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/commands/__init__.py +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/commands/addhealthprobes.py +68 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/commands/help.py +70 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/commands/project.py +22 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/commands/rendering.py +15 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/commands/startapp.py +170 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/commands/startproject.py +82 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/commands/validation.py +17 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/__init__.py +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/app/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/app/endpoints/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/app/endpoints/api.py.tpl +14 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/app/models/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/app/router.py.tpl +9 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/app/schemas/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/app/schemas/validator.py.tpl +7 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/app/service/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/app/service/app_service.py.tpl +5 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/app/websocket/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/app/websocket/router.py.tpl +25 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/healthprobes/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/healthprobes/endpoints/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/healthprobes/endpoints/api.py.tpl +19 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/healthprobes/models/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/healthprobes/router.py.tpl +9 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/healthprobes/schemas/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/healthprobes/schemas/validator.py.tpl +7 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/healthprobes/service/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/healthprobes/service/healthprobes_service.py.tpl +5 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/project/README.md.tpl +12 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/project/env.example.tpl +4 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/project/fastapi_templatekit.toml.tpl +5 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/project/gitignore.tpl +9 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/project/package/__init__.py.tpl +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/project/package/cli.py.tpl +88 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/project/package/config.py.tpl +15 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/project/package/main.py.tpl +15 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/project/package/router.py.tpl +6 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit/templates/project/pyproject.toml.tpl +26 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit.egg-info/PKG-INFO +163 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit.egg-info/SOURCES.txt +52 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit.egg-info/dependency_links.txt +1 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit.egg-info/entry_points.txt +2 -0
- fastapi_templatekit-0.1.0/fastapi_templatekit.egg-info/top_level.txt +1 -0
- fastapi_templatekit-0.1.0/pyproject.toml +74 -0
- fastapi_templatekit-0.1.0/setup.cfg +4 -0
- fastapi_templatekit-0.1.0/tests/test_commands.py +155 -0
- fastapi_templatekit-0.1.0/tests/test_startapp.py +232 -0
- fastapi_templatekit-0.1.0/tests/test_startproject.py +23 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Amogha Hegde
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastapi-templatekit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: FastAPI project generator with a root-level, Django-style app layout
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Dynamic: license-file
|
|
9
|
+
|
|
10
|
+
# fastapi-templatekit
|
|
11
|
+
|
|
12
|
+
[](https://github.com/Amogha-Hegde/fastapi-templatekit/actions/workflows/ci.yml)
|
|
13
|
+
[](https://codecov.io/gh/Amogha-Hegde/fastapi-templatekit)
|
|
14
|
+
[](https://pypi.org/project/fastapi-templatekit/)
|
|
15
|
+
[](https://pypi.org/project/fastapi-templatekit/)
|
|
16
|
+
[](https://pepy.tech/project/fastapi-templatekit)
|
|
17
|
+
|
|
18
|
+
A FastAPI TemplateKit with a root-level, Django-style app layout.
|
|
19
|
+
|
|
20
|
+
## CLI
|
|
21
|
+
|
|
22
|
+
Create a new project without installing this template into that project's
|
|
23
|
+
environment:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
uvx fastapi-templatekit startproject myproject
|
|
27
|
+
cd myproject
|
|
28
|
+
uvx fastapi-templatekit startapp users
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Create the project files directly in the current directory:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uvx fastapi-templatekit startproject myproject .
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
If generated files already exist, the CLI asks before overwriting them. Use
|
|
38
|
+
`--force` to overwrite without a prompt:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uvx fastapi-templatekit startproject myproject . --force
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Create the project at a custom path:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
uvx fastapi-templatekit startproject myproject ../services/myproject
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
For local development from this repository:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
uvx --from . fastapi-templatekit startproject myproject
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Generated projects include a Typer management command to discover registered
|
|
57
|
+
HTTP and websocket routes:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
uv run myproject urls
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Show available commands and details:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
uvx fastapi-templatekit help
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Add health probes to an existing generated project:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
uvx fastapi-templatekit addhealthprobes
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Create an app with optional websocket and database scaffolding:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uvx fastapi-templatekit startapp users
|
|
79
|
+
uvx fastapi-templatekit startapp users --with-websockets --with-database
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Generated projects keep the main router beside `main.py`:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
myproject/
|
|
86
|
+
├── pyproject.toml
|
|
87
|
+
├── fastapi_templatekit.toml
|
|
88
|
+
├── myproject/
|
|
89
|
+
│ ├── __init__.py
|
|
90
|
+
│ ├── main.py
|
|
91
|
+
│ ├── config.py
|
|
92
|
+
│ └── router.py
|
|
93
|
+
└── users/
|
|
94
|
+
├── __init__.py
|
|
95
|
+
├── router.py
|
|
96
|
+
├── endpoints/
|
|
97
|
+
│ ├── __init__.py
|
|
98
|
+
│ └── api.py
|
|
99
|
+
├── schemas/
|
|
100
|
+
│ ├── __init__.py
|
|
101
|
+
│ └── validator.py
|
|
102
|
+
├── service/
|
|
103
|
+
│ ├── __init__.py
|
|
104
|
+
│ └── users_service.py
|
|
105
|
+
├── models/ # created only with database/tables enabled
|
|
106
|
+
│ └── __init__.py
|
|
107
|
+
└── websocket/ # created only with websockets enabled
|
|
108
|
+
├── __init__.py
|
|
109
|
+
└── router.py
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Structure
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
.
|
|
116
|
+
├── api/ # top-level router registration
|
|
117
|
+
├── health/ # example domain app at project root
|
|
118
|
+
├── main/
|
|
119
|
+
│ ├── config.py # settings and config live here
|
|
120
|
+
│ └── app.py # FastAPI declaration lives here
|
|
121
|
+
└── pyproject.toml
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
This follows the same domain-first idea from `fastapi-best-practices`, but without a `src/` directory.
|
|
125
|
+
Feature apps and the shared API router live directly under the project root, similar to Django apps.
|
|
126
|
+
|
|
127
|
+
## Run
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
uv run uvicorn main.app:app --reload
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## WebSockets
|
|
134
|
+
|
|
135
|
+
WebSocket routes are mounted under the same API prefix, so the default endpoint is:
|
|
136
|
+
|
|
137
|
+
```text
|
|
138
|
+
/api/v1/ws/{room_name}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
There is also a built-in browser test page at:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
/api/v1/ws/test
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
This app uses `fastapi-websockets` with the package's environment-based channel-layer loader.
|
|
148
|
+
For websocket-related environment configuration, refer to https://github.com/Amogha-Hegde/fastapi-websockets.
|
|
149
|
+
|
|
150
|
+
Tests force `FASTAPI_WEBSOCKETS_BACKEND=inmemory` so they do not depend on a running database.
|
|
151
|
+
|
|
152
|
+
Example session:
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
connect ws://127.0.0.1:8000/api/v1/ws/demo
|
|
156
|
+
receive {"event":"connected","room":"demo",...}
|
|
157
|
+
send {"sender":"alice","message":"hello"}
|
|
158
|
+
receive {"event":"message","room":"demo","sender":"alice","message":"hello"}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Add a new app
|
|
162
|
+
|
|
163
|
+
Create a root-level package such as `users/` or `orders/`, define its router there, and include it from your project's main `router.py`.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# fastapi-templatekit
|
|
2
|
+
|
|
3
|
+
[](https://github.com/Amogha-Hegde/fastapi-templatekit/actions/workflows/ci.yml)
|
|
4
|
+
[](https://codecov.io/gh/Amogha-Hegde/fastapi-templatekit)
|
|
5
|
+
[](https://pypi.org/project/fastapi-templatekit/)
|
|
6
|
+
[](https://pypi.org/project/fastapi-templatekit/)
|
|
7
|
+
[](https://pepy.tech/project/fastapi-templatekit)
|
|
8
|
+
|
|
9
|
+
A FastAPI TemplateKit with a root-level, Django-style app layout.
|
|
10
|
+
|
|
11
|
+
## CLI
|
|
12
|
+
|
|
13
|
+
Create a new project without installing this template into that project's
|
|
14
|
+
environment:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
uvx fastapi-templatekit startproject myproject
|
|
18
|
+
cd myproject
|
|
19
|
+
uvx fastapi-templatekit startapp users
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Create the project files directly in the current directory:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
uvx fastapi-templatekit startproject myproject .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
If generated files already exist, the CLI asks before overwriting them. Use
|
|
29
|
+
`--force` to overwrite without a prompt:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uvx fastapi-templatekit startproject myproject . --force
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Create the project at a custom path:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
uvx fastapi-templatekit startproject myproject ../services/myproject
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For local development from this repository:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
uvx --from . fastapi-templatekit startproject myproject
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Generated projects include a Typer management command to discover registered
|
|
48
|
+
HTTP and websocket routes:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
uv run myproject urls
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Show available commands and details:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uvx fastapi-templatekit help
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Add health probes to an existing generated project:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
uvx fastapi-templatekit addhealthprobes
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Create an app with optional websocket and database scaffolding:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
uvx fastapi-templatekit startapp users
|
|
70
|
+
uvx fastapi-templatekit startapp users --with-websockets --with-database
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Generated projects keep the main router beside `main.py`:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
myproject/
|
|
77
|
+
├── pyproject.toml
|
|
78
|
+
├── fastapi_templatekit.toml
|
|
79
|
+
├── myproject/
|
|
80
|
+
│ ├── __init__.py
|
|
81
|
+
│ ├── main.py
|
|
82
|
+
│ ├── config.py
|
|
83
|
+
│ └── router.py
|
|
84
|
+
└── users/
|
|
85
|
+
├── __init__.py
|
|
86
|
+
├── router.py
|
|
87
|
+
├── endpoints/
|
|
88
|
+
│ ├── __init__.py
|
|
89
|
+
│ └── api.py
|
|
90
|
+
├── schemas/
|
|
91
|
+
│ ├── __init__.py
|
|
92
|
+
│ └── validator.py
|
|
93
|
+
├── service/
|
|
94
|
+
│ ├── __init__.py
|
|
95
|
+
│ └── users_service.py
|
|
96
|
+
├── models/ # created only with database/tables enabled
|
|
97
|
+
│ └── __init__.py
|
|
98
|
+
└── websocket/ # created only with websockets enabled
|
|
99
|
+
├── __init__.py
|
|
100
|
+
└── router.py
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Structure
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
.
|
|
107
|
+
├── api/ # top-level router registration
|
|
108
|
+
├── health/ # example domain app at project root
|
|
109
|
+
├── main/
|
|
110
|
+
│ ├── config.py # settings and config live here
|
|
111
|
+
│ └── app.py # FastAPI declaration lives here
|
|
112
|
+
└── pyproject.toml
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
This follows the same domain-first idea from `fastapi-best-practices`, but without a `src/` directory.
|
|
116
|
+
Feature apps and the shared API router live directly under the project root, similar to Django apps.
|
|
117
|
+
|
|
118
|
+
## Run
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
uv run uvicorn main.app:app --reload
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## WebSockets
|
|
125
|
+
|
|
126
|
+
WebSocket routes are mounted under the same API prefix, so the default endpoint is:
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
/api/v1/ws/{room_name}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
There is also a built-in browser test page at:
|
|
133
|
+
|
|
134
|
+
```text
|
|
135
|
+
/api/v1/ws/test
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
This app uses `fastapi-websockets` with the package's environment-based channel-layer loader.
|
|
139
|
+
For websocket-related environment configuration, refer to https://github.com/Amogha-Hegde/fastapi-websockets.
|
|
140
|
+
|
|
141
|
+
Tests force `FASTAPI_WEBSOCKETS_BACKEND=inmemory` so they do not depend on a running database.
|
|
142
|
+
|
|
143
|
+
Example session:
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
connect ws://127.0.0.1:8000/api/v1/ws/demo
|
|
147
|
+
receive {"event":"connected","room":"demo",...}
|
|
148
|
+
send {"sender":"alice","message":"hello"}
|
|
149
|
+
receive {"event":"message","room":"demo","sender":"alice","message":"hello"}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Add a new app
|
|
153
|
+
|
|
154
|
+
Create a root-level package such as `users/` or `orders/`, define its router there, and include it from your project's main `router.py`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from fastapi_templatekit.commands.addhealthprobes import add_addhealthprobes_parser
|
|
6
|
+
from fastapi_templatekit.commands.help import add_help_parser
|
|
7
|
+
from fastapi_templatekit.commands.startapp import add_startapp_parser
|
|
8
|
+
from fastapi_templatekit.commands.startproject import add_startproject_parser
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
12
|
+
parser = argparse.ArgumentParser(
|
|
13
|
+
prog="fastapi-templatekit",
|
|
14
|
+
description="Create FastAPI projects and apps.",
|
|
15
|
+
)
|
|
16
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
17
|
+
|
|
18
|
+
add_startproject_parser(subparsers)
|
|
19
|
+
add_startapp_parser(subparsers)
|
|
20
|
+
add_addhealthprobes_parser(subparsers)
|
|
21
|
+
add_help_parser(subparsers)
|
|
22
|
+
|
|
23
|
+
return parser
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def main() -> None:
|
|
27
|
+
parser = build_parser()
|
|
28
|
+
args = parser.parse_args()
|
|
29
|
+
args.handler(args)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
if __name__ == "__main__":
|
|
33
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from fastapi_templatekit.commands.project import load_project_config
|
|
7
|
+
from fastapi_templatekit.commands.rendering import render_template
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
HEALTHPROBES_APP_NAME = "healthprobes"
|
|
11
|
+
|
|
12
|
+
HEALTHPROBES_TEMPLATES = (
|
|
13
|
+
("healthprobes/__init__.py.tpl", "healthprobes/__init__.py"),
|
|
14
|
+
("healthprobes/router.py.tpl", "healthprobes/router.py"),
|
|
15
|
+
("healthprobes/endpoints/__init__.py.tpl", "healthprobes/endpoints/__init__.py"),
|
|
16
|
+
("healthprobes/endpoints/api.py.tpl", "healthprobes/endpoints/api.py"),
|
|
17
|
+
("healthprobes/schemas/__init__.py.tpl", "healthprobes/schemas/__init__.py"),
|
|
18
|
+
("healthprobes/schemas/validator.py.tpl", "healthprobes/schemas/validator.py"),
|
|
19
|
+
("healthprobes/service/__init__.py.tpl", "healthprobes/service/__init__.py"),
|
|
20
|
+
("healthprobes/service/healthprobes_service.py.tpl", "healthprobes/service/healthprobes_service.py"),
|
|
21
|
+
("healthprobes/models/__init__.py.tpl", "healthprobes/models/__init__.py"),
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def add_addhealthprobes_parser(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
|
|
26
|
+
parser = subparsers.add_parser(
|
|
27
|
+
"addhealthprobes",
|
|
28
|
+
help="Add healthz and livez endpoints to an existing generated project.",
|
|
29
|
+
)
|
|
30
|
+
parser.add_argument(
|
|
31
|
+
"--force",
|
|
32
|
+
action="store_true",
|
|
33
|
+
help="Overwrite existing healthprobes files without prompting.",
|
|
34
|
+
)
|
|
35
|
+
parser.set_defaults(handler=handle_addhealthprobes)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def handle_addhealthprobes(args: argparse.Namespace) -> None:
|
|
39
|
+
project_root = Path.cwd()
|
|
40
|
+
project = load_project_config(project_root)
|
|
41
|
+
apps_dir = project_root / project.get("apps_dir", ".")
|
|
42
|
+
app_dir = apps_dir / HEALTHPROBES_APP_NAME
|
|
43
|
+
|
|
44
|
+
context = {
|
|
45
|
+
"app_name": HEALTHPROBES_APP_NAME,
|
|
46
|
+
"route_prefix": HEALTHPROBES_APP_NAME,
|
|
47
|
+
}
|
|
48
|
+
destinations = [
|
|
49
|
+
apps_dir / destination_pattern.format(**context)
|
|
50
|
+
for _, destination_pattern in HEALTHPROBES_TEMPLATES
|
|
51
|
+
]
|
|
52
|
+
existing_paths = [destination for destination in destinations if destination.exists()]
|
|
53
|
+
|
|
54
|
+
if existing_paths and not args.force:
|
|
55
|
+
conflicts = "\n".join(f" {path}" for path in existing_paths)
|
|
56
|
+
print(f"Healthprobes files already exist:\n{conflicts}")
|
|
57
|
+
answer = input("Overwrite these files? [y/N]: ").strip().lower()
|
|
58
|
+
if answer not in {"y", "yes"}:
|
|
59
|
+
raise SystemExit("Aborted.")
|
|
60
|
+
|
|
61
|
+
for template_path, destination_pattern in HEALTHPROBES_TEMPLATES:
|
|
62
|
+
destination = apps_dir / destination_pattern.format(**context)
|
|
63
|
+
render_template(template_path, destination, context)
|
|
64
|
+
|
|
65
|
+
print(f"Created health probes app at {app_dir}")
|
|
66
|
+
print("Register the router in your project router:")
|
|
67
|
+
print(" from healthprobes.router import router as healthprobes_router")
|
|
68
|
+
print(" api_router.include_router(healthprobes_router, tags=[\"healthprobes\"])")
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
HELP_TEXT = """fastapi-templatekit
|
|
7
|
+
|
|
8
|
+
Available commands:
|
|
9
|
+
|
|
10
|
+
startproject <name> [directory]
|
|
11
|
+
Create a new FastAPI project.
|
|
12
|
+
|
|
13
|
+
Examples:
|
|
14
|
+
fastapi-templatekit startproject myproject
|
|
15
|
+
fastapi-templatekit startproject myproject .
|
|
16
|
+
fastapi-templatekit startproject myproject ../services/myproject
|
|
17
|
+
|
|
18
|
+
Details:
|
|
19
|
+
- Without directory, creates ./<name>/.
|
|
20
|
+
- With '.', creates project files in the current directory.
|
|
21
|
+
- With a custom directory, creates project files at that path.
|
|
22
|
+
- If generated files already exist, asks before overwriting.
|
|
23
|
+
- Use --force to overwrite generated files without prompting.
|
|
24
|
+
|
|
25
|
+
startapp <name>
|
|
26
|
+
Create a root-level app inside an existing generated project.
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
fastapi-templatekit startapp users
|
|
30
|
+
fastapi-templatekit startapp users --with-websockets --with-database
|
|
31
|
+
|
|
32
|
+
Details:
|
|
33
|
+
- Must be run from a directory containing fastapi_templatekit.toml.
|
|
34
|
+
- Creates endpoints, schemas, service, and router.py.
|
|
35
|
+
- Includes a hello-world GET endpoint.
|
|
36
|
+
- Asks whether to include websockets.
|
|
37
|
+
- Asks whether to include database/tables.
|
|
38
|
+
- Use --with-websockets to add websocket scaffolding without prompting for it.
|
|
39
|
+
- Use --with-database to add the models folder without prompting for it.
|
|
40
|
+
- Prints the router registration lines for your project router.py.
|
|
41
|
+
|
|
42
|
+
addhealthprobes
|
|
43
|
+
Create a root-level healthprobes app inside an existing generated project.
|
|
44
|
+
|
|
45
|
+
Example:
|
|
46
|
+
fastapi-templatekit addhealthprobes
|
|
47
|
+
|
|
48
|
+
Details:
|
|
49
|
+
- Must be run from a directory containing fastapi_templatekit.toml.
|
|
50
|
+
- Creates /healthz and /livez GET endpoints.
|
|
51
|
+
- Prints the router registration lines for your project router.py.
|
|
52
|
+
- Use --force to overwrite generated healthprobes files without prompting.
|
|
53
|
+
|
|
54
|
+
help
|
|
55
|
+
Show this command summary.
|
|
56
|
+
|
|
57
|
+
Use 'fastapi-templatekit <command> --help' for argparse usage details.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def add_help_parser(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
|
|
62
|
+
parser = subparsers.add_parser(
|
|
63
|
+
"help",
|
|
64
|
+
help="Show available commands and details.",
|
|
65
|
+
)
|
|
66
|
+
parser.set_defaults(handler=handle_help)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def handle_help(_: argparse.Namespace) -> None:
|
|
70
|
+
print(HELP_TEXT)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import tomllib
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def load_project_config(project_root: Path) -> dict[str, Any]:
|
|
9
|
+
marker_path = project_root / "fastapi_templatekit.toml"
|
|
10
|
+
|
|
11
|
+
if not marker_path.exists():
|
|
12
|
+
raise SystemExit(
|
|
13
|
+
"Error: command must be run inside a fastapi-templatekit project.\n"
|
|
14
|
+
"Run: fastapi-templatekit startproject <project_name>"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
marker = tomllib.loads(marker_path.read_text(encoding="utf-8"))
|
|
18
|
+
project = marker.get("project", {})
|
|
19
|
+
if not isinstance(project, dict):
|
|
20
|
+
raise SystemExit(f"Error: invalid project config: {marker_path}")
|
|
21
|
+
|
|
22
|
+
return project
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from importlib import resources
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from string import Template
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
TEMPLATE_ROOT = "fastapi_templatekit.templates"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def render_template(template_path: str, destination: Path, context: dict[str, str]) -> None:
|
|
12
|
+
template = resources.files(TEMPLATE_ROOT).joinpath(template_path)
|
|
13
|
+
content = Template(template.read_text(encoding="utf-8")).safe_substitute(context)
|
|
14
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
15
|
+
destination.write_text(content, encoding="utf-8")
|