fastapi-voyager 0.8.3__tar.gz → 0.9.2__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_voyager-0.8.3 → fastapi_voyager-0.9.2}/PKG-INFO +85 -42
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/README.md +84 -41
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/__init__.py +4 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/cli.py +1 -1
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/server.py +89 -21
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/type.py +0 -4
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/version.py +1 -1
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/voyager.py +1 -7
- fastapi_voyager-0.9.2/src/fastapi_voyager/web/component/route-code-display.js +133 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/component/schema-code-display.js +53 -19
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/component/schema-field-filter.js +13 -10
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/index.html +1 -2
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/vue-main.js +38 -79
- fastapi_voyager-0.9.2/tests/programatic.py +4 -0
- fastapi_voyager-0.8.3/src/fastapi_voyager/web/component/route-code-display.js +0 -73
- fastapi_voyager-0.8.3/tests/programatic.py +0 -4
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/.gitignore +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/.python-version +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/LICENSE +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/pyproject.toml +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/filter.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/module.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/render.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/type_helper.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/component/render-graph.js +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/graph-ui.js +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/graphviz.svg.css +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/graphviz.svg.js +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/icon/android-chrome-192x192.png +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/icon/android-chrome-512x512.png +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/icon/apple-touch-icon.png +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/icon/favicon-16x16.png +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/icon/favicon-32x32.png +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/icon/favicon.ico +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/icon/site.webmanifest +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/quasar.min.css +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/src/fastapi_voyager/web/quasar.min.js +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/tests/__init__.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/tests/demo.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/tests/demo_anno.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/tests/service/__init__.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/tests/service/schema.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/tests/test_analysis.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/tests/test_filter.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/tests/test_generic.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/tests/test_import.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/tests/test_module.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/tests/test_type_helper.py +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/uv.lock +0 -0
- {fastapi_voyager-0.8.3 → fastapi_voyager-0.9.2}/voyager.jpg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-voyager
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.2
|
|
4
4
|
Summary: Visualize FastAPI application's routing tree and dependencies
|
|
5
5
|
Project-URL: Homepage, https://github.com/allmonday/fastapi-voyager
|
|
6
6
|
Project-URL: Source, https://github.com/allmonday/fastapi-voyager
|
|
@@ -28,13 +28,12 @@ Description-Content-Type: text/markdown
|
|
|
28
28
|
[](https://pypi.python.org/pypi/fastapi-voyager)
|
|
29
29
|

|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
> This repo is still in early stage, currently it supports pydantic v2 only, previous name: fastapi-router-viz
|
|
31
|
+
> This repo is still in early stage, it supports pydantic v2 only
|
|
34
32
|
|
|
35
|
-
Inspect your API interactively
|
|
33
|
+
Inspect your API interactively!
|
|
36
34
|
|
|
37
|
-
<
|
|
35
|
+
<p align="center"><img src="./voyager.jpg" alt="" /></p>
|
|
36
|
+
<p align="center"><a target="_blank" rel="" href="https://www.youtube.com/watch?v=PGlbQq1M-n8"><img src="http://img.youtube.com/vi/PGlbQq1M-n8/0.jpg" alt="" style="max-width: 100%;"></a></p>
|
|
38
37
|
|
|
39
38
|
## Installation
|
|
40
39
|
|
|
@@ -48,11 +47,6 @@ uv add fastapi-voyager
|
|
|
48
47
|
voyager -m path.to.your.app.module --server
|
|
49
48
|
```
|
|
50
49
|
|
|
51
|
-
## Dependencies
|
|
52
|
-
|
|
53
|
-
- FastAPI
|
|
54
|
-
- [pydantic-resolve](https://github.com/allmonday/pydantic-resolve)
|
|
55
|
-
|
|
56
50
|
|
|
57
51
|
## Feature
|
|
58
52
|
|
|
@@ -75,9 +69,9 @@ voyager -m tests.demo
|
|
|
75
69
|
```
|
|
76
70
|
|
|
77
71
|
### generate the graph
|
|
78
|
-
after initialization, pick tag, rotue
|
|
72
|
+
after initialization, pick tag, rotue to render graph
|
|
79
73
|
|
|
80
|
-
<img width="
|
|
74
|
+
<img width="1628" height="765" alt="image" src="https://github.com/user-attachments/assets/b4712f82-e754-453b-aa69-24c932b8f48f" />
|
|
81
75
|
|
|
82
76
|
### highlight
|
|
83
77
|
click a node to highlight it's upperstream and downstream nodes. figure out the related models of one page, or homw many pages are related with one model.
|
|
@@ -85,9 +79,9 @@ click a node to highlight it's upperstream and downstream nodes. figure out the
|
|
|
85
79
|
<img width="1485" height="616" alt="image" style="border: 1px solid #aaa" src="https://github.com/user-attachments/assets/70c4095f-86c7-45da-a6f0-fd41ac645813" />
|
|
86
80
|
|
|
87
81
|
### filter related nodes
|
|
88
|
-
`shift` click a node to check related node, pick a field to narrow the result.
|
|
82
|
+
`shift` click a node to check related node, pick a field to narrow the result, picked node is marked as red.
|
|
89
83
|
|
|
90
|
-
<img width="
|
|
84
|
+
<img width="1423" height="552" alt="image" src="https://github.com/user-attachments/assets/468a058d-afa1-4601-a7c5-c6aad6a8a557" />
|
|
91
85
|
|
|
92
86
|
### view source code
|
|
93
87
|
`alt` click a node to show source code or open file in vscode.
|
|
@@ -105,10 +99,10 @@ click a node to highlight it's upperstream and downstream nodes. figure out the
|
|
|
105
99
|
|
|
106
100
|
```python
|
|
107
101
|
from fastapi import FastAPI
|
|
108
|
-
from fastapi_voyager
|
|
102
|
+
from fastapi_voyager import create_voyager
|
|
109
103
|
from tests.demo import app
|
|
110
104
|
|
|
111
|
-
app.mount('/voyager',
|
|
105
|
+
app.mount('/voyager', create_voyager(
|
|
112
106
|
app,
|
|
113
107
|
module_color={"tests.service": "red"},
|
|
114
108
|
module_prefix="tests.service"))
|
|
@@ -164,7 +158,25 @@ or you can open router_viz.dot with vscode extension `graphviz interactive previ
|
|
|
164
158
|
|
|
165
159
|
## Plan before v1.0
|
|
166
160
|
|
|
167
|
-
|
|
161
|
+
|
|
162
|
+
### backlog
|
|
163
|
+
- [ ] user can generate nodes/edges manually and connect to generated ones
|
|
164
|
+
- [ ] add owner
|
|
165
|
+
- [ ] add extra info for schema
|
|
166
|
+
- [ ] fixed left/right bar show field information
|
|
167
|
+
- [ ] display standard ER diagram `hard`
|
|
168
|
+
- [ ] display potential invalid links
|
|
169
|
+
- [ ] support dataclass (pending)
|
|
170
|
+
|
|
171
|
+
### in analysis
|
|
172
|
+
- [ ] click field to highlight links
|
|
173
|
+
- [ ] animation effect for edges
|
|
174
|
+
- [ ] customrized right click panel
|
|
175
|
+
- [ ] show own dependencies
|
|
176
|
+
- [ ] clean up fe code
|
|
177
|
+
|
|
178
|
+
### plan:
|
|
179
|
+
#### <0.9:
|
|
168
180
|
- [x] group schemas by module hierarchy
|
|
169
181
|
- [x] module-based coloring via Analytics(module_color={...})
|
|
170
182
|
- [x] view in web browser
|
|
@@ -183,49 +195,80 @@ features:
|
|
|
183
195
|
- [x] add tooltips
|
|
184
196
|
- [x] route
|
|
185
197
|
- [x] group routes by module hierarchy
|
|
186
|
-
- [
|
|
187
|
-
- [
|
|
188
|
-
- [ ] click field to highlight links
|
|
189
|
-
- [ ] user can generate nodes/edges manually and connect to generated ones
|
|
190
|
-
- [ ] add owner
|
|
191
|
-
- [ ] add extra info for schema
|
|
192
|
-
- [ ] ui optimization
|
|
193
|
-
- [ ] fixed left/right bar show field information
|
|
194
|
-
- [x] fixed left bar show tag/ route
|
|
195
|
-
- [ ] display standard ER diagram `difference`
|
|
196
|
-
- [ ] display potential invalid links
|
|
197
|
-
- [ ] integration with pydantic-resolve
|
|
198
|
-
- [ ] show difference between resolve, post fields
|
|
199
|
-
- [x] strikethrough for excluded fields
|
|
200
|
-
- [ ] display loader as edges
|
|
198
|
+
- [x] add response_model in route
|
|
199
|
+
- [x] fixed left bar show tag/ route
|
|
201
200
|
- [x] export voyager core data into json (for better debugging)
|
|
202
201
|
- [x] add api to rebuild core data from json, and render it
|
|
203
202
|
- [x] fix Generic case `test_generic.py`
|
|
204
|
-
- [
|
|
205
|
-
- [ ] add http method for route
|
|
206
|
-
|
|
207
|
-
bugs & non feature:
|
|
203
|
+
- [x] show tips for routes not return pydantic type.
|
|
208
204
|
- [x] fix duplicated link from class and parent class, it also break clicking highlight
|
|
205
|
+
- [x] refactor: abstract render module
|
|
206
|
+
|
|
207
|
+
#### 0.9
|
|
208
|
+
- [x] refactor: server.py
|
|
209
|
+
- [x] rename create_app_with_fastapi -> create_voyager
|
|
210
|
+
- [x] add doc for parameters
|
|
211
|
+
- [x] improve initialization time cost
|
|
212
|
+
- [x] query route / schema info through realtime api
|
|
213
|
+
- [x] adjust fe
|
|
214
|
+
|
|
215
|
+
#### 0.10
|
|
216
|
+
- [ ] support opening route in swagger
|
|
217
|
+
- config docs path
|
|
218
|
+
- [ ] add http method for route
|
|
219
|
+
- [ ] enable/disable module cluster (may save space)
|
|
220
|
+
- [ ] logging information
|
|
209
221
|
- [ ] add tests
|
|
210
|
-
- [
|
|
211
|
-
|
|
222
|
+
- [ ] hide brief mode if not configured
|
|
223
|
+
- [ ] optimize static resource
|
|
224
|
+
- [ ] show route count in tag expansion item
|
|
225
|
+
- [ ] route list show have a max height to trigger scrollable
|
|
226
|
+
- [ ] fix layout issue when rendering huge graph
|
|
227
|
+
|
|
228
|
+
#### 0.11
|
|
229
|
+
- [ ] improve user experience
|
|
230
|
+
- double click to show detail
|
|
231
|
+
- improve search dialog
|
|
232
|
+
|
|
233
|
+
#### 0.12
|
|
234
|
+
- [ ] integration with pydantic-resolve
|
|
235
|
+
- [ ] show hint for resolve, post fields
|
|
236
|
+
- [ ] display loader as edges
|
|
237
|
+
|
|
212
238
|
|
|
213
239
|
## Using with pydantic-resolve
|
|
214
240
|
|
|
241
|
+
WIP: ...
|
|
242
|
+
|
|
215
243
|
pydantic-resolve's @ensure_subset decorator is helpful to pick fields from `source class` in safe.
|
|
216
244
|
|
|
217
|
-
TODO: ...
|
|
218
245
|
|
|
219
246
|
|
|
220
247
|
## Credits
|
|
221
248
|
|
|
222
|
-
- https://apis.guru/graphql-voyager/, for inspiration.
|
|
223
|
-
- https://github.com/tintinweb/vscode-interactive-graphviz, for web visualization.
|
|
249
|
+
- https://apis.guru/graphql-voyager/, thanks for inspiration.
|
|
250
|
+
- https://github.com/tintinweb/vscode-interactive-graphviz, thanks for web visualization.
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
## Dependencies
|
|
254
|
+
|
|
255
|
+
- FastAPI
|
|
256
|
+
- [pydantic-resolve](https://github.com/allmonday/pydantic-resolve)
|
|
257
|
+
- Quasar
|
|
224
258
|
|
|
225
259
|
|
|
226
260
|
## Changelog
|
|
227
261
|
|
|
262
|
+
- 0.9:
|
|
263
|
+
- 0.9.2:
|
|
264
|
+
- fix: missing fields in schema detail panel
|
|
265
|
+
- optimization: clean up fe codes.
|
|
266
|
+
- 0.9.1:
|
|
267
|
+
- api change: from `create_app_with_fastapi` to `create_voyager`, and expose as `from fastapi_voyager import create_voyager`
|
|
268
|
+
- optimization: lazy load vscode link and source code, speed up the initialization.
|
|
228
269
|
- 0.8:
|
|
270
|
+
- 0.8.3
|
|
271
|
+
- upgrade theme
|
|
229
272
|
- 0.8.2
|
|
230
273
|
- fix silly typo.
|
|
231
274
|
- 0.8.1
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
[](https://pypi.python.org/pypi/fastapi-voyager)
|
|
2
2
|

|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
> This repo is still in early stage, currently it supports pydantic v2 only, previous name: fastapi-router-viz
|
|
4
|
+
> This repo is still in early stage, it supports pydantic v2 only
|
|
7
5
|
|
|
8
|
-
Inspect your API interactively
|
|
6
|
+
Inspect your API interactively!
|
|
9
7
|
|
|
10
|
-
<
|
|
8
|
+
<p align="center"><img src="./voyager.jpg" alt="" /></p>
|
|
9
|
+
<p align="center"><a target="_blank" rel="" href="https://www.youtube.com/watch?v=PGlbQq1M-n8"><img src="http://img.youtube.com/vi/PGlbQq1M-n8/0.jpg" alt="" style="max-width: 100%;"></a></p>
|
|
11
10
|
|
|
12
11
|
## Installation
|
|
13
12
|
|
|
@@ -21,11 +20,6 @@ uv add fastapi-voyager
|
|
|
21
20
|
voyager -m path.to.your.app.module --server
|
|
22
21
|
```
|
|
23
22
|
|
|
24
|
-
## Dependencies
|
|
25
|
-
|
|
26
|
-
- FastAPI
|
|
27
|
-
- [pydantic-resolve](https://github.com/allmonday/pydantic-resolve)
|
|
28
|
-
|
|
29
23
|
|
|
30
24
|
## Feature
|
|
31
25
|
|
|
@@ -48,9 +42,9 @@ voyager -m tests.demo
|
|
|
48
42
|
```
|
|
49
43
|
|
|
50
44
|
### generate the graph
|
|
51
|
-
after initialization, pick tag, rotue
|
|
45
|
+
after initialization, pick tag, rotue to render graph
|
|
52
46
|
|
|
53
|
-
<img width="
|
|
47
|
+
<img width="1628" height="765" alt="image" src="https://github.com/user-attachments/assets/b4712f82-e754-453b-aa69-24c932b8f48f" />
|
|
54
48
|
|
|
55
49
|
### highlight
|
|
56
50
|
click a node to highlight it's upperstream and downstream nodes. figure out the related models of one page, or homw many pages are related with one model.
|
|
@@ -58,9 +52,9 @@ click a node to highlight it's upperstream and downstream nodes. figure out the
|
|
|
58
52
|
<img width="1485" height="616" alt="image" style="border: 1px solid #aaa" src="https://github.com/user-attachments/assets/70c4095f-86c7-45da-a6f0-fd41ac645813" />
|
|
59
53
|
|
|
60
54
|
### filter related nodes
|
|
61
|
-
`shift` click a node to check related node, pick a field to narrow the result.
|
|
55
|
+
`shift` click a node to check related node, pick a field to narrow the result, picked node is marked as red.
|
|
62
56
|
|
|
63
|
-
<img width="
|
|
57
|
+
<img width="1423" height="552" alt="image" src="https://github.com/user-attachments/assets/468a058d-afa1-4601-a7c5-c6aad6a8a557" />
|
|
64
58
|
|
|
65
59
|
### view source code
|
|
66
60
|
`alt` click a node to show source code or open file in vscode.
|
|
@@ -78,10 +72,10 @@ click a node to highlight it's upperstream and downstream nodes. figure out the
|
|
|
78
72
|
|
|
79
73
|
```python
|
|
80
74
|
from fastapi import FastAPI
|
|
81
|
-
from fastapi_voyager
|
|
75
|
+
from fastapi_voyager import create_voyager
|
|
82
76
|
from tests.demo import app
|
|
83
77
|
|
|
84
|
-
app.mount('/voyager',
|
|
78
|
+
app.mount('/voyager', create_voyager(
|
|
85
79
|
app,
|
|
86
80
|
module_color={"tests.service": "red"},
|
|
87
81
|
module_prefix="tests.service"))
|
|
@@ -137,7 +131,25 @@ or you can open router_viz.dot with vscode extension `graphviz interactive previ
|
|
|
137
131
|
|
|
138
132
|
## Plan before v1.0
|
|
139
133
|
|
|
140
|
-
|
|
134
|
+
|
|
135
|
+
### backlog
|
|
136
|
+
- [ ] user can generate nodes/edges manually and connect to generated ones
|
|
137
|
+
- [ ] add owner
|
|
138
|
+
- [ ] add extra info for schema
|
|
139
|
+
- [ ] fixed left/right bar show field information
|
|
140
|
+
- [ ] display standard ER diagram `hard`
|
|
141
|
+
- [ ] display potential invalid links
|
|
142
|
+
- [ ] support dataclass (pending)
|
|
143
|
+
|
|
144
|
+
### in analysis
|
|
145
|
+
- [ ] click field to highlight links
|
|
146
|
+
- [ ] animation effect for edges
|
|
147
|
+
- [ ] customrized right click panel
|
|
148
|
+
- [ ] show own dependencies
|
|
149
|
+
- [ ] clean up fe code
|
|
150
|
+
|
|
151
|
+
### plan:
|
|
152
|
+
#### <0.9:
|
|
141
153
|
- [x] group schemas by module hierarchy
|
|
142
154
|
- [x] module-based coloring via Analytics(module_color={...})
|
|
143
155
|
- [x] view in web browser
|
|
@@ -156,49 +168,80 @@ features:
|
|
|
156
168
|
- [x] add tooltips
|
|
157
169
|
- [x] route
|
|
158
170
|
- [x] group routes by module hierarchy
|
|
159
|
-
- [
|
|
160
|
-
- [
|
|
161
|
-
- [ ] click field to highlight links
|
|
162
|
-
- [ ] user can generate nodes/edges manually and connect to generated ones
|
|
163
|
-
- [ ] add owner
|
|
164
|
-
- [ ] add extra info for schema
|
|
165
|
-
- [ ] ui optimization
|
|
166
|
-
- [ ] fixed left/right bar show field information
|
|
167
|
-
- [x] fixed left bar show tag/ route
|
|
168
|
-
- [ ] display standard ER diagram `difference`
|
|
169
|
-
- [ ] display potential invalid links
|
|
170
|
-
- [ ] integration with pydantic-resolve
|
|
171
|
-
- [ ] show difference between resolve, post fields
|
|
172
|
-
- [x] strikethrough for excluded fields
|
|
173
|
-
- [ ] display loader as edges
|
|
171
|
+
- [x] add response_model in route
|
|
172
|
+
- [x] fixed left bar show tag/ route
|
|
174
173
|
- [x] export voyager core data into json (for better debugging)
|
|
175
174
|
- [x] add api to rebuild core data from json, and render it
|
|
176
175
|
- [x] fix Generic case `test_generic.py`
|
|
177
|
-
- [
|
|
178
|
-
- [ ] add http method for route
|
|
179
|
-
|
|
180
|
-
bugs & non feature:
|
|
176
|
+
- [x] show tips for routes not return pydantic type.
|
|
181
177
|
- [x] fix duplicated link from class and parent class, it also break clicking highlight
|
|
178
|
+
- [x] refactor: abstract render module
|
|
179
|
+
|
|
180
|
+
#### 0.9
|
|
181
|
+
- [x] refactor: server.py
|
|
182
|
+
- [x] rename create_app_with_fastapi -> create_voyager
|
|
183
|
+
- [x] add doc for parameters
|
|
184
|
+
- [x] improve initialization time cost
|
|
185
|
+
- [x] query route / schema info through realtime api
|
|
186
|
+
- [x] adjust fe
|
|
187
|
+
|
|
188
|
+
#### 0.10
|
|
189
|
+
- [ ] support opening route in swagger
|
|
190
|
+
- config docs path
|
|
191
|
+
- [ ] add http method for route
|
|
192
|
+
- [ ] enable/disable module cluster (may save space)
|
|
193
|
+
- [ ] logging information
|
|
182
194
|
- [ ] add tests
|
|
183
|
-
- [
|
|
184
|
-
|
|
195
|
+
- [ ] hide brief mode if not configured
|
|
196
|
+
- [ ] optimize static resource
|
|
197
|
+
- [ ] show route count in tag expansion item
|
|
198
|
+
- [ ] route list show have a max height to trigger scrollable
|
|
199
|
+
- [ ] fix layout issue when rendering huge graph
|
|
200
|
+
|
|
201
|
+
#### 0.11
|
|
202
|
+
- [ ] improve user experience
|
|
203
|
+
- double click to show detail
|
|
204
|
+
- improve search dialog
|
|
205
|
+
|
|
206
|
+
#### 0.12
|
|
207
|
+
- [ ] integration with pydantic-resolve
|
|
208
|
+
- [ ] show hint for resolve, post fields
|
|
209
|
+
- [ ] display loader as edges
|
|
210
|
+
|
|
185
211
|
|
|
186
212
|
## Using with pydantic-resolve
|
|
187
213
|
|
|
214
|
+
WIP: ...
|
|
215
|
+
|
|
188
216
|
pydantic-resolve's @ensure_subset decorator is helpful to pick fields from `source class` in safe.
|
|
189
217
|
|
|
190
|
-
TODO: ...
|
|
191
218
|
|
|
192
219
|
|
|
193
220
|
## Credits
|
|
194
221
|
|
|
195
|
-
- https://apis.guru/graphql-voyager/, for inspiration.
|
|
196
|
-
- https://github.com/tintinweb/vscode-interactive-graphviz, for web visualization.
|
|
222
|
+
- https://apis.guru/graphql-voyager/, thanks for inspiration.
|
|
223
|
+
- https://github.com/tintinweb/vscode-interactive-graphviz, thanks for web visualization.
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
## Dependencies
|
|
227
|
+
|
|
228
|
+
- FastAPI
|
|
229
|
+
- [pydantic-resolve](https://github.com/allmonday/pydantic-resolve)
|
|
230
|
+
- Quasar
|
|
197
231
|
|
|
198
232
|
|
|
199
233
|
## Changelog
|
|
200
234
|
|
|
235
|
+
- 0.9:
|
|
236
|
+
- 0.9.2:
|
|
237
|
+
- fix: missing fields in schema detail panel
|
|
238
|
+
- optimization: clean up fe codes.
|
|
239
|
+
- 0.9.1:
|
|
240
|
+
- api change: from `create_app_with_fastapi` to `create_voyager`, and expose as `from fastapi_voyager import create_voyager`
|
|
241
|
+
- optimization: lazy load vscode link and source code, speed up the initialization.
|
|
201
242
|
- 0.8:
|
|
243
|
+
- 0.8.3
|
|
244
|
+
- upgrade theme
|
|
202
245
|
- 0.8.2
|
|
203
246
|
- fix silly typo.
|
|
204
247
|
- 0.8.1
|
|
@@ -281,7 +281,7 @@ Examples:
|
|
|
281
281
|
except ImportError:
|
|
282
282
|
print("Error: uvicorn is required to run the server. Install via 'pip install uvicorn' or 'uv add uvicorn'.")
|
|
283
283
|
sys.exit(1)
|
|
284
|
-
app_server = viz_server.
|
|
284
|
+
app_server = viz_server.create_voyager(
|
|
285
285
|
app,
|
|
286
286
|
module_color=module_color,
|
|
287
287
|
module_prefix=args.module_prefix,
|
|
@@ -6,23 +6,18 @@ from pydantic import BaseModel
|
|
|
6
6
|
from fastapi.responses import HTMLResponse, PlainTextResponse, JSONResponse
|
|
7
7
|
from fastapi.staticfiles import StaticFiles
|
|
8
8
|
from fastapi_voyager.voyager import Voyager
|
|
9
|
-
from fastapi_voyager.type import Tag, FieldInfo, CoreData
|
|
9
|
+
from fastapi_voyager.type import Tag, FieldInfo, CoreData, SchemaNode
|
|
10
10
|
from fastapi_voyager.render import Renderer
|
|
11
|
+
from fastapi_voyager.type_helper import get_source, get_vscode_link
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
WEB_DIR = Path(__file__).parent / "web"
|
|
14
15
|
WEB_DIR.mkdir(exist_ok=True)
|
|
15
16
|
|
|
16
|
-
class SchemaType(BaseModel):
|
|
17
|
-
name: str
|
|
18
|
-
fullname: str
|
|
19
|
-
source_code: str
|
|
20
|
-
vscode_link: str
|
|
21
|
-
fields: list[FieldInfo]
|
|
22
17
|
|
|
23
18
|
class OptionParam(BaseModel):
|
|
24
19
|
tags: list[Tag]
|
|
25
|
-
schemas: list[
|
|
20
|
+
schemas: list[SchemaNode]
|
|
26
21
|
dot: str
|
|
27
22
|
|
|
28
23
|
class Payload(BaseModel):
|
|
@@ -40,26 +35,22 @@ def create_route(
|
|
|
40
35
|
module_color: dict[str, str] | None = None,
|
|
41
36
|
module_prefix: Optional[str] = None,
|
|
42
37
|
):
|
|
38
|
+
"""
|
|
39
|
+
module_color: dict mapping module name to color string, e.g. {'models': 'lightblue'}
|
|
40
|
+
module_prefix: prefix string to define schemas show in brief mode
|
|
41
|
+
"""
|
|
43
42
|
router = APIRouter(tags=['fastapi-voyager'])
|
|
44
43
|
|
|
45
44
|
@router.get("/dot", response_model=OptionParam)
|
|
46
45
|
def get_dot() -> str:
|
|
47
|
-
voyager = Voyager(module_color=module_color
|
|
46
|
+
voyager = Voyager(module_color=module_color)
|
|
48
47
|
voyager.analysis(target_app)
|
|
49
48
|
dot = voyager.render_dot()
|
|
50
49
|
|
|
51
50
|
# include tags and their routes
|
|
52
51
|
tags = voyager.tags
|
|
53
52
|
|
|
54
|
-
schemas = [
|
|
55
|
-
SchemaType(
|
|
56
|
-
name=s.name,
|
|
57
|
-
fullname=s.id,
|
|
58
|
-
fields=s.fields,
|
|
59
|
-
source_code=s.source_code,
|
|
60
|
-
vscode_link=s.vscode_link
|
|
61
|
-
) for s in voyager.nodes
|
|
62
|
-
]
|
|
53
|
+
schemas = voyager.nodes[:]
|
|
63
54
|
schemas.sort(key=lambda s: s.name)
|
|
64
55
|
|
|
65
56
|
return OptionParam(tags=tags, schemas=schemas, dot=dot)
|
|
@@ -74,7 +65,6 @@ def create_route(
|
|
|
74
65
|
show_fields=payload.show_fields,
|
|
75
66
|
module_color=module_color,
|
|
76
67
|
route_name=payload.route_name,
|
|
77
|
-
load_meta=False,
|
|
78
68
|
hide_primitive_route=payload.hide_primitive_route,
|
|
79
69
|
)
|
|
80
70
|
voyager.analysis(target_app)
|
|
@@ -92,7 +82,6 @@ def create_route(
|
|
|
92
82
|
show_fields=payload.show_fields,
|
|
93
83
|
module_color=module_color,
|
|
94
84
|
route_name=payload.route_name,
|
|
95
|
-
load_meta=False,
|
|
96
85
|
)
|
|
97
86
|
voyager.analysis(target_app)
|
|
98
87
|
return voyager.dump_core_data()
|
|
@@ -117,11 +106,90 @@ def create_route(
|
|
|
117
106
|
</body>
|
|
118
107
|
</html>
|
|
119
108
|
"""
|
|
109
|
+
|
|
110
|
+
class SourcePayload(BaseModel):
|
|
111
|
+
schema_name: str
|
|
120
112
|
|
|
113
|
+
@router.post("/source")
|
|
114
|
+
def get_object_by_module_name(payload: SourcePayload):
|
|
115
|
+
"""
|
|
116
|
+
input: __module__ + __name__, eg: tests.demo.PageStories
|
|
117
|
+
output: source code of the object
|
|
118
|
+
"""
|
|
119
|
+
try:
|
|
120
|
+
components = payload.schema_name.split('.')
|
|
121
|
+
if len(components) < 2:
|
|
122
|
+
return JSONResponse(
|
|
123
|
+
status_code=400,
|
|
124
|
+
content={"error": "Invalid schema name format. Expected format: module.ClassName"}
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
module_name = '.'.join(components[:-1])
|
|
128
|
+
class_name = components[-1]
|
|
129
|
+
|
|
130
|
+
mod = __import__(module_name, fromlist=[class_name])
|
|
131
|
+
obj = getattr(mod, class_name)
|
|
132
|
+
source_code = get_source(obj)
|
|
133
|
+
|
|
134
|
+
return JSONResponse(content={"source_code": source_code})
|
|
135
|
+
except ImportError as e:
|
|
136
|
+
return JSONResponse(
|
|
137
|
+
status_code=404,
|
|
138
|
+
content={"error": f"Module not found: {e}"}
|
|
139
|
+
)
|
|
140
|
+
except AttributeError as e:
|
|
141
|
+
return JSONResponse(
|
|
142
|
+
status_code=404,
|
|
143
|
+
content={"error": f"Class not found: {e}"}
|
|
144
|
+
)
|
|
145
|
+
except Exception as e:
|
|
146
|
+
return JSONResponse(
|
|
147
|
+
status_code=500,
|
|
148
|
+
content={"error": f"Internal error: {str(e)}"}
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
@router.post("/vscode-link")
|
|
152
|
+
def get_vscode_link_by_module_name(payload: SourcePayload):
|
|
153
|
+
"""
|
|
154
|
+
input: __module__ + __name__, eg: tests.demo.PageStories
|
|
155
|
+
output: source path of the object
|
|
156
|
+
"""
|
|
157
|
+
try:
|
|
158
|
+
components = payload.schema_name.split('.')
|
|
159
|
+
if len(components) < 2:
|
|
160
|
+
return JSONResponse(
|
|
161
|
+
status_code=400,
|
|
162
|
+
content={"error": "Invalid schema name format. Expected format: module.ClassName"}
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
module_name = '.'.join(components[:-1])
|
|
166
|
+
class_name = components[-1]
|
|
167
|
+
|
|
168
|
+
mod = __import__(module_name, fromlist=[class_name])
|
|
169
|
+
obj = getattr(mod, class_name)
|
|
170
|
+
link = get_vscode_link(obj)
|
|
171
|
+
|
|
172
|
+
return JSONResponse(content={"link": link})
|
|
173
|
+
except ImportError as e:
|
|
174
|
+
return JSONResponse(
|
|
175
|
+
status_code=404,
|
|
176
|
+
content={"error": f"Module not found: {e}"}
|
|
177
|
+
)
|
|
178
|
+
except AttributeError as e:
|
|
179
|
+
return JSONResponse(
|
|
180
|
+
status_code=404,
|
|
181
|
+
content={"error": f"Class not found: {e}"}
|
|
182
|
+
)
|
|
183
|
+
except Exception as e:
|
|
184
|
+
return JSONResponse(
|
|
185
|
+
status_code=500,
|
|
186
|
+
content={"error": f"Internal error: {str(e)}"}
|
|
187
|
+
)
|
|
188
|
+
|
|
121
189
|
return router
|
|
122
190
|
|
|
123
191
|
|
|
124
|
-
def
|
|
192
|
+
def create_voyager(
|
|
125
193
|
target_app: FastAPI,
|
|
126
194
|
module_color: dict[str, str] | None = None,
|
|
127
195
|
gzip_minimum_size: int | None = 500,
|
|
@@ -22,8 +22,6 @@ class Tag(NodeBase):
|
|
|
22
22
|
@dataclass
|
|
23
23
|
class Route(NodeBase):
|
|
24
24
|
module: str
|
|
25
|
-
source_code: str = ''
|
|
26
|
-
vscode_link: str = '' # optional vscode deep link
|
|
27
25
|
response_schema: str = ''
|
|
28
26
|
is_primitive: bool = True
|
|
29
27
|
|
|
@@ -37,8 +35,6 @@ class ModuleRoute:
|
|
|
37
35
|
@dataclass
|
|
38
36
|
class SchemaNode(NodeBase):
|
|
39
37
|
module: str
|
|
40
|
-
source_code: str = '' # optional for tests / backward compatibility
|
|
41
|
-
vscode_link: str = '' # optional vscode deep link
|
|
42
38
|
fields: list[FieldInfo] = field(default_factory=list)
|
|
43
39
|
|
|
44
40
|
@dataclass
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__all__ = ["__version__"]
|
|
2
|
-
__version__ = "0.
|
|
2
|
+
__version__ = "0.9.2"
|
|
@@ -29,7 +29,6 @@ class Voyager:
|
|
|
29
29
|
module_color: dict[str, str] | None = None,
|
|
30
30
|
route_name: str | None = None,
|
|
31
31
|
hide_primitive_route: bool = False,
|
|
32
|
-
load_meta: bool = False
|
|
33
32
|
):
|
|
34
33
|
|
|
35
34
|
self.routes: list[Route] = []
|
|
@@ -50,7 +49,6 @@ class Voyager:
|
|
|
50
49
|
self.show_fields = show_fields if show_fields in ('single','object','all') else 'object'
|
|
51
50
|
self.module_color = module_color or {}
|
|
52
51
|
self.route_name = route_name
|
|
53
|
-
self.load_meta = load_meta
|
|
54
52
|
self.hide_primitive_route = hide_primitive_route
|
|
55
53
|
|
|
56
54
|
|
|
@@ -85,7 +83,7 @@ class Voyager:
|
|
|
85
83
|
self.tags.append(tag_obj)
|
|
86
84
|
|
|
87
85
|
# add route and create links
|
|
88
|
-
route_id =
|
|
86
|
+
route_id = full_class_name(route.endpoint)
|
|
89
87
|
route_name = route.endpoint.__name__
|
|
90
88
|
route_module = route.endpoint.__module__
|
|
91
89
|
|
|
@@ -110,8 +108,6 @@ class Voyager:
|
|
|
110
108
|
id=route_id,
|
|
111
109
|
name=route_name,
|
|
112
110
|
module=route_module,
|
|
113
|
-
vscode_link=get_vscode_link(route.endpoint) if self.load_meta else '',
|
|
114
|
-
source_code=inspect.getsource(route.endpoint) if self.load_meta else '',
|
|
115
111
|
response_schema=get_type_name(route.response_model),
|
|
116
112
|
is_primitive=is_primitive_response
|
|
117
113
|
)
|
|
@@ -154,8 +150,6 @@ class Voyager:
|
|
|
154
150
|
id=full_name,
|
|
155
151
|
module=schema.__module__,
|
|
156
152
|
name=schema.__name__,
|
|
157
|
-
source_code=get_source(schema) if self.load_meta else '',
|
|
158
|
-
vscode_link=get_vscode_link(schema) if self.load_meta else '',
|
|
159
153
|
fields=get_pydantic_fields(schema, bases_fields)
|
|
160
154
|
)
|
|
161
155
|
return full_name
|