fastapi-route 0.1.0__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.
Files changed (58) hide show
  1. fastapi_route-0.1.0.dist-info/METADATA +304 -0
  2. fastapi_route-0.1.0.dist-info/RECORD +58 -0
  3. fastapi_route-0.1.0.dist-info/WHEEL +5 -0
  4. fastapi_route-0.1.0.dist-info/entry_points.txt +2 -0
  5. fastapi_route-0.1.0.dist-info/licenses/LICENSE +1 -0
  6. fastapi_route-0.1.0.dist-info/top_level.txt +1 -0
  7. fastapi_router/__init__.py +34 -0
  8. fastapi_router/app.py +280 -0
  9. fastapi_router/build/__init__.py +5 -0
  10. fastapi_router/build/builder.py +211 -0
  11. fastapi_router/build/cache.py +352 -0
  12. fastapi_router/build/loader.py +93 -0
  13. fastapi_router/cli/commands.py +445 -0
  14. fastapi_router/config/loader.py +462 -0
  15. fastapi_router/config/py_loader.py +263 -0
  16. fastapi_router/config/schema.py +75 -0
  17. fastapi_router/config/validator.py +141 -0
  18. fastapi_router/constants.py +83 -0
  19. fastapi_router/core/builder.py +630 -0
  20. fastapi_router/core/lifecycle.py +89 -0
  21. fastapi_router/core/registry.py +147 -0
  22. fastapi_router/core/scanner.py +325 -0
  23. fastapi_router/core/validator.py +344 -0
  24. fastapi_router/custom/__init__.py +6 -0
  25. fastapi_router/custom/context.py +166 -0
  26. fastapi_router/custom/error_page.py +311 -0
  27. fastapi_router/custom/loader.py +269 -0
  28. fastapi_router/custom/validator.py +213 -0
  29. fastapi_router/decorators/__init__.py +5 -0
  30. fastapi_router/decorators/methods.py +130 -0
  31. fastapi_router/dev/config_watcher.py +136 -0
  32. fastapi_router/dev/error_handler.py +346 -0
  33. fastapi_router/dev/error_page.py +893 -0
  34. fastapi_router/dev/server.py +492 -0
  35. fastapi_router/docs/__init__.py +11 -0
  36. fastapi_router/docs/collector.py +270 -0
  37. fastapi_router/docs/generator.py +644 -0
  38. fastapi_router/docs/renderer.py +153 -0
  39. fastapi_router/exceptions.py +204 -0
  40. fastapi_router/middleware/custom.py +201 -0
  41. fastapi_router/middleware/manager.py +87 -0
  42. fastapi_router/middleware/validator.py +153 -0
  43. fastapi_router/request.py +211 -0
  44. fastapi_router/response.py +210 -0
  45. fastapi_router/routing/compiler.py +70 -0
  46. fastapi_router/routing/filesystem.py +67 -0
  47. fastapi_router/routing/matcher.py +89 -0
  48. fastapi_router/routing/parser.py +125 -0
  49. fastapi_router/routing/router.py +93 -0
  50. fastapi_router/static/__init__.py +7 -0
  51. fastapi_router/static/directory_listing.py +240 -0
  52. fastapi_router/static/handler.py +220 -0
  53. fastapi_router/static/middleware.py +115 -0
  54. fastapi_router/types.py +234 -0
  55. fastapi_router/utils/imports.py +70 -0
  56. fastapi_router/utils/logger.py +285 -0
  57. fastapi_router/utils/paths.py +67 -0
  58. fastapi_router/version.py +1 -0
@@ -0,0 +1,304 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastapi-route
3
+ Version: 0.1.0
4
+ Summary: File-based routing for FastAPI with automatic route discovery
5
+ Author-email: Your Name <you@example.com>
6
+ License: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: fastapi>=0.100.0
11
+ Requires-Dist: uvicorn>=0.23.0
12
+ Requires-Dist: pydantic>=2.0.0
13
+ Requires-Dist: watchdog>=3.0.0
14
+ Provides-Extra: dev
15
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
16
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
17
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
18
+ Requires-Dist: httpx>=0.24.0; extra == "dev"
19
+ Requires-Dist: black>=23.0.0; extra == "dev"
20
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
21
+ Requires-Dist: isort>=5.12.0; extra == "dev"
22
+ Requires-Dist: ruff>=0.0.260; extra == "dev"
23
+ Provides-Extra: test
24
+ Requires-Dist: pytest>=7.0.0; extra == "test"
25
+ Requires-Dist: pytest-cov>=4.0.0; extra == "test"
26
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
27
+ Requires-Dist: httpx>=0.24.0; extra == "test"
28
+ Dynamic: license-file
29
+
30
+ <p align="center">
31
+ <img src="https://raw.githubusercontent.com/fastapi-router/fastapi-router/main/docs/logo.png" alt="FastAPI Router Logo" width="300">
32
+ </p>
33
+
34
+ # FastAPI Router
35
+
36
+ A file-based routing system for FastAPI — build APIs with the simplicity of files and folders, not decorators.
37
+
38
+ **[Full Documentation](https://inject3r.github.io/fastapi-router)** — Complete API reference, advanced guides, and examples
39
+
40
+ <br/>
41
+
42
+ ## Why FastAPI Router?
43
+
44
+ Stop writing decorators. Start organizing your API with files and folders. Just drop Python files in directories — each file becomes an endpoint, each directory becomes a route segment. Dynamic parameters? Use `[param]` directories. Route groups? Use `(group)` directories. It's that simple.
45
+
46
+ ## Features
47
+
48
+ - **File-Based Routing**: Routes defined by directory structure — no decorators needed
49
+ - **Dynamic Routes**: `[user_id]` directories automatically become `{user_id}` parameters
50
+ - **Cache-All Routes**: `[...slug]` captures unlimited path segments
51
+ - **Route Groups**: `(auth)` directories organize code without affecting URLs
52
+ - **Hot Reload**: Instant rebuild on file changes during development
53
+ - **Production Build Cache**: Pre-compiled routes for lightning-fast startup
54
+ - **Beautiful Error Pages**: Syntax highlighting, line numbers, and helpful suggestions
55
+ - **Custom Handlers**: Bring your own `docs.py` and `not-found.py`
56
+ - **Custom Middleware**: Intercept requests with `middleware.py`
57
+ - **Static File Serving**: Drop files in `/public` — served automatically
58
+ - **Built-in Documentation**: Auto-generated API docs at `/docs`
59
+ - **CLI Tools**: `init`, `build`, `run`, `dev`, `clean`, `status` commands
60
+ - **Zero Config**: Works out of the box — but fully customizable when you need it
61
+ - **Type Hints**: Full typing support for excellent IDE autocompletion
62
+
63
+ ## Installation
64
+
65
+ ```bash
66
+ pip install fastapi-router
67
+ ```
68
+
69
+ With development dependencies:
70
+
71
+ ```bash
72
+ pip install fastapi-router[dev]
73
+ ```
74
+
75
+ ## Quick Start
76
+
77
+ ### 1. Initialize a new project
78
+
79
+ ```bash
80
+ fastapi-router init
81
+ ```
82
+
83
+ ### 2. Create your first route
84
+
85
+ ```python
86
+ # routes/index.py
87
+ from fastapi_router import Request
88
+
89
+ def GET(request: Request):
90
+ return {"message": "Hello World!"}
91
+
92
+ def POST(request: Request):
93
+ data = await request.json()
94
+ return {"received": data}
95
+ ```
96
+
97
+ ### 3. Add a dynamic route
98
+
99
+ ```python
100
+ # routes/users/[user_id]/route.py
101
+ from fastapi_router import Request
102
+
103
+ def GET(request: Request, user_id: int):
104
+ return {"user_id": user_id, "name": f"User {user_id}"}
105
+ ```
106
+
107
+ ### 4. Run your API
108
+
109
+ ```bash
110
+ # Development mode (with hot reload)
111
+ fastapi-router dev
112
+
113
+ # Production mode (requires build first)
114
+ fastapi-router build
115
+ fastapi-router run
116
+ ```
117
+
118
+ Visit `http://localhost:8000/docs` for auto-generated documentation.
119
+
120
+ ## How It Works
121
+
122
+ ```text
123
+ routes/
124
+ ├── index.py → GET /, POST /
125
+ ├── about/
126
+ │ └── route.py → GET /about
127
+ ├── users/
128
+ │ ├── route.py → GET /users, POST /users
129
+ │ ├── [user_id]/
130
+ │ │ └── route.py → GET /users/{user_id}, PUT /users/{user_id}
131
+ │ └── [user_id]/posts/
132
+ │ └── route.py → GET /users/{user_id}/posts
133
+ ├── docs/
134
+ │ └── [...slug]/
135
+ │ └── route.py → GET /docs/*
136
+ └── (auth)/ # Route group (ignored in URL)
137
+ └── profile/
138
+ └── route.py → GET /profile
139
+ ```
140
+
141
+ ## CLI Commands
142
+
143
+ | Command | Description |
144
+ | ----------------------- | ------------------------------------------- |
145
+ | `fastapi-router init` | Create a new project with default structure |
146
+ | `fastapi-router build` | Compile routes into production cache |
147
+ | `fastapi-router run` | Start production server (requires build) |
148
+ | `fastapi-router dev` | Start development server with hot reload |
149
+ | `fastapi-router clean` | Remove build cache |
150
+ | `fastapi-router status` | Show build cache information |
151
+
152
+ ## Customization
153
+
154
+ ### Configuration (`config.py`)
155
+
156
+ ```python
157
+ app_name = "My API"
158
+ debug = False
159
+ cors_enabled = True
160
+ cors_origins = ["https://example.com"]
161
+
162
+ server = {
163
+ "host": "0.0.0.0",
164
+ "port": 8080,
165
+ "workers": 4
166
+ }
167
+
168
+ logging = {
169
+ "level": "INFO",
170
+ "format": "[%Y-%m-%d %H:%M:%S]",
171
+ "color": True
172
+ }
173
+
174
+ commands = {
175
+ "deploy": "fastapi-router build && rsync -avz .cache/ deploy/"
176
+ }
177
+ ```
178
+
179
+ ### Custom Middleware (`middleware.py`)
180
+
181
+ ```python
182
+ from fastapi_router import Request
183
+
184
+ async def middleware(request: Request, call_next):
185
+ # Log every request
186
+ print(f"{request.method} {request.path}")
187
+
188
+ # Continue to the route handler
189
+ response = await call_next(request)
190
+
191
+ # Add custom header
192
+ response.headers["X-Powered-By"] = "FastAPI Router"
193
+
194
+ return response
195
+ ```
196
+
197
+ ### Custom 404 Page (`not-found.py`)
198
+
199
+ ```python
200
+ from fastapi_router import Request, HTMLResponse
201
+
202
+ def handler(request: Request, context):
203
+ routes = context.get_routes()
204
+
205
+ return HTMLResponse(content=f"""
206
+ <!DOCTYPE html>
207
+ <html>
208
+ <head><title>404 - Not Found</title></head>
209
+ <body>
210
+ <h1>404 - Page Not Found</h1>
211
+ <p>{request.path} does not exist</p>
212
+ <p>Total routes: {len(routes)}</p>
213
+ <a href="/">Go Home</a>
214
+ </body>
215
+ </html>
216
+ """, status_code=404)
217
+ ```
218
+
219
+ ## Documentation
220
+
221
+ For complete documentation, API reference, and advanced usage examples, visit:
222
+
223
+ **[https://inject3r.github.io/fastapi-router](https://inject3r.github.io/fastapi-router)**
224
+
225
+ The documentation includes:
226
+
227
+ - Detailed API reference for all modules and classes
228
+ - Advanced routing patterns and best practices
229
+ - Configuration options and their effects
230
+ - Error handling strategies
231
+ - Migration guides from traditional FastAPI
232
+ - Production deployment guides
233
+
234
+ ## Repository
235
+
236
+ Source code and issue tracking:
237
+
238
+ **[https://github.com/inject3r/fastapi-router](https://github.com/inject3r/fastapi-router)**
239
+
240
+ ## Requirements
241
+
242
+ - Python 3.9+
243
+ - FastAPI 0.100.0+
244
+ - Uvicorn 0.23.0+
245
+
246
+ ## Running Tests
247
+
248
+ ```bash
249
+ # Run all tests with coverage
250
+ ./scripts/test.sh
251
+
252
+ # Clean test output files
253
+ ./scripts/test_clean.sh
254
+ ```
255
+
256
+ ## Project Structure
257
+
258
+ ```text
259
+ your-project/
260
+ ├── routes/ # Your API routes (file-based)
261
+ │ ├── index.py
262
+ │ └── ...
263
+ ├── public/ # Static files (served at /)
264
+ │ ├── css/
265
+ │ ├── js/
266
+ │ └── images/
267
+ ├── config.py # Application configuration
268
+ ├── middleware.py # Custom middleware (optional)
269
+ ├── docs.py # Custom documentation (optional)
270
+ ├── not-found.py # Custom 404 page (optional)
271
+ └── .cache/ # Build cache (auto-generated)
272
+ ```
273
+
274
+ ## Why No Decorators?
275
+
276
+ FastAPI Router was built for developers who think in terms of files and directories, not decorators and route registrations. Just create files — they become endpoints. Create directories — they become route segments. Use `[param]` for dynamic parameters. Use `(group)` for organization.
277
+
278
+ No decorators. No route registration. Just files.
279
+
280
+ ## License
281
+
282
+ This project is licensed under the MIT License.
283
+
284
+ ## Author
285
+
286
+ **Abolfazl Hosseini**
287
+
288
+ - Email: tryuzr@gmail.com
289
+ - GitHub: [@inject3r](https://github.com/inject3r)
290
+
291
+ ## Contributing
292
+
293
+ Contributions are welcome! Please feel free to submit a Pull Request.
294
+
295
+ 1. Fork the repository
296
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
297
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
298
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
299
+ 5. Open a Pull Request
300
+
301
+ ## Acknowledgments
302
+
303
+ - [FastAPI](https://fastapi.tiangolo.com/) - The amazing web framework
304
+ - All contributors and users of this project
@@ -0,0 +1,58 @@
1
+ fastapi_route-0.1.0.dist-info/licenses/LICENSE,sha256=NAC7SVw_jEw0g6RMa8GpLp2UQG23Wm8n28zBHHZFDYo,5
2
+ fastapi_router/__init__.py,sha256=-PukPobOAT285s77hzDde9jWZDtt62VM56jXR_PIrMg,841
3
+ fastapi_router/app.py,sha256=3bJufHnLEUChReILbLWuuY-rXqN0VDAY7xsoUA3OY_I,10800
4
+ fastapi_router/constants.py,sha256=blF47Ep8zXzzz3E63fSP_tanCR9-aPVJA5GedNLcMLA,2879
5
+ fastapi_router/exceptions.py,sha256=3zcOXmvsex7LJewjhBdZjpfiAhnfTqlyyD5qTc_dUXw,7167
6
+ fastapi_router/request.py,sha256=gC1D2KmbN-qCNCGHva3T7wyzlW5nGflh80CAk8hd0-s,6927
7
+ fastapi_router/response.py,sha256=PUMKNgwSp90NFqT-e-BMlRDp-5R186X2IlVfHID_t2A,5985
8
+ fastapi_router/types.py,sha256=PlYAoGIsNfpqGiJxCDBJLsX1gPUUtGnHXx4Itbpm9Ys,7949
9
+ fastapi_router/version.py,sha256=Pru0BlFBASFCFo7McHdohtKkUtgMPDwbGfyUZlE2_Vw,21
10
+ fastapi_router/build/__init__.py,sha256=91l0wsho3C4oxb0DpZPja0icvsIm0DjfAwSHy1T2I7s,156
11
+ fastapi_router/build/builder.py,sha256=Ila_spVDLisULCivjBvR-eLRwIr8qscmMqJEXf0OCXo,9355
12
+ fastapi_router/build/cache.py,sha256=eu2qV6EDC1hJECMArqD_OE17u_UMJiqRlGw56jhh_K4,13100
13
+ fastapi_router/build/loader.py,sha256=m6TANs0QHmpwXH70uY8dLmm_TsCl457eAkDP920h6eQ,3103
14
+ fastapi_router/cli/commands.py,sha256=vZRGrkjjDcp3p4gvPbFSsaPiB6D8EE9sCKzAiwU_bDE,14443
15
+ fastapi_router/config/loader.py,sha256=yUfjKp3m-4D7PtFqKSZD0YZ9VPS92JDYeb_AQgNQx-I,15656
16
+ fastapi_router/config/py_loader.py,sha256=dG_YVf01f-btrEIS26wfc4ndW81KAePry0Y73rgAwhQ,9519
17
+ fastapi_router/config/schema.py,sha256=CGIJZ9LwBNvu7RdKm8v1_2mZMWIXwP4Mulr_YQtIevw,2885
18
+ fastapi_router/config/validator.py,sha256=8od8V3L8duRUqrEiVoMeLZIba8QoYEofECefCmN10MI,6301
19
+ fastapi_router/core/builder.py,sha256=0dI4XpUFsZ10sGsd1RjL52aI_knmbC_CSZwq4SYgIbA,28054
20
+ fastapi_router/core/lifecycle.py,sha256=M7V4p7rVAhPU67qWhRyvqWYkAhgYkjdDod5cW49g81o,3303
21
+ fastapi_router/core/registry.py,sha256=X0nEgqBnfF3p9OCjEWVLy7_MFcpaCetcavtuf1WAx64,4991
22
+ fastapi_router/core/scanner.py,sha256=FCPXZODXCzXbps4hzzUCmjSxufo9VKevv61TlAdRdRc,12324
23
+ fastapi_router/core/validator.py,sha256=mX8mEcGKBK92-8zNy2I9EA-9IJvw3R8zwmrqk_Sv3qM,12899
24
+ fastapi_router/custom/__init__.py,sha256=YfyZWKvceo5u5tpzC5ouNdUJL4tOb__gXhmezHxFqr0,186
25
+ fastapi_router/custom/context.py,sha256=kJxjrCHk5VFVbM3iTTY00UsyW9dAIUctrf1YQpaxTaY,5666
26
+ fastapi_router/custom/error_page.py,sha256=BIq4hGktQv1DX3I6o-7XO6ckcuKVNhWa84AKkIA48U4,8511
27
+ fastapi_router/custom/loader.py,sha256=t42QCEObG_qBJZdVNc8bdZ6-x7inlaj0-BumUWgBhJA,10723
28
+ fastapi_router/custom/validator.py,sha256=y_zeV3JUROjUfAHqzuhN6Q4ouBcm23kJDzcmpg9M5eU,8794
29
+ fastapi_router/decorators/__init__.py,sha256=LGfYrvPdU76S6dmahJm-bm5ZhWITMUTudg0Io0j-ywE,142
30
+ fastapi_router/decorators/methods.py,sha256=MH60kMKXNTMcxCEoHf4PBIlU0wjkNPNcINoC-tbHrKQ,3483
31
+ fastapi_router/dev/config_watcher.py,sha256=9mIkf83jQ3rz2P2tUkJPA2rtt4l5qh1n47lEU5YZWTg,4797
32
+ fastapi_router/dev/error_handler.py,sha256=yGmJdVT8zIBQTqYulZiFpO707wuoayhKilTaomku2uk,10950
33
+ fastapi_router/dev/error_page.py,sha256=sXkduQJHzJSO_384cn2MfPwpWJ_f0iYY_GwwykXf6ec,27384
34
+ fastapi_router/dev/server.py,sha256=NT5IsYD3LP2HU0NoQulKMozz7GCOj1xJlpZO99e46X4,19707
35
+ fastapi_router/docs/__init__.py,sha256=MX-gTxmOwh9nAsleVrcNe_gc1YY_-5r0eVe0ZiL1SqI,233
36
+ fastapi_router/docs/collector.py,sha256=CWiE6R-Ew8ZlmmJribXmtC1e42uX544K8BbAwi_bOXY,8882
37
+ fastapi_router/docs/generator.py,sha256=mvqsidetpKGWSqRVhGQzLllfx9K5Kc6swbqPOle2JGM,20772
38
+ fastapi_router/docs/renderer.py,sha256=i3jdo0GQr26SeKfg99Z_5CD-hGrddfT-Qc1iAOY-Mbs,5628
39
+ fastapi_router/middleware/custom.py,sha256=fReInKnLCsCb1RC3jR7jYkP_WjPZFKWY_rPpPgW2YWM,7670
40
+ fastapi_router/middleware/manager.py,sha256=GRY5XDHssDeZ1I9z7ahmCxpX12u42OKY9DGWQ32uxwA,3403
41
+ fastapi_router/middleware/validator.py,sha256=xc38xzvdUptDJS_wPMDZr42QYSI8nFoiq1Laj_6H-cc,6426
42
+ fastapi_router/routing/compiler.py,sha256=iYBTM5ISmoYiMRgSiUiUluiCg91NVvwccHbLD_hWPMk,2588
43
+ fastapi_router/routing/filesystem.py,sha256=MaCS6YlyG8Kif-hupK2WxS5Mwcexhb5zktR15qLFtxM,2141
44
+ fastapi_router/routing/matcher.py,sha256=_ARdCy7vFK28xDAqzYRlqetUXIm62PDFW8_QuUxIsEw,3179
45
+ fastapi_router/routing/parser.py,sha256=ZtXBY_qgqS7jbzad7pM8bWy3MT3HwUaa8-T_4jkSQSw,4623
46
+ fastapi_router/routing/router.py,sha256=yY_Jnx0n6B1wWYReKH5sQLNVSFvW_0cJnB8_H5mffQo,3122
47
+ fastapi_router/static/__init__.py,sha256=kAiHJFMrgBfzYZezazcz-gB0PncZAUGUpxIFxnkS6rQ,242
48
+ fastapi_router/static/directory_listing.py,sha256=c8VoT4_2bdlhOCpolBbVY8IbCd5XtvE9hZT6mq6BrbA,6751
49
+ fastapi_router/static/handler.py,sha256=wW_o8CWrRSTuNoWymvehYgBlZJk5R6HA0j0w156eLbo,8219
50
+ fastapi_router/static/middleware.py,sha256=i-RIB1ugXlCaaqSEnjxpG59EqLwacW9LJQova7ZGutA,4536
51
+ fastapi_router/utils/imports.py,sha256=HK6mSaHxcncLsY42tfyKaKVCq92jW41uar1X2LsqcEU,2387
52
+ fastapi_router/utils/logger.py,sha256=Fb6P2y6bWxKluiwWBAzcP1RNZwb_2hXtRlREjq6EjUI,9253
53
+ fastapi_router/utils/paths.py,sha256=3KnHY7AV6GH3flDkkTYBKpD6BkJ_F0rvE1j-AEH_kT4,1977
54
+ fastapi_route-0.1.0.dist-info/METADATA,sha256=lgcSOE2q7FLM9V35qHrS-NIeQDFk_2XqudD-cE2FMhU,8847
55
+ fastapi_route-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
56
+ fastapi_route-0.1.0.dist-info/entry_points.txt,sha256=uas8lkNWaE-YcKwF7CS3j27mXu5c4U27iiIy5DB3aOI,68
57
+ fastapi_route-0.1.0.dist-info/top_level.txt,sha256=hZIWNXAsKb6zyMweL16KPzeKS7XqBsrH6AGxS7ZT0I4,15
58
+ fastapi_route-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ fastapi-router = fastapi_router.cli.commands:main
@@ -0,0 +1 @@
1
+ lorem
@@ -0,0 +1 @@
1
+ fastapi_router
@@ -0,0 +1,34 @@
1
+ """FastAPI Router - File-based routing for FastAPI"""
2
+
3
+ from .app import create_app, FastAPIRouterApp
4
+ from .version import __version__
5
+ from .routing.router import Router
6
+ from .request import Request
7
+ from .response import Response, JSONResponse, HTMLResponse, PlainTextResponse, RedirectResponse
8
+ from .exceptions import (
9
+ HTTPException,
10
+ BadRequestException,
11
+ UnauthorizedException,
12
+ ForbiddenException,
13
+ NotFoundException,
14
+ MethodNotAllowedException,
15
+ )
16
+
17
+ __all__ = [
18
+ "create_app",
19
+ "FastAPIRouterApp",
20
+ "__version__",
21
+ "Router",
22
+ "Request",
23
+ "Response",
24
+ "JSONResponse",
25
+ "HTMLResponse",
26
+ "PlainTextResponse",
27
+ "RedirectResponse",
28
+ "HTTPException",
29
+ "BadRequestException",
30
+ "UnauthorizedException",
31
+ "ForbiddenException",
32
+ "NotFoundException",
33
+ "MethodNotAllowedException",
34
+ ]
fastapi_router/app.py ADDED
@@ -0,0 +1,280 @@
1
+ """
2
+ Main application factory for FastAPI Router.
3
+
4
+ This module provides the core application class that builds and runs the
5
+ FastAPI application. It handles route discovery, caching, configuration,
6
+ and lifecycle management.
7
+
8
+ The application can run in two modes:
9
+ - Development: Routes are scanned from filesystem on each build
10
+ - Production: Routes are loaded from build cache for faster startup
11
+
12
+ Features:
13
+ - Automatic route discovery from filesystem
14
+ - Build cache support for production
15
+ - Custom documentation endpoint
16
+ - Lifecycle hooks for startup/shutdown
17
+ - Configurable logging levels
18
+ """
19
+
20
+ import sys
21
+ from pathlib import Path
22
+ from typing import Optional, Any, Dict, List
23
+
24
+ from .config.loader import ConfigLoader
25
+ from .core.registry import RouteRegistry
26
+ from .core.builder import AppBuilder
27
+ from .core.lifecycle import LifecycleManager
28
+ from .routing.filesystem import FileSystemRouter
29
+ from .build import CacheLoader
30
+ from .types import RouteInfo
31
+ from .utils.logger import logger, Logger
32
+
33
+
34
+ class FastAPIRouterApp:
35
+ """
36
+ Main application class for FastAPI Router.
37
+
38
+ This class orchestrates the entire application lifecycle:
39
+ 1. Load configuration
40
+ 2. Discover routes (from filesystem or cache)
41
+ 3. Build the FastAPI application
42
+ 4. Set up middleware and handlers
43
+ 5. Run the server
44
+
45
+ The application can be used in two ways:
46
+ - Direct execution: app = FastAPIRouterApp(); app.run()
47
+ - As ASGI app: app = FastAPIRouterApp(); app = app.build()
48
+
49
+ Args:
50
+ config_path: Optional path to configuration file
51
+ enable_docs: Whether to enable the /docs endpoint
52
+ custom_docs_template: Custom HTML template for documentation
53
+ use_cache: Use build cache for routes (production mode)
54
+ is_production: Run in production mode (reduced logging)
55
+ """
56
+
57
+ def __init__(self, config_path: Optional[str] = None, enable_docs: bool = True,
58
+ custom_docs_template: Optional[str] = None, use_cache: bool = False,
59
+ is_production: bool = False):
60
+ self.config_path = config_path
61
+ self.config = ConfigLoader.load(config_path)
62
+
63
+ # Apply settings from config or constructor args
64
+ self.enable_docs = enable_docs if hasattr(self.config, 'docs_enabled') else enable_docs
65
+ self.custom_docs_template = custom_docs_template or getattr(self.config, 'custom_docs_template', None)
66
+ self.use_cache = use_cache
67
+ self.is_production = is_production
68
+
69
+ # Configure logger based on mode
70
+ Logger.set_production_mode(is_production)
71
+
72
+ # Initialize core components
73
+ self.registry = RouteRegistry()
74
+ self.lifecycle = LifecycleManager()
75
+ self._fastapi_app = None
76
+ self._is_built = False
77
+
78
+ def _load_handler_from_file(self, file_path: Path, handler_name: str):
79
+ """
80
+ Dynamically load a handler function from a Python file.
81
+
82
+ This is used in production mode to load route handlers from the
83
+ original source files when using build cache.
84
+
85
+ Args:
86
+ file_path: Path to the route file
87
+ handler_name: Name of the handler function (e.g., "GET")
88
+
89
+ Returns:
90
+ Handler function if found, None otherwise
91
+ """
92
+ import importlib.util
93
+ import sys
94
+
95
+ try:
96
+ # Convert file path to module name
97
+ module_name = str(file_path).replace("/", ".").replace("\\", ".").replace(".py", "")
98
+
99
+ # Use cached module if available
100
+ if module_name in sys.modules:
101
+ module = sys.modules[module_name]
102
+ else:
103
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
104
+ if spec is None or spec.loader is None:
105
+ return None
106
+ module = importlib.util.module_from_spec(spec)
107
+ sys.modules[module_name] = module
108
+ spec.loader.exec_module(module)
109
+
110
+ return getattr(module, handler_name, None)
111
+ except Exception as e:
112
+ if not self.is_production:
113
+ logger.error(f"Failed to load handler {handler_name} from {file_path}: {e}")
114
+ return None
115
+
116
+ def build(self) -> Any:
117
+ """
118
+ Build and return the FastAPI application.
119
+
120
+ This method performs the actual application construction:
121
+ 1. Discover routes (filesystem or cache)
122
+ 2. Register routes in the registry
123
+ 3. Build the FastAPI app with all middleware and handlers
124
+ 4. Set up lifecycle events
125
+
126
+ Returns:
127
+ Configured FastAPI application instance
128
+ """
129
+ if self._is_built and self._fastapi_app:
130
+ return self._fastapi_app
131
+
132
+ if not self.is_production:
133
+ logger.info("Building FastAPI Router application...")
134
+
135
+ try:
136
+ routes: List[RouteInfo] = []
137
+ routes_metadata: List[Dict[str, Any]] = []
138
+
139
+ # Try to load from cache if production mode
140
+ if self.use_cache:
141
+ cache_loader = CacheLoader(Path.cwd())
142
+ routes_metadata = cache_loader.load_routes_metadata()
143
+ if routes_metadata:
144
+ if not self.is_production:
145
+ logger.info(f"Loading {len(routes_metadata)} routes from cache")
146
+ else:
147
+ if not self.is_production:
148
+ logger.warning("Cache invalid or missing, falling back to filesystem scan")
149
+ self.use_cache = False
150
+
151
+ # Fall back to filesystem scan if cache not available
152
+ if not self.use_cache:
153
+ router = FileSystemRouter(self.config.route_dir)
154
+ routes = router.scan()
155
+ if not self.is_production:
156
+ logger.info(f"Discovered {len(routes)} routes via filesystem scan")
157
+ else:
158
+ # Load handlers from source files for cached routes
159
+ for meta in routes_metadata:
160
+ handler = self._load_handler_from_file(
161
+ Path(meta['file_path']),
162
+ meta['method']
163
+ )
164
+ if handler is None:
165
+ if not self.is_production:
166
+ logger.error(f"Failed to load handler for {meta['method']} {meta['path']}")
167
+ continue
168
+
169
+ route = RouteInfo(
170
+ path=meta['path'],
171
+ method=meta['method'],
172
+ handler=handler,
173
+ file_path=Path(meta['file_path']),
174
+ is_dynamic=meta['is_dynamic'],
175
+ param_names=meta['param_names']
176
+ )
177
+ routes.append(route)
178
+
179
+ if not self.is_production:
180
+ logger.info(f"Loaded {len(routes)} routes from cache")
181
+
182
+ # No routes found - cannot start
183
+ if not routes:
184
+ logger.warning("No routes found")
185
+ return None
186
+
187
+ # Register all routes
188
+ for route in routes:
189
+ self.registry.register(route)
190
+
191
+ # Build the FastAPI application
192
+ builder = AppBuilder(self.config, self.registry, self.enable_docs, self.custom_docs_template)
193
+ self._fastapi_app = builder.build()
194
+
195
+ # Set up lifecycle hooks
196
+ self.lifecycle.setup(self._fastapi_app)
197
+
198
+ self._is_built = True
199
+
200
+ # Log success
201
+ if not self.is_production:
202
+ logger.info(f"Application built with {len(routes)} routes")
203
+ if self.enable_docs:
204
+ logger.info(f"Documentation available at /docs")
205
+
206
+ return self._fastapi_app
207
+
208
+ except Exception as e:
209
+ logger.error(f"Build failed: {e}")
210
+ if not self.is_production:
211
+ import traceback
212
+ traceback.print_exc()
213
+ raise
214
+
215
+ def run(self, host: str = "127.0.0.1", port: int = 8000, reload: bool = False):
216
+ """
217
+ Run the application using uvicorn server.
218
+
219
+ Args:
220
+ host: Host address to bind to
221
+ port: Port number to listen on
222
+ reload: Enable auto-reload (development mode)
223
+ """
224
+ try:
225
+ import uvicorn
226
+ except ImportError:
227
+ logger.error("uvicorn not installed. Please install it: pip install uvicorn")
228
+ return
229
+
230
+ app = self.build()
231
+
232
+ if app is None:
233
+ logger.error("No routes found, cannot start server")
234
+ return
235
+
236
+ mode = "development" if reload else "production"
237
+ logger.info(f"Starting {mode} server on http://{host}:{port}")
238
+
239
+ if not reload and self.use_cache:
240
+ logger.info("Running in production mode with build cache")
241
+
242
+ # Reduce uvicorn log noise in production
243
+ if self.is_production:
244
+ import logging
245
+ log_config = uvicorn.config.LOGGING_CONFIG
246
+ log_config["loggers"]["uvicorn"]["level"] = "WARNING"
247
+ log_config["loggers"]["uvicorn.access"]["level"] = "WARNING"
248
+ log_config["loggers"]["uvicorn.error"]["level"] = "WARNING"
249
+ uvicorn.run(app, host=host, port=port, reload=reload,
250
+ log_config=log_config, access_log=False)
251
+ else:
252
+ uvicorn.run(app, host=host, port=port, reload=reload)
253
+
254
+
255
+ def create_app(config_path: Optional[str] = None, enable_docs: bool = True,
256
+ custom_docs_template: Optional[str] = None, use_cache: bool = False,
257
+ is_production: bool = False) -> Any:
258
+ """
259
+ Factory function to create a FastAPI Router application.
260
+
261
+ This is a convenience wrapper around FastAPIRouterApp for use with
262
+ ASGI servers like uvicorn directly.
263
+
264
+ Example:
265
+ app = create_app()
266
+ # Use with uvicorn: uvicorn.run(app)
267
+
268
+ Args:
269
+ config_path: Optional path to configuration file
270
+ enable_docs: Enable documentation endpoint
271
+ custom_docs_template: Custom HTML template for docs
272
+ use_cache: Use build cache (production mode)
273
+ is_production: Run in production mode
274
+
275
+ Returns:
276
+ Configured FastAPI application instance
277
+ """
278
+ app_wrapper = FastAPIRouterApp(config_path, enable_docs, custom_docs_template,
279
+ use_cache, is_production)
280
+ return app_wrapper.build()