fastapi-voyager 0.15.3__py3-none-any.whl → 0.15.4__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/server.py CHANGED
@@ -19,6 +19,7 @@ WEB_DIR = Path(__file__).parent / "web"
19
19
  WEB_DIR.mkdir(exist_ok=True)
20
20
 
21
21
  GA_PLACEHOLDER = "<!-- GA_SNIPPET -->"
22
+ VERSION_PLACEHOLDER = "<!-- VERSION_PLACEHOLDER -->"
22
23
 
23
24
  def _build_ga_snippet(ga_id: str | None) -> str:
24
25
  if not ga_id:
@@ -197,7 +198,9 @@ def create_voyager(
197
198
  index_file = WEB_DIR / "index.html"
198
199
  if index_file.exists():
199
200
  content = index_file.read_text(encoding="utf-8")
200
- return content.replace(GA_PLACEHOLDER, _build_ga_snippet(ga_id))
201
+ content = content.replace(GA_PLACEHOLDER, _build_ga_snippet(ga_id))
202
+ content = content.replace(VERSION_PLACEHOLDER, f"?v={__version__}")
203
+ return content
201
204
  # fallback simple page if index.html missing
202
205
  return """
203
206
  <!doctype html>
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "0.15.3"
2
+ __version__ = "0.15.4"
@@ -69,10 +69,45 @@ export class GraphUI {
69
69
  }
70
70
 
71
71
  highlightSchemaBanner(node) {
72
+ // Get all polygons in the node
72
73
  const polygons = node.querySelectorAll("polygon")
73
- const ele = polygons[2] // select the second polygon
74
- if (ele) {
75
- ele.setAttribute("stroke-width", "3.5")
74
+
75
+ // The first polygon is typically the outer frame of the entire node
76
+ const outerFrame = polygons[0]
77
+ // The second polygon is typically the title background
78
+ const titleBg = polygons[1]
79
+
80
+ if (outerFrame) {
81
+ // Save original attributes for potential restoration
82
+ if (!outerFrame.hasAttribute("data-original-stroke")) {
83
+ outerFrame.setAttribute("data-original-stroke", outerFrame.getAttribute("stroke") || "")
84
+ outerFrame.setAttribute(
85
+ "data-original-stroke-width",
86
+ outerFrame.getAttribute("stroke-width") || "1"
87
+ )
88
+ outerFrame.setAttribute("data-original-fill", outerFrame.getAttribute("fill") || "")
89
+ }
90
+
91
+ // Apply bold purple border to the outer frame
92
+ outerFrame.setAttribute("stroke", "#822dba")
93
+ outerFrame.setAttribute("stroke-width", "3.0")
94
+ }
95
+
96
+ if (titleBg) {
97
+ // Save original attributes
98
+ if (!titleBg.hasAttribute("data-original-stroke")) {
99
+ titleBg.setAttribute("data-original-stroke", titleBg.getAttribute("stroke") || "")
100
+ titleBg.setAttribute(
101
+ "data-original-stroke-width",
102
+ titleBg.getAttribute("stroke-width") || "1"
103
+ )
104
+ titleBg.setAttribute("data-original-fill", titleBg.getAttribute("fill") || "")
105
+ }
106
+
107
+ // Apply purple background to title
108
+ titleBg.setAttribute("fill", "#822dba")
109
+ // Also update the stroke to match
110
+ titleBg.setAttribute("stroke", "#822dba")
76
111
  }
77
112
  }
78
113
 
@@ -2,8 +2,14 @@
2
2
  <head>
3
3
  <title>FastAPI Voyager</title>
4
4
  <meta name="theme-color" content="#ffffff" />
5
- <link rel="stylesheet" href="fastapi-voyager-static/graphviz.svg.css" />
6
- <link rel="stylesheet" href="fastapi-voyager-static/quasar.min.css" />
5
+ <link
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 -->"
12
+ />
7
13
  <!-- App Icons / Favicons -->
8
14
  <link
9
15
  rel="apple-touch-icon"
@@ -111,8 +117,6 @@
111
117
  border-radius: 50%;
112
118
  background: #009485;
113
119
  color: white;
114
- border: 2px solid white;
115
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
116
120
  cursor: pointer;
117
121
  display: flex;
118
122
  align-items: center;
@@ -284,10 +288,15 @@
284
288
  aria-label="Help"
285
289
  style="margin-right: 50px; margin-left: 20px"
286
290
  >
287
- <q-tooltip anchor="bottom middle" self="top middle" :offset="[0,8]">
291
+ <q-tooltip
292
+ anchor="bottom middle"
293
+ self="top middle"
294
+ :offset="[0,8]"
295
+ style="background-color: #f5f5f5; color: black; border: 1px solid #666"
296
+ >
288
297
  <div
289
298
  class="column items-start text-left"
290
- style="line-height: 1.4; font-size: 12px"
299
+ style="line-height: 1.4; font-size: 14px"
291
300
  >
292
301
  <ul>
293
302
  <li>scroll to zoom in/out</li>
@@ -571,7 +580,7 @@
571
580
  </q-dialog>
572
581
  </div>
573
582
  <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
574
- <script src="fastapi-voyager-static/quasar.min.js"></script>
583
+ <script src="fastapi-voyager-static/quasar.min.js<!-- VERSION_PLACEHOLDER -->"></script>
575
584
  <script
576
585
  src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"
577
586
  integrity="sha512-egJ/Y+22P9NQ9aIyVCh0VCOsfydyn8eNmqBy+y2CnJG+fpRIxXMS6jbWP8tVKp0jp+NO5n8WtMUAnNnGoJKi4w=="
@@ -593,7 +602,7 @@
593
602
  ></script>
594
603
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"></script>
595
604
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-color/2.1.2/jquery.color.min.js"></script>
596
- <script src="fastapi-voyager-static/graphviz.svg.js"></script>
605
+ <script src="fastapi-voyager-static/graphviz.svg.js<!-- VERSION_PLACEHOLDER -->"></script>
597
606
  <!-- highlight.js minimal ES module load (python only) -->
598
607
  <link
599
608
  rel="stylesheet"
@@ -615,7 +624,10 @@
615
624
  }
616
625
  })
617
626
  </script>
618
- <script type="module" src="fastapi-voyager-static/vue-main.js"></script>
627
+ <script
628
+ type="module"
629
+ src="fastapi-voyager-static/vue-main.js<!-- VERSION_PLACEHOLDER -->"
630
+ ></script>
619
631
 
620
632
  <!-- GA_SNIPPET -->
621
633
  </body>
@@ -120,22 +120,23 @@ const getters = {
120
120
 
121
121
  const actions = {
122
122
  /**
123
- * Read tag and route from URL query parameters
124
- * @returns {{ tag: string|null, route: string|null }}
123
+ * Read tag, route and mode from URL query parameters
124
+ * @returns {{ tag: string|null, route: string|null, mode: string|null }}
125
125
  */
126
126
  readQuerySelection() {
127
127
  if (typeof window === "undefined") {
128
- return { tag: null, route: null }
128
+ return { tag: null, route: null, mode: null }
129
129
  }
130
130
  const params = new URLSearchParams(window.location.search)
131
131
  return {
132
132
  tag: params.get("tag") || null,
133
133
  route: params.get("route") || null,
134
+ mode: params.get("mode") || null,
134
135
  }
135
136
  },
136
137
 
137
138
  /**
138
- * Sync current tag and route selection to URL
139
+ * Sync current tag, route and mode selection to URL
139
140
  * Updates browser URL without reloading the page
140
141
  */
141
142
  syncSelectionToUrl() {
@@ -153,6 +154,12 @@ const actions = {
153
154
  } else {
154
155
  params.delete("route")
155
156
  }
157
+ // Always sync mode to URL for consistency
158
+ if (state.mode) {
159
+ params.set("mode", state.mode)
160
+ } else {
161
+ params.delete("mode")
162
+ }
156
163
  const hash = window.location.hash || ""
157
164
  const search = params.toString()
158
165
  const base = window.location.pathname
@@ -162,7 +169,7 @@ const actions = {
162
169
 
163
170
  /**
164
171
  * Apply selection from URL query parameters to state
165
- * @param {{ tag: string|null, route: string|null }} selection
172
+ * @param {{ tag: string|null, route: string|null, mode: string|null }} selection
166
173
  * @returns {boolean} - true if any selection was applied
167
174
  */
168
175
  applySelectionFromQuery(selection) {
@@ -181,6 +188,11 @@ const actions = {
181
188
  state.leftPanel._tag = inferredTag
182
189
  }
183
190
  }
191
+ // Apply mode from URL if it's valid
192
+ if (selection.mode === "voyager" || selection.mode === "er-diagram") {
193
+ state.mode = selection.mode
194
+ applied = true
195
+ }
184
196
  return applied
185
197
  },
186
198
 
@@ -304,6 +316,15 @@ const actions = {
304
316
  return
305
317
  } else {
306
318
  state.config.initial_page_policy = data.initial_page_policy
319
+ // Check if mode was applied from URL even if tag/route wasn't
320
+ if (
321
+ querySelection.mode &&
322
+ (querySelection.mode === "voyager" || querySelection.mode === "er-diagram")
323
+ ) {
324
+ this.syncSelectionToUrl()
325
+ onGenerate()
326
+ return
327
+ }
307
328
  renderBasedOnInitialPolicy()
308
329
  }
309
330
 
@@ -163,12 +163,14 @@ const app = createApp({
163
163
  store.state.leftPanel.previousWidth = store.state.leftPanel.width
164
164
  }
165
165
  store.state.leftPanel.width = 0
166
+ store.actions.syncSelectionToUrl()
166
167
  await renderErDiagram()
167
168
  } else {
168
169
  store.state.search.invisible = false
169
170
 
170
171
  const fallbackWidth = store.state.leftPanel.previousWidth || 300
171
172
  store.state.leftPanel.width = fallbackWidth
173
+ store.actions.syncSelectionToUrl()
172
174
  await onGenerate()
173
175
  }
174
176
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-voyager
3
- Version: 0.15.3
3
+ Version: 0.15.4
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
@@ -6,10 +6,10 @@ fastapi_voyager/module.py,sha256=h9YR3BpS-CAcJW9WCdVkF4opqwY32w9T67g9GfdLytk,342
6
6
  fastapi_voyager/pydantic_resolve_util.py,sha256=r4Rq7BtBcFOMV7O2Ab9TwLyRNL1yNDiQlGUVybf-sXs,3524
7
7
  fastapi_voyager/render.py,sha256=5tTuvvCCUwFCq3WJGT1rfTSW41mSDoVyJwMyQGrmhiQ,17271
8
8
  fastapi_voyager/render_style.py,sha256=mPOuChEl71-3agCbPwkMt2sFmax2AEKDI6dK90eFPRc,2552
9
- fastapi_voyager/server.py,sha256=MUc_ia3_QIbYQ8VenOxv3CEYVTiPDs7e_H40YoalxZs,8970
9
+ fastapi_voyager/server.py,sha256=E0gGU7D1pBvnV7gFLBUvnkwtiBFbU1PbxEXHHSIA1oA,9115
10
10
  fastapi_voyager/type.py,sha256=zluWvh5vpnjXJ9aAmyNJTSmXZPjAHCvgRT5oQRAjHrg,2104
11
11
  fastapi_voyager/type_helper.py,sha256=FmfrZAI3Z4uDdh3sH_kH7UGoY6yNVPapneSN86qY_wo,10209
12
- fastapi_voyager/version.py,sha256=mV_h7Kelwuchi4ZvsHaY1gjoGeeu7EK0TqrMYIGLwgI,49
12
+ fastapi_voyager/version.py,sha256=AgJGrnhFIPGdn_tW4I4oEPuyTOgMXEkK0I5qVj2kag0,49
13
13
  fastapi_voyager/voyager.py,sha256=4vonmL-xt54C5San-DRBq4mjoV8Q96eoWRy68MJ1IJw,14169
14
14
  fastapi_voyager/templates/dot/cluster.j2,sha256=I2z9KkfCzmAtqXe0gXBnxnOfBXUSpdlATs3uf-O8_B8,307
15
15
  fastapi_voyager/templates/dot/cluster_container.j2,sha256=2tH1mOJvPoVKE_aHVMR3t06TfH_dYa9OeH6DBqSHt_A,204
@@ -24,14 +24,14 @@ fastapi_voyager/templates/html/pydantic_meta.j2,sha256=_tsSqjucs_QrAlPIVRy9u6I2-
24
24
  fastapi_voyager/templates/html/schema_field_row.j2,sha256=KfKexHO_QJV-OIJS0eiY_7fqA8031fWpD2g2wTv4BuE,111
25
25
  fastapi_voyager/templates/html/schema_header.j2,sha256=9WpuHLy3Zbv5GHG08qqaj5Xf-gaR-79ErBYuANZp7iA,179
26
26
  fastapi_voyager/templates/html/schema_table.j2,sha256=rzphiGk1il7uv4Gr2p_HLPHqyLZk63vLrGAmIduTdSE,117
27
- fastapi_voyager/web/graph-ui.js,sha256=cmEcM35rQsR6eQA2Sc8zJ_MOA0UfEQ9WvGA1zNInUUc,6285
27
+ fastapi_voyager/web/graph-ui.js,sha256=4gEkXTgbA6CouD4IDMW5yKYfJTxHN2vL9G0CAr6w4qA,7662
28
28
  fastapi_voyager/web/graphviz.svg.css,sha256=K218ov_mdSe3ga4KwhiBB92ynVvm5zaAk9_D9a3d8hE,1546
29
29
  fastapi_voyager/web/graphviz.svg.js,sha256=deI815RgxpZ3_MpELeV-TBYy2MVuUvZtQOHfS3aeXHY,18203
30
- fastapi_voyager/web/index.html,sha256=lA59Op4u1bb-B105Iadn2KN_n11-AtXFdJglUezZIDg,23225
30
+ fastapi_voyager/web/index.html,sha256=wM9vJ_UfHR8p98F6SEMCKKjJcBEl0EyosWuPqVZYXvA,23496
31
31
  fastapi_voyager/web/quasar.min.css,sha256=F5jQe7X2XT54VlvAaa2V3GsBFdVD-vxDZeaPLf6U9CU,203145
32
32
  fastapi_voyager/web/quasar.min.js,sha256=h0ftyPMW_CRiyzeVfQqiup0vrVt4_QWojpqmpnpn07E,502974
33
- fastapi_voyager/web/store.js,sha256=zjmtx1HGN_umfyOQVwQgET-2V5hvXbS50YgXCr294Ok,14370
34
- fastapi_voyager/web/vue-main.js,sha256=1s11NOjILgjncJ4WbN1DGzTeLUb0a2-LYIA3lUIX8Bc,10564
33
+ fastapi_voyager/web/store.js,sha256=7anY7HGF7aEx1xpXWz58Ca5WbnYCRnzdj7kqNjcaT_M,15103
34
+ fastapi_voyager/web/vue-main.js,sha256=4lJi6ADrcaOzjXcQePkp7CyiCkAnvhnO-nkF3E6G3s4,10650
35
35
  fastapi_voyager/web/component/demo.js,sha256=sAklFGhKGmMy9-ofgOw2oPIidAoIOgHu6yvV51L_MAA,350
36
36
  fastapi_voyager/web/component/render-graph.js,sha256=9wnO70n3eyPKTpa744idgs5PSwgvzbfv4InZ68eEOKs,2454
37
37
  fastapi_voyager/web/component/route-code-display.js,sha256=a823nBz3EEjutW2pfi73rcF3hodCBmgYNmuZi94sXE4,3615
@@ -43,8 +43,8 @@ fastapi_voyager/web/icon/favicon-16x16.png,sha256=JC07jEzfIYxBIoQn_FHXvyHuxESdhW
43
43
  fastapi_voyager/web/icon/favicon-32x32.png,sha256=C7v1h58cfWOsiLp9yOIZtlx-dLasBcq3NqpHVGRmpt4,1859
44
44
  fastapi_voyager/web/icon/favicon.ico,sha256=tZolYIXkkBcFiYl1A8ksaXN2VjGamzcSdes838dLvNc,15406
45
45
  fastapi_voyager/web/icon/site.webmanifest,sha256=GRozZ5suTykYcPMap1QhjrAB8PLW0mbT_phhzw_utvQ,316
46
- fastapi_voyager-0.15.3.dist-info/METADATA,sha256=_NFcPd07mWHADnTH01kf6c2y0Lw9AQgqQNnHMK0Y5xE,8513
47
- fastapi_voyager-0.15.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
48
- fastapi_voyager-0.15.3.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
49
- fastapi_voyager-0.15.3.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
50
- fastapi_voyager-0.15.3.dist-info/RECORD,,
46
+ fastapi_voyager-0.15.4.dist-info/METADATA,sha256=6BftnkJpr0w8cKiAubLyJ6ZiOeGmvlkOwE9jZLZ5UMM,8513
47
+ fastapi_voyager-0.15.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
48
+ fastapi_voyager-0.15.4.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
49
+ fastapi_voyager-0.15.4.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
50
+ fastapi_voyager-0.15.4.dist-info/RECORD,,