FastAPI-fastkit 1.0.0__py3-none-any.whl → 1.0.2__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.
- fastapi_fastkit/__init__.py +10 -1
- fastapi_fastkit/backend/main.py +482 -482
- fastapi_fastkit/backend/transducer.py +106 -106
- fastapi_fastkit/cli.py +664 -631
- fastapi_fastkit/core/settings.py +155 -155
- fastapi_fastkit/fastapi_project_template/README.md +90 -90
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/.env-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/.gitignore-tpl +30 -30
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/README.md-tpl +107 -107
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/requirements.txt-tpl +36 -36
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/scripts/format.sh-tpl +5 -5
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/scripts/lint.sh-tpl +5 -5
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/scripts/run-server.sh-tpl +8 -8
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/scripts/test.sh-tpl +6 -6
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/setup.cfg-tpl +14 -14
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/setup.py-tpl +25 -25
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/api/api.py-tpl +9 -9
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/api/routes/items.py-tpl +57 -57
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/core/config.py-tpl +64 -64
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/crud/items.py-tpl +21 -21
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/main.py-tpl +26 -26
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/mocks/mock_items.json-tpl +8 -8
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/schemas/items.py-tpl +22 -22
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/tests/conftest.py-tpl +42 -42
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/tests/test_items.py-tpl +48 -48
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/.env-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/.gitignore-tpl +191 -191
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/README.md-tpl +156 -156
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/requirements.txt-tpl +36 -36
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/scripts/format.sh-tpl +5 -5
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/scripts/lint.sh-tpl +5 -5
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/scripts/run-server.sh-tpl +8 -8
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/scripts/test.sh-tpl +6 -6
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/setup.cfg-tpl +12 -12
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/setup.py-tpl +27 -27
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/.DS_Store +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/api/api.py-tpl +9 -9
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/api/routes/items.py-tpl +172 -172
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/core/config.py-tpl +64 -64
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/crud/items.py-tpl +21 -21
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/helper/exceptions.py-tpl +103 -103
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/helper/pagination.py-tpl +72 -72
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/main.py-tpl +39 -39
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/mocks/mock_items.json-tpl +8 -8
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/schemas/base.py-tpl +49 -49
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/schemas/items.py-tpl +22 -22
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/utils/documents.py-tpl +20 -20
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/tests/conftest.py-tpl +42 -42
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/tests/test_items.py-tpl +61 -61
- fastapi_fastkit/fastapi_project_template/fastapi-default/README.md-tpl +101 -101
- fastapi_fastkit/fastapi_project_template/fastapi-default/scripts/run-server.sh-tpl +8 -8
- fastapi_fastkit/fastapi_project_template/fastapi-default/setup.py-tpl +22 -22
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/mocks/mock_items.json-tpl +8 -8
- fastapi_fastkit/fastapi_project_template/fastapi-default/tests/conftest.py-tpl +30 -30
- fastapi_fastkit/fastapi_project_template/fastapi-default/tests/test_items.py-tpl +44 -44
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/.env-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/.gitignore-tpl +30 -30
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/Dockerfile-tpl +23 -23
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/README.md-tpl +119 -119
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/requirements.txt-tpl +36 -36
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/scripts/format.sh-tpl +5 -5
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/scripts/lint.sh-tpl +5 -5
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/scripts/run-server.sh-tpl +8 -8
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/scripts/test.sh-tpl +6 -6
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/setup.cfg-tpl +13 -13
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/setup.py-tpl +22 -22
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/api/api.py-tpl +6 -6
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/api/routes/items.py-tpl +54 -54
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/core/config.py-tpl +64 -64
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/crud/items.py-tpl +15 -15
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/main.py-tpl +26 -26
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/mocks/mock_items.json-tpl +8 -8
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/schemas/items.py-tpl +19 -19
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/tests/conftest.py-tpl +30 -30
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/tests/test_items.py-tpl +44 -44
- fastapi_fastkit/fastapi_project_template/fastapi-empty/.env-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-empty/setup.py-tpl +22 -22
- fastapi_fastkit/fastapi_project_template/fastapi-empty/src/core/config.py-tpl +75 -75
- fastapi_fastkit/fastapi_project_template/fastapi-empty/src/main.py-tpl +36 -36
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/.env-tpl +9 -9
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/.gitignore-tpl +30 -30
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/Dockerfile-tpl +23 -23
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/README.md-tpl +144 -144
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/alembic.ini-tpl +119 -119
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/docker-compose.yml-tpl +44 -44
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/requirements.txt-tpl +41 -41
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/scripts/format.sh-tpl +5 -5
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/scripts/lint.sh-tpl +5 -5
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/scripts/pre-start.sh-tpl +16 -16
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/scripts/run-server.sh-tpl +8 -8
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/scripts/test.sh-tpl +10 -10
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/setup.cfg-tpl +13 -13
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/setup.py-tpl +25 -25
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/alembic/README-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/alembic/env.py-tpl +85 -85
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/alembic/script.py.mako-tpl +26 -26
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/alembic/versions/bedcdc35b64a_first_alembic.py-tpl +37 -37
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/api/api.py-tpl +11 -11
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/api/deps.py-tpl +19 -19
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/api/routes/items.py-tpl +109 -109
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/core/config.py-tpl +88 -88
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/core/db.py-tpl +53 -53
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/crud/items.py-tpl +102 -102
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/main.py-tpl +45 -45
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/schemas/items.py-tpl +54 -54
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/utils/backend_pre_start.py-tpl +39 -39
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/utils/init_data.py-tpl +23 -23
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/utils/tests_pre_start.py-tpl +39 -39
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/tests/conftest.py-tpl +63 -63
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/tests/test_items.py-tpl +44 -44
- fastapi_fastkit/fastapi_project_template/modules/api/routes/new_route.py-tpl +64 -64
- fastapi_fastkit/fastapi_project_template/modules/crud/new_route.py-tpl +29 -29
- fastapi_fastkit/fastapi_project_template/modules/schemas/new_route.py-tpl +23 -23
- fastapi_fastkit/logs/fastkit_debug_20250702_161423.log +21 -0
- fastapi_fastkit/logs/fastkit_debug_20250702_162706.log +20 -0
- fastapi_fastkit/logs/fastkit_debug_20250702_163010.log +21 -0
- fastapi_fastkit/logs/fastkit_debug_20250702_163526.log +21 -0
- fastapi_fastkit/logs/fastkit_debug_20250702_164053.log +21 -0
- fastapi_fastkit/logs/fastkit_debug_20250702_165220.log +21 -0
- fastapi_fastkit/logs/fastkit_debug_20250702_165647.log +21 -0
- fastapi_fastkit/utils/logging.py +112 -1
- fastapi_fastkit/utils/main.py +140 -129
- fastapi_fastkit-1.0.2.dist-info/METADATA +320 -0
- {fastapi_fastkit-1.0.0.dist-info → fastapi_fastkit-1.0.2.dist-info}/RECORD +127 -119
- {fastapi_fastkit-1.0.0.dist-info → fastapi_fastkit-1.0.2.dist-info}/WHEEL +1 -1
- {fastapi_fastkit-1.0.0.dist-info → fastapi_fastkit-1.0.2.dist-info}/licenses/LICENSE +21 -21
- fastapi_fastkit-1.0.0.dist-info/METADATA +0 -208
- {fastapi_fastkit-1.0.0.dist-info → fastapi_fastkit-1.0.2.dist-info}/entry_points.txt +0 -0
fastapi_fastkit/cli.py
CHANGED
|
@@ -1,631 +1,664 @@
|
|
|
1
|
-
# --------------------------------------------------------------------------
|
|
2
|
-
# The Module defines main and core CLI operations for FastAPI-fastkit.
|
|
3
|
-
#
|
|
4
|
-
# @author bnbong bbbong9@gmail.com
|
|
5
|
-
# --------------------------------------------------------------------------
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
from
|
|
15
|
-
|
|
16
|
-
from
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
from fastapi_fastkit.
|
|
27
|
-
from fastapi_fastkit.
|
|
28
|
-
from fastapi_fastkit.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
@click.
|
|
44
|
-
@click.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
:param
|
|
52
|
-
:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
"
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
)
|
|
163
|
-
@click.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
""
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
)
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
)
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
)
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
""
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
)
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
"
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
f"
|
|
354
|
-
)
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
f"
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
)
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
venv_python,
|
|
582
|
-
|
|
583
|
-
"
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
1
|
+
# --------------------------------------------------------------------------
|
|
2
|
+
# The Module defines main and core CLI operations for FastAPI-fastkit.
|
|
3
|
+
#
|
|
4
|
+
# @author bnbong bbbong9@gmail.com
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
import atexit
|
|
7
|
+
import os
|
|
8
|
+
import shutil
|
|
9
|
+
import subprocess
|
|
10
|
+
import sys
|
|
11
|
+
from typing import Union
|
|
12
|
+
|
|
13
|
+
import click
|
|
14
|
+
from click.core import BaseCommand, Context
|
|
15
|
+
from rich import print
|
|
16
|
+
from rich.panel import Panel
|
|
17
|
+
|
|
18
|
+
from fastapi_fastkit.backend.main import (
|
|
19
|
+
add_new_route,
|
|
20
|
+
create_venv,
|
|
21
|
+
find_template_core_modules,
|
|
22
|
+
inject_project_metadata,
|
|
23
|
+
install_dependencies,
|
|
24
|
+
read_template_stack,
|
|
25
|
+
)
|
|
26
|
+
from fastapi_fastkit.backend.transducer import copy_and_convert_template
|
|
27
|
+
from fastapi_fastkit.core.exceptions import CLIExceptions
|
|
28
|
+
from fastapi_fastkit.core.settings import FastkitConfig
|
|
29
|
+
from fastapi_fastkit.utils.logging import get_logger, setup_logging
|
|
30
|
+
from fastapi_fastkit.utils.main import (
|
|
31
|
+
create_info_table,
|
|
32
|
+
is_fastkit_project,
|
|
33
|
+
print_error,
|
|
34
|
+
print_info,
|
|
35
|
+
print_success,
|
|
36
|
+
print_warning,
|
|
37
|
+
validate_email,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
from . import __version__, console
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@click.group()
|
|
44
|
+
@click.option("--debug/--no-debug", default=False)
|
|
45
|
+
@click.version_option(__version__, prog_name="fastapi-fastkit")
|
|
46
|
+
@click.pass_context
|
|
47
|
+
def fastkit_cli(ctx: Context, debug: bool) -> Union["BaseCommand", None]:
|
|
48
|
+
"""
|
|
49
|
+
main FastAPI-fastkit CLI operation group
|
|
50
|
+
|
|
51
|
+
:param ctx: context of passing configurations (NOT specify it at CLI)
|
|
52
|
+
:type ctx: <Object click.Context>
|
|
53
|
+
:param debug: parameter from CLI
|
|
54
|
+
:return: None(will be wrapped with click.core.BaseCommand via @click decorator)
|
|
55
|
+
"""
|
|
56
|
+
settings = FastkitConfig()
|
|
57
|
+
|
|
58
|
+
ctx.ensure_object(dict)
|
|
59
|
+
|
|
60
|
+
if debug:
|
|
61
|
+
print_warning("running at debugging mode!!")
|
|
62
|
+
settings.set_debug_mode()
|
|
63
|
+
|
|
64
|
+
ctx.obj["settings"] = settings
|
|
65
|
+
|
|
66
|
+
# Setup logging and get debug capture if debug mode is enabled
|
|
67
|
+
debug_capture = setup_logging(settings=settings)
|
|
68
|
+
ctx.obj["debug_capture"] = debug_capture
|
|
69
|
+
|
|
70
|
+
# If debug mode is enabled, start capturing output
|
|
71
|
+
if debug_capture:
|
|
72
|
+
debug_capture.__enter__()
|
|
73
|
+
# Log CLI invocation
|
|
74
|
+
logger = get_logger()
|
|
75
|
+
logger.info(f"CLI invoked with debug mode: {' '.join(sys.argv)}")
|
|
76
|
+
|
|
77
|
+
# Register cleanup function for when the CLI exits
|
|
78
|
+
def cleanup_debug_capture() -> None:
|
|
79
|
+
try:
|
|
80
|
+
debug_capture.__exit__(None, None, None)
|
|
81
|
+
logger.info("FastAPI-fastkit CLI session ended")
|
|
82
|
+
except Exception:
|
|
83
|
+
pass # Fail silently during cleanup
|
|
84
|
+
|
|
85
|
+
atexit.register(cleanup_debug_capture)
|
|
86
|
+
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@fastkit_cli.command()
|
|
91
|
+
@click.pass_context
|
|
92
|
+
def echo(ctx: Context) -> None:
|
|
93
|
+
"""
|
|
94
|
+
About FastAPI-fastkit
|
|
95
|
+
|
|
96
|
+
:param ctx: context of passing configurations (NOT specify it at CLI)
|
|
97
|
+
:type ctx: <Object click.Context>
|
|
98
|
+
:return: None
|
|
99
|
+
"""
|
|
100
|
+
fastkit_info = f"""
|
|
101
|
+
⚡️ FastAPI fastkit - fastest [bold]FastAPI[/bold] initializer. ⚡️
|
|
102
|
+
|
|
103
|
+
Deploy FastAPI app foundation instantly at your local!
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
- Project Maintainer : [link=mailto:bbbong9@gmail.com]bnbong(JunHyeok Lee)[/link]
|
|
107
|
+
- Current Version : {__version__}
|
|
108
|
+
- Github : [link]https://github.com/bnbong/FastAPI-fastkit[/link]
|
|
109
|
+
"""
|
|
110
|
+
settings = ctx.obj["settings"]
|
|
111
|
+
description_panel = Panel(fastkit_info, title="About FastAPI-fastkit")
|
|
112
|
+
click.echo(print(description_panel))
|
|
113
|
+
|
|
114
|
+
if settings.DEBUG_MODE:
|
|
115
|
+
debug_output = f"FASTKIT_PROJECT_ROOT: {settings.FASTKIT_PROJECT_ROOT}\nUSER_WORKSPACE: {settings.USER_WORKSPACE}"
|
|
116
|
+
|
|
117
|
+
click.echo(debug_output)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@fastkit_cli.command()
|
|
121
|
+
@click.pass_context
|
|
122
|
+
def list_templates(ctx: Context) -> None:
|
|
123
|
+
"""
|
|
124
|
+
Display the list of available templates.
|
|
125
|
+
"""
|
|
126
|
+
settings = ctx.obj["settings"]
|
|
127
|
+
template_dir = settings.FASTKIT_TEMPLATE_ROOT
|
|
128
|
+
|
|
129
|
+
if not os.path.exists(template_dir):
|
|
130
|
+
print_error("Template directory not found.")
|
|
131
|
+
return
|
|
132
|
+
|
|
133
|
+
excluded_dirs = ["__pycache__", "modules"]
|
|
134
|
+
templates = [
|
|
135
|
+
d
|
|
136
|
+
for d in os.listdir(template_dir)
|
|
137
|
+
if os.path.isdir(os.path.join(template_dir, d)) and d not in excluded_dirs
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
if not templates:
|
|
141
|
+
print_warning("No available templates.")
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
table = create_info_table("Available Templates")
|
|
145
|
+
|
|
146
|
+
for template in templates:
|
|
147
|
+
template_path = os.path.join(template_dir, template)
|
|
148
|
+
readme_path = os.path.join(template_path, "README.md-tpl")
|
|
149
|
+
|
|
150
|
+
description = "No description"
|
|
151
|
+
if os.path.exists(readme_path):
|
|
152
|
+
with open(readme_path, "r") as f:
|
|
153
|
+
first_line = f.readline().strip()
|
|
154
|
+
if first_line.startswith("# "):
|
|
155
|
+
description = first_line[2:]
|
|
156
|
+
|
|
157
|
+
table.add_row(template, description)
|
|
158
|
+
|
|
159
|
+
console.print(table)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@fastkit_cli.command(context_settings={"ignore_unknown_options": True})
|
|
163
|
+
@click.argument("template", default="fastapi-default")
|
|
164
|
+
@click.option(
|
|
165
|
+
"--project-name",
|
|
166
|
+
prompt="Enter the project name",
|
|
167
|
+
help="The name of the new FastAPI project.",
|
|
168
|
+
)
|
|
169
|
+
@click.option(
|
|
170
|
+
"--author", prompt="Enter the author name", help="The name of the project author."
|
|
171
|
+
)
|
|
172
|
+
@click.option(
|
|
173
|
+
"--author-email",
|
|
174
|
+
prompt="Enter the author email",
|
|
175
|
+
help="The email of the project author.",
|
|
176
|
+
type=str,
|
|
177
|
+
callback=validate_email,
|
|
178
|
+
)
|
|
179
|
+
@click.option(
|
|
180
|
+
"--description",
|
|
181
|
+
prompt="Enter the project description",
|
|
182
|
+
help="The description of the new FastAPI project.",
|
|
183
|
+
)
|
|
184
|
+
@click.pass_context
|
|
185
|
+
def startdemo(
|
|
186
|
+
ctx: Context,
|
|
187
|
+
template: str,
|
|
188
|
+
project_name: str,
|
|
189
|
+
author: str,
|
|
190
|
+
author_email: str,
|
|
191
|
+
description: str,
|
|
192
|
+
) -> None:
|
|
193
|
+
"""
|
|
194
|
+
Create a new FastAPI project from templates and inject metadata.
|
|
195
|
+
|
|
196
|
+
:param ctx: Click context object
|
|
197
|
+
:param template: Template name
|
|
198
|
+
:param project_name: Project name for the new project
|
|
199
|
+
:param author: Author name
|
|
200
|
+
:param author_email: Author email
|
|
201
|
+
:param description: Project description
|
|
202
|
+
:return: None
|
|
203
|
+
"""
|
|
204
|
+
settings = ctx.obj["settings"]
|
|
205
|
+
|
|
206
|
+
template_dir = settings.FASTKIT_TEMPLATE_ROOT
|
|
207
|
+
click.echo(f"Deploying FastAPI project using '{template}' template")
|
|
208
|
+
target_template = os.path.join(template_dir, template)
|
|
209
|
+
print(f"Template path: {target_template}")
|
|
210
|
+
|
|
211
|
+
if not os.path.exists(target_template):
|
|
212
|
+
print_error(f"Template '{template}' does not exist in '{template_dir}'.")
|
|
213
|
+
raise CLIExceptions(
|
|
214
|
+
f"Template '{template}' does not exist in '{template_dir}'."
|
|
215
|
+
)
|
|
216
|
+
table = create_info_table(
|
|
217
|
+
"Project Information",
|
|
218
|
+
{
|
|
219
|
+
"Project Name": project_name,
|
|
220
|
+
"Author": author,
|
|
221
|
+
"Author Email": author_email,
|
|
222
|
+
"Description": description,
|
|
223
|
+
},
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
console.print("\n")
|
|
227
|
+
console.print(table)
|
|
228
|
+
|
|
229
|
+
template_deps = read_template_stack(target_template)
|
|
230
|
+
if template_deps:
|
|
231
|
+
deps_table = create_info_table(
|
|
232
|
+
"Template Dependencies",
|
|
233
|
+
{f"Dependency {i+1}": dep for i, dep in enumerate(template_deps)},
|
|
234
|
+
)
|
|
235
|
+
console.print("\n")
|
|
236
|
+
console.print(deps_table)
|
|
237
|
+
|
|
238
|
+
confirm = click.confirm(
|
|
239
|
+
"\nDo you want to proceed with project creation?", default=False
|
|
240
|
+
)
|
|
241
|
+
if not confirm:
|
|
242
|
+
print_error("Project creation aborted!")
|
|
243
|
+
return
|
|
244
|
+
|
|
245
|
+
try:
|
|
246
|
+
user_local = settings.USER_WORKSPACE
|
|
247
|
+
project_dir = os.path.join(user_local, project_name)
|
|
248
|
+
|
|
249
|
+
click.echo(f"FastAPI template project will deploy at '{user_local}'")
|
|
250
|
+
|
|
251
|
+
copy_and_convert_template(target_template, user_local, project_name)
|
|
252
|
+
|
|
253
|
+
venv_path = create_venv(project_dir)
|
|
254
|
+
|
|
255
|
+
inject_project_metadata(
|
|
256
|
+
project_dir, project_name, author, author_email, description
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
install_dependencies(project_dir, venv_path)
|
|
260
|
+
|
|
261
|
+
print_success(
|
|
262
|
+
f"FastAPI project '{project_name}' from '{template}' has been created and saved to {user_local}!"
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
except Exception as e:
|
|
266
|
+
logger = get_logger()
|
|
267
|
+
logger.exception(f"Error during project creation in startdemo: {str(e)}")
|
|
268
|
+
print_error(f"Error during project creation: {str(e)}")
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
@fastkit_cli.command(context_settings={"ignore_unknown_options": True})
|
|
272
|
+
@click.option(
|
|
273
|
+
"--project-name",
|
|
274
|
+
prompt="Enter the project name",
|
|
275
|
+
help="The name of the new FastAPI project.",
|
|
276
|
+
)
|
|
277
|
+
@click.option(
|
|
278
|
+
"--author", prompt="Enter the author name", help="The name of the project author."
|
|
279
|
+
)
|
|
280
|
+
@click.option(
|
|
281
|
+
"--author-email",
|
|
282
|
+
prompt="Enter the author email",
|
|
283
|
+
help="The email of the project author.",
|
|
284
|
+
type=str,
|
|
285
|
+
callback=validate_email,
|
|
286
|
+
)
|
|
287
|
+
@click.option(
|
|
288
|
+
"--description",
|
|
289
|
+
prompt="Enter the project description",
|
|
290
|
+
help="The description of the new FastAPI project.",
|
|
291
|
+
)
|
|
292
|
+
@click.pass_context
|
|
293
|
+
def init(
|
|
294
|
+
ctx: Context, project_name: str, author: str, author_email: str, description: str
|
|
295
|
+
) -> None:
|
|
296
|
+
"""
|
|
297
|
+
Start a empty FastAPI project setup.
|
|
298
|
+
This command will automatically create a new FastAPI project directory and a python virtual environment.
|
|
299
|
+
Dependencies will be automatically installed based on the selected stack at venv.
|
|
300
|
+
Project metadata will be injected to the project files.
|
|
301
|
+
|
|
302
|
+
:param ctx: Click context object
|
|
303
|
+
:param project_name: Project name for the new project
|
|
304
|
+
:param author: Author name
|
|
305
|
+
:param author_email: Author email
|
|
306
|
+
:param description: Project description
|
|
307
|
+
:return: None
|
|
308
|
+
"""
|
|
309
|
+
settings = ctx.obj["settings"]
|
|
310
|
+
project_dir = os.path.join(settings.USER_WORKSPACE, project_name)
|
|
311
|
+
|
|
312
|
+
if os.path.exists(project_dir):
|
|
313
|
+
print_error(f"Error: Project '{project_name}' already exists.")
|
|
314
|
+
return
|
|
315
|
+
|
|
316
|
+
# Display project information
|
|
317
|
+
project_info_table = create_info_table(
|
|
318
|
+
"Project Information",
|
|
319
|
+
{
|
|
320
|
+
"Project Name": project_name,
|
|
321
|
+
"Author": author,
|
|
322
|
+
"Author Email": author_email,
|
|
323
|
+
"Description": description,
|
|
324
|
+
},
|
|
325
|
+
)
|
|
326
|
+
console.print("\n")
|
|
327
|
+
console.print(project_info_table)
|
|
328
|
+
|
|
329
|
+
# Display available stacks
|
|
330
|
+
console.print("\n[bold]Available Stacks and Dependencies:[/bold]")
|
|
331
|
+
|
|
332
|
+
for stack_name, deps in settings.PROJECT_STACKS.items():
|
|
333
|
+
table = create_info_table(
|
|
334
|
+
f"{stack_name.upper()} Stack",
|
|
335
|
+
{f"Dependency {i+1}": dep for i, dep in enumerate(deps)},
|
|
336
|
+
)
|
|
337
|
+
console.print(table)
|
|
338
|
+
console.print("\n")
|
|
339
|
+
|
|
340
|
+
stack = click.prompt(
|
|
341
|
+
"Select stack",
|
|
342
|
+
type=click.Choice(list(settings.PROJECT_STACKS.keys())),
|
|
343
|
+
show_choices=True,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
template = "fastapi-empty"
|
|
347
|
+
template_dir = settings.FASTKIT_TEMPLATE_ROOT
|
|
348
|
+
target_template = os.path.join(template_dir, template)
|
|
349
|
+
|
|
350
|
+
if not os.path.exists(target_template):
|
|
351
|
+
print_error(f"Template '{template}' does not exist in '{template_dir}'.")
|
|
352
|
+
raise CLIExceptions(
|
|
353
|
+
f"Template '{template}' does not exist in '{template_dir}'."
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
confirm = click.confirm(
|
|
357
|
+
"\nDo you want to proceed with project creation?", default=False
|
|
358
|
+
)
|
|
359
|
+
if not confirm:
|
|
360
|
+
print_error("Project creation aborted!")
|
|
361
|
+
return
|
|
362
|
+
|
|
363
|
+
try:
|
|
364
|
+
user_local = settings.USER_WORKSPACE
|
|
365
|
+
project_dir = os.path.join(user_local, project_name)
|
|
366
|
+
|
|
367
|
+
click.echo(f"FastAPI project will deploy at '{user_local}'")
|
|
368
|
+
|
|
369
|
+
copy_and_convert_template(target_template, user_local, project_name)
|
|
370
|
+
|
|
371
|
+
inject_project_metadata(
|
|
372
|
+
project_dir, project_name, author, author_email, description
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
deps_table = create_info_table(
|
|
376
|
+
f"Creating Project: {project_name}", {"Component": "Collected"}
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
with open(os.path.join(project_dir, "requirements.txt"), "w") as f:
|
|
380
|
+
for dep in settings.PROJECT_STACKS[stack]:
|
|
381
|
+
f.write(f"{dep}\n")
|
|
382
|
+
deps_table.add_row(dep, "✓")
|
|
383
|
+
|
|
384
|
+
console.print(deps_table)
|
|
385
|
+
|
|
386
|
+
venv_path = create_venv(project_dir)
|
|
387
|
+
install_dependencies(project_dir, venv_path)
|
|
388
|
+
|
|
389
|
+
print_success(
|
|
390
|
+
f"FastAPI project '{project_name}' has been created successfully and saved to {user_local}!"
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
print_info(
|
|
394
|
+
"To start your project, run 'fastkit runserver' at newly created FastAPI project directory"
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
except Exception as e:
|
|
398
|
+
logger = get_logger()
|
|
399
|
+
logger.exception(f"Error during project creation in init: {str(e)}")
|
|
400
|
+
print_error(f"Error during project creation: {str(e)}")
|
|
401
|
+
if os.path.exists(project_dir):
|
|
402
|
+
shutil.rmtree(project_dir, ignore_errors=True)
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
@fastkit_cli.command()
|
|
406
|
+
@click.argument("project_name")
|
|
407
|
+
@click.argument("route_name")
|
|
408
|
+
@click.pass_context
|
|
409
|
+
def addroute(ctx: Context, project_name: str, route_name: str) -> None:
|
|
410
|
+
"""
|
|
411
|
+
Add a new route to the FastAPI project.
|
|
412
|
+
|
|
413
|
+
:param ctx: Click context object
|
|
414
|
+
:param project_name: Project name
|
|
415
|
+
:param route_name: Name of the new route to add
|
|
416
|
+
:return: None
|
|
417
|
+
"""
|
|
418
|
+
settings = ctx.obj["settings"]
|
|
419
|
+
user_local = settings.USER_WORKSPACE
|
|
420
|
+
project_dir = os.path.join(user_local, project_name)
|
|
421
|
+
|
|
422
|
+
# Check if project exists
|
|
423
|
+
if not os.path.exists(project_dir):
|
|
424
|
+
print_error(f"Project '{project_name}' does not exist in '{user_local}'.")
|
|
425
|
+
return
|
|
426
|
+
|
|
427
|
+
# Verify it's a fastkit project
|
|
428
|
+
if not is_fastkit_project(project_dir):
|
|
429
|
+
print_error(f"'{project_name}' is not a FastAPI-fastkit project.")
|
|
430
|
+
return
|
|
431
|
+
|
|
432
|
+
# Validate route name
|
|
433
|
+
if not route_name.isidentifier():
|
|
434
|
+
print_error(f"Route name '{route_name}' is not a valid Python identifier.")
|
|
435
|
+
return
|
|
436
|
+
|
|
437
|
+
# Route name shouldn't match reserved keywords
|
|
438
|
+
import keyword
|
|
439
|
+
|
|
440
|
+
if keyword.iskeyword(route_name):
|
|
441
|
+
print_error(
|
|
442
|
+
f"Route name '{route_name}' is a Python keyword and cannot be used."
|
|
443
|
+
)
|
|
444
|
+
return
|
|
445
|
+
|
|
446
|
+
try:
|
|
447
|
+
# Show information about the operation
|
|
448
|
+
table = create_info_table(
|
|
449
|
+
"Adding New Route",
|
|
450
|
+
{
|
|
451
|
+
"Project": project_name,
|
|
452
|
+
"Route Name": route_name,
|
|
453
|
+
"Target Directory": project_dir,
|
|
454
|
+
},
|
|
455
|
+
)
|
|
456
|
+
console.print(table)
|
|
457
|
+
|
|
458
|
+
# Confirm before proceeding
|
|
459
|
+
confirm = click.confirm(
|
|
460
|
+
f"\nDo you want to add route '{route_name}' to project '{project_name}'?",
|
|
461
|
+
default=True,
|
|
462
|
+
)
|
|
463
|
+
if not confirm:
|
|
464
|
+
print_error("Operation cancelled!")
|
|
465
|
+
return
|
|
466
|
+
|
|
467
|
+
# Add the new route
|
|
468
|
+
add_new_route(project_dir, route_name)
|
|
469
|
+
|
|
470
|
+
print_success(
|
|
471
|
+
f"Successfully added new route '{route_name}' to project `{project_name}`"
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
except Exception as e:
|
|
475
|
+
logger = get_logger()
|
|
476
|
+
logger.exception(f"Error during route addition: {str(e)}")
|
|
477
|
+
print_error(f"Error during route addition: {str(e)}")
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
@fastkit_cli.command()
|
|
481
|
+
@click.argument("project_name")
|
|
482
|
+
@click.pass_context
|
|
483
|
+
def deleteproject(ctx: Context, project_name: str) -> None:
|
|
484
|
+
"""
|
|
485
|
+
Delete a FastAPI project.
|
|
486
|
+
|
|
487
|
+
:param ctx: Click context object
|
|
488
|
+
:param project_name: Project name
|
|
489
|
+
:return: None
|
|
490
|
+
"""
|
|
491
|
+
settings = ctx.obj["settings"]
|
|
492
|
+
user_local = settings.USER_WORKSPACE
|
|
493
|
+
project_dir = os.path.join(user_local, project_name)
|
|
494
|
+
|
|
495
|
+
if not os.path.exists(project_dir):
|
|
496
|
+
print_error(f"Project '{project_name}' does not exist in '{user_local}'.")
|
|
497
|
+
return
|
|
498
|
+
|
|
499
|
+
if not is_fastkit_project(project_dir):
|
|
500
|
+
print_error(f"'{project_name}' is not a FastAPI-fastkit project.")
|
|
501
|
+
return
|
|
502
|
+
|
|
503
|
+
confirm = click.confirm(
|
|
504
|
+
f"\nDo you want to delete project '{project_name}' at '{project_dir}'?",
|
|
505
|
+
default=False,
|
|
506
|
+
)
|
|
507
|
+
if not confirm:
|
|
508
|
+
print_error("Project deletion cancelled!")
|
|
509
|
+
return
|
|
510
|
+
|
|
511
|
+
try:
|
|
512
|
+
shutil.rmtree(project_dir)
|
|
513
|
+
print_success(f"Project '{project_name}' has been deleted successfully!")
|
|
514
|
+
|
|
515
|
+
except Exception as e:
|
|
516
|
+
logger = get_logger()
|
|
517
|
+
logger.exception(f"Error during project deletion: {e}")
|
|
518
|
+
print_error(f"Error during project deletion: {e}")
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
@fastkit_cli.command()
|
|
522
|
+
@click.option(
|
|
523
|
+
"--host",
|
|
524
|
+
default="127.0.0.1",
|
|
525
|
+
show_default=True,
|
|
526
|
+
help="Host to bind the server",
|
|
527
|
+
)
|
|
528
|
+
@click.option(
|
|
529
|
+
"--port",
|
|
530
|
+
default=8000,
|
|
531
|
+
show_default=True,
|
|
532
|
+
help="Port to bind the server",
|
|
533
|
+
)
|
|
534
|
+
@click.option(
|
|
535
|
+
"--reload/--no-reload",
|
|
536
|
+
default=True,
|
|
537
|
+
show_default=True,
|
|
538
|
+
help="Enable/disable auto-reload on code changes",
|
|
539
|
+
)
|
|
540
|
+
@click.option(
|
|
541
|
+
"--workers",
|
|
542
|
+
default=1,
|
|
543
|
+
show_default=True,
|
|
544
|
+
help="Number of worker processes",
|
|
545
|
+
)
|
|
546
|
+
@click.pass_context
|
|
547
|
+
def runserver(
|
|
548
|
+
ctx: Context,
|
|
549
|
+
host: str = "127.0.0.1",
|
|
550
|
+
port: int = 8000,
|
|
551
|
+
reload: bool = True,
|
|
552
|
+
workers: int = 1,
|
|
553
|
+
) -> None:
|
|
554
|
+
"""
|
|
555
|
+
Run the FastAPI server for the current project.
|
|
556
|
+
|
|
557
|
+
:param ctx: Click context object
|
|
558
|
+
:param host: Host address to bind the server to
|
|
559
|
+
:param port: Port number to bind the server to
|
|
560
|
+
:param reload: Enable or disable auto-reload
|
|
561
|
+
:param workers: Number of worker processes
|
|
562
|
+
:return: None
|
|
563
|
+
"""
|
|
564
|
+
settings = ctx.obj["settings"]
|
|
565
|
+
project_dir = settings.USER_WORKSPACE
|
|
566
|
+
|
|
567
|
+
# Check for virtual environment
|
|
568
|
+
venv_path = os.path.join(project_dir, ".venv")
|
|
569
|
+
if not os.path.exists(venv_path) or not os.path.isdir(venv_path):
|
|
570
|
+
print_error(
|
|
571
|
+
"Virtual environment not found. Is this a project deployed with Fastkit?"
|
|
572
|
+
)
|
|
573
|
+
confirm = click.confirm(
|
|
574
|
+
"Do you want to continue with system Python?", default=False
|
|
575
|
+
)
|
|
576
|
+
if not confirm:
|
|
577
|
+
return
|
|
578
|
+
venv_python = None
|
|
579
|
+
else:
|
|
580
|
+
if os.name == "nt": # Windows
|
|
581
|
+
venv_python = os.path.join(venv_path, "Scripts", "python.exe")
|
|
582
|
+
else: # Unix/Linux/Mac
|
|
583
|
+
venv_python = os.path.join(venv_path, "bin", "python")
|
|
584
|
+
|
|
585
|
+
if not os.path.exists(venv_python):
|
|
586
|
+
print_error(
|
|
587
|
+
f"Python interpreter not found in virtual environment: {venv_python}"
|
|
588
|
+
)
|
|
589
|
+
confirm = click.confirm(
|
|
590
|
+
"Do you want to continue with system Python?", default=False
|
|
591
|
+
)
|
|
592
|
+
if not confirm:
|
|
593
|
+
return
|
|
594
|
+
venv_python = None
|
|
595
|
+
|
|
596
|
+
core_modules = find_template_core_modules(project_dir)
|
|
597
|
+
if not core_modules["main"]:
|
|
598
|
+
print_error(f"Could not find 'main.py' in '{project_dir}'.")
|
|
599
|
+
return
|
|
600
|
+
|
|
601
|
+
main_path = core_modules["main"]
|
|
602
|
+
if "src/" in main_path:
|
|
603
|
+
app_module = "src.main:app"
|
|
604
|
+
else:
|
|
605
|
+
app_module = "main:app"
|
|
606
|
+
|
|
607
|
+
if venv_python:
|
|
608
|
+
print_info(f"Using Python from virtual environment: {venv_python}")
|
|
609
|
+
command = [
|
|
610
|
+
venv_python,
|
|
611
|
+
"-m",
|
|
612
|
+
"uvicorn",
|
|
613
|
+
app_module,
|
|
614
|
+
"--host",
|
|
615
|
+
host,
|
|
616
|
+
"--port",
|
|
617
|
+
str(port),
|
|
618
|
+
"--workers",
|
|
619
|
+
str(workers),
|
|
620
|
+
]
|
|
621
|
+
else:
|
|
622
|
+
command = [
|
|
623
|
+
"uvicorn",
|
|
624
|
+
app_module,
|
|
625
|
+
"--host",
|
|
626
|
+
host,
|
|
627
|
+
"--port",
|
|
628
|
+
str(port),
|
|
629
|
+
"--workers",
|
|
630
|
+
str(workers),
|
|
631
|
+
]
|
|
632
|
+
|
|
633
|
+
if reload:
|
|
634
|
+
command.append("--reload")
|
|
635
|
+
|
|
636
|
+
try:
|
|
637
|
+
print_success(f"Starting FastAPI server at {host}:{port}...")
|
|
638
|
+
|
|
639
|
+
# Set up environment variables for the subprocess
|
|
640
|
+
env = os.environ.copy()
|
|
641
|
+
if venv_python:
|
|
642
|
+
python_path = os.path.dirname(os.path.dirname(venv_python))
|
|
643
|
+
if "PYTHONPATH" in env:
|
|
644
|
+
env["PYTHONPATH"] = f"{python_path}:{env['PYTHONPATH']}"
|
|
645
|
+
else:
|
|
646
|
+
env["PYTHONPATH"] = python_path
|
|
647
|
+
|
|
648
|
+
# Run the server with the configured environment
|
|
649
|
+
subprocess.run(command, check=True, env=env)
|
|
650
|
+
except subprocess.CalledProcessError as e:
|
|
651
|
+
logger = get_logger()
|
|
652
|
+
logger.exception(f"Failed to start FastAPI server: {e}")
|
|
653
|
+
print_error(f"Failed to start FastAPI server.\n{e}")
|
|
654
|
+
except FileNotFoundError as e:
|
|
655
|
+
logger = get_logger()
|
|
656
|
+
logger.exception(f"FileNotFoundError when starting server: {e}")
|
|
657
|
+
if venv_python:
|
|
658
|
+
print_error(
|
|
659
|
+
f"Failed to run Python from the virtual environment. Make sure uvicorn is installed in the project's virtual environment."
|
|
660
|
+
)
|
|
661
|
+
else:
|
|
662
|
+
print_error(
|
|
663
|
+
f"uvicorn not found. Make sure it's installed in your system Python."
|
|
664
|
+
)
|