fastapi-voyager 0.9.5__py3-none-any.whl → 0.10.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fastapi_voyager/render.py CHANGED
@@ -62,9 +62,8 @@ class Renderer:
62
62
  else:
63
63
  raise ValueError(f'Unknown link type: {link.type}')
64
64
 
65
- def render_module_schema_wrapper(self, mods: list[ModuleNode]) -> str:
65
+ def render_module_schema_content(self, mods: list[ModuleNode]) -> str:
66
66
  module_color_flag = set(self.module_color.keys())
67
- print(module_color_flag)
68
67
 
69
68
  def render_module_schema(mod: ModuleNode) -> str:
70
69
  color: Optional[str] = None
@@ -104,7 +103,7 @@ class Renderer:
104
103
  inner_nodes = [
105
104
  f'''
106
105
  "{r.id}" [
107
- label = " {r.name}: {r.response_schema} "
106
+ label = " {r.name} | {r.response_schema} "
108
107
  margin="0.5,0.1"
109
108
  shape = "record"
110
109
  ];''' for r in mod.routes
@@ -122,7 +121,7 @@ class Renderer:
122
121
  {child_str}
123
122
  }}'''
124
123
 
125
- def render_dot(self, tags: list[Tag], routes: list[Route], nodes: list[SchemaNode], links: list[Link]) -> str:
124
+ def render_dot(self, tags: list[Tag], routes: list[Route], nodes: list[SchemaNode], links: list[Link], spline_line=False) -> str:
126
125
  module_schemas = build_module_schema_tree(nodes)
127
126
  module_routes = build_module_route_tree(routes)
128
127
 
@@ -136,7 +135,7 @@ class Renderer:
136
135
  ])
137
136
 
138
137
 
139
- module_schemas_str = self.render_module_schema_wrapper(module_schemas)
138
+ module_schemas_str = self.render_module_schema_content(module_schemas)
140
139
  module_routes_str = '\n'.join(self.render_module_route(m) for m in module_routes)
141
140
  link_str = '\n'.join(self.render_link(link) for link in links)
142
141
 
@@ -144,6 +143,7 @@ class Renderer:
144
143
  digraph world {{
145
144
  pad="0.5"
146
145
  nodesep=0.8
146
+ {'splines=line' if spline_line else ''}
147
147
  fontname="Helvetica,Arial,sans-serif"
148
148
  node [fontname="Helvetica,Arial,sans-serif"]
149
149
  edge [
fastapi_voyager/server.py CHANGED
@@ -9,6 +9,7 @@ from fastapi_voyager.voyager import Voyager
9
9
  from fastapi_voyager.type import Tag, FieldInfo, CoreData, SchemaNode
10
10
  from fastapi_voyager.render import Renderer
11
11
  from fastapi_voyager.type_helper import get_source, get_vscode_link
12
+ from fastapi_voyager.version import __version__
12
13
 
13
14
 
14
15
  WEB_DIR = Path(__file__).parent / "web"
@@ -19,6 +20,8 @@ class OptionParam(BaseModel):
19
20
  tags: list[Tag]
20
21
  schemas: list[SchemaNode]
21
22
  dot: str
23
+ enable_brief_mode: bool
24
+ version: str
22
25
 
23
26
  class Payload(BaseModel):
24
27
  tags: Optional[list[str]] = None
@@ -53,11 +56,10 @@ def create_route(
53
56
  schemas = voyager.nodes[:]
54
57
  schemas.sort(key=lambda s: s.name)
55
58
 
56
- return OptionParam(tags=tags, schemas=schemas, dot=dot)
59
+ return OptionParam(tags=tags, schemas=schemas, dot=dot, enable_brief_mode=bool(module_prefix), version=__version__)
57
60
 
58
61
  @router.post("/dot", response_class=PlainTextResponse)
59
62
  def get_filtered_dot(payload: Payload) -> str:
60
- print(payload)
61
63
  voyager = Voyager(
62
64
  include_tags=payload.tags,
63
65
  schema=payload.schema_name,
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "0.9.5"
2
+ __version__ = "0.10.2"
@@ -1,4 +1,4 @@
1
- import inspect
1
+ from pydantic import BaseModel
2
2
  from fastapi import FastAPI, routing
3
3
  from fastapi_voyager.type_helper import (
4
4
  get_core_types,
@@ -54,9 +54,14 @@ class Voyager:
54
54
 
55
55
  def _get_available_route(self, app: FastAPI):
56
56
  for route in app.routes:
57
- if isinstance(route, routing.APIRoute) and route.response_model:
57
+ if isinstance(route, routing.APIRoute):
58
58
  yield route
59
59
 
60
+ def analysis_route(self, route: routing.APIRoute):
61
+ ...
62
+
63
+ def analysis_tags(self, tag: str):
64
+ ...
60
65
 
61
66
  def analysis(self, app: FastAPI):
62
67
  """
@@ -68,67 +73,76 @@ class Voyager:
68
73
  """
69
74
  schemas: list[type[BaseModel]] = []
70
75
 
76
+ # First, group all routes by tag
77
+ routes_by_tag: dict[str, list] = {}
71
78
  for route in self._get_available_route(app):
72
- # check tags
73
79
  tags = getattr(route, 'tags', None)
74
- route_tag = tags[0] if tags else '__default__'
75
- if self.include_tags and route_tag not in self.include_tags:
76
- continue
77
80
 
78
- # add tag if not exists
79
- tag_id = f'tag__{route_tag}'
80
- if tag_id not in self.tag_set:
81
- tag_obj = Tag(id=tag_id, name=route_tag, routes=[])
82
- self.tag_set[tag_id] = tag_obj
83
- self.tags.append(tag_obj)
84
-
85
- # add route and create links
86
- route_id = full_class_name(route.endpoint)
87
- route_name = route.endpoint.__name__
88
- route_module = route.endpoint.__module__
89
-
90
- # filter by route_name (route.id) if provided
91
- if self.route_name is not None and route_id != self.route_name:
92
- continue
81
+ # using multiple tags is harmful, it's not recommended and will not be supported
82
+ route_tag = tags[0] if tags else '__default__'
83
+ routes_by_tag.setdefault(route_tag, []).append(route)
93
84
 
94
- is_primitive_response = is_non_pydantic_type(route.response_model)
95
- # filter primitive route if needed
96
- if self.hide_primitive_route and is_primitive_response:
97
- continue
85
+ # Then filter by include_tags if provided
86
+ if self.include_tags:
87
+ filtered_routes_by_tag = {tag: routes for tag, routes in routes_by_tag.items()
88
+ if tag in self.include_tags}
89
+ else:
90
+ filtered_routes_by_tag = routes_by_tag
98
91
 
99
- self.links.append(Link(
100
- source=tag_id,
101
- source_origin=tag_id,
102
- target=route_id,
103
- target_origin=route_id,
104
- type='tag_route'
105
- ))
92
+ # Process filtered routes
93
+ for route_tag, routes in filtered_routes_by_tag.items():
106
94
 
107
- route_obj = Route(
108
- id=route_id,
109
- name=route_name,
110
- module=route_module,
111
- response_schema=get_type_name(route.response_model),
112
- is_primitive=is_primitive_response
113
- )
114
- self.routes.append(route_obj)
115
- # add route into current tag
116
- self.tag_set[tag_id].routes.append(route_obj)
117
-
118
- # add response_models and create links from route -> response_model
119
- for schema in get_core_types(route.response_model):
120
- if schema and issubclass(schema, BaseModel):
121
- is_primitive_response = False
122
- target_name = full_class_name(schema)
123
- self.links.append(Link(
124
- source=route_id,
125
- source_origin=route_id,
126
- target=self.generate_node_head(target_name),
127
- target_origin=target_name,
128
- type='route_to_schema'
129
- ))
130
-
131
- schemas.append(schema)
95
+ tag_id = f'tag__{route_tag}'
96
+ tag_obj = Tag(id=tag_id, name=route_tag, routes=[])
97
+ self.tags.append(tag_obj)
98
+
99
+ for route in routes:
100
+ # add route and create links
101
+ route_id = full_class_name(route.endpoint)
102
+ route_name = route.endpoint.__name__
103
+ route_module = route.endpoint.__module__
104
+
105
+ # filter by route_name (route.id) if provided
106
+ if self.route_name is not None and route_id != self.route_name:
107
+ continue
108
+
109
+ is_primitive_response = is_non_pydantic_type(route.response_model)
110
+ # filter primitive route if needed
111
+ if self.hide_primitive_route and is_primitive_response:
112
+ continue
113
+
114
+ self.links.append(Link(
115
+ source=tag_id,
116
+ source_origin=tag_id,
117
+ target=route_id,
118
+ target_origin=route_id,
119
+ type='tag_route'
120
+ ))
121
+
122
+ route_obj = Route(
123
+ id=route_id,
124
+ name=route_name,
125
+ module=route_module,
126
+ response_schema=get_type_name(route.response_model),
127
+ is_primitive=is_primitive_response
128
+ )
129
+ self.routes.append(route_obj)
130
+ tag_obj.routes.append(route_obj)
131
+
132
+ # add response_models and create links from route -> response_model
133
+ for schema in get_core_types(route.response_model):
134
+ if schema and issubclass(schema, BaseModel):
135
+ is_primitive_response = False
136
+ target_name = full_class_name(schema)
137
+ self.links.append(Link(
138
+ source=route_id,
139
+ source_origin=route_id,
140
+ target=self.generate_node_head(target_name),
141
+ target_origin=target_name,
142
+ type='route_to_schema'
143
+ ))
144
+
145
+ schemas.append(schema)
132
146
 
133
147
  for s in schemas:
134
148
  self.analysis_schemas(s)
@@ -271,6 +285,12 @@ class Voyager:
271
285
  schema=self.schema
272
286
  )
273
287
 
288
+ def handle_hide(self, tags, routes, links):
289
+ if self.include_tags:
290
+ return [], routes, [lk for lk in links if lk.type != 'tag_route']
291
+ else:
292
+ return tags, routes, links
293
+
274
294
  def render_dot(self):
275
295
  _tags, _routes, _nodes, _links = filter_graph(
276
296
  schema=self.schema,
@@ -281,7 +301,10 @@ class Voyager:
281
301
  links=self.links,
282
302
  node_set=self.node_set,
283
303
  )
304
+
284
305
  renderer = Renderer(show_fields=self.show_fields, module_color=self.module_color, schema=self.schema)
306
+
307
+ _tags, _routes, _links = self.handle_hide(_tags, _routes, _links)
285
308
  return renderer.render_dot(_tags, _routes, _nodes, _links)
286
309
 
287
310
  def render_brief_dot(self, module_prefix: str | None = None):
@@ -293,4 +316,6 @@ class Voyager:
293
316
  links=self.links,
294
317
  )
295
318
  renderer = Renderer(show_fields=self.show_fields, module_color=self.module_color, schema=None)
296
- return renderer.render_dot(_tags, _routes, _nodes, _links)
319
+
320
+ _tags, _routes, _links = self.handle_hide(_tags, _routes, _links)
321
+ return renderer.render_dot(_tags, _routes, _nodes, _links, True)
@@ -57,7 +57,7 @@
57
57
  }
58
58
 
59
59
  .adjust-fit {
60
- height: calc(100% - 54px);
60
+ height: calc(100vh - 54px);
61
61
  }
62
62
  </style>
63
63
  <body>
@@ -67,10 +67,11 @@
67
67
  <q-toolbar class="row text-grey-9 bg-white" style="width: 100%">
68
68
  <div
69
69
  class="col-auto text-primary"
70
- style="font-size: 16px; font-weight: bold"
70
+ style="font-size: 18px; font-weight: bold; display: flex; align-items: baseline;"
71
71
  >
72
72
  <q-icon class="q-mr-sm" name="satellite_alt"></q-icon>
73
73
  <span> FastAPI Voyager </span>
74
+ <span v-if="state.version" style="font-size: 12px; margin-left: 8px; font-weight: normal;">{{ state.version }}</span>
74
75
  </div>
75
76
  <div class="col-auto" style="font-size: 16px">
76
77
  <q-option-group
@@ -86,6 +87,7 @@
86
87
  </div>
87
88
  <div class="col-auto q-ml-auto">
88
89
  <q-toggle
90
+ v-if="state.enableBriefMode"
89
91
  class="q-mr-md"
90
92
  v-model="state.brief"
91
93
  label="Brief Mode"
@@ -163,12 +165,29 @@
163
165
 
164
166
  <q-drawer
165
167
  v-model="state.detailDrawer"
166
- width="500"
168
+ :width="state.drawerWidth"
167
169
  side="right"
170
+ style="border-left: 1px solid #888;"
168
171
  overlay
169
172
  bordered
170
173
  >
171
- <div style="z-index: 1; position: absolute; left: -17px; top: 9px">
174
+ <!-- 可拖拽的调整栏 -->
175
+ <div
176
+ @mousedown="startDragDrawer"
177
+ style="
178
+ position: absolute;
179
+ left: -3px;
180
+ top: 0;
181
+ width: 6px;
182
+ height: 100%;
183
+ cursor: col-resize;
184
+ background: transparent;
185
+ z-index: 10;
186
+ "
187
+ title="drag to resize"
188
+ ></div>
189
+
190
+ <div style="z-index: 11; position: absolute; left: -17px; top: 9px">
172
191
  <q-btn
173
192
  @click="state.detailDrawer = !state.detailDrawer"
174
193
  round
@@ -208,14 +227,14 @@
208
227
  v-for="tag in state.rawTags"
209
228
  :key="tag.name"
210
229
  expand-separator
211
- :model-value="state.tag === tag.name"
230
+ :model-value="state._tag === tag.name"
212
231
  @update:model-value="(val) => toggleTag(tag.name, val)"
213
232
  :header-class="state.tag === tag.name ? 'text-primary text-bold' : ''"
214
233
  content-class="q-pa-none"
215
234
  >
216
235
  <template #header>
217
236
  <div class="row items-center" style="width: 100%">
218
- <div class="row items-end">
237
+ <div class="row items-center">
219
238
  <q-icon
220
239
  class="q-mr-sm"
221
240
  :name="state.tag == tag.name ? 'folder' : 'folder_open'"
@@ -260,7 +279,17 @@
260
279
  </template>
261
280
 
262
281
  <template #after>
263
- <div id="graph" class="fit"></div>
282
+ <div style="position: relative; width: 100%; height: 100%;">
283
+ <div id="graph" class="adjust-fit"></div>
284
+ <q-toggle
285
+ v-model="state.focus"
286
+ v-show="schemaCodeName"
287
+ @update:model-value="val => onFocusChange(val)"
288
+ label="Focus"
289
+ style="position: absolute; left: 8px; top: 8px; z-index: 10; background: rgba(255,255,255,0.85); border-radius: 4px; padding: 2px 8px;"
290
+ size="sm"
291
+ />
292
+ </div>
264
293
  </template>
265
294
  </q-splitter>
266
295
  </q-page-container>
@@ -10,6 +10,7 @@ const app = createApp({
10
10
  const state = reactive({
11
11
  // options and selections
12
12
  tag: null, // picked tag
13
+ _tag: null, // display tag
13
14
  routeId: null, // picked route
14
15
  schemaId: null, // picked schema
15
16
  showFields: "object",
@@ -18,7 +19,9 @@ const app = createApp({
18
19
  { label: "Object fields", value: "object" },
19
20
  { label: "All fields", value: "all" },
20
21
  ],
22
+ enableBriefMode: false,
21
23
  brief: false,
24
+ focus: false,
22
25
  hidePrimitiveRoute: false,
23
26
  generating: false,
24
27
  rawTags: [], // [{ name, routes: [{ id, name }] }]
@@ -28,6 +31,8 @@ const app = createApp({
28
31
  // Splitter size (left panel width in px)
29
32
  splitter: 300,
30
33
  detailDrawer: false,
34
+ drawerWidth: 300, // drawer 宽度
35
+ version: "", // version from backend
31
36
  });
32
37
 
33
38
  const showDetail = ref(false);
@@ -70,6 +75,8 @@ const app = createApp({
70
75
  acc[r.id] = r;
71
76
  return acc;
72
77
  }, {});
78
+ state.enableBriefMode = data.enable_brief_mode || false;
79
+ state.version = data.version || "";
73
80
 
74
81
  // default route options placeholder
75
82
  } catch (e) {
@@ -79,18 +86,30 @@ const app = createApp({
79
86
  }
80
87
  }
81
88
 
82
- async function onGenerate(resetZoom = true) {
89
+ async function onFocusChange(val) {
90
+ if (val) {
91
+ await onGenerate(false, schemaCodeName.value)
92
+ } else {
93
+ await onGenerate(false, null)
94
+ setTimeout(() => {
95
+ const ele = $(`[data-name='${schemaCodeName.value}'] polygon`)
96
+ debugger
97
+ ele.click()
98
+ }, 1)
99
+ }
100
+ }
101
+
102
+ async function onGenerate(resetZoom = true, schema_name = null) {
83
103
  state.generating = true;
84
104
  try {
85
105
  const payload = {
86
106
  tags: state.tag ? [state.tag] : null,
87
- schema_name: state.schemaId || null,
107
+ schema_name: schema_name || null,
88
108
  route_name: state.routeId || null,
89
109
  show_fields: state.showFields,
90
110
  brief: state.brief,
91
111
  hide_primitive_route: state.hidePrimitiveRoute,
92
112
  };
93
-
94
113
  const res = await fetch("dot", {
95
114
  method: "POST",
96
115
  headers: { "Content-Type": "application/json" },
@@ -119,6 +138,7 @@ const app = createApp({
119
138
  resetCb: () => {
120
139
  state.detailDrawer = false;
121
140
  showRouteDetail.value = false;
141
+ schemaCodeName.value = ''
122
142
  }
123
143
  });
124
144
 
@@ -198,15 +218,23 @@ const app = createApp({
198
218
  state.schemaId = null;
199
219
  // state.showFields = "object";
200
220
  state.brief = false;
221
+ state.focus = false
222
+ schemaCodeName.value = ''
201
223
  onGenerate();
202
224
  }
203
225
 
204
226
  function toggleTag(tagName, expanded = null) {
205
227
  if (expanded === true) {
228
+ state._tag = tagName;
206
229
  state.tag = tagName;
207
230
  state.routeId = "";
231
+ state.focus = false
232
+ schemaCodeName.value = ''
208
233
  onGenerate();
234
+ } else {
235
+ state._tag = null
209
236
  }
237
+
210
238
  state.detailDrawer = false;
211
239
  showRouteDetail.value = false;
212
240
  }
@@ -219,6 +247,8 @@ const app = createApp({
219
247
  }
220
248
  state.detailDrawer = false;
221
249
  showRouteDetail.value = false;
250
+ state.focus = false
251
+ schemaCodeName.value = ''
222
252
  onGenerate();
223
253
  }
224
254
 
@@ -237,6 +267,30 @@ const app = createApp({
237
267
  onGenerate(false);
238
268
  }
239
269
 
270
+ function startDragDrawer(e) {
271
+ const startX = e.clientX;
272
+ const startWidth = state.drawerWidth;
273
+
274
+ function onMouseMove(moveEvent) {
275
+ const deltaX = startX - moveEvent.clientX;
276
+ const newWidth = Math.max(300, Math.min(800, startWidth + deltaX));
277
+ state.drawerWidth = newWidth;
278
+ }
279
+
280
+ function onMouseUp() {
281
+ document.removeEventListener('mousemove', onMouseMove);
282
+ document.removeEventListener('mouseup', onMouseUp);
283
+ document.body.style.cursor = '';
284
+ document.body.style.userSelect = '';
285
+ }
286
+
287
+ document.addEventListener('mousemove', onMouseMove);
288
+ document.addEventListener('mouseup', onMouseUp);
289
+ document.body.style.cursor = 'col-resize';
290
+ document.body.style.userSelect = 'none';
291
+ e.preventDefault();
292
+ }
293
+
240
294
  onMounted(async () => {
241
295
  await loadInitial();
242
296
  });
@@ -272,6 +326,8 @@ const app = createApp({
272
326
  showRenderGraph,
273
327
  renderCoreData,
274
328
  toggleShowField,
329
+ startDragDrawer,
330
+ onFocusChange
275
331
  };
276
332
  },
277
333
  });
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-voyager
3
- Version: 0.9.5
3
+ Version: 0.10.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
@@ -167,14 +167,15 @@ or you can open router_viz.dot with vscode extension `graphviz interactive previ
167
167
  - [ ] add extra info for schema
168
168
  - [ ] display standard ER diagram `hard`
169
169
  - [ ] display potential invalid links
170
- - [ ] support dataclass (pending)
170
+ - [ ] optimize static resource (allow manually config url)
171
+ - [ ] improve search dialog
172
+ - [ ] add route/tag list
171
173
 
172
174
  ### in analysis
173
175
  - [ ] click field to highlight links
174
176
  - [ ] animation effect for edges
175
177
  - [ ] customrized right click panel
176
178
  - [ ] show own dependencies
177
- - [ ] clean up fe code
178
179
 
179
180
  ### plan:
180
181
  #### <0.9:
@@ -225,23 +226,24 @@ or you can open router_viz.dot with vscode extension `graphviz interactive previ
225
226
  - [x] route list should have a max height
226
227
 
227
228
  #### 0.10
228
- - [ ] perfomance: cache the origin data, refactor voyager.py
229
- - [ ] better edge for brief mode
229
+ - 0.10.1
230
+ - [x] refactor voyager.py tag -> route structure
231
+ - [x] fix missing route (tag has only one route which return primitive value)
232
+ - [x] make right panel resizable by dragging
233
+ - [x] allow closing tag expansion item
234
+ - [x] hide brief mode if not configured
235
+ - [x] add focus button to only show related nodes under current route/tag graph in dialog
236
+ - 0.10.2
237
+ - [x] fix graph height
238
+ - [x] show version in title
239
+
240
+ #### 0.11
241
+ - [ ] enable/disable module cluster (to save space)
242
+ - [ ] fix layout issue when rendering huge graph
243
+ - [ ] logging information
230
244
  - [ ] support opening route in swagger
231
245
  - config docs path
232
- - [ ] add http method for route
233
- - [ ] enable/disable module cluster (may save space)
234
- - [ ] logging information
235
246
  - [ ] add tests
236
- - [ ] hide brief mode if not configured
237
- - [ ] optimize static resource (allow manually config url)
238
- - [ ] show route count in tag expansion item
239
- - [ ] route list should have a max height to trigger scrollable
240
- - [ ] fix layout issue when rendering huge graph
241
- - [ ] fix missing route (tag has only one route which return primitive value)
242
-
243
- #### 0.11
244
- - [ ] improve search dialog
245
247
 
246
248
  #### 0.12
247
249
  - [ ] integration with pydantic-resolve
@@ -251,6 +253,7 @@ or you can open router_viz.dot with vscode extension `graphviz interactive previ
251
253
  #### 0.13
252
254
  - [ ] config release pipeline
253
255
 
256
+
254
257
  ## Using with pydantic-resolve
255
258
 
256
259
  WIP: ...
@@ -2,19 +2,19 @@ fastapi_voyager/__init__.py,sha256=tZy0Nkj8kTaMgbvHy-mGxVcFGVX0Km-36dnzsAIG2uk,2
2
2
  fastapi_voyager/cli.py,sha256=kQb4g6JEGZR99e5r8LyFFEeb_-uT-n_gp_sDoYG3R7k,11118
3
3
  fastapi_voyager/filter.py,sha256=2Yt37o8mhqSqleafO4YRrumh_ExYUqzXFOxQRPuTbAc,8078
4
4
  fastapi_voyager/module.py,sha256=Z2QHNmiLk6ZAJlm2nSmO875Q33TweSg8UxZSzIpU9zY,3499
5
- fastapi_voyager/render.py,sha256=qy3g1Rz1s8XkuR_6n1Q1YPwy_oMOjWjNswTHQjdz4N0,7765
6
- fastapi_voyager/server.py,sha256=pg-LHDj4yU0usDA1b2X2Kt2_OCrexFA2G9ifGxb52Uc,6196
5
+ fastapi_voyager/render.py,sha256=sR1oUh8d3hhDalQhUcrL-k2ZYAWbLDGpGDOB0dDaqRQ,7804
6
+ fastapi_voyager/server.py,sha256=6kCj906N4PVpKbUI8eq7bJ4RoET1kIQgUQUf-oMFdSY,6326
7
7
  fastapi_voyager/type.py,sha256=pWYKmgb9e0W_JeD7k54Mr2lxUZV_Ir9TNpewGRwHyHQ,1629
8
8
  fastapi_voyager/type_helper.py,sha256=hjBC4E0tgBpQDlYxGg74uK07SXjsrAgictEETJfIpYM,9231
9
- fastapi_voyager/version.py,sha256=edeIqVARN2rX8n02TnXhblafTm15NsTYlNCYyC9fXBo,48
10
- fastapi_voyager/voyager.py,sha256=QKWletUwZeHm8e8ZRcGm6OuhAdiik3tT7sOU-QnEuGA,11036
9
+ fastapi_voyager/version.py,sha256=KhkBU7axnprYVOcYbZBAgdkdrD7vU8iriPE75NCnHgI,49
10
+ fastapi_voyager/voyager.py,sha256=DIc93SFPVwrsk1Nga74ZZyc4L0J50OAESE9j3fnEty0,12053
11
11
  fastapi_voyager/web/graph-ui.js,sha256=FmKA3eeHMEeUDNuay3f54_fv4eGHT7MT0TaGqXhyMWQ,4978
12
12
  fastapi_voyager/web/graphviz.svg.css,sha256=zDCjjpT0Idufu5YOiZI76PL70-avP3vTyzGPh9M85Do,1563
13
13
  fastapi_voyager/web/graphviz.svg.js,sha256=lvAdbjHc-lMSk4GQp-iqYA2PCFX4RKnW7dFaoe0LUHs,16005
14
- fastapi_voyager/web/index.html,sha256=qH7vs_1SpFJWZlzMsPBuHToCysLpRsb4LC5vRBjWhZM,13930
14
+ fastapi_voyager/web/index.html,sha256=3cvaqXgwGdTkNSdvrw8Grn0xbhjWPvlo_A12ltjs5j0,15164
15
15
  fastapi_voyager/web/quasar.min.css,sha256=F5jQe7X2XT54VlvAaa2V3GsBFdVD-vxDZeaPLf6U9CU,203145
16
16
  fastapi_voyager/web/quasar.min.js,sha256=h0ftyPMW_CRiyzeVfQqiup0vrVt4_QWojpqmpnpn07E,502974
17
- fastapi_voyager/web/vue-main.js,sha256=bn4Q9FqX5RJVG9bA5xgUUt5TJf9CjiXcKtn_ikLsaKQ,8357
17
+ fastapi_voyager/web/vue-main.js,sha256=pEk6CKtsL-CBIWi6vdLvfa-BxYgIW2OFIvBVFNAWdjI,10149
18
18
  fastapi_voyager/web/component/render-graph.js,sha256=e8Xgh2Kl-nYU0P1gstEmAepCgFnk2J6UdxW8TlMafGs,2322
19
19
  fastapi_voyager/web/component/route-code-display.js,sha256=8NJPPjNRUC21gjpY8XYEQs4RBbhX1pCiqEhJp39ku6k,3678
20
20
  fastapi_voyager/web/component/schema-code-display.js,sha256=UgFotzvqSuhnPXNOr6w_r1fV2_savRiCdokEvferutE,6244
@@ -26,8 +26,8 @@ fastapi_voyager/web/icon/favicon-16x16.png,sha256=JC07jEzfIYxBIoQn_FHXvyHuxESdhW
26
26
  fastapi_voyager/web/icon/favicon-32x32.png,sha256=C7v1h58cfWOsiLp9yOIZtlx-dLasBcq3NqpHVGRmpt4,1859
27
27
  fastapi_voyager/web/icon/favicon.ico,sha256=tZolYIXkkBcFiYl1A8ksaXN2VjGamzcSdes838dLvNc,15406
28
28
  fastapi_voyager/web/icon/site.webmanifest,sha256=ep4Hzh9zhmiZF2At3Fp1dQrYQuYF_3ZPZxc1KcGBvwQ,263
29
- fastapi_voyager-0.9.5.dist-info/METADATA,sha256=fnFPewv9pgh6hA4k1SXufzEmq7a-2vmMwAvCl49xdQk,8833
30
- fastapi_voyager-0.9.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
- fastapi_voyager-0.9.5.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
32
- fastapi_voyager-0.9.5.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
33
- fastapi_voyager-0.9.5.dist-info/RECORD,,
29
+ fastapi_voyager-0.10.2.dist-info/METADATA,sha256=XzmFjR4-CyMlrJUO8mVze18hbRrrAcUmT8wWEnNTrXY,8895
30
+ fastapi_voyager-0.10.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
+ fastapi_voyager-0.10.2.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
32
+ fastapi_voyager-0.10.2.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
33
+ fastapi_voyager-0.10.2.dist-info/RECORD,,