fastapi-voyager 0.12.5__tar.gz → 0.12.6__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.
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/PKG-INFO +1 -1
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/docs/changelog.md +4 -1
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/version.py +1 -1
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/graph-ui.js +36 -20
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/graphviz.svg.js +82 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/.github/workflows/publish.yml +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/.gitignore +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/.python-version +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/CONTRIBUTING.md +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/LICENSE +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/README.md +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/docs/idea.md +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/pyproject.toml +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/release.md +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/__init__.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/cli.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/filter.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/module.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/render.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/server.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/type.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/type_helper.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/voyager.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/component/demo.js +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/component/render-graph.js +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/component/route-code-display.js +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/component/schema-code-display.js +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/component/schema-field-filter.js +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/graphviz.svg.css +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/icon/android-chrome-192x192.png +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/icon/android-chrome-512x512.png +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/icon/apple-touch-icon.png +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/icon/favicon-16x16.png +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/icon/favicon-32x32.png +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/icon/favicon.ico +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/icon/site.webmanifest +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/index.html +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/quasar.min.css +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/quasar.min.js +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/store.js +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/vue-main.js +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/__init__.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/demo.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/demo_anno.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/programatic.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/service/__init__.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/service/schema/__init__.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/service/schema/extra.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/service/schema/schema.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/test_analysis.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/test_filter.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/test_generic.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/test_import.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/test_module.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/tests/test_type_helper.py +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/uv.lock +0 -0
- {fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/voyager.jpg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-voyager
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.6
|
|
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
|
|
@@ -116,9 +116,12 @@
|
|
|
116
116
|
- [x] refactor fe with store based on reactive
|
|
117
117
|
- [x] fix duplicated focus toggle
|
|
118
118
|
- 0.12.6
|
|
119
|
+
- [x] fix overlapped edges
|
|
120
|
+
- [x] click link(edge) to highlight related nodes
|
|
121
|
+
- [x] on hover cursor effect
|
|
122
|
+
- 0.12.7
|
|
119
123
|
- [ ] refactor render.py
|
|
120
124
|
- [ ] remove search component, integrated into main page
|
|
121
|
-
- [ ] click link to highlight related nodes
|
|
122
125
|
|
|
123
126
|
## 0.13
|
|
124
127
|
- 0.13.2
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__all__ = ["__version__"]
|
|
2
|
-
__version__ = "0.12.
|
|
2
|
+
__version__ = "0.12.6"
|
|
@@ -9,14 +9,31 @@ export class GraphUI {
|
|
|
9
9
|
this._init();
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
_highlight() {
|
|
12
|
+
_highlight(mode = "bidirectional") {
|
|
13
13
|
let highlightedNodes = $();
|
|
14
14
|
for (const selection of this.currentSelection) {
|
|
15
|
-
const nodes = this._getAffectedNodes(selection.set,
|
|
15
|
+
const nodes = this._getAffectedNodes(selection.set, mode);
|
|
16
16
|
highlightedNodes = highlightedNodes.add(nodes);
|
|
17
17
|
}
|
|
18
18
|
if (this.gv) {
|
|
19
19
|
this.gv.highlight(highlightedNodes, true);
|
|
20
|
+
this.gv.bringToFront(highlightedNodes);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_highlightEdgeNodes() {
|
|
25
|
+
let highlightedNodes = $();
|
|
26
|
+
const [up, down, edge] = this.currentSelection
|
|
27
|
+
highlightedNodes = highlightedNodes.add(
|
|
28
|
+
this._getAffectedNodes(up.set, up.direction)
|
|
29
|
+
);
|
|
30
|
+
highlightedNodes = highlightedNodes.add(
|
|
31
|
+
this._getAffectedNodes(down.set, down.direction)
|
|
32
|
+
);
|
|
33
|
+
highlightedNodes = highlightedNodes.add(edge.set)
|
|
34
|
+
if (this.gv) {
|
|
35
|
+
this.gv.highlight(highlightedNodes, true);
|
|
36
|
+
this.gv.bringToFront(highlightedNodes);
|
|
20
37
|
}
|
|
21
38
|
}
|
|
22
39
|
|
|
@@ -65,6 +82,7 @@ export class GraphUI {
|
|
|
65
82
|
}
|
|
66
83
|
}
|
|
67
84
|
|
|
85
|
+
|
|
68
86
|
_init() {
|
|
69
87
|
const self = this;
|
|
70
88
|
$(this.selector).graphviz({
|
|
@@ -93,13 +111,20 @@ export class GraphUI {
|
|
|
93
111
|
});
|
|
94
112
|
|
|
95
113
|
self.gv.edges().click(function (event) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
114
|
+
const up = $();
|
|
115
|
+
const down = $();
|
|
116
|
+
const edge = $();
|
|
117
|
+
const [upStreamNode, downStreamNode] = event.currentTarget.dataset.name.split("->");
|
|
118
|
+
const nodes = self.gv.nodesByName();
|
|
119
|
+
up.push(nodes[upStreamNode]);
|
|
120
|
+
down.push(nodes[downStreamNode]);
|
|
121
|
+
edge.push(this)
|
|
122
|
+
const upObj = { set: up, direction: "upstream" };
|
|
123
|
+
const downObj = { set: down, direction: "downstream" };
|
|
124
|
+
const edgeOjb = { set: edge, direction: "single"};
|
|
125
|
+
self.currentSelection = [upObj, downObj, edgeOjb];
|
|
126
|
+
|
|
127
|
+
self._highlightEdgeNodes();
|
|
103
128
|
})
|
|
104
129
|
|
|
105
130
|
self.gv.nodes().click(function (event) {
|
|
@@ -127,15 +152,6 @@ export class GraphUI {
|
|
|
127
152
|
}
|
|
128
153
|
});
|
|
129
154
|
|
|
130
|
-
self.gv.clusters().click(function (event) {
|
|
131
|
-
const set = $();
|
|
132
|
-
set.push(this);
|
|
133
|
-
const obj = { set, direction: "single" };
|
|
134
|
-
self.currentSelection = [obj];
|
|
135
|
-
self._highlight();
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// click background to reset highlight
|
|
139
155
|
$(document)
|
|
140
156
|
.off("click.graphui")
|
|
141
157
|
.on("click.graphui", function (evt) {
|
|
@@ -150,9 +166,9 @@ export class GraphUI {
|
|
|
150
166
|
}
|
|
151
167
|
|
|
152
168
|
let isNode = false;
|
|
153
|
-
const $
|
|
169
|
+
const $everything = self.gv.$nodes.add(self.gv.$edges).add(self.gv.$clusters);
|
|
154
170
|
const node = evt.target.parentNode;
|
|
155
|
-
$
|
|
171
|
+
$everything.each(function () {
|
|
156
172
|
if (this === node) {
|
|
157
173
|
isNode = true;
|
|
158
174
|
}
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
url: null,
|
|
22
22
|
svg: null,
|
|
23
23
|
shrink: "0.125pt",
|
|
24
|
+
edgeHitPadding: 12,
|
|
25
|
+
pointerCursor: true,
|
|
24
26
|
tooltips: {
|
|
25
27
|
init: function ($graph) {
|
|
26
28
|
var $a = $(this);
|
|
@@ -168,9 +170,20 @@
|
|
|
168
170
|
var that = this;
|
|
169
171
|
var options = this.options;
|
|
170
172
|
|
|
173
|
+
if (type === "edge" && options.edgeHitPadding) {
|
|
174
|
+
this.ensureEdgeHitArea($el, options.edgeHitPadding);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (options.pointerCursor && (type === "edge" || type === "node")) {
|
|
178
|
+
this.setInteractiveCursor($el, type === "edge");
|
|
179
|
+
}
|
|
180
|
+
|
|
171
181
|
// save the colors of the paths, ellipses and polygons
|
|
172
182
|
$el.find("polygon, ellipse, path").each(function () {
|
|
173
183
|
var $this = $(this);
|
|
184
|
+
if ($this.attr("data-graphviz-hitbox") === "true") {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
174
187
|
// save original colors
|
|
175
188
|
$this.data("graphviz.svg.color", {
|
|
176
189
|
fill: $this.attr("fill"),
|
|
@@ -314,6 +327,69 @@
|
|
|
314
327
|
}
|
|
315
328
|
};
|
|
316
329
|
|
|
330
|
+
GraphvizSvg.prototype.ensureEdgeHitArea = function ($edge, padding) {
|
|
331
|
+
var width = parseFloat(padding);
|
|
332
|
+
if (!isFinite(width) || width <= 0) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
var $paths = $edge
|
|
336
|
+
.children("path")
|
|
337
|
+
.filter(function () {
|
|
338
|
+
return $(this).attr("data-graphviz-hitbox") !== "true";
|
|
339
|
+
});
|
|
340
|
+
if (!$paths.length) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
$paths.each(function () {
|
|
344
|
+
var $path = $(this);
|
|
345
|
+
var $existing = $path.prev('[data-graphviz-hitbox="true"]');
|
|
346
|
+
if ($existing.length) {
|
|
347
|
+
$existing.attr("stroke-width", width);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
var clone = this.cloneNode(false);
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* gtp-5-codex:
|
|
354
|
+
* Cloning the edge paths without copying D3’s data binding caused those Cannot
|
|
355
|
+
* read properties of undefined (reading 'key') errors when d3-graphviz re-rendered.
|
|
356
|
+
* I now copy the original path’s bound datum (__data__) onto the transparent hitbox
|
|
357
|
+
* clone inside ensureEdgeHitArea, so D3 still finds the expected metadata.
|
|
358
|
+
*/
|
|
359
|
+
if (this.__data__) {
|
|
360
|
+
clone.__data__ = this.__data__;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
var $clone = $(clone);
|
|
364
|
+
$clone.attr({
|
|
365
|
+
"data-graphviz-hitbox": "true",
|
|
366
|
+
stroke: "transparent",
|
|
367
|
+
fill: "none",
|
|
368
|
+
"stroke-width": width,
|
|
369
|
+
});
|
|
370
|
+
$clone.attr("pointer-events", "stroke");
|
|
371
|
+
$clone.css("pointer-events", "stroke");
|
|
372
|
+
if (!$clone.attr("stroke-linecap")) {
|
|
373
|
+
$clone.attr("stroke-linecap", $path.attr("stroke-linecap") || "round");
|
|
374
|
+
}
|
|
375
|
+
$clone.insertBefore($path);
|
|
376
|
+
});
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
GraphvizSvg.prototype.setInteractiveCursor = function ($el, isEdge) {
|
|
380
|
+
$el.css("cursor", "pointer");
|
|
381
|
+
var selectors = "path, polygon, ellipse, rect, text";
|
|
382
|
+
$el.find(selectors).each(function () {
|
|
383
|
+
$(this).css("cursor", "pointer");
|
|
384
|
+
});
|
|
385
|
+
if (isEdge) {
|
|
386
|
+
$el.children('[data-graphviz-hitbox="true"]').css("cursor", "pointer");
|
|
387
|
+
}
|
|
388
|
+
$el.find("a").each(function () {
|
|
389
|
+
$(this).css("cursor", "pointer");
|
|
390
|
+
});
|
|
391
|
+
};
|
|
392
|
+
|
|
317
393
|
GraphvizSvg.prototype.convertToPx = function (val) {
|
|
318
394
|
var retval = val;
|
|
319
395
|
if (typeof val == "string") {
|
|
@@ -372,6 +448,9 @@
|
|
|
372
448
|
var bg = this.$element.css("background");
|
|
373
449
|
$el.find("polygon, ellipse, path").each(function () {
|
|
374
450
|
var $this = $(this);
|
|
451
|
+
if ($this.attr("data-graphviz-hitbox") === "true") {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
375
454
|
var color = $this.data("graphviz.svg.color");
|
|
376
455
|
if (color.fill && color.fill != "none") {
|
|
377
456
|
$this.attr("fill", getColor(color.fill, bg)); // don't set fill if it's a path
|
|
@@ -386,6 +465,9 @@
|
|
|
386
465
|
GraphvizSvg.prototype.restoreElement = function ($el) {
|
|
387
466
|
$el.find("polygon, ellipse, path").each(function () {
|
|
388
467
|
var $this = $(this);
|
|
468
|
+
if ($this.attr("data-graphviz-hitbox") === "true") {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
389
471
|
var color = $this.data("graphviz.svg.color");
|
|
390
472
|
if (color.fill && color.fill != "none") {
|
|
391
473
|
$this.attr("fill", color.fill); // don't set fill if it's a path
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/component/render-graph.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/icon/apple-touch-icon.png
RENAMED
|
File without changes
|
{fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/icon/favicon-16x16.png
RENAMED
|
File without changes
|
{fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/icon/favicon-32x32.png
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_voyager-0.12.5 → fastapi_voyager-0.12.6}/src/fastapi_voyager/web/icon/site.webmanifest
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|