Graphinate 0.5.1__tar.gz → 0.6.0__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.
- {graphinate-0.5.1 → graphinate-0.6.0}/.github/workflows/publish.yml +1 -1
- {graphinate-0.5.1 → graphinate-0.6.0}/.github/workflows/test.yml +1 -1
- {graphinate-0.5.1 → graphinate-0.6.0}/PKG-INFO +3 -1
- {graphinate-0.5.1 → graphinate-0.6.0}/README.md +2 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/intro.md +14 -10
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/usage/cli.md +8 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/math/graph_atlas.py +2 -6
- {graphinate-0.5.1 → graphinate-0.6.0}/mkdocs.yml +6 -2
- {graphinate-0.5.1 → graphinate-0.6.0}/pyproject.toml +9 -9
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/builders.py +4 -3
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/__init__.py +12 -4
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/rapidoc/index.html +3 -2
- graphinate-0.6.0/src/graphinate/server/web/viewer/index.html +542 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_builders.py +2 -2
- graphinate-0.5.1/src/graphinate/server/web/viewer/index.html +0 -162
- {graphinate-0.5.1 → graphinate-0.6.0}/.coveragerc +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/.github/dependabot.yml +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/.github/workflows/codeql.yml +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/.github/workflows/publish-docs.yaml +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/.github/workflows/test-beta.yml +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/.gitignore +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/.sonarcloud.properties +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/LICENSE +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/STATS.md +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/acknowledge.md +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/assets/badge/v0.json +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/assets/images/logo-128.png +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/assets/images/network_graph.png +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/assets/stylesheets/extra.css +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/dev.md +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/examples/code.md +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/examples/github.md +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/examples/math.md +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/examples/system.md +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/examples/web.md +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/gen_ref_pages.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/index.md +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/start.md +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/docs/usage/lib.md +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/code/python_ast.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/code/python_dependencies.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/code/requirements.txt +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/_client.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/commits_visibilty_graph.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/followers.graphql +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/followers.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/graphql.config.yml +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/repositories.graphql +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/repositories.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/requirements.txt +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/math/graphs.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/math/gui.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/math/polygonal_graph.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/math/requirements.txt +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/system/processes.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/system/requirements.txt +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/web/page_links.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/examples/web/requirements.txt +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/playground/ethernet/traceroute.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/playground/genric_graph.graphql +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/playground/graphql.config.yml +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/playground/house_of_graphs.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/playground/social/albums.json +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/playground/social/musicisians.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/playground/text/nlp_graph.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/playground/text/requirements.txt +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/playground/time_series/requirements.txt +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/playground/time_series/visibility_graph.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/sonar-project.properties +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/__init__.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/__main__.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/cli.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/color.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/materializers/__init__.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/materializers/matplotlib.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/modeling.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/starlette/__init__.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/starlette/views.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/__init__.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/elements/__init__.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/elements/index.html +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/graphiql/__init__.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/graphiql/index.html +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/rapidoc/__init__.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/static/images/logo-128.png +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/static/images/logo.svg +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/static/images/network_graph.png +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/viewer/__init__.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/voyager/__init__.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/voyager/index.html +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/tools/__init__.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/tools/converters.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/tools/mutators.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/typing.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/tests/conftest.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_cli.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_color.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_materializers.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_modeling.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_server.py +0 -0
- {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_tools.py +0 -0
|
@@ -28,7 +28,7 @@ jobs:
|
|
|
28
28
|
- name: Build package
|
|
29
29
|
run: python -m build
|
|
30
30
|
- name: Publish package
|
|
31
|
-
uses: pypa/gh-action-pypi-publish@
|
|
31
|
+
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc
|
|
32
32
|
with:
|
|
33
33
|
user: __token__
|
|
34
34
|
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -40,7 +40,7 @@ jobs:
|
|
|
40
40
|
python -m pip install faker pytest pytest-asyncio pytest-cov pytest-randomly pytest-xdist starlette-prometheus uvicorn[standard]
|
|
41
41
|
pytest tests --cov=src --cov-branch --cov-report=xml --junitxml=test_results.xml -n auto
|
|
42
42
|
- name: Upload coverage reports to Codecov
|
|
43
|
-
uses: codecov/codecov-action@
|
|
43
|
+
uses: codecov/codecov-action@v5
|
|
44
44
|
with:
|
|
45
45
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
46
46
|
- name: Run codacy-coverage-reporter
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Graphinate
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: 𝔾raphinate. Data to Graphs.
|
|
5
5
|
Project-URL: Homepage, https://erivlis.github.io/graphinate
|
|
6
6
|
Project-URL: Documentation, https://erivlis.github.io/graphinate
|
|
@@ -221,6 +221,8 @@ Options:
|
|
|
221
221
|
|
|
222
222
|
#### Server
|
|
223
223
|
|
|
224
|
+
> TIP: requires the `server` extra to be installed. e.g., `pip install graphinate[server]`
|
|
225
|
+
|
|
224
226
|
```text
|
|
225
227
|
Usage: python -m graphinate server [OPTIONS]
|
|
226
228
|
|
|
@@ -15,21 +15,25 @@ In addition, there are several modes of output to enable examination of the Grap
|
|
|
15
15
|
|
|
16
16
|
### What is a Graph?
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
of them.
|
|
20
|
-
The points of a graph are most commonly known as graph *vertices*, but may also be called *nodes* or *points*.
|
|
21
|
-
Similarly, the lines connecting the vertices of a graph are most commonly known as graph *edges*, but may also
|
|
22
|
-
be called *arcs* or *lines*.”
|
|
18
|
+
!!! quote
|
|
23
19
|
|
|
24
|
-
|
|
20
|
+
“In a mathematician's terminology, a graph is a collection of points and lines connecting some (possibly empty) subset
|
|
21
|
+
of them.
|
|
22
|
+
The points of a graph are most commonly known as graph *vertices*, but may also be called *nodes* or *points*.
|
|
23
|
+
Similarly, the lines connecting the vertices of a graph are most commonly known as graph *edges*, but may also
|
|
24
|
+
be called *arcs* or *lines*.”
|
|
25
|
+
|
|
26
|
+
— [https://mathworld.wolfram.com/Graph.html](https://mathworld.wolfram.com/Graph.html)
|
|
25
27
|
|
|
26
28
|
### What is Data?
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
fact, statistics, other basic units of meaning, or simply sequences of symbols that may be further interpreted
|
|
30
|
-
formally.”
|
|
30
|
+
!!! quote
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
“...data is a collection of discrete or continuous values that convey information, describing the quantity, quality,
|
|
33
|
+
fact, statistics, other basic units of meaning, or simply sequences of symbols that may be further interpreted
|
|
34
|
+
formally.”
|
|
35
|
+
|
|
36
|
+
— [https://en.wikipedia.org/wiki/Data](https://en.wikipedia.org/wiki/Data)
|
|
33
37
|
|
|
34
38
|
## How?
|
|
35
39
|
|
|
@@ -38,13 +38,9 @@ def model(items: list[tuple[str, nx.Graph]]) -> graphinate.GraphModel:
|
|
|
38
38
|
def nodes():
|
|
39
39
|
yield from g.nodes(data='type')
|
|
40
40
|
|
|
41
|
-
@graph_model.edge(operator.itemgetter(
|
|
42
|
-
source=operator.itemgetter(0),
|
|
43
|
-
target=operator.itemgetter(1),
|
|
44
|
-
label=operator.itemgetter(0, 1),
|
|
45
|
-
value=operator.itemgetter(0, 1))
|
|
41
|
+
@graph_model.edge(operator.itemgetter('type'))
|
|
46
42
|
def edge():
|
|
47
|
-
yield from g.edges.data(
|
|
43
|
+
yield from ({'source': e[0], 'target': e[1], **e[2]} for e in g.edges.data())
|
|
48
44
|
|
|
49
45
|
return graph_model
|
|
50
46
|
|
|
@@ -101,8 +101,12 @@ extra:
|
|
|
101
101
|
link: https://pypi.org/project/graphinate
|
|
102
102
|
- icon: fontawesome/brands/mastodon
|
|
103
103
|
link: https://mastodon.social/@erivlis
|
|
104
|
-
- icon: fontawesome/brands/
|
|
105
|
-
link: https://
|
|
104
|
+
- icon: fontawesome/brands/bluesky
|
|
105
|
+
link: https://bsky.app/profile/erivlis.bsky.social
|
|
106
|
+
- icon: fontawesome/brands/x-twitter
|
|
107
|
+
link: https://x.com/erivlis
|
|
108
|
+
- icon: fontawesome/brands/linkedin
|
|
109
|
+
link: https://www.linkedin.com/in/eranrivlis
|
|
106
110
|
|
|
107
111
|
|
|
108
112
|
plugins:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "Graphinate"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.6.0"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name = "Eran Rivlis", email = "eran@rivlis.info" },
|
|
6
6
|
]
|
|
@@ -36,14 +36,6 @@ dependencies = [
|
|
|
36
36
|
"strawberry-graphql[asgi,opentelemetry]"
|
|
37
37
|
]
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
[project.urls]
|
|
41
|
-
"Homepage" = "https://erivlis.github.io/graphinate"
|
|
42
|
-
"Documentation" = "https://erivlis.github.io/graphinate"
|
|
43
|
-
"Bug Tracker" = "https://github.com/erivlis/graphinate/issues"
|
|
44
|
-
"Source" = "https://github.com/erivlis/graphinate"
|
|
45
|
-
|
|
46
|
-
|
|
47
39
|
[project.optional-dependencies]
|
|
48
40
|
plot = [
|
|
49
41
|
"scipy"
|
|
@@ -53,8 +45,16 @@ server = [
|
|
|
53
45
|
"uvicorn[standard]"
|
|
54
46
|
]
|
|
55
47
|
|
|
48
|
+
[project.urls]
|
|
49
|
+
"Homepage" = "https://erivlis.github.io/graphinate"
|
|
50
|
+
"Documentation" = "https://erivlis.github.io/graphinate"
|
|
51
|
+
"Bug Tracker" = "https://github.com/erivlis/graphinate/issues"
|
|
52
|
+
"Source" = "https://github.com/erivlis/graphinate"
|
|
53
|
+
|
|
54
|
+
|
|
56
55
|
[dependency-groups]
|
|
57
56
|
dev = [
|
|
57
|
+
"uv",
|
|
58
58
|
"ruff",
|
|
59
59
|
"pipdeptree"
|
|
60
60
|
]
|
|
@@ -30,7 +30,7 @@ from .tools import converters, mutators, utcnow
|
|
|
30
30
|
from .typing import NodeTypeAbsoluteId, UniverseNode
|
|
31
31
|
|
|
32
32
|
DEFAULT_NODE_DELIMITER = ' ∋ '
|
|
33
|
-
DEFAULT_EDGE_DELIMITER = '
|
|
33
|
+
DEFAULT_EDGE_DELIMITER = ' ⟹ '
|
|
34
34
|
|
|
35
35
|
GraphRepresentation = Union[dict, nx.Graph, strawberry.Schema] # noqa: UP007
|
|
36
36
|
|
|
@@ -235,13 +235,14 @@ class NetworkxBuilder(Builder):
|
|
|
235
235
|
for edge_generator in edge_generators:
|
|
236
236
|
for edge in edge_generator(**kwargs):
|
|
237
237
|
edge_id = ((edge.source,), (edge.target,))
|
|
238
|
+
edge_label = edge.label(edge_id) if callable(edge.label) else edge.label
|
|
238
239
|
edge_weight = edge.weight or 1.0
|
|
239
240
|
edge_type = edge.type.lower()
|
|
240
241
|
logger.debug("Adding edge from: '{}' to: '{}'", *edge_id)
|
|
241
242
|
|
|
242
243
|
if isinstance(self._graph, nx.MultiGraph) or edge_id not in self._graph.edges:
|
|
243
244
|
self._graph.add_edge(*edge_id,
|
|
244
|
-
label=
|
|
245
|
+
label=edge_label,
|
|
245
246
|
type=edge_type,
|
|
246
247
|
value=[edge.value],
|
|
247
248
|
weight=edge_weight,
|
|
@@ -277,7 +278,7 @@ class NetworkxBuilder(Builder):
|
|
|
277
278
|
for name, default in defaults.items():
|
|
278
279
|
if callable(default):
|
|
279
280
|
values = {tuple(e): default(tuple(e)) for *e, a in self._graph_edges(data=name, default=None)
|
|
280
|
-
if a is None}
|
|
281
|
+
if a is not None}
|
|
281
282
|
elif isinstance(default, dict):
|
|
282
283
|
values = default
|
|
283
284
|
elif default:
|
|
@@ -4,6 +4,7 @@ import webbrowser
|
|
|
4
4
|
import strawberry
|
|
5
5
|
from starlette.applications import Starlette
|
|
6
6
|
from starlette.requests import Request
|
|
7
|
+
from starlette.responses import RedirectResponse
|
|
7
8
|
from starlette.schemas import SchemaGenerator
|
|
8
9
|
from starlette.types import ASGIApp
|
|
9
10
|
from strawberry.asgi import GraphQL
|
|
@@ -28,7 +29,7 @@ def openapi_schema(request: Request) -> ASGIApp:
|
|
|
28
29
|
"""
|
|
29
30
|
schema_data = {
|
|
30
31
|
'openapi': '3.0.0',
|
|
31
|
-
'info': {'title': 'Graphinate API', 'version': '0.
|
|
32
|
+
'info': {'title': 'Graphinate API', 'version': '0.6.0'},
|
|
32
33
|
'paths': {
|
|
33
34
|
'/graphql': {'get': {'responses': {200: {'description': 'GraphQL'}}}},
|
|
34
35
|
'/graphiql': {'get': {'responses': {200: {'description': 'GraphiQL UI.'}}}},
|
|
@@ -54,11 +55,12 @@ def graphql(graphql_schema: strawberry.Schema, port: int = DEFAULT_PORT):
|
|
|
54
55
|
"""
|
|
55
56
|
graphql_schema.extensions.append(OpenTelemetryExtension)
|
|
56
57
|
|
|
58
|
+
def open_url():
|
|
59
|
+
for app_name in ('viewer',):
|
|
60
|
+
webbrowser.open(f'http://localhost:{port}/{app_name}')
|
|
61
|
+
|
|
57
62
|
@contextlib.asynccontextmanager
|
|
58
63
|
async def lifespan(app: Starlette): # pragma: no cover
|
|
59
|
-
def open_url():
|
|
60
|
-
for app_name in ('voyager', 'graphiql', 'viewer'):
|
|
61
|
-
webbrowser.open(f'http://localhost:{port}/{app_name}')
|
|
62
64
|
|
|
63
65
|
open_url()
|
|
64
66
|
yield
|
|
@@ -75,6 +77,12 @@ def graphql(graphql_schema: strawberry.Schema, port: int = DEFAULT_PORT):
|
|
|
75
77
|
app.add_middleware(PrometheusMiddleware)
|
|
76
78
|
app.add_route("/metrics", metrics)
|
|
77
79
|
app.add_route("/schema", route=openapi_schema, include_in_schema=False)
|
|
80
|
+
app.add_route("/openapi.json", route=openapi_schema, include_in_schema=False)
|
|
81
|
+
|
|
82
|
+
async def redirect_to_existing_route(request):
|
|
83
|
+
return RedirectResponse(url='/viewer')
|
|
84
|
+
|
|
85
|
+
app.add_route('/', redirect_to_existing_route)
|
|
78
86
|
|
|
79
87
|
import uvicorn
|
|
80
88
|
uvicorn.run(app, host='0.0.0.0', port=port)
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8"> <!-- Important: rapi-doc uses utf8 characters -->
|
|
5
|
-
<script
|
|
6
|
-
integrity="sha384-
|
|
5
|
+
<script src="https://unpkg.com/rapidoc@9.3.8/dist/rapidoc-min.js"
|
|
6
|
+
integrity="sha384-szzoYhqSJqZH8X90KwbBjYL1CMLEa3U7xl/oAZg4ViKpYEY5GVhM+peBQB4u7ANM"
|
|
7
|
+
crossorigin="anonymous"></script>
|
|
7
8
|
<title>Graphinate - OpenAPI RapiDoc UI</title>
|
|
8
9
|
</head>
|
|
9
10
|
<body>
|