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

  1. Startup – Vite reads src/App.jsx (the root React component) and injects it into index.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.
  2. State Management – The most widely referenced hook is src/hooks/useLayout.js (called from 30 other files). It supplies layout‑related state to components like Workspace.jsx and EditorCanvas/Canvas.jsx. useDiagram.js, useUndoRedo.js, and useSelect.js are similarly hot‑spots, each exported from src/hooks/index.js (hub module with 53 inbound imports).
  3. Diagram Operations – User actions (add table, move, undo) flow through the custom hooks: e.g., ControlPanel.jsx calls undo/redo from useUndoRedo.js, which ultimately invoke updateTable/updateArea defined in src/context/DiagramContext.jsx. The call graph shows undo → updateTable (8 edges) and redo → updateTable (7 edges).
  4. 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.
  5. Import Path – src/utils/importSQL/index.js reads a DBML/SQL blob, parses it via src/utils/importSQL/shared.js, and populates the diagram by calling the same context mutators used by the UI.
  6. External Touches – Nine functions perform outbound HTTP (e.g., src/api/email.js for 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.js is 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, and src/utils/utils.js; breaking these cycles reduces coupling.
  • Deep nesting (up to 7 levels) appears in Workspace.jsx and 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@v3 etc.). 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_TOKEN permissions.
  • MEDIUM – No Dependabot/Renovate configuration; add .github/dependabot.yml.
  • MEDIUM – CI installs with npm install; replace with npm ci to 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-action or osv-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.