fastapi-voyager 0.11.10__tar.gz → 0.12.1__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.
Files changed (54) hide show
  1. fastapi_voyager-0.12.1/PKG-INFO +183 -0
  2. fastapi_voyager-0.12.1/README.md +154 -0
  3. fastapi_voyager-0.12.1/docs/changelog.md +122 -0
  4. fastapi_voyager-0.12.1/docs/idea.md +22 -0
  5. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/cli.py +35 -47
  6. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/filter.py +0 -1
  7. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/render.py +64 -41
  8. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/server.py +3 -0
  9. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/type_helper.py +6 -4
  10. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/version.py +1 -1
  11. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/component/schema-code-display.js +1 -0
  12. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/graph-ui.js +3 -8
  13. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/index.html +5 -3
  14. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/vue-main.js +71 -0
  15. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/programatic.py +1 -1
  16. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/service/schema.py +3 -2
  17. fastapi_voyager-0.11.10/PKG-INFO +0 -336
  18. fastapi_voyager-0.11.10/README.md +0 -307
  19. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/.github/workflows/publish.yml +0 -0
  20. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/.gitignore +0 -0
  21. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/.python-version +0 -0
  22. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/LICENSE +0 -0
  23. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/pyproject.toml +0 -0
  24. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/release.md +0 -0
  25. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/__init__.py +0 -0
  26. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/module.py +0 -0
  27. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/type.py +0 -0
  28. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/voyager.py +0 -0
  29. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/component/render-graph.js +0 -0
  30. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/component/route-code-display.js +0 -0
  31. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/component/schema-field-filter.js +0 -0
  32. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/graphviz.svg.css +0 -0
  33. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/graphviz.svg.js +0 -0
  34. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/icon/android-chrome-192x192.png +0 -0
  35. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/icon/android-chrome-512x512.png +0 -0
  36. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/icon/apple-touch-icon.png +0 -0
  37. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/icon/favicon-16x16.png +0 -0
  38. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/icon/favicon-32x32.png +0 -0
  39. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/icon/favicon.ico +0 -0
  40. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/icon/site.webmanifest +0 -0
  41. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/quasar.min.css +0 -0
  42. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/src/fastapi_voyager/web/quasar.min.js +0 -0
  43. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/__init__.py +0 -0
  44. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/demo.py +0 -0
  45. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/demo_anno.py +0 -0
  46. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/service/__init__.py +0 -0
  47. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/test_analysis.py +0 -0
  48. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/test_filter.py +0 -0
  49. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/test_generic.py +0 -0
  50. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/test_import.py +0 -0
  51. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/test_module.py +0 -0
  52. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/tests/test_type_helper.py +0 -0
  53. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/uv.lock +0 -0
  54. {fastapi_voyager-0.11.10 → fastapi_voyager-0.12.1}/voyager.jpg +0 -0
@@ -0,0 +1,183 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastapi-voyager
3
+ Version: 0.12.1
4
+ Summary: Visualize FastAPI application's routing tree and dependencies
5
+ Project-URL: Homepage, https://github.com/allmonday/fastapi-voyager
6
+ Project-URL: Source, https://github.com/allmonday/fastapi-voyager
7
+ Author-email: Tangkikodo <allmonday@126.com>
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: fastapi,openapi,routing,visualization
11
+ Classifier: Framework :: FastAPI
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: fastapi>=0.110
23
+ Requires-Dist: pydantic-resolve>=1.13.2
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest; extra == 'dev'
26
+ Requires-Dist: ruff; extra == 'dev'
27
+ Requires-Dist: uvicorn; extra == 'dev'
28
+ Description-Content-Type: text/markdown
29
+
30
+ [![pypi](https://img.shields.io/pypi/v/fastapi-voyager.svg)](https://pypi.python.org/pypi/fastapi-voyager)
31
+ ![Python Versions](https://img.shields.io/pypi/pyversions/fastapi-voyager)
32
+ [![PyPI Downloads](https://static.pepy.tech/badge/fastapi-voyager/month)](https://pepy.tech/projects/fastapi-voyager)
33
+
34
+
35
+ > This repo is still in early stage, it supports pydantic v2 only
36
+
37
+ Visualize your FastAPI endpoints, and explore them interactively.
38
+
39
+ [visit online demo](https://www.newsyeah.fun/voyager/) of project: [composition oriented development pattern](https://github.com/allmonday/composition-oriented-development-pattern)
40
+
41
+ <img width="1600" height="986" alt="image" src="https://github.com/user-attachments/assets/8829cda0-f42d-4c84-be2f-b019bb5fe7e1" />
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ pip install fastapi-voyager
47
+ # or
48
+ uv add fastapi-voyager
49
+ ```
50
+
51
+ ```shell
52
+ voyager -m path.to.your.app.module --server
53
+ ```
54
+
55
+ > [Sub-Application mounts](https://fastapi.tiangolo.com/advanced/sub-applications/) are not supported yet, but you can specify the name of the FastAPI application used with `--app`. Only a single application (default: 'app') can be selected, but in a scenario where `api` is attached through `app.mount("/api", api)`, you can select `api` like this:
56
+
57
+ ```shell
58
+ voyager -m path.to.your.app.module --server --app api
59
+ ```
60
+
61
+ ## Mount into project
62
+
63
+ ```python
64
+ from fastapi import FastAPI
65
+ from fastapi_voyager import create_voyager
66
+ from tests.demo import app
67
+
68
+ app.mount('/voyager', create_voyager(
69
+ app,
70
+ module_color={"tests.service": "red"},
71
+ module_prefix="tests.service"),
72
+ swagger_url="/docs")
73
+ ```
74
+
75
+ ## Features
76
+
77
+ For scenarios of using FastAPI as internal API integration endpoints, `fastapi-voyager` helps to visualize the dependencies.
78
+
79
+ It is also an architecture inspection tool that can identify issues in data relationships during design phase before turly implemtatioin.
80
+
81
+ If the process of building the view model follows the ER model, the full potential of fastapi-voyager can be realized. It allows for quick identification of APIs that use entities, as well as which entities are used by a specific API
82
+
83
+ ### highlight nodes and links
84
+ 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
+
86
+
87
+ <img width="1100" height="700" alt="image" src="https://github.com/user-attachments/assets/3e0369ea-5fa4-469a-82c1-ed57d407e53d" />
88
+
89
+ ### focus on nodes
90
+
91
+ Double click a node, and then toggle focus to hide irrelevant nodes.
92
+
93
+ <img width="1061" height="937" alt="image" src="https://github.com/user-attachments/assets/79709b02-7571-43fc-abc9-17a287a97515" />
94
+
95
+ ### view source code
96
+
97
+ double click a node or route to show source code or open file in vscode.
98
+
99
+ <img width="1297" height="940" alt="image" src="https://github.com/user-attachments/assets/c8bb2e7d-b727-42a6-8c9e-64dce297d2d8" />
100
+
101
+ <img width="1132" height="824" alt="image" src="https://github.com/user-attachments/assets/b706e879-e4fc-48dd-ace1-99bf97e3ed6a" />
102
+
103
+
104
+ ## Command Line Usage
105
+
106
+ ### open in browser
107
+
108
+ ```bash
109
+ # open in browser
110
+ voyager -m tests.demo --server
111
+
112
+ voyager -m tests.demo --server --port=8002
113
+ ```
114
+
115
+ ### generate the dot file
116
+ ```bash
117
+ # generate .dot file
118
+ voyager -m tests.demo
119
+
120
+ voyager -m tests.demo --app my_app
121
+
122
+ voyager -m tests.demo --schema Task
123
+
124
+ voyager -m tests.demo --show_fields all
125
+
126
+ voyager -m tests.demo --module_color=tests.demo:red --module_color=tests.service:tomato
127
+
128
+ voyager -m tests.demo -o my_visualization.dot
129
+
130
+ voyager --version
131
+
132
+ voyager --help
133
+ ```
134
+
135
+ ## About pydantic-resolve
136
+
137
+ pydantic-resolve's `@ensure_subset` decorator helps safely pick fields from the 'source class' while **indicating the reference** from the current class to the base class.
138
+
139
+ pydantic-resolve is a lightweight tool designed to build complex, nested data in a simple, declarative way. In version 2.0.0alpha, it will introduce an important feature: ER Diagram, and fastapi-voyager will support this feature, allowing for a clearer understanding of the business relationships between the data.
140
+
141
+ Developers can use fastapi-voyager without needing to know anything about pydantic-resolve, but I still highly recommend everyone to give it a try.
142
+
143
+ ## Dependencies
144
+
145
+ - FastAPI
146
+ - [pydantic-resolve](https://github.com/allmonday/pydantic-resolve)
147
+ - Quasar
148
+
149
+
150
+ ## Credits
151
+
152
+ - https://apis.guru/graphql-voyager/, thanks for inspiration.
153
+ - https://github.com/tintinweb/vscode-interactive-graphviz, thanks for web visualization.
154
+
155
+
156
+ ## How to develop & contribute?
157
+
158
+ fork, clone.
159
+
160
+ install uv.
161
+
162
+ ```shell
163
+ uv venv
164
+ source .venv/bin/activate
165
+ uv pip install ".[dev]"
166
+ uvicorn tests.programatic:app --reload
167
+ ```
168
+
169
+ open `localhost:8000/voyager`
170
+
171
+
172
+ frontend:
173
+ - `src/web/vue-main.js`: main js
174
+
175
+ backend:
176
+ - `voyager.py`: main entry
177
+ - `render.py`: generate dot file
178
+ - `server.py`: serve mode
179
+
180
+
181
+ ## Plan & Raodmap
182
+ - [ideas](./docs/idea.md)
183
+ - [changelog & roadmap](./docs/changelog.md)
@@ -0,0 +1,154 @@
1
+ [![pypi](https://img.shields.io/pypi/v/fastapi-voyager.svg)](https://pypi.python.org/pypi/fastapi-voyager)
2
+ ![Python Versions](https://img.shields.io/pypi/pyversions/fastapi-voyager)
3
+ [![PyPI Downloads](https://static.pepy.tech/badge/fastapi-voyager/month)](https://pepy.tech/projects/fastapi-voyager)
4
+
5
+
6
+ > This repo is still in early stage, it supports pydantic v2 only
7
+
8
+ Visualize your FastAPI endpoints, and explore them interactively.
9
+
10
+ [visit online demo](https://www.newsyeah.fun/voyager/) of project: [composition oriented development pattern](https://github.com/allmonday/composition-oriented-development-pattern)
11
+
12
+ <img width="1600" height="986" alt="image" src="https://github.com/user-attachments/assets/8829cda0-f42d-4c84-be2f-b019bb5fe7e1" />
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pip install fastapi-voyager
18
+ # or
19
+ uv add fastapi-voyager
20
+ ```
21
+
22
+ ```shell
23
+ voyager -m path.to.your.app.module --server
24
+ ```
25
+
26
+ > [Sub-Application mounts](https://fastapi.tiangolo.com/advanced/sub-applications/) are not supported yet, but you can specify the name of the FastAPI application used with `--app`. Only a single application (default: 'app') can be selected, but in a scenario where `api` is attached through `app.mount("/api", api)`, you can select `api` like this:
27
+
28
+ ```shell
29
+ voyager -m path.to.your.app.module --server --app api
30
+ ```
31
+
32
+ ## Mount into project
33
+
34
+ ```python
35
+ from fastapi import FastAPI
36
+ from fastapi_voyager import create_voyager
37
+ from tests.demo import app
38
+
39
+ app.mount('/voyager', create_voyager(
40
+ app,
41
+ module_color={"tests.service": "red"},
42
+ module_prefix="tests.service"),
43
+ swagger_url="/docs")
44
+ ```
45
+
46
+ ## Features
47
+
48
+ For scenarios of using FastAPI as internal API integration endpoints, `fastapi-voyager` helps to visualize the dependencies.
49
+
50
+ It is also an architecture inspection tool that can identify issues in data relationships during design phase before turly implemtatioin.
51
+
52
+ If the process of building the view model follows the ER model, the full potential of fastapi-voyager can be realized. It allows for quick identification of APIs that use entities, as well as which entities are used by a specific API
53
+
54
+ ### highlight nodes and links
55
+ 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.
56
+
57
+
58
+ <img width="1100" height="700" alt="image" src="https://github.com/user-attachments/assets/3e0369ea-5fa4-469a-82c1-ed57d407e53d" />
59
+
60
+ ### focus on nodes
61
+
62
+ Double click a node, and then toggle focus to hide irrelevant nodes.
63
+
64
+ <img width="1061" height="937" alt="image" src="https://github.com/user-attachments/assets/79709b02-7571-43fc-abc9-17a287a97515" />
65
+
66
+ ### view source code
67
+
68
+ double click a node or route to show source code or open file in vscode.
69
+
70
+ <img width="1297" height="940" alt="image" src="https://github.com/user-attachments/assets/c8bb2e7d-b727-42a6-8c9e-64dce297d2d8" />
71
+
72
+ <img width="1132" height="824" alt="image" src="https://github.com/user-attachments/assets/b706e879-e4fc-48dd-ace1-99bf97e3ed6a" />
73
+
74
+
75
+ ## Command Line Usage
76
+
77
+ ### open in browser
78
+
79
+ ```bash
80
+ # open in browser
81
+ voyager -m tests.demo --server
82
+
83
+ voyager -m tests.demo --server --port=8002
84
+ ```
85
+
86
+ ### generate the dot file
87
+ ```bash
88
+ # generate .dot file
89
+ voyager -m tests.demo
90
+
91
+ voyager -m tests.demo --app my_app
92
+
93
+ voyager -m tests.demo --schema Task
94
+
95
+ voyager -m tests.demo --show_fields all
96
+
97
+ voyager -m tests.demo --module_color=tests.demo:red --module_color=tests.service:tomato
98
+
99
+ voyager -m tests.demo -o my_visualization.dot
100
+
101
+ voyager --version
102
+
103
+ voyager --help
104
+ ```
105
+
106
+ ## About pydantic-resolve
107
+
108
+ pydantic-resolve's `@ensure_subset` decorator helps safely pick fields from the 'source class' while **indicating the reference** from the current class to the base class.
109
+
110
+ pydantic-resolve is a lightweight tool designed to build complex, nested data in a simple, declarative way. In version 2.0.0alpha, it will introduce an important feature: ER Diagram, and fastapi-voyager will support this feature, allowing for a clearer understanding of the business relationships between the data.
111
+
112
+ Developers can use fastapi-voyager without needing to know anything about pydantic-resolve, but I still highly recommend everyone to give it a try.
113
+
114
+ ## Dependencies
115
+
116
+ - FastAPI
117
+ - [pydantic-resolve](https://github.com/allmonday/pydantic-resolve)
118
+ - Quasar
119
+
120
+
121
+ ## Credits
122
+
123
+ - https://apis.guru/graphql-voyager/, thanks for inspiration.
124
+ - https://github.com/tintinweb/vscode-interactive-graphviz, thanks for web visualization.
125
+
126
+
127
+ ## How to develop & contribute?
128
+
129
+ fork, clone.
130
+
131
+ install uv.
132
+
133
+ ```shell
134
+ uv venv
135
+ source .venv/bin/activate
136
+ uv pip install ".[dev]"
137
+ uvicorn tests.programatic:app --reload
138
+ ```
139
+
140
+ open `localhost:8000/voyager`
141
+
142
+
143
+ frontend:
144
+ - `src/web/vue-main.js`: main js
145
+
146
+ backend:
147
+ - `voyager.py`: main entry
148
+ - `render.py`: generate dot file
149
+ - `server.py`: serve mode
150
+
151
+
152
+ ## Plan & Raodmap
153
+ - [ideas](./docs/idea.md)
154
+ - [changelog & roadmap](./docs/changelog.md)
@@ -0,0 +1,122 @@
1
+ # Changelog & roadmap
2
+
3
+ ## <0.9:
4
+ - [x] group schemas by module hierarchy
5
+ - [x] module-based coloring via Analytics(module_color={...})
6
+ - [x] view in web browser
7
+ - [x] config params
8
+ - [x] make a explorer dashboard, provide list of routes, schemas, to make it easy to switch and search
9
+ - [x] support programmatic usage
10
+ - [x] better schema /router node appearance
11
+ - [x] hide fields duplicated with parent's (show `parent fields` instead)
12
+ - [x] refactor the frontend to vue, and tweak the build process
13
+ - [x] find dependency based on picked schema and it's field.
14
+ - [x] optimize static resource (cdn -> local)
15
+ - [x] add configuration for highlight (optional)
16
+ - [x] alt+click to show field details
17
+ - [x] display source code of routes (including response_model)
18
+ - [x] handle excluded field
19
+ - [x] add tooltips
20
+ - [x] route
21
+ - [x] group routes by module hierarchy
22
+ - [x] add response_model in route
23
+ - [x] fixed left bar show tag/ route
24
+ - [x] export voyager core data into json (for better debugging)
25
+ - [x] add api to rebuild core data from json, and render it
26
+ - [x] fix Generic case `test_generic.py`
27
+ - [x] show tips for routes not return pydantic type.
28
+ - [x] fix duplicated link from class and parent class, it also break clicking highlight
29
+ - [x] refactor: abstract render module
30
+
31
+ ## 0.9
32
+ - [x] refactor: server.py
33
+ - [x] rename create_app_with_fastapi -> create_voyager
34
+ - [x] add doc for parameters
35
+ - [x] improve initialization time cost
36
+ - [x] query route / schema info through realtime api
37
+ - [x] adjust fe
38
+ - 0.9.3
39
+ - [x] adjust layout
40
+ - [x] show field detail in right panel
41
+ - [x] show route info in bottom
42
+ - 0.9.4
43
+ - [x] close schema sidebar when switch tag/route
44
+ - [x] schema detail panel show fields by default
45
+ - [x] adjust schema panel's height
46
+ - [x] show from base information in subset case
47
+ - 0.9.5
48
+ - [x] route list should have a max height
49
+
50
+ ## 0.10
51
+ - 0.10.1
52
+ - [x] refactor voyager.py tag -> route structure
53
+ - [x] fix missing route (tag has only one route which return primitive value)
54
+ - [x] make right panel resizable by dragging
55
+ - [x] allow closing tag expansion item
56
+ - [x] hide brief mode if not configured
57
+ - [x] add focus button to only show related nodes under current route/tag graph in dialog
58
+ - 0.10.2
59
+ - [x] fix graph height
60
+ - [x] show version in title
61
+ - 0.10.3
62
+ - [x] fix focus in brief-mode
63
+ - [x] ui: adjust focus position
64
+ - [x] refactor naming
65
+ - [x] fix layout issue when rendering huge graph
66
+ - 0.10.4
67
+ - [x] fix: when focus is on, should ensure changes from other params not broken.
68
+ - 0.10.5
69
+ - [x] double click to show details, and highlight as tomato
70
+
71
+
72
+ ## 0.11
73
+ - 0.11.1
74
+ - [x] support opening route in swagger
75
+ - [x] config docs path
76
+ - [x] provide option to hide routes in brief mode (auto hide in full graph mode)
77
+ - 0.11.2
78
+ - [x] enable/disable module cluster (to save space)
79
+ - 0.11.3
80
+ - [x] support online repo url
81
+ - 0.11.4
82
+ - [x] add loading for field detail panel
83
+ - 0.11.5
84
+ - [x] optimize open in swagger link
85
+ - [x] change jquery cdn
86
+ - 0.11.6
87
+ - [x] flag of loading full graph in first render or not
88
+ - [x] optimize loading static resource
89
+ - 0.11.7
90
+ - [x] fix swagger link
91
+ - 0.11.8
92
+ - [x] fix swagger link in another way
93
+ - 0.11.9
94
+ - [x] replace issubclass with safe_issubclass to prevent exception.
95
+ - 0.11.10
96
+ - [x] fix bug during updating forward refs
97
+ - 0.11.11
98
+ - [x] replace print with logging and add `--log-level` in cli, by default info
99
+ - [x] fill node title color with module color
100
+ - [x] optimize cluster render logic
101
+
102
+ ## 0.12
103
+ - 0.12.1
104
+ - [x] sort tag / route names in left panel
105
+ - [x] display schema name on top of detail panel
106
+ - [x] optimize dbclick style
107
+ - [x] persist the tag/ route in url
108
+ - 0.12.2
109
+ - [ ] search tag/ route
110
+ - [ ] refactor render.py
111
+ - [ ] reorg: move variable into reactive in vue-main.js
112
+
113
+ ## 0.13
114
+ - 0.12.0
115
+ - [ ] integration with pydantic-resolve
116
+ - [ ] show hint for resolve, post fields
117
+ - [ ] display loader as edges
118
+ - [ ] add tests
119
+
120
+ ## 0.13
121
+ todo
122
+
@@ -0,0 +1,22 @@
1
+ # Idea
2
+
3
+ ## backlog
4
+ - [ ] user can generate nodes/edges manually and connect to generated ones
5
+ - [ ] eg: add owner
6
+ - [ ] add extra info for schema
7
+ - [ ] optimize static resource (allow manually config url)
8
+ - [ ] improve search dialog
9
+ - [ ] add route/tag list
10
+ - [ ] type alias should not be kept as node instead of compiling to original type
11
+ - [ ] how to correctly handle the generic type ?
12
+ - [ ] support Google analysis config
13
+ - [ ] sort field name in nodes (only table inside right panel), pending
14
+ - [ ] set max limit for fields in nodes
15
+
16
+ ## in analysis
17
+ - [ ] upgrade network algorithm (optional)
18
+ - [ ] click field to highlight links
19
+ - [ ] animation effect for edges
20
+ - [ ] display standard ER diagram spec. `hard but important`
21
+ - [ ] display potential invalid links
22
+ - [ ] highlight relationship belongs to ER diagram
@@ -1,15 +1,18 @@
1
1
  """Command line interface for fastapi-voyager."""
2
2
  import argparse
3
- import sys
4
- import importlib.util
5
3
  import importlib
4
+ import importlib.util
5
+ import logging
6
6
  import os
7
+ import sys
7
8
  from typing import Optional
8
9
 
9
10
  from fastapi import FastAPI
10
- from fastapi_voyager.voyager import Voyager
11
- from fastapi_voyager.version import __version__
12
11
  from fastapi_voyager import server as viz_server
12
+ from fastapi_voyager.version import __version__
13
+ from fastapi_voyager.voyager import Voyager
14
+
15
+ logger = logging.getLogger(__name__)
13
16
 
14
17
 
15
18
  def load_fastapi_app_from_file(module_path: str, app_name: str = "app") -> Optional[FastAPI]:
@@ -22,7 +25,7 @@ def load_fastapi_app_from_file(module_path: str, app_name: str = "app") -> Optio
22
25
  # Load the module
23
26
  spec = importlib.util.spec_from_file_location("app_module", module_path)
24
27
  if spec is None or spec.loader is None:
25
- print(f"Error: Could not load module from {module_path}")
28
+ logger.error(f"Could not load module from {module_path}")
26
29
  return None
27
30
 
28
31
  module = importlib.util.module_from_spec(spec)
@@ -34,15 +37,13 @@ def load_fastapi_app_from_file(module_path: str, app_name: str = "app") -> Optio
34
37
  app = getattr(module, app_name)
35
38
  if isinstance(app, FastAPI):
36
39
  return app
37
- else:
38
- print(f"Error: '{app_name}' is not a FastAPI instance")
39
- return None
40
- else:
41
- print(f"Error: No attribute '{app_name}' found in the module")
40
+ logger.error(f"'{app_name}' is not a FastAPI instance")
42
41
  return None
42
+ logger.error(f"No attribute '{app_name}' found in the module")
43
+ return None
43
44
 
44
45
  except Exception as e:
45
- print(f"Error loading FastAPI app: {e}")
46
+ logger.error(f"Error loading FastAPI app: {e}")
46
47
  return None
47
48
 
48
49
 
@@ -66,22 +67,20 @@ def load_fastapi_app_from_module(module_name: str, app_name: str = "app") -> Opt
66
67
  app = getattr(module, app_name)
67
68
  if isinstance(app, FastAPI):
68
69
  return app
69
- else:
70
- print(f"Error: '{app_name}' is not a FastAPI instance")
71
- return None
72
- else:
73
- print(f"Error: No attribute '{app_name}' found in module '{module_name}'")
70
+ logger.error(f"'{app_name}' is not a FastAPI instance")
74
71
  return None
72
+ logger.error(f"No attribute '{app_name}' found in module '{module_name}'")
73
+ return None
75
74
  finally:
76
75
  # Cleanup: if we added the path, remove it
77
76
  if path_added and current_dir in sys.path:
78
77
  sys.path.remove(current_dir)
79
78
 
80
79
  except ImportError as e:
81
- print(f"Error: Could not import module '{module_name}': {e}")
80
+ logger.error(f"Could not import module '{module_name}': {e}")
82
81
  return None
83
82
  except Exception as e:
84
- print(f"Error loading FastAPI app from module '{module_name}': {e}")
83
+ logger.error(f"Error loading FastAPI app from module '{module_name}': {e}")
85
84
  return None
86
85
 
87
86
 
@@ -110,9 +109,9 @@ def generate_visualization(
110
109
  # Optionally write to file
111
110
  with open(output_file, 'w', encoding='utf-8') as f:
112
111
  f.write(dot_content)
113
- print(f"DOT file generated: {output_file}")
114
- print("To render the graph, use: dot -Tpng router_viz.dot -o router_viz.png")
115
- print("Or view online: https://dreampuf.github.io/GraphvizOnline/")
112
+ logger.info(f"DOT file generated: {output_file}")
113
+ logger.info("To render the graph, use: dot -Tpng router_viz.dot -o router_viz.png")
114
+ logger.info("Or view online: https://dreampuf.github.io/GraphvizOnline/")
116
115
 
117
116
 
118
117
  def main():
@@ -217,41 +216,30 @@ Examples:
217
216
  help="Filter by route id (format: <endpoint>_<path with _>)"
218
217
  )
219
218
  parser.add_argument(
220
- "--demo",
221
- action="store_true",
222
- help="Run built-in demo (equivalent to: --module tests.demo --server --module_color=tests.service:blue --module_color=tests.demo:tomato)"
219
+ "--log-level",
220
+ dest="log_level",
221
+ default="INFO",
222
+ help="Logging level: DEBUG, INFO, WARNING, ERROR, CRITICAL (default: INFO)"
223
223
  )
224
224
 
225
225
  args = parser.parse_args()
226
226
 
227
- # Handle demo mode: override module_name and defaults
228
- if args.demo:
229
- # Force module loading path
230
- args.module_name = "tests.demo"
231
- # Ensure server mode on
232
- args.server = True
233
- # Inject default module colors if absent / merge
234
- demo_defaults = ["tests.service:blue", "tests.demo:tomato"]
235
- existing = set(args.module_color or [])
236
- for d in demo_defaults:
237
- # only add if same key not already provided
238
- key = d.split(":", 1)[0]
239
- if not any(mc.startswith(key + ":") for mc in existing):
240
- args.module_color = (args.module_color or []) + [d]
241
-
242
227
  if args.module_prefix and not args.server:
243
228
  parser.error("--module_prefix can only be used together with --server")
244
229
 
245
- # Validate required target if not demo
246
- if not args.demo and not (args.module_name or args.module):
247
- parser.error("You must provide a module file, -m module name, or use --demo")
230
+ if not (args.module_name or args.module):
231
+ parser.error("You must provide a module file, -m module name")
232
+
233
+ # Configure logging based on --log-level
234
+ level_name = (args.log_level or "INFO").upper()
235
+ logging.basicConfig(level=level_name)
248
236
 
249
237
  # Load FastAPI app based on the input method (module_name takes precedence)
250
238
  if args.module_name:
251
239
  app = load_fastapi_app_from_module(args.module_name, args.app)
252
240
  else:
253
241
  if not os.path.exists(args.module):
254
- print(f"Error: File '{args.module}' not found")
242
+ logger.error(f"File '{args.module}' not found")
255
243
  sys.exit(1)
256
244
  app = load_fastapi_app_from_file(args.module, args.app)
257
245
 
@@ -279,15 +267,15 @@ Examples:
279
267
  try:
280
268
  import uvicorn
281
269
  except ImportError:
282
- print("Error: uvicorn is required to run the server. Install via 'pip install uvicorn' or 'uv add uvicorn'.")
270
+ logger.info("uvicorn is required to run the server. Install via 'pip install uvicorn' or 'uv add uvicorn'.")
283
271
  sys.exit(1)
284
272
  app_server = viz_server.create_voyager(
285
273
  app,
286
274
  module_color=module_color,
287
275
  module_prefix=args.module_prefix,
288
276
  )
289
- print(f"Starting preview server at http://{args.host}:{args.port} ... (Ctrl+C to stop)")
290
- uvicorn.run(app_server, host=args.host, port=args.port)
277
+ logger.info(f"Starting preview server at http://{args.host}:{args.port} ... (Ctrl+C to stop)")
278
+ uvicorn.run(app_server, host=args.host, port=args.port, log_level=level_name.lower())
291
279
  else:
292
280
  # Generate and write dot file locally
293
281
  generate_visualization(
@@ -300,7 +288,7 @@ Examples:
300
288
  route_name=args.route_name,
301
289
  )
302
290
  except Exception as e:
303
- print(f"Error generating visualization: {e}")
291
+ logger.info(f"Error generating visualization: {e}")
304
292
  sys.exit(1)
305
293
 
306
294
 
@@ -236,7 +236,6 @@ def filter_subgraph_from_tag_to_schema_by_module_prefix(
236
236
  seen_pairs: set[tuple[str, str]] = set()
237
237
 
238
238
  for link in tag_route_links:
239
- # print(link)
240
239
  tag_id = link.source_origin
241
240
  start_node_id = link.target_origin
242
241
  if tag_id is None or start_node_id is None: