fastapi-voyager 0.13.2__py3-none-any.whl → 0.14.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,99 @@
1
+ import inspect
2
+ from pydantic import BaseModel
3
+ from pydantic.fields import FieldInfo
4
+ from pydantic_resolve.utils.er_diagram import LoaderInfo
5
+ import pydantic_resolve.constant as const
6
+ from pydantic_resolve.utils.expose import ExposeInfo
7
+ from pydantic_resolve.utils.collector import SendToInfo, ICollector
8
+
9
+ def analysis_pydantic_resolve_fields(schema: type[BaseModel], field: str):
10
+ """
11
+ get information for pydantic resolve specific info
12
+ in future, this function will be provide by pydantic-resolve package
13
+
14
+ is_resolve: bool = False
15
+ - check existence of def resolve_{field} method
16
+ - check existence of LoaderInfo in field.metadata
17
+
18
+ is_post: bool = False
19
+ - check existence of def post_{field} method
20
+
21
+ expose_as_info: str | None = None
22
+ - check ExposeInfo in field.metadata
23
+ - check field in schema.__pydantic_resolve_expose__ (const.EXPOSE_TO_DESCENDANT)
24
+
25
+ send_to_info: list[str] | None = None
26
+ - check SendToInfo in field.metadata
27
+ - check field in schema.__pydantic_resolve_collect__ (const.COLLECTOR_CONFIGURATION)
28
+
29
+ collect_info: list[str] | None = None
30
+ - 1. check existence of def post_{field} method
31
+ - 2. get the signature of this method
32
+ - 3. extrace the collector names from the parameters with ICollector metadata
33
+
34
+
35
+
36
+ return dict in form of
37
+ {
38
+ "is_resolve": True,
39
+ ...
40
+ }
41
+ """
42
+ has_meta = False
43
+ field_info: FieldInfo = schema.model_fields.get(field)
44
+
45
+ is_resolve = hasattr(schema, f'{const.RESOLVE_PREFIX}{field}')
46
+ is_post = hasattr(schema, f'{const.POST_PREFIX}{field}')
47
+ expose_as_info = None
48
+ send_to_info = None
49
+ post_collector = []
50
+
51
+ send_to_info_list = []
52
+
53
+ if field_info:
54
+ # Check metadata
55
+ for meta in field_info.metadata:
56
+ if isinstance(meta, LoaderInfo):
57
+ is_resolve = True
58
+ if isinstance(meta, ExposeInfo):
59
+ expose_as_info = meta.alias
60
+ if isinstance(meta, SendToInfo):
61
+ if isinstance(meta.collector_name, str):
62
+ send_to_info_list.append(meta.collector_name)
63
+ else:
64
+ send_to_info_list.extend(list(meta.collector_name))
65
+
66
+ # Check class attributes
67
+ expose_dict = getattr(schema, const.EXPOSE_TO_DESCENDANT, {})
68
+ if field in expose_dict:
69
+ expose_as_info = expose_dict[field]
70
+
71
+ collect_dict = getattr(schema, const.COLLECTOR_CONFIGURATION, {})
72
+
73
+ for keys, collectors in collect_dict.items():
74
+ target_keys = [keys] if isinstance(keys, str) else list(keys)
75
+ if field in target_keys:
76
+ if isinstance(collectors, str):
77
+ send_to_info_list.append(collectors)
78
+ else:
79
+ send_to_info_list.extend(list(collectors))
80
+
81
+ if send_to_info_list:
82
+ send_to_info = list(set(send_to_info_list)) # unique collectors
83
+
84
+ if is_post:
85
+ post_method = getattr(schema, f'{const.POST_PREFIX}{field}')
86
+ for _, param in inspect.signature(post_method).parameters.items():
87
+ if isinstance(param.default, ICollector):
88
+ post_collector.append(param.default.alias)
89
+
90
+ has_meta = any([is_resolve, is_post, expose_as_info, send_to_info])
91
+
92
+ return {
93
+ "has_pydantic_resolve_meta": has_meta,
94
+ "is_resolve": is_resolve,
95
+ "is_post": is_post,
96
+ "expose_as_info": expose_as_info,
97
+ "send_to_info": send_to_info,
98
+ "collect_info": None if len(post_collector) == 0 else post_collector
99
+ }
fastapi_voyager/render.py CHANGED
@@ -5,6 +5,7 @@ from fastapi_voyager.type import (
5
5
  PK,
6
6
  FieldType,
7
7
  Link,
8
+ FieldInfo,
8
9
  ModuleNode,
9
10
  ModuleRoute,
10
11
  Route,
@@ -22,24 +23,62 @@ class Renderer:
22
23
  show_fields: FieldType = 'single',
23
24
  module_color: dict[str, str] | None = None,
24
25
  schema: str | None = None,
25
- show_module: bool = True
26
+ show_module: bool = True,
27
+ show_pydantic_resolve_meta: bool = False,
26
28
  ) -> None:
27
29
  self.show_fields = show_fields if show_fields in ('single', 'object', 'all') else 'single'
28
30
  self.module_color = module_color or {}
29
31
  self.schema = schema
30
32
  self.show_module = show_module
33
+ self.show_pydantic_resolve_meta = show_pydantic_resolve_meta
31
34
 
32
35
  logger.info(f'show_module: {self.show_module}')
33
36
  logger.info(f'module_color: {self.module_color}')
37
+
38
+ def render_pydantic_related_markup(self, field: FieldInfo):
39
+ if self.show_pydantic_resolve_meta is False:
40
+ return ''
41
+
42
+ parts: list[str] = []
43
+ if field.is_resolve:
44
+ parts.append('<font color="#47a80f"> ● resolve</font>')
45
+ if field.is_post:
46
+ parts.append('<font color="#427fa4"> ● post</font>')
47
+ if field.expose_as_info:
48
+ parts.append(f'<font color="#895cb9"> ● expose as: {field.expose_as_info}</font>')
49
+ if field.send_to_info:
50
+ to_collectors = ', '.join(field.send_to_info)
51
+ parts.append(f'<font color="#ca6d6d"> ● send to: {to_collectors}</font>')
52
+ if field.collect_info:
53
+ defined_collectors = ', '.join(field.collect_info)
54
+ parts.append(f'<font color="#777"> ● collectors: {defined_collectors}</font>')
55
+
56
+ if not parts:
57
+ return ''
58
+
59
+ return '<br align="left"/><br align="left"/>' + '<br align="left"/>'.join(parts) + '<br align="left"/>'
34
60
 
35
61
  def render_schema_label(self, node: SchemaNode, color: str | None=None) -> str:
62
+ """
63
+ TODO: should improve the logic with show_pydantic_resolve_meta
64
+ """
65
+
36
66
  has_base_fields = any(f.from_base for f in node.fields)
37
- fields = [n for n in node.fields if n.from_base is False]
67
+
68
+ # if self.show_pydantic_resolve_meta, show all fields with resolve/post/expose/collector info
69
+ if self.show_pydantic_resolve_meta:
70
+ fields = [n for n in node.fields if n.has_pydantic_resolve_meta is True or n.from_base is False]
71
+ else:
72
+ fields = [n for n in node.fields if n.from_base is False]
38
73
 
39
74
  if self.show_fields == 'all':
40
75
  _fields = fields
41
76
  elif self.show_fields == 'object':
42
- _fields = [f for f in fields if f.is_object is True]
77
+ if self.show_pydantic_resolve_meta:
78
+ # to better display resolve meta info
79
+ _fields = [f for f in fields if f.is_object is True or f.has_pydantic_resolve_meta is True]
80
+ else:
81
+ _fields = [f for f in fields if f.is_object is True]
43
82
  else: # 'single'
44
83
  _fields = []
45
84
 
@@ -49,8 +88,8 @@ class Renderer:
49
88
 
50
89
  for field in _fields:
51
90
  type_name = field.type_name[:25] + '..' if len(field.type_name) > 25 else field.type_name
52
- display_xml = f'<s align="left">{field.name}: {type_name}</s>' if field.is_exclude else f'{field.name}: {type_name}'
53
- field_str = f"""<tr><td align="left" port="f{field.name}" cellpadding="8"><font> {display_xml} </font></td></tr>"""
91
+ display_xml = f'<s align="left">{field.name}: {type_name} </s>' if field.is_exclude else f'{field.name}: {type_name}'
92
+ field_str = f"""<tr><td align="left" port="f{field.name}" cellpadding="8"><font> {display_xml} </font> {self.render_pydantic_related_markup(field)} </td></tr>"""
54
93
  fields_parts.append(field_str)
55
94
 
56
95
  default_color = '#009485' if color is None else color
fastapi_voyager/server.py CHANGED
@@ -47,6 +47,7 @@ class OptionParam(BaseModel):
47
47
  initial_page_policy: INITIAL_PAGE_POLICY
48
48
  swagger_url: str | None = None
49
49
  has_er_diagram: bool = False
50
+ enable_pydantic_resolve_meta: bool = False
50
51
 
51
52
  class Payload(BaseModel):
52
53
  tags: list[str] | None = None
@@ -57,6 +58,7 @@ class Payload(BaseModel):
57
58
  brief: bool = False
58
59
  hide_primitive_route: bool = False
59
60
  show_module: bool = True
61
+ show_pydantic_resolve_meta: bool = False
60
62
 
61
63
  # ---------- search ----------
62
64
  class SearchResultOptionParam(BaseModel):
@@ -86,6 +88,7 @@ def create_voyager(
86
88
  initial_page_policy: INITIAL_PAGE_POLICY = 'first',
87
89
  ga_id: str | None = None,
88
90
  er_diagram: ErDiagram | None = None,
91
+ enable_pydantic_resolve_meta: bool = False,
89
92
  ) -> FastAPI:
90
93
  router = APIRouter(tags=['fastapi-voyager'])
91
94
 
@@ -121,7 +124,8 @@ def create_voyager(
121
124
  version=__version__,
122
125
  swagger_url=swagger_url,
123
126
  initial_page_policy=initial_page_policy,
124
- has_er_diagram=er_diagram is not None)
127
+ has_er_diagram=er_diagram is not None,
128
+ enable_pydantic_resolve_meta=enable_pydantic_resolve_meta)
125
129
 
126
130
 
127
131
  @router.post("/dot-search", response_model=SearchResultOptionParam)
@@ -133,6 +137,7 @@ def create_voyager(
133
137
  module_color=module_color,
134
138
  hide_primitive_route=payload.hide_primitive_route,
135
139
  show_module=payload.show_module,
140
+ show_pydantic_resolve_meta=payload.show_pydantic_resolve_meta,
136
141
  )
137
142
  voyager.analysis(target_app)
138
143
  tags = voyager.calculate_filtered_tag_and_route()
@@ -154,6 +159,7 @@ def create_voyager(
154
159
  route_name=payload.route_name,
155
160
  hide_primitive_route=payload.hide_primitive_route,
156
161
  show_module=payload.show_module,
162
+ show_pydantic_resolve_meta=payload.show_pydantic_resolve_meta,
157
163
  )
158
164
  voyager.analysis(target_app)
159
165
  if payload.brief:
@@ -179,7 +185,10 @@ def create_voyager(
179
185
 
180
186
  @router.post('/dot-render-core-data', response_class=PlainTextResponse)
181
187
  def render_dot_from_core_data(core_data: CoreData) -> str:
182
- renderer = Renderer(show_fields=core_data.show_fields, module_color=core_data.module_color, schema=core_data.schema)
188
+ renderer = Renderer(
189
+ show_fields=core_data.show_fields,
190
+ module_color=core_data.module_color,
191
+ schema=core_data.schema)
183
192
  return renderer.render_dot(core_data.tags, core_data.routes, core_data.nodes, core_data.links)
184
193
 
185
194
  @router.get("/", response_class=HTMLResponse)
fastapi_voyager/type.py CHANGED
@@ -16,6 +16,15 @@ class FieldInfo:
16
16
  from_base: bool = False
17
17
  is_object: bool = False
18
18
  is_exclude: bool = False
19
+ desc: str = ''
20
+
21
+ # pydantic resolve specific fields
22
+ has_pydantic_resolve_meta: bool = False # overall flag
23
+ is_resolve: bool = False
24
+ is_post: bool = False
25
+ expose_as_info: str | None = None
26
+ send_to_info: list[str] | None = None
27
+ collect_info: list[str] | None = None
19
28
 
20
29
  @dataclass
21
30
  class Tag(NodeBase):
@@ -8,6 +8,7 @@ import pydantic_resolve.constant as const
8
8
  from pydantic import BaseModel
9
9
 
10
10
  from fastapi_voyager.type import FieldInfo
11
+ from fastapi_voyager.pydantic_resolve_util import analysis_pydantic_resolve_fields
11
12
 
12
13
  logger = logging.getLogger(__name__)
13
14
 
@@ -177,12 +178,15 @@ def get_pydantic_fields(schema: type[BaseModel], bases_fields: set[str]) -> list
177
178
  fields: list[FieldInfo] = []
178
179
  for k, v in schema.model_fields.items():
179
180
  anno = v.annotation
181
+ pydantic_resolve_specific_params = analysis_pydantic_resolve_fields(schema, k)
180
182
  fields.append(FieldInfo(
181
183
  is_object=_is_object(anno),
182
184
  name=k,
183
185
  from_base=k in bases_fields,
184
186
  type_name=get_type_name(anno),
185
- is_exclude=bool(v.exclude)
187
+ is_exclude=bool(v.exclude),
188
+ desc=v.description or '',
189
+ **pydantic_resolve_specific_params
186
190
  ))
187
191
  return fields
188
192
 
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "0.13.2"
2
+ __version__ = "0.14.0"
@@ -33,6 +33,7 @@ class Voyager:
33
33
  route_name: str | None = None,
34
34
  hide_primitive_route: bool = False,
35
35
  show_module: bool = True,
36
+ show_pydantic_resolve_meta: bool = False,
36
37
  ):
37
38
 
38
39
  self.routes: list[Route] = []
@@ -55,6 +56,7 @@ class Voyager:
55
56
  self.route_name = route_name
56
57
  self.hide_primitive_route = hide_primitive_route
57
58
  self.show_module = show_module
59
+ self.show_pydantic_resolve_meta = show_pydantic_resolve_meta
58
60
 
59
61
 
60
62
  def _get_available_route(self, app: FastAPI):
@@ -319,7 +321,12 @@ class Voyager:
319
321
  node_set=self.node_set,
320
322
  )
321
323
 
322
- renderer = Renderer(show_fields=self.show_fields, module_color=self.module_color, schema=self.schema, show_module=self.show_module)
324
+ renderer = Renderer(
325
+ show_fields=self.show_fields,
326
+ module_color=self.module_color,
327
+ schema=self.schema,
328
+ show_module=self.show_module,
329
+ show_pydantic_resolve_meta=self.show_pydantic_resolve_meta)
323
330
 
324
331
  _tags, _routes, _links = self.handle_hide(_tags, _routes, _links)
325
332
  return renderer.render_dot(_tags, _routes, _nodes, _links)
@@ -179,6 +179,7 @@ export default defineComponent({
179
179
  <tr>
180
180
  <th style="text-align:left; border-bottom:1px solid #ddd; padding:4px 6px;">Field</th>
181
181
  <th style="text-align:left; border-bottom:1px solid #ddd; padding:4px 6px;">Type</th>
182
+ <th style="text-align:left; border-bottom:1px solid #ddd; padding:4px 6px;">Description</th>
182
183
  <th style="text-align:left; border-bottom:1px solid #ddd; padding:4px 6px;">Inherited</th>
183
184
  </tr>
184
185
  </thead>
@@ -186,6 +187,7 @@ export default defineComponent({
186
187
  <tr v-for="f in fields" :key="f.name">
187
188
  <td style="padding:4px 6px; border-bottom:1px solid #f0f0f0;">{{ f.name }}</td>
188
189
  <td style="padding:4px 6px; border-bottom:1px solid #f0f0f0; white-space:nowrap;">{{ f.type_name }}</td>
190
+ <td style="padding:4px 6px; border-bottom:1px solid #f0f0f0; max-width: 200px;">{{ f.desc }}</td>
189
191
  <td style="padding:4px 6px; border-bottom:1px solid #f0f0f0; text-align:left;">{{ f.from_base ? '✔︎' : '' }}</td>
190
192
  </tr>
191
193
  <tr v-if="!fields.length">
@@ -380,6 +380,15 @@
380
380
  title="show module cluster"
381
381
  />
382
382
  </div>
383
+ <div class="q-mt-sm" v-if="store.state.config.enable_pydantic_resolve_meta">
384
+ <q-toggle
385
+ v-model="store.state.modeControl.pydanticResolveMetaEnabled"
386
+ @update:model-value="(val) => togglePydanticResolveMeta(val)"
387
+ label="Pydantic Resolve Meta"
388
+ dense
389
+ title="show fields with pydantic resolve/post/expose/collector info"
390
+ />
391
+ </div>
383
392
  </div>
384
393
  </template>
385
394
  </q-splitter>
@@ -9,6 +9,7 @@ const state = reactive({
9
9
  config: {
10
10
  initial_page_policy: 'first',
11
11
  has_er_diagram: false,
12
+ enable_pydantic_resolve_meta: false,
12
13
  },
13
14
 
14
15
  mode: 'voyager', // voyager / er-diagram
@@ -90,6 +91,7 @@ const state = reactive({
90
91
  modeControl: {
91
92
  focus: false, // control the schema param
92
93
  briefModeEnabled: false, // show brief mode toggle
94
+ pydanticResolveMetaEnabled: false, // show pydantic resolve meta toggle
93
95
  },
94
96
 
95
97
  // api filters
@@ -244,6 +244,7 @@ const app = createApp({
244
244
  store.state.version = data.version || "";
245
245
  store.state.swagger.url = data.swagger_url || null;
246
246
  store.state.config.has_er_diagram = data.has_er_diagram || false;
247
+ store.state.config.enable_pydantic_resolve_meta = data.enable_pydantic_resolve_meta || false;
247
248
 
248
249
  rebuildSchemaOptions();
249
250
 
@@ -314,6 +315,7 @@ const app = createApp({
314
315
  brief: store.state.filter.brief,
315
316
  hide_primitive_route: store.state.filter.hidePrimitiveRoute,
316
317
  show_module: store.state.filter.showModule,
318
+ show_pydantic_resolve_meta: store.state.modeControl.pydanticResolveMetaEnabled
317
319
  };
318
320
  initGraphUI();
319
321
  const res = await fetch("dot", {
@@ -345,6 +347,11 @@ const app = createApp({
345
347
  onGenerate()
346
348
  }
347
349
 
350
+ async function togglePydanticResolveMeta(val) {
351
+ store.state.modeControl.pydanticResolveMetaEnabled = val;
352
+ onGenerate();
353
+ }
354
+
348
355
  async function renderErDiagram(resetZoom = true) {
349
356
  initGraphUI();
350
357
  erDiagramLoading.value = true;
@@ -525,6 +532,7 @@ const app = createApp({
525
532
  toggleShowModule,
526
533
  onModeChange,
527
534
  renderErDiagram,
535
+ togglePydanticResolveMeta
528
536
  };
529
537
  },
530
538
  });
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-voyager
3
- Version: 0.13.2
3
+ Version: 0.14.0
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
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.13
19
19
  Classifier: Programming Language :: Python :: 3.14
20
20
  Requires-Python: >=3.10
21
21
  Requires-Dist: fastapi>=0.110
22
- Requires-Dist: pydantic-resolve>=2.2.3
22
+ Requires-Dist: pydantic-resolve>=2.3.1
23
23
  Provides-Extra: dev
24
24
  Requires-Dist: pytest; extra == 'dev'
25
25
  Requires-Dist: ruff; extra == 'dev'
@@ -33,6 +33,8 @@ Description-Content-Type: text/markdown
33
33
 
34
34
  Visualize your FastAPI endpoints, and explore them interactively.
35
35
 
36
+ Its vision is to make code easier to read and understand, serving as an ideal documentation tool.
37
+
36
38
  > This repo is still in early stage, it supports pydantic v2 only
37
39
 
38
40
  visit [live demo](https://www.newsyeah.fun/voyager/)
@@ -91,6 +93,7 @@ It is also an architecture tool that can identify issues inside implementation,
91
93
 
92
94
  Given ErDiagram defined by pydantic-resolve, application level entity relationship diagram can be visualized too.
93
95
 
96
+
94
97
  ### highlight nodes and links
95
98
  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.
96
99
 
@@ -190,9 +193,9 @@ voyager --help
190
193
 
191
194
  ## About pydantic-resolve
192
195
 
193
- 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.
196
+ pydantic-resolve is a lightweight tool designed to build complex, nested data in a simple, declarative way. In v2 it introduced an important feature: ER Diagram, and fastapi-voyager has supported this feature, allowing for a clearer understanding of the business relationships.
194
197
 
195
- 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.
198
+ pydantic-resolve's ~~`@ensure_subset` decorator~~ `DefineSubset` metaclass helps safely pick fields from the 'source class' while **indicating the reference** from the current class to the base class.
196
199
 
197
200
  Developers can use fastapi-voyager without needing to know anything about pydantic-resolve, but I still highly recommend everyone to give it a try.
198
201
 
@@ -3,24 +3,25 @@ fastapi_voyager/cli.py,sha256=td3yIIigEomhSdDO-Xkh-CgpEwCafwlwnpvxnT9QsBo,10488
3
3
  fastapi_voyager/er_diagram.py,sha256=cMiNKk4ufSM147ldvvfdqfv34Q5mj533VcELsp4Gwwc,10384
4
4
  fastapi_voyager/filter.py,sha256=AN_HIu8-DtKisIq5mFt7CnqRHtxKewedNGyyaI82hSY,11529
5
5
  fastapi_voyager/module.py,sha256=h9YR3BpS-CAcJW9WCdVkF4opqwY32w9T67g9GfdLytk,3425
6
- fastapi_voyager/render.py,sha256=O_HR8ypOrFhjejkBpKIH_8foB78DgzH0hvO-CWeYt0w,9976
7
- fastapi_voyager/server.py,sha256=UZi-VdsurjDnqDgf3l5LfgWfZ4OxzilC_A_Ju6x9jQc,8592
8
- fastapi_voyager/type.py,sha256=asNHhkYoTMnAqz9_d-BS1Vz9EEfGaRDMpYR1aiOH1kM,1808
9
- fastapi_voyager/type_helper.py,sha256=UTCFWluFeGdGkJX3wiE_bZ2EgZsu4JkmqHjsJVdG81Q,9953
10
- fastapi_voyager/version.py,sha256=-vDCciVkW5QNe8J14nbt6lxBenezXsExPxuBwiH26tQ,49
11
- fastapi_voyager/voyager.py,sha256=iWt-_QsoKavhb9ZawhU3W8gv3vTwn8PWTevg8BooyV8,13923
6
+ fastapi_voyager/pydantic_resolve_util.py,sha256=r4Rq7BtBcFOMV7O2Ab9TwLyRNL1yNDiQlGUVybf-sXs,3524
7
+ fastapi_voyager/render.py,sha256=jST413qpp4JEkgc6OftpWXYnjLkjTM4zUagAmZpQkLo,11791
8
+ fastapi_voyager/server.py,sha256=DN4KP37lD_lt4ISg7yoJwzVvw3nKn6qr9C6aH75mR-g,8928
9
+ fastapi_voyager/type.py,sha256=zluWvh5vpnjXJ9aAmyNJTSmXZPjAHCvgRT5oQRAjHrg,2104
10
+ fastapi_voyager/type_helper.py,sha256=FmfrZAI3Z4uDdh3sH_kH7UGoY6yNVPapneSN86qY_wo,10209
11
+ fastapi_voyager/version.py,sha256=Z7SMv33jTyy1f3GgVRf2iMDpmp7vVS5MXyRZTWhZoSg,49
12
+ fastapi_voyager/voyager.py,sha256=4vonmL-xt54C5San-DRBq4mjoV8Q96eoWRy68MJ1IJw,14169
12
13
  fastapi_voyager/web/graph-ui.js,sha256=hTsZO1Ly1JuoRg0kZWQ62jeLiD2kbnzACfbSPd0F95U,6634
13
14
  fastapi_voyager/web/graphviz.svg.css,sha256=zDCjjpT0Idufu5YOiZI76PL70-avP3vTyzGPh9M85Do,1563
14
15
  fastapi_voyager/web/graphviz.svg.js,sha256=wZwz_lBztoXmujEN21P0w-HMpdmbqPwTQQ6Ebxd9rGo,18569
15
- fastapi_voyager/web/index.html,sha256=_VaTvHNnuu_KcG2lLYB_bk7MGkG-Ok0-WgAAdFFGB2s,19336
16
+ fastapi_voyager/web/index.html,sha256=-3i9ZsgbePj1tQ6AeAY-orL0b5_5M6QO3yLC-LcDfzA,19847
16
17
  fastapi_voyager/web/quasar.min.css,sha256=F5jQe7X2XT54VlvAaa2V3GsBFdVD-vxDZeaPLf6U9CU,203145
17
18
  fastapi_voyager/web/quasar.min.js,sha256=h0ftyPMW_CRiyzeVfQqiup0vrVt4_QWojpqmpnpn07E,502974
18
- fastapi_voyager/web/store.js,sha256=wMApI0p3C9rBAEi4cfgU__bYwBm2cGO-cwIKdOvQaEk,2065
19
- fastapi_voyager/web/vue-main.js,sha256=BqFfjKRj1b2_nmR0Jmd2pL59Zk6qesrTNjRPpDRYMc4,16942
19
+ fastapi_voyager/web/store.js,sha256=2-SpyfiQDtl2mCCOpCoJuxOP_pSIRnlIaY4Tm2H0SOQ,2191
20
+ fastapi_voyager/web/vue-main.js,sha256=3kaHd4B1V6IcsHie-MQ5QdaKwmGmZlSwR4XaZUsFj6o,17308
20
21
  fastapi_voyager/web/component/demo.js,sha256=bQb16Un4XZ3Mf8qL6gvyrXe_mmA3V3mSIRMQAWg2MNk,352
21
22
  fastapi_voyager/web/component/render-graph.js,sha256=e8Xgh2Kl-nYU0P1gstEmAepCgFnk2J6UdxW8TlMafGs,2322
22
23
  fastapi_voyager/web/component/route-code-display.js,sha256=8NJPPjNRUC21gjpY8XYEQs4RBbhX1pCiqEhJp39ku6k,3678
23
- fastapi_voyager/web/component/schema-code-display.js,sha256=qKUMV2RFQzR8deof2iC4vyp65UaWadtVsDAXjY-i3vE,7042
24
+ fastapi_voyager/web/component/schema-code-display.js,sha256=E4XiX0ahPxQhvPhZxe_uAbm5FdZYJiml3UAfvIRyrBw,7269
24
25
  fastapi_voyager/web/icon/android-chrome-192x192.png,sha256=35sBy6jmUFJCcquStaafHH1qClZIbd-X3PIKSeLkrNo,37285
25
26
  fastapi_voyager/web/icon/android-chrome-512x512.png,sha256=eb2eDjCwIruc05029_0L9hcrkVkv8KceLn1DJMYU0zY,210789
26
27
  fastapi_voyager/web/icon/apple-touch-icon.png,sha256=gnWK46tPnvSw1-oYZjgI02wpoO4OrIzsVzGHC5oKWO0,33187
@@ -28,8 +29,8 @@ fastapi_voyager/web/icon/favicon-16x16.png,sha256=JC07jEzfIYxBIoQn_FHXvyHuxESdhW
28
29
  fastapi_voyager/web/icon/favicon-32x32.png,sha256=C7v1h58cfWOsiLp9yOIZtlx-dLasBcq3NqpHVGRmpt4,1859
29
30
  fastapi_voyager/web/icon/favicon.ico,sha256=tZolYIXkkBcFiYl1A8ksaXN2VjGamzcSdes838dLvNc,15406
30
31
  fastapi_voyager/web/icon/site.webmanifest,sha256=ep4Hzh9zhmiZF2At3Fp1dQrYQuYF_3ZPZxc1KcGBvwQ,263
31
- fastapi_voyager-0.13.2.dist-info/METADATA,sha256=5eGuPGvTPfSymMO8ZAmk-w55w4kytbCD0pK-uCuG5hQ,7777
32
- fastapi_voyager-0.13.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
33
- fastapi_voyager-0.13.2.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
34
- fastapi_voyager-0.13.2.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
35
- fastapi_voyager-0.13.2.dist-info/RECORD,,
32
+ fastapi_voyager-0.14.0.dist-info/METADATA,sha256=uLASxCBmhDKf6-ab8CUkTrKP2HBVclemXmsbc5_OPQA,7869
33
+ fastapi_voyager-0.14.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
34
+ fastapi_voyager-0.14.0.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
35
+ fastapi_voyager-0.14.0.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
36
+ fastapi_voyager-0.14.0.dist-info/RECORD,,