The Problem
Designing and maintaining relational‑database diagrams is tedious when the tooling forces manual layout, copy‑paste SQL, or external installs. Teams that need a quick visual model –‑ for onboarding, documentation, or rapid prototyping –‑ often resort to heavyweight desktop apps or ad‑hoc sketches, which slows iteration and introduces errors.
What This Does
drawdb provides a browser‑based editor that lets users drag‑and‑drop tables, define columns, relationships, and export the resulting schema as SQL. The UI lives under src/ with React components such as src/components/EditorCanvas/Table.jsx and src/components/EditorHeader/ControlPanel.jsx. Core data definitions are in src/data/constants.js, src/data/datatypes.js, and src/data/db.js. The app is bundled with Vite (vite.config.js) and served either via the built static files (index.html) or a thin Express wrapper defined in src/api/ and the Dockerfile.
How It Is Wired
- Startup – Vite reads
src/App.jsx(the root React component) and injects it intoindex.html. The development server (npm run dev) launches the Vite dev process; the production build (npm run build) outputs static assets consumed by the Docker container. - State Management – The most widely referenced hook is
src/hooks/useLayout.js(called from 30 other files). It supplies layout‑related state to components likeWorkspace.jsxandEditorCanvas/Canvas.jsx.useDiagram.js,useUndoRedo.js, anduseSelect.jsare similarly hot‑spots, each exported fromsrc/hooks/index.js(hub module with 53 inbound imports). - Diagram Operations – User actions (add table, move, undo) flow through the custom hooks: e.g.,
ControlPanel.jsxcallsundo/redofromuseUndoRedo.js, which ultimately invokeupdateTable/updateAreadefined insrc/context/DiagramContext.jsx. The call graph showsundo→updateTable(8 edges) andredo→updateTable(7 edges). - SQL Generation – The export path starts at
src/utils/exportSQL/index.js→generateMigrationSQL→ helper functions (escapeQuotes,quoteIdentifier,columnDefinition). These helpers are invoked 18–24 times per export, ending in a string written to the browser download API – no external network calls. - Import Path –
src/utils/importSQL/index.jsreads a DBML/SQL blob, parses it viasrc/utils/importSQL/shared.js, and populates the diagram by calling the same context mutators used by the UI. - External Touches – Nine functions perform outbound HTTP (e.g.,
src/api/email.jsfor sharing links) and three read/write the file system (Docker build copies static assets). No database server is contacted; the app is purely client‑side unless the optional server is deployed.
Blast‑radius notes –
src/data/constants.jsis a hub (70 inbound imports); any change ripples through most of the UI.- Circular imports involve 21 modules, notably
src/hooks/index.js,src/data/datatypes.js, andsrc/utils/utils.js; breaking these cycles reduces coupling. - Deep nesting (up to 7 levels) appears in
Workspace.jsxand several canvas components, making future modifications harder to reason about.
How To Use It
# Clone the exact repo
git clone https://github.com/moses-y/drawdb
cd drawdb
# Install dependencies (npm uses the lockfile)
npm ci
# Development server
npm run dev # Vite serves on http://localhost:5173
# Production build
npm run build # outputs to ./dist
docker build -t drawdb . # builds the container
docker run -p 3000:80 drawdb # serves static files
No environment variables are required for the standalone UI; sharing features need the separate drawdb-server and variables described in .env.sample.
Real‑World Use
A SaaS product can embed drawdb in its admin console to let product managers sketch new data models. The UI stores the diagram in local storage; on “Export”, exportSQL produces a migration script that the CI pipeline applies to the production database, eliminating manual copy‑paste.
Code Health & Issues
- HIGH – GitHub Actions use mutable tags (
docker/setup-qemu-action@v3etc.). Pin to commit SHAs. - HIGH – Audit flags insufficient test coverage despite three test files; add a comprehensive suite covering public hooks and export/import.
- MEDIUM – Workflows lack least‑privilege
GITHUB_TOKENpermissions. - MEDIUM – No Dependabot/Renovate configuration; add
.github/dependabot.yml. - MEDIUM – CI installs with
npm install; replace withnpm cito respect the lockfile. - MEDIUM – Base images (
node:20-alpine,nginx:stable-alpine3.17) are unpinned; use digests. - MEDIUM – No dependency‑vulnerability gate; add
dependency-review-actionorosv-scanner. - MEDIUM – Checkout step keeps credentials; set
persist-credentials: false. - MEDIUM – Dockerfile runs as root; add a non‑root
USER. - LOW – Workflow jobs lack
timeout-minutes; define reasonable limits.
Additional static findings (import cycles, oversized files, duplicated 6‑line blocks) indicate maintainability pressure and should be addressed in a refactor.
The Bottom Line
drawdb delivers a functional, client‑side diagram editor with a clear React architecture, but the codebase suffers from tight coupling, deep nesting, and several production‑grade hygiene gaps. It is suitable for teams that need a quick visual tool and are comfortable adding tests, tightening CI, and refactoring hub modules for long‑term stability.