|
| 1 | +<!--- |
| 2 | + Licensed to the Apache Software Foundation (ASF) under one |
| 3 | + or more contributor license agreements. See the NOTICE file |
| 4 | + distributed with this work for additional information |
| 5 | + regarding copyright ownership. The ASF licenses this file |
| 6 | + to you under the Apache License, Version 2.0 (the |
| 7 | + "License"); you may not use this file except in compliance |
| 8 | + with the License. You may obtain a copy of the License at |
| 9 | +
|
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | +
|
| 12 | + Unless required by applicable law or agreed to in writing, |
| 13 | + software distributed under the License is distributed on an |
| 14 | + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | + KIND, either express or implied. See the License for the |
| 16 | + specific language governing permissions and limitations |
| 17 | + under the License. |
| 18 | +--> |
| 19 | + |
| 20 | +# Workspace Dependency Graph |
| 21 | + |
| 22 | +This page shows the dependency relationships between DataFusion's workspace |
| 23 | +crates. This only includes internal dependencies, external crates like `Arrow` are not included |
| 24 | + |
| 25 | +The dependency graph is auto-generated by `docs/scripts/generate_dependency_graph.sh` to ensure it stays up-to-date, and the script now runs automatically as part of `docs/build.sh`. |
| 26 | + |
| 27 | +## Dependency Graph for Workspace Crates |
| 28 | + |
| 29 | +<!-- |
| 30 | + Below is an embedded .svg file, with interactive functionalities like drag/zoom-in/etc. |
| 31 | + --> |
| 32 | + |
| 33 | +```{raw} html |
| 34 | +<div id="workspace-deps-wrapper" style="border:1px solid #d4d4d8;border-radius:10px;overflow:hidden;background:#fff;"> |
| 35 | + <div id="workspace-deps-inline" style="min-height:760px;width:100%;background:#f8fafc;overflow:hidden;padding:0;margin:0;"> |
| 36 | +``` |
| 37 | + |
| 38 | +```{eval-rst} |
| 39 | +.. raw:: html |
| 40 | + :file: ../../_static/data/deps.svg |
| 41 | +``` |
| 42 | + |
| 43 | +```{raw} html |
| 44 | + </div> |
| 45 | + <div style="padding:10px 12px;background:#f1f5f9;border-top:1px solid #e5e7eb;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;"> |
| 46 | + <span style="color:#334155;font-size:0.95rem;">Interactive SVG (pan, zoom, search)</span> |
| 47 | + <div style="display:flex;align-items:center;gap:6px;"> |
| 48 | + <button id="workspace-deps-zoom-out" type="button" style="padding:6px 10px;border:1px solid #cbd5e1;border-radius:6px;background:#fff;color:#334155;cursor:pointer;">−</button> |
| 49 | + <button id="workspace-deps-zoom-in" type="button" style="padding:6px 10px;border:1px solid #cbd5e1;border-radius:6px;background:#fff;color:#334155;cursor:pointer;">+</button> |
| 50 | + </div> |
| 51 | + <a href="../../_static/data/deps.svg" target="_blank" rel="noopener" |
| 52 | + style="font-weight:600;color:#2563eb;text-decoration:none;">Open SVG ↗</a> |
| 53 | + </div> |
| 54 | +</div> |
| 55 | +<script> |
| 56 | + (function () { |
| 57 | + const host = document.getElementById("workspace-deps-inline"); |
| 58 | + if (!host) { |
| 59 | + return; |
| 60 | + } |
| 61 | +
|
| 62 | + const svg = host.querySelector("svg"); |
| 63 | + if (!svg) { |
| 64 | + host.textContent = "Unable to load dependency graph."; |
| 65 | + host.style.display = "flex"; |
| 66 | + host.style.alignItems = "center"; |
| 67 | + host.style.justifyContent = "center"; |
| 68 | + host.style.background = "#f8fafc"; |
| 69 | + return; |
| 70 | + } |
| 71 | +
|
| 72 | + svg.removeAttribute("width"); |
| 73 | + svg.removeAttribute("height"); |
| 74 | + svg.style.width = "100%"; |
| 75 | + svg.style.height = "100%"; |
| 76 | + svg.style.cursor = "grab"; |
| 77 | + svg.style.touchAction = "none"; |
| 78 | +
|
| 79 | + const rawViewBox = (svg.getAttribute("viewBox") || "").split(/\s+/).map(Number); |
| 80 | + if (rawViewBox.length !== 4 || rawViewBox.some((v) => Number.isNaN(v))) { |
| 81 | + return; |
| 82 | + } |
| 83 | +
|
| 84 | + const initial = { |
| 85 | + x: rawViewBox[0], |
| 86 | + y: rawViewBox[1], |
| 87 | + width: rawViewBox[2], |
| 88 | + height: rawViewBox[3], |
| 89 | + }; |
| 90 | +
|
| 91 | + const state = { ...initial }; |
| 92 | + const applyViewBox = () => { |
| 93 | + svg.setAttribute("viewBox", `${state.x} ${state.y} ${state.width} ${state.height}`); |
| 94 | + }; |
| 95 | +
|
| 96 | + let isPanning = false; |
| 97 | + let last = { x: 0, y: 0 }; |
| 98 | +
|
| 99 | + svg.addEventListener("pointerdown", (event) => { |
| 100 | + isPanning = true; |
| 101 | + last = { x: event.clientX, y: event.clientY }; |
| 102 | + svg.setPointerCapture(event.pointerId); |
| 103 | + svg.style.cursor = "grabbing"; |
| 104 | + }); |
| 105 | +
|
| 106 | + const endPan = (event) => { |
| 107 | + if (event && svg.hasPointerCapture(event.pointerId)) { |
| 108 | + svg.releasePointerCapture(event.pointerId); |
| 109 | + } |
| 110 | + isPanning = false; |
| 111 | + svg.style.cursor = "grab"; |
| 112 | + }; |
| 113 | +
|
| 114 | + svg.addEventListener("pointerup", endPan); |
| 115 | + svg.addEventListener("pointerleave", endPan); |
| 116 | + svg.addEventListener("pointercancel", endPan); |
| 117 | +
|
| 118 | + const zoomBy = (factor) => { |
| 119 | + const targetWidth = state.width * factor; |
| 120 | + const targetHeight = state.height * factor; |
| 121 | + const minSize = Math.max(initial.width * 0.05, 10); |
| 122 | + const maxSize = initial.width * 20; |
| 123 | + const clampedWidth = Math.min(Math.max(targetWidth, minSize), maxSize); |
| 124 | + const clampedHeight = Math.min(Math.max(targetHeight, minSize), maxSize); |
| 125 | +
|
| 126 | + state.x += (state.width - clampedWidth) / 2; |
| 127 | + state.y += (state.height - clampedHeight) / 2; |
| 128 | + state.width = clampedWidth; |
| 129 | + state.height = clampedHeight; |
| 130 | + applyViewBox(); |
| 131 | + }; |
| 132 | +
|
| 133 | + const normalizeDelta = (deltaY, deltaMode) => { |
| 134 | + // Make trackpad/wheel zoom feel smooth across devices. |
| 135 | + const multiplier = deltaMode === 1 ? 16 : deltaMode === 2 ? window.innerHeight : 1; |
| 136 | + return deltaY * multiplier; |
| 137 | + }; |
| 138 | +
|
| 139 | + svg.addEventListener("pointermove", (event) => { |
| 140 | + if (!isPanning) { |
| 141 | + return; |
| 142 | + } |
| 143 | + const scaleX = state.width / svg.clientWidth; |
| 144 | + const scaleY = state.height / svg.clientHeight; |
| 145 | + state.x -= (event.clientX - last.x) * scaleX; |
| 146 | + state.y -= (event.clientY - last.y) * scaleY; |
| 147 | + last = { x: event.clientX, y: event.clientY }; |
| 148 | + applyViewBox(); |
| 149 | + }); |
| 150 | +
|
| 151 | + svg.addEventListener("wheel", (event) => { |
| 152 | + event.preventDefault(); |
| 153 | +
|
| 154 | + const delta = normalizeDelta(event.deltaY, event.deltaMode); |
| 155 | + const factor = Math.exp(delta * 0.0015); // smaller magnitude for smoother scrolling |
| 156 | + zoomBy(factor); |
| 157 | + }, { passive: false }); |
| 158 | +
|
| 159 | + const zoomIn = document.getElementById("workspace-deps-zoom-in"); |
| 160 | + const zoomOut = document.getElementById("workspace-deps-zoom-out"); |
| 161 | + if (zoomIn) { |
| 162 | + zoomIn.addEventListener("click", () => zoomBy(0.9)); |
| 163 | + } |
| 164 | + if (zoomOut) { |
| 165 | + zoomOut.addEventListener("click", () => zoomBy(1.1)); |
| 166 | + } |
| 167 | + })(); |
| 168 | +</script> |
| 169 | +``` |
| 170 | + |
| 171 | +### Legend |
| 172 | + |
| 173 | +- black lines: normal dependency |
| 174 | +- blue lines: dev-dependency |
| 175 | +- green lines: build-dependency |
| 176 | +- dotted lines: optional dependency (could be removed by disabling a cargo feature) |
| 177 | + |
| 178 | +Transitive dependencies are intentionally ignored to keep the graph readable. |
| 179 | + |
| 180 | +The dependency graph is generated through `cargo depgraph` by `docs/scripts/generate_dependency_graph.sh`. |
0 commit comments