fastapi-voyager 0.15.6__py3-none-any.whl → 0.16.0a1__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 (29) hide show
  1. fastapi_voyager/__init__.py +2 -2
  2. fastapi_voyager/adapters/__init__.py +16 -0
  3. fastapi_voyager/adapters/base.py +44 -0
  4. fastapi_voyager/adapters/common.py +260 -0
  5. fastapi_voyager/adapters/django_ninja_adapter.py +299 -0
  6. fastapi_voyager/adapters/fastapi_adapter.py +165 -0
  7. fastapi_voyager/adapters/litestar_adapter.py +188 -0
  8. fastapi_voyager/er_diagram.py +15 -14
  9. fastapi_voyager/introspectors/__init__.py +34 -0
  10. fastapi_voyager/introspectors/base.py +81 -0
  11. fastapi_voyager/introspectors/detector.py +123 -0
  12. fastapi_voyager/introspectors/django_ninja.py +114 -0
  13. fastapi_voyager/introspectors/fastapi.py +83 -0
  14. fastapi_voyager/introspectors/litestar.py +166 -0
  15. fastapi_voyager/pydantic_resolve_util.py +4 -2
  16. fastapi_voyager/render.py +2 -2
  17. fastapi_voyager/render_style.py +0 -1
  18. fastapi_voyager/server.py +174 -295
  19. fastapi_voyager/type_helper.py +2 -2
  20. fastapi_voyager/version.py +1 -1
  21. fastapi_voyager/voyager.py +75 -47
  22. fastapi_voyager/web/index.html +11 -14
  23. fastapi_voyager/web/store.js +2 -0
  24. fastapi_voyager/web/vue-main.js +4 -0
  25. {fastapi_voyager-0.15.6.dist-info → fastapi_voyager-0.16.0a1.dist-info}/METADATA +133 -7
  26. {fastapi_voyager-0.15.6.dist-info → fastapi_voyager-0.16.0a1.dist-info}/RECORD +29 -17
  27. {fastapi_voyager-0.15.6.dist-info → fastapi_voyager-0.16.0a1.dist-info}/WHEEL +0 -0
  28. {fastapi_voyager-0.15.6.dist-info → fastapi_voyager-0.16.0a1.dist-info}/entry_points.txt +0 -0
  29. {fastapi_voyager-0.15.6.dist-info → fastapi_voyager-0.16.0a1.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,5 @@
1
1
 
2
2
  import pydantic_resolve.constant as const
3
- from fastapi import FastAPI, routing
4
3
  from pydantic import BaseModel
5
4
 
6
5
  from fastapi_voyager.filter import (
@@ -8,6 +7,7 @@ from fastapi_voyager.filter import (
8
7
  filter_subgraph_by_module_prefix,
9
8
  filter_subgraph_from_tag_to_schema_by_module_prefix,
10
9
  )
10
+ from fastapi_voyager.introspectors import AppIntrospector, RouteInfo
11
11
  from fastapi_voyager.render import Renderer
12
12
  from fastapi_voyager.type import PK, CoreData, FieldType, Link, LinkType, Route, SchemaNode, Tag
13
13
  from fastapi_voyager.type_helper import (
@@ -57,99 +57,127 @@ class Voyager:
57
57
  self.hide_primitive_route = hide_primitive_route
58
58
  self.show_module = show_module
59
59
  self.show_pydantic_resolve_meta = show_pydantic_resolve_meta
60
-
61
60
 
62
- def _get_available_route(self, app: FastAPI):
63
- for route in app.routes:
64
- if isinstance(route, routing.APIRoute):
65
- yield route
61
+ def _get_introspector(self, app) -> AppIntrospector:
62
+ """
63
+ Get the appropriate introspector for the given app.
64
+
65
+ Automatically detects the framework type and returns the matching introspector.
66
66
 
67
+ Args:
68
+ app: A web application instance or AppIntrospector
67
69
 
68
- def analysis(self, app: FastAPI):
70
+ Returns:
71
+ An AppIntrospector instance
72
+
73
+ Raises:
74
+ TypeError: If the app type is not supported
69
75
  """
76
+ from fastapi_voyager.introspectors import get_introspector
77
+
78
+ return get_introspector(app)
79
+
80
+ def analysis(self, app):
81
+ """
82
+ Analyze routes and schemas from a web application.
83
+
84
+ This method automatically detects the framework type and uses the appropriate
85
+ introspector. Supported frameworks:
86
+ - FastAPI (built-in)
87
+ - Any framework with a custom AppIntrospector implementation
88
+
89
+ Args:
90
+ app: A web application instance (FastAPI, Django Ninja API, etc.)
91
+ or an AppIntrospector instance for custom frameworks.
92
+
70
93
  1. get routes which return pydantic schema
71
94
  1.1 collect tags and routes, add links tag-> route
72
95
  1.2 collect response_model and links route -> response_model
73
96
 
74
97
  2. iterate schemas, construct the schema/model nodes and their links
75
98
  """
99
+ introspector = self._get_introspector(app)
76
100
  schemas: list[type[BaseModel]] = []
77
101
 
78
102
  # First, group all routes by tag
79
- routes_by_tag: dict[str, list] = {}
80
- for route in self._get_available_route(app):
81
- tags = getattr(route, 'tags', None)
82
-
103
+ routes_by_tag: dict[str, list[RouteInfo]] = {}
104
+ for route_info in introspector.get_routes():
83
105
  # using multiple tags is harmful, it's not recommended and will not be supported
84
- route_tag = tags[0] if tags else '__default__'
85
- routes_by_tag.setdefault(route_tag, []).append(route)
106
+ route_tag = route_info.tags[0] if route_info.tags else '__default__'
107
+ routes_by_tag.setdefault(route_tag, []).append(route_info)
86
108
 
87
109
  # Then filter by include_tags if provided
88
110
  if self.include_tags:
89
- filtered_routes_by_tag = {tag: routes for tag, routes in routes_by_tag.items()
90
- if tag in self.include_tags}
111
+ filtered_routes_by_tag = {
112
+ tag: routes
113
+ for tag, routes in routes_by_tag.items()
114
+ if tag in self.include_tags
115
+ }
91
116
  else:
92
117
  filtered_routes_by_tag = routes_by_tag
93
118
 
94
119
  # Process filtered routes
95
- for route_tag, routes in filtered_routes_by_tag.items():
96
-
120
+ for route_tag, route_infos in filtered_routes_by_tag.items():
97
121
  tag_id = f'tag__{route_tag}'
98
122
  tag_obj = Tag(id=tag_id, name=route_tag, routes=[])
99
123
  self.tags.append(tag_obj)
100
124
 
101
- for route in routes:
102
- # add route and create links
103
- route_id = full_class_name(route.endpoint)
104
- route_name = route.endpoint.__name__
105
- route_module = route.endpoint.__module__
106
-
125
+ for route_info in route_infos:
107
126
  # filter by route_name (route.id) if provided
108
- if self.route_name is not None and route_id != self.route_name:
127
+ if self.route_name is not None and route_info.id != self.route_name:
109
128
  continue
110
129
 
111
- is_primitive_response = is_non_pydantic_type(route.response_model)
130
+ is_primitive_response = is_non_pydantic_type(route_info.response_model)
112
131
  # filter primitive route if needed
113
132
  if self.hide_primitive_route and is_primitive_response:
114
133
  continue
115
134
 
116
- self.links.append(Link(
117
- source=tag_id,
118
- source_origin=tag_id,
119
- target=route_id,
120
- target_origin=route_id,
121
- type='tag_route'
122
- ))
135
+ self.links.append(
136
+ Link(
137
+ source=tag_id,
138
+ source_origin=tag_id,
139
+ target=route_info.id,
140
+ target_origin=route_info.id,
141
+ type='tag_route',
142
+ )
143
+ )
144
+
145
+ # Get unique_id from extra data if available
146
+ unique_id = route_info.operation_id
147
+ if route_info.extra and 'unique_id' in route_info.extra:
148
+ unique_id = unique_id or route_info.extra['unique_id']
123
149
 
124
150
  route_obj = Route(
125
- id=route_id,
126
- name=route_name,
127
- module=route_module,
128
- unique_id=route.operation_id or route.unique_id,
129
- response_schema=get_type_name(route.response_model),
130
- is_primitive=is_primitive_response
151
+ id=route_info.id,
152
+ name=route_info.name,
153
+ module=route_info.module,
154
+ unique_id=unique_id,
155
+ response_schema=get_type_name(route_info.response_model),
156
+ is_primitive=is_primitive_response,
131
157
  )
132
158
  self.routes.append(route_obj)
133
159
  tag_obj.routes.append(route_obj)
134
160
 
135
161
  # add response_models and create links from route -> response_model
136
- for schema in get_core_types(route.response_model):
162
+ for schema in get_core_types(route_info.response_model):
137
163
  if schema and issubclass(schema, BaseModel):
138
164
  is_primitive_response = False
139
165
  target_name = full_class_name(schema)
140
- self.links.append(Link(
141
- source=route_id,
142
- source_origin=route_id,
143
- target=self.generate_node_head(target_name),
144
- target_origin=target_name,
145
- type='route_to_schema'
146
- ))
166
+ self.links.append(
167
+ Link(
168
+ source=route_info.id,
169
+ source_origin=route_info.id,
170
+ target=self.generate_node_head(target_name),
171
+ target_origin=target_name,
172
+ type='route_to_schema',
173
+ )
174
+ )
147
175
 
148
176
  schemas.append(schema)
149
177
 
150
178
  for s in schemas:
151
179
  self.analysis_schemas(s)
152
-
180
+
153
181
  self.nodes = list(self.node_set.values())
154
182
 
155
183
 
@@ -4,32 +4,29 @@
4
4
  <meta name="theme-color" content="#ffffff" />
5
5
  <link
6
6
  rel="stylesheet"
7
- href="fastapi-voyager-static/graphviz.svg.css<!-- VERSION_PLACEHOLDER -->"
8
- />
9
- <link
10
- rel="stylesheet"
11
- href="fastapi-voyager-static/quasar.min.css<!-- VERSION_PLACEHOLDER -->"
7
+ href="<!-- STATIC_PATH -->/graphviz.svg.css<!-- VERSION_PLACEHOLDER -->"
12
8
  />
9
+ <link rel="stylesheet" href="<!-- STATIC_PATH -->/quasar.min.css<!-- VERSION_PLACEHOLDER -->" />
13
10
  <!-- App Icons / Favicons -->
14
11
  <link
15
12
  rel="apple-touch-icon"
16
13
  sizes="180x180"
17
- href="fastapi-voyager-static/icon/apple-touch-icon.png"
14
+ href="<!-- STATIC_PATH -->/icon/apple-touch-icon.png"
18
15
  />
19
16
  <link
20
17
  rel="icon"
21
18
  type="image/png"
22
19
  sizes="32x32"
23
- href="fastapi-voyager-static/icon/favicon-32x32.png"
20
+ href="<!-- STATIC_PATH -->/icon/favicon-32x32.png"
24
21
  />
25
22
  <link
26
23
  rel="icon"
27
24
  type="image/png"
28
25
  sizes="16x16"
29
- href="fastapi-voyager-static/icon/favicon-16x16.png"
26
+ href="<!-- STATIC_PATH -->/icon/favicon-16x16.png"
30
27
  />
31
- <link rel="icon" href="fastapi-voyager-static/icon/favicon.ico" sizes="any" />
32
- <link rel="manifest" href="fastapi-voyager-static/icon/site.webmanifest" />
28
+ <link rel="icon" href="<!-- STATIC_PATH -->/icon/favicon.ico" sizes="any" />
29
+ <link rel="manifest" href="<!-- STATIC_PATH -->/icon/site.webmanifest" />
33
30
  <link
34
31
  href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
35
32
  rel="stylesheet"
@@ -191,7 +188,7 @@
191
188
  style="font-size: 18px; font-weight: bold; display: flex; align-items: baseline"
192
189
  >
193
190
  <q-icon class="q-mr-sm" name="satellite_alt"></q-icon>
194
- <span> FastAPI Voyager </span>
191
+ <span> {{ store.state.framework_name }} Voyager </span>
195
192
  <span
196
193
  v-if="store.state.version"
197
194
  style="font-size: 12px; margin-left: 8px; font-weight: normal"
@@ -580,7 +577,7 @@
580
577
  </q-dialog>
581
578
  </div>
582
579
  <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
583
- <script src="fastapi-voyager-static/quasar.min.js<!-- VERSION_PLACEHOLDER -->"></script>
580
+ <script src="<!-- STATIC_PATH -->/quasar.min.js<!-- VERSION_PLACEHOLDER -->"></script>
584
581
  <script
585
582
  src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"
586
583
  integrity="sha512-egJ/Y+22P9NQ9aIyVCh0VCOsfydyn8eNmqBy+y2CnJG+fpRIxXMS6jbWP8tVKp0jp+NO5n8WtMUAnNnGoJKi4w=="
@@ -602,7 +599,7 @@
602
599
  ></script>
603
600
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"></script>
604
601
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-color/2.1.2/jquery.color.min.js"></script>
605
- <script src="fastapi-voyager-static/graphviz.svg.js<!-- VERSION_PLACEHOLDER -->"></script>
602
+ <script src="<!-- STATIC_PATH -->/graphviz.svg.js<!-- VERSION_PLACEHOLDER -->"></script>
606
603
  <!-- highlight.js minimal ES module load (python only) -->
607
604
  <link
608
605
  rel="stylesheet"
@@ -626,7 +623,7 @@
626
623
  </script>
627
624
  <script
628
625
  type="module"
629
- src="fastapi-voyager-static/vue-main.js<!-- VERSION_PLACEHOLDER -->"
626
+ src="<!-- STATIC_PATH -->/vue-main.js<!-- VERSION_PLACEHOLDER -->"
630
627
  ></script>
631
628
 
632
629
  <!-- GA_SNIPPET -->
@@ -2,6 +2,7 @@ const { reactive } = window.Vue
2
2
 
3
3
  const state = reactive({
4
4
  version: "",
5
+ framework_name: "",
5
6
  config: {
6
7
  initial_page_policy: "first",
7
8
  has_er_diagram: false,
@@ -305,6 +306,7 @@ const actions = {
305
306
  state.swagger.url = data.swagger_url || null
306
307
  state.config.has_er_diagram = data.has_er_diagram || false
307
308
  state.config.enable_pydantic_resolve_meta = data.enable_pydantic_resolve_meta || false
309
+ state.framework_name = data.framework_name || "API"
308
310
 
309
311
  this.rebuildSchemaOptions()
310
312
 
@@ -291,6 +291,10 @@ const app = createApp({
291
291
  onMounted(async () => {
292
292
  document.body.classList.remove("app-loading")
293
293
  await loadInitial()
294
+ // Update document title after framework_name is loaded
295
+ if (store.state.framework_name) {
296
+ document.title = `${store.state.framework_name} Voyager`
297
+ }
294
298
  // Reveal app content only after initial JS/data is ready
295
299
  })
296
300
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-voyager
3
- Version: 0.15.6
3
+ Version: 0.16.0a1
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
@@ -18,11 +18,15 @@ Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Programming Language :: Python :: 3.13
19
19
  Classifier: Programming Language :: Python :: 3.14
20
20
  Requires-Python: >=3.10
21
- Requires-Dist: fastapi>=0.110
22
21
  Requires-Dist: jinja2>=3.0.0
23
22
  Requires-Dist: pydantic-resolve>=2.4.3
24
23
  Provides-Extra: dev
24
+ Requires-Dist: django-ninja; extra == 'dev'
25
+ Requires-Dist: fastapi>=0.110; extra == 'dev'
26
+ Requires-Dist: httpx; extra == 'dev'
27
+ Requires-Dist: litestar; extra == 'dev'
25
28
  Requires-Dist: pytest; extra == 'dev'
29
+ Requires-Dist: pytest-asyncio; extra == 'dev'
26
30
  Requires-Dist: ruff; extra == 'dev'
27
31
  Requires-Dist: uvicorn; extra == 'dev'
28
32
  Description-Content-Type: text/markdown
@@ -34,10 +38,12 @@ Description-Content-Type: text/markdown
34
38
 
35
39
  # FastAPI Voyager
36
40
 
37
- Visualize your FastAPI endpoints and explore them interactively.
41
+ Visualize your API endpoints and explore them interactively.
38
42
 
39
43
  Its vision is to make code easier to read and understand, serving as an ideal documentation tool.
40
44
 
45
+ **Now supports multiple frameworks:** FastAPI, Django Ninja, and Litestar.
46
+
41
47
  > This repo is still in early stage, it supports Pydantic v2 only.
42
48
 
43
49
  - **Live Demo**: https://www.newsyeah.fun/voyager/
@@ -49,6 +55,7 @@ Its vision is to make code easier to read and understand, serving as an ideal do
49
55
 
50
56
  - [Quick Start](#quick-start)
51
57
  - [Installation](#installation)
58
+ - [Supported Frameworks](#supported-frameworks)
52
59
  - [Features](#features)
53
60
  - [Command Line Usage](#command-line-usage)
54
61
  - [About pydantic-resolve](#about-pydantic-resolve)
@@ -58,7 +65,7 @@ Its vision is to make code easier to read and understand, serving as an ideal do
58
65
 
59
66
  ## Quick Start
60
67
 
61
- With simple configuration, fastapi-voyager can be embedded into FastAPI:
68
+ With simple configuration, fastapi-voyager can be embedded into your web application:
62
69
 
63
70
  ```python
64
71
  from fastapi import FastAPI
@@ -66,6 +73,8 @@ from fastapi_voyager import create_voyager
66
73
 
67
74
  app = FastAPI()
68
75
 
76
+ # ... define your routes ...
77
+
69
78
  app.mount('/voyager',
70
79
  create_voyager(
71
80
  app,
@@ -74,12 +83,14 @@ app.mount('/voyager',
74
83
  swagger_url="/docs",
75
84
  ga_id="G-XXXXXXXXVL",
76
85
  initial_page_policy='first',
77
- online_repo_url='https://github.com/allmonday/composition-oriented-development-pattern/blob/master',
86
+ online_repo_url='https://github.com/your-org/your-repo/blob/master',
78
87
  enable_pydantic_resolve_meta=True))
79
88
  ```
80
89
 
81
90
  Visit `http://localhost:8000/voyager` to explore your API visually.
82
91
 
92
+ For framework-specific examples (Django Ninja, Litestar), see [Supported Frameworks](#supported-frameworks).
93
+
83
94
  [View full example](https://github.com/allmonday/composition-oriented-development-pattern/blob/master/src/main.py#L48)
84
95
 
85
96
  ## Installation
@@ -110,9 +121,106 @@ voyager -m path.to.your.app.module --server --app api
110
121
 
111
122
  > **Note**: [Sub-Application mounts](https://fastapi.tiangolo.com/advanced/sub-applications/) are not supported yet, but you can specify the name of the FastAPI application with `--app`. Only a single application (default: `app`) can be selected.
112
123
 
124
+ ## Supported Frameworks
125
+
126
+ fastapi-voyager automatically detects your framework and provides the appropriate integration. Currently supported frameworks:
127
+
128
+ ### FastAPI
129
+
130
+ ```python
131
+ from fastapi import FastAPI
132
+ from fastapi_voyager import create_voyager
133
+
134
+ app = FastAPI()
135
+
136
+ @app.get("/hello")
137
+ def hello():
138
+ return {"message": "Hello World"}
139
+
140
+ # Mount voyager
141
+ app.mount("/voyager", create_voyager(app))
142
+ ```
143
+
144
+ Start with:
145
+ ```bash
146
+ uvicorn your_app:app --reload
147
+ # Visit http://localhost:8000/voyager
148
+ ```
149
+
150
+ ### Django Ninja
151
+
152
+ ```python
153
+ import os
154
+ import django
155
+ from django.core.asgi import get_asgi_application
156
+ from ninja import NinjaAPI
157
+ from fastapi_voyager import create_voyager
158
+
159
+ # Configure Django
160
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.settings")
161
+ django.setup()
162
+
163
+ # Create Django Ninja API
164
+ api = NinjaAPI()
165
+
166
+ @api.get("/hello")
167
+ def hello(request):
168
+ return {"message": "Hello World"}
169
+
170
+ # Create voyager ASGI app
171
+ voyager_app = create_voyager(api)
172
+
173
+ # Create ASGI application that routes between Django and voyager
174
+ async def application(scope, receive, send):
175
+ if scope["type"] == "http" and scope["path"].startswith("/voyager"):
176
+ await voyager_app(scope, receive, send)
177
+ else:
178
+ django_app = get_asgi_application()
179
+ await django_app(scope, receive, send)
180
+ ```
181
+
182
+ Start with:
183
+ ```bash
184
+ uvicorn your_app:application --reload
185
+ # Visit http://localhost:8000/voyager
186
+ ```
187
+
188
+ ### Litestar
189
+
190
+ ```python
191
+ from litestar import Litestar, get
192
+ from fastapi_voyager import create_voyager
193
+
194
+ # Create Litestar app
195
+ app = Litestar()
196
+
197
+ @get("/hello")
198
+ def hello() -> dict:
199
+ return {"message": "Hello World"}
200
+
201
+ # Create voyager app (returns a Litestar app)
202
+ voyager_app = create_voyager(app)
203
+
204
+ # Create ASGI application that routes between main app and voyager
205
+ async def asgi_app(scope, receive, send):
206
+ if scope["type"] == "http" and scope["path"].startswith("/voyager"):
207
+ # Remove /voyager prefix for voyager app
208
+ new_scope = dict(scope)
209
+ new_scope["path"] = scope["path"][8:] or "/"
210
+ await voyager_app(new_scope, receive, send)
211
+ else:
212
+ await app(scope, receive, send)
213
+ ```
214
+
215
+ Start with:
216
+ ```bash
217
+ uvicorn your_app:asgi_app --reload
218
+ # Visit http://localhost:8000/voyager
219
+ ```
220
+
113
221
  ## Features
114
222
 
115
- fastapi-voyager is designed for scenarios using FastAPI as internal API integration endpoints. It helps visualize dependencies and serves as an architecture tool to identify implementation issues such as wrong relationships, overfetching, and more.
223
+ fastapi-voyager is designed for scenarios using web frameworks with Pydantic models (FastAPI, Django Ninja, Litestar). It helps visualize dependencies and serves as an architecture tool to identify implementation issues such as wrong relationships, overfetching, and more.
116
224
 
117
225
  **Best Practice**: When building view models following the ER model pattern, fastapi-voyager can fully realize its potential - quickly identifying which APIs use specific entities and vice versa.
118
226
 
@@ -258,6 +366,21 @@ uv pip install ".[dev]"
258
366
  uvicorn tests.programatic:app --reload
259
367
  ```
260
368
 
369
+ ### Test Different Frameworks
370
+
371
+ You can test the framework-specific examples:
372
+
373
+ ```bash
374
+ # FastAPI example
375
+ uvicorn tests.fastapi.embedding:app --reload
376
+
377
+ # Django Ninja example
378
+ uvicorn tests.django_ninja.embedding:app --reload
379
+
380
+ # Litestar example
381
+ uvicorn tests.litestar.embedding:asgi_app --reload
382
+ ```
383
+
261
384
  Visit `http://localhost:8000/voyager` to see changes.
262
385
 
263
386
  ### Setup Git Hooks (Optional)
@@ -289,9 +412,12 @@ This will run Prettier automatically before each commit. See [`.githooks/README.
289
412
 
290
413
  ## Dependencies
291
414
 
292
- - [FastAPI](https://fastapi.tiangolo.com/)
293
415
  - [pydantic-resolve](https://github.com/allmonday/pydantic-resolve)
294
416
  - [Quasar Framework](https://quasar.dev/)
417
+ ### Dev dependencies
418
+ - [FastAPI](https://fastapi.tiangolo.com/)
419
+ - [Django Ninja](https://django-ninja.rest-framework.com/)
420
+ - [Litestar](https://litestar.dev/)
295
421
 
296
422
  ## Credits
297
423
 
@@ -1,16 +1,28 @@
1
- fastapi_voyager/__init__.py,sha256=kqwzThE1YhmQ_7jPKGlnWvqRGC-hFrRqq_lKhKaleYU,229
1
+ fastapi_voyager/__init__.py,sha256=1IdDy6JUMgQqQo33qUe2znX9YeI7S35pjVrbt0QLOzY,228
2
2
  fastapi_voyager/cli.py,sha256=td3yIIigEomhSdDO-Xkh-CgpEwCafwlwnpvxnT9QsBo,10488
3
- fastapi_voyager/er_diagram.py,sha256=AbaKbcNd3cgCaQBsE0aHzvljTiZza3bmRiGJI3BGhGo,7873
3
+ fastapi_voyager/er_diagram.py,sha256=4Ba5u-T7XmVmk9MltVMe-m-18mUAHMTybTdE-zNZLrU,7860
4
4
  fastapi_voyager/filter.py,sha256=AN_HIu8-DtKisIq5mFt7CnqRHtxKewedNGyyaI82hSY,11529
5
5
  fastapi_voyager/module.py,sha256=h9YR3BpS-CAcJW9WCdVkF4opqwY32w9T67g9GfdLytk,3425
6
- fastapi_voyager/pydantic_resolve_util.py,sha256=r4Rq7BtBcFOMV7O2Ab9TwLyRNL1yNDiQlGUVybf-sXs,3524
7
- fastapi_voyager/render.py,sha256=5tTuvvCCUwFCq3WJGT1rfTSW41mSDoVyJwMyQGrmhiQ,17271
8
- fastapi_voyager/render_style.py,sha256=mPOuChEl71-3agCbPwkMt2sFmax2AEKDI6dK90eFPRc,2552
9
- fastapi_voyager/server.py,sha256=E0gGU7D1pBvnV7gFLBUvnkwtiBFbU1PbxEXHHSIA1oA,9115
6
+ fastapi_voyager/pydantic_resolve_util.py,sha256=0UfAp6Yi6FNpsI1bUu89hRVWFy6keBu1KtcZl-6NYso,3526
7
+ fastapi_voyager/render.py,sha256=A1jFDraQFOfnFHguYlsvBbGIDJ527VQH0jZ-xgTjqIk,17270
8
+ fastapi_voyager/render_style.py,sha256=1y3aRhBSJSWU-JuSgjn9il_xFEqjv6mJCoUzImLQT6M,2525
9
+ fastapi_voyager/server.py,sha256=sgUUscbt736VNB6CN2J_6rJ6fpWO4vJFW7oP7FmAjvA,6739
10
10
  fastapi_voyager/type.py,sha256=zluWvh5vpnjXJ9aAmyNJTSmXZPjAHCvgRT5oQRAjHrg,2104
11
- fastapi_voyager/type_helper.py,sha256=FmfrZAI3Z4uDdh3sH_kH7UGoY6yNVPapneSN86qY_wo,10209
12
- fastapi_voyager/version.py,sha256=ILB2INUiq4EGupYfMT2L0gsR_3dHm9fPDuoUnU5BSf0,49
13
- fastapi_voyager/voyager.py,sha256=4vonmL-xt54C5San-DRBq4mjoV8Q96eoWRy68MJ1IJw,14169
11
+ fastapi_voyager/type_helper.py,sha256=5HYUHdghTISZ44NvVsrMWlRGD5C9-xrGeNKuLYDMA6s,10209
12
+ fastapi_voyager/version.py,sha256=0KZ1gUzWpAnbQTYDMdcLc-qEsyVlYlG265SEa7S4Ij4,56
13
+ fastapi_voyager/voyager.py,sha256=S0cCMLFv_wPfEMVdp4cYqbc-Y207SjCTSmsYdqzIDHg,15307
14
+ fastapi_voyager/adapters/__init__.py,sha256=a95rBvV4QVcX_yAzjuJQKOW-EbJ79R--YjUJ3BGkC3k,517
15
+ fastapi_voyager/adapters/base.py,sha256=m-E74LlNgYCpj-gqfYsKl2mzWW5iFiaDTjiBri_5cfo,1283
16
+ fastapi_voyager/adapters/common.py,sha256=DXVLsjLn65U3RR7YyKL_ELV74mnINWmZ4hQ6zISdV0E,9684
17
+ fastapi_voyager/adapters/django_ninja_adapter.py,sha256=tl1rMcotAhOwBxT8poG8rTXm1v3wn_cpaoda79NEFxE,11424
18
+ fastapi_voyager/adapters/fastapi_adapter.py,sha256=-VvCXdMRsV_zZzEkplOGK8HjQ9ICoTyapG3ZluQ1Nvk,5870
19
+ fastapi_voyager/adapters/litestar_adapter.py,sha256=-ILD8jIb82_JKV87p4IfV9IXvhUJ6RSic6i_iHapo5w,6812
20
+ fastapi_voyager/introspectors/__init__.py,sha256=HbmoUyM-BSwd4Rg2ptd9u-qvZSD3UykKyHYVoRg03OM,917
21
+ fastapi_voyager/introspectors/base.py,sha256=hMfka9gVXr-E8MA1rKSSmYk0OppqgiFPWavfgAkPmQI,2131
22
+ fastapi_voyager/introspectors/detector.py,sha256=rmlpQARJMrFXPty6OUdjmFRTtBYErGDH4l7Tivnu_FQ,3910
23
+ fastapi_voyager/introspectors/django_ninja.py,sha256=Ytneh_kpsakTo_Njv1e4nvqfErjT1PrYelLZ-8xX5Gg,4052
24
+ fastapi_voyager/introspectors/fastapi.py,sha256=SyWGKAH8cM3CENY-Uu3YY6e8kFM5BE-jEBBZLoIF--A,2696
25
+ fastapi_voyager/introspectors/litestar.py,sha256=QXnaT0-hCa_0sByKJoUWuu0vIzRpCCKLokCBDTtv_s4,6100
14
26
  fastapi_voyager/templates/dot/cluster.j2,sha256=I2z9KkfCzmAtqXe0gXBnxnOfBXUSpdlATs3uf-O8_B8,307
15
27
  fastapi_voyager/templates/dot/cluster_container.j2,sha256=2tH1mOJvPoVKE_aHVMR3t06TfH_dYa9OeH6DBqSHt_A,204
16
28
  fastapi_voyager/templates/dot/digraph.j2,sha256=wZuiO-vvZ-AJ1FcMQG4BLevUyxk6yA-yEpUa3Us05mE,435
@@ -27,11 +39,11 @@ fastapi_voyager/templates/html/schema_table.j2,sha256=rzphiGk1il7uv4Gr2p_HLPHqyL
27
39
  fastapi_voyager/web/graph-ui.js,sha256=9b2auyGWEpUcF65YV231GNojQ9Uk6FsT1SlRR3lSYnc,7664
28
40
  fastapi_voyager/web/graphviz.svg.css,sha256=K218ov_mdSe3ga4KwhiBB92ynVvm5zaAk9_D9a3d8hE,1546
29
41
  fastapi_voyager/web/graphviz.svg.js,sha256=VokgCghvP4zm3SFiFVPIikdW6XzjkZJXQkBbCrEitug,19885
30
- fastapi_voyager/web/index.html,sha256=wM9vJ_UfHR8p98F6SEMCKKjJcBEl0EyosWuPqVZYXvA,23496
42
+ fastapi_voyager/web/index.html,sha256=4HGVavdd15u_BA7BwC-RJEeKal6hcYbiQaLcoOANQHI,23485
31
43
  fastapi_voyager/web/quasar.min.css,sha256=F5jQe7X2XT54VlvAaa2V3GsBFdVD-vxDZeaPLf6U9CU,203145
32
44
  fastapi_voyager/web/quasar.min.js,sha256=h0ftyPMW_CRiyzeVfQqiup0vrVt4_QWojpqmpnpn07E,502974
33
- fastapi_voyager/web/store.js,sha256=vwiqeLw7DfTOUDu9oN7b6nSBw8KG6W-5Dc-voQ1leL8,15113
34
- fastapi_voyager/web/vue-main.js,sha256=4lJi6ADrcaOzjXcQePkp7CyiCkAnvhnO-nkF3E6G3s4,10650
45
+ fastapi_voyager/web/store.js,sha256=CKQz5tZtv6W70TDVqeQiOt2gUXzD0WIc0ufCa0dB8sU,15193
46
+ fastapi_voyager/web/vue-main.js,sha256=MedNrfgy2KJCFiyv8sczC8d8M2yytZDX58PQGvjUYdM,10825
35
47
  fastapi_voyager/web/component/demo.js,sha256=sAklFGhKGmMy9-ofgOw2oPIidAoIOgHu6yvV51L_MAA,350
36
48
  fastapi_voyager/web/component/render-graph.js,sha256=9wnO70n3eyPKTpa744idgs5PSwgvzbfv4InZ68eEOKs,2454
37
49
  fastapi_voyager/web/component/route-code-display.js,sha256=a823nBz3EEjutW2pfi73rcF3hodCBmgYNmuZi94sXE4,3615
@@ -43,8 +55,8 @@ fastapi_voyager/web/icon/favicon-16x16.png,sha256=JC07jEzfIYxBIoQn_FHXvyHuxESdhW
43
55
  fastapi_voyager/web/icon/favicon-32x32.png,sha256=C7v1h58cfWOsiLp9yOIZtlx-dLasBcq3NqpHVGRmpt4,1859
44
56
  fastapi_voyager/web/icon/favicon.ico,sha256=tZolYIXkkBcFiYl1A8ksaXN2VjGamzcSdes838dLvNc,15406
45
57
  fastapi_voyager/web/icon/site.webmanifest,sha256=GRozZ5suTykYcPMap1QhjrAB8PLW0mbT_phhzw_utvQ,316
46
- fastapi_voyager-0.15.6.dist-info/METADATA,sha256=D-09okYHB5uaatoDc5SqmOVr_jTbw18o4_76pmxO4_g,9870
47
- fastapi_voyager-0.15.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
48
- fastapi_voyager-0.15.6.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
49
- fastapi_voyager-0.15.6.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
50
- fastapi_voyager-0.15.6.dist-info/RECORD,,
58
+ fastapi_voyager-0.16.0a1.dist-info/METADATA,sha256=pGOq7n96lV1BKAXvCKPXUU8BvXN89HzgAMI90dmnH_Y,12943
59
+ fastapi_voyager-0.16.0a1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
60
+ fastapi_voyager-0.16.0a1.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
61
+ fastapi_voyager-0.16.0a1.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
62
+ fastapi_voyager-0.16.0a1.dist-info/RECORD,,