Skip to content

Visualization

The typestates dot command generates GraphViz DOT output for visualizing state machines as diagrams.

Basic Usage

# Generate DOT output
typestates dot src/

# Save to file
typestates dot src/ > states.dot

# Generate PNG directly
typestates dot src/ | dot -Tpng -o states.png

# Generate SVG for web
typestates dot src/ | dot -Tsvg -o states.svg

Options

Option Description
--splines=MODE Edge routing: spline (default), ortho, polyline, line
--separate Generate separate graph per typestate
--no-style Output minimal DOT without styling

Edge Routing Modes

# Curved edges (default) - best edge separation
typestates dot src/

# Right-angle edges only
typestates dot --splines=ortho src/

# Straight line segments
typestates dot --splines=polyline src/

# Direct straight lines
typestates dot --splines=line src/

Edge Styles

The CLI uses dark mode styling with different edge styles to distinguish transition types:

Type Style Description
Normal Solid light gray Standard state transitions
Wildcard Dotted gray Transitions from any state (* -> State)
Bridge Dashed light purple Cross-typestate transitions

Wildcard transitions are deduplicated: if an explicit transition exists (e.g., Pooled -> Closed), the wildcard-expanded version is skipped.

Example: File State Machine

Given this typestate definition:

import typestates

type
  File = object
    path: string
  Closed = distinct File
  Open = distinct File

typestate File:
  states Closed, Open
  transitions:
    Closed -> Open
    Open -> Closed

Running typestates dot src/ produces:

digraph {
  rankdir=TB;
  splines=spline;
  compound=true;
  nodesep=1.0;
  ranksep=1.0;
  bgcolor="transparent";
  pad=0.3;

  node [shape=box, style="rounded,filled", fillcolor="#2d2d2d", color="#b39ddb", fontcolor="#e0e0e0", fontname="sans-serif", fontsize=14, margin="0.4,0.3"];
  edge [fontname="sans-serif", fontsize=11, color="#b0b0b0"];

  subgraph cluster_File {
    label="File";
    fontname="sans-serif";
    fontsize=16;
    fontcolor="#e0e0e0";
    labelloc=t;
    style="rounded";
    color="#b39ddb";
    bgcolor="#1e1e1e";
    margin=30;

    Closed;
    Open;

    Closed -> Open;
    Open -> Closed;
  }
}

Rendered as a diagram:

File State Machine

Output Format

The CLI generates a unified graph with each typestate as a labeled subgraph. This allows multiple typestates and bridges to be visualized together in a single diagram.

Example: Payment Processing

A more complex example with branching transitions:

typestate Payment:
  states Created, Authorized, Captured, PartiallyRefunded, FullyRefunded, Settled, Voided
  transitions:
    Created -> Authorized
    Authorized -> (Captured | Voided) as AuthResult
    Captured -> (PartiallyRefunded | FullyRefunded | Settled) as CaptureResult
    PartiallyRefunded -> (PartiallyRefunded | FullyRefunded | Settled) as RefundResult
    FullyRefunded -> Settled

Payment State Machine

Example: Wildcard Transitions

Wildcard transitions (* -> State) are rendered with dotted gray edges:

typestate DbConnection:
  states Pooled, CheckedOut, InTransaction, Closed
  transitions:
    Pooled -> (CheckedOut | Closed) as PoolResult
    CheckedOut -> (Pooled | InTransaction | Closed) as CheckoutResult
    InTransaction -> CheckedOut
    * -> Closed

Database Connection States

The dotted gray edges indicate transitions that come only from the wildcard. Explicit transitions (like Pooled -> Closed) remain solid.

Installing GraphViz

The DOT output can be rendered with GraphViz. Install it for your platform:

brew install graphviz
sudo apt install graphviz
choco install graphviz

Output Formats

GraphViz supports many output formats:

Format Command Use Case
PNG dot -Tpng Documentation, README
SVG dot -Tsvg Web, scalable graphics
PDF dot -Tpdf Print, documentation
DOT (raw output) Further processing

Customizing Output

The CLI produces dark mode styled output by default with light purple accents. For easier customization, use --no-style to get minimal DOT output:

# Minimal output without styling - easier to customize
typestates dot --no-style src/ > minimal.dot

You can also post-process the styled output:

# Light mode (swap colors)
typestates dot src/ | sed 's/#2d2d2d/#f5f5f5/g; s/#1e1e1e/#fafafa/g; s/#e0e0e0/#212121/g; s/#b0b0b0/#424242/g' | dot -Tpng -o light.png

--no-style Output

The --no-style flag produces bare DOT structure with no styling attributes:

digraph {
  subgraph cluster_File {
    label="File";

    Closed;
    Open;

    Closed -> Open;
    Open -> Closed;
  }
}

This is ideal when you want to apply your own colors, fonts, and layout settings. Edge styles (dotted, dashed) are preserved to distinguish wildcard and bridge transitions.

Generating Documentation Images

To include diagrams in your documentation:

# Create images directory
mkdir -p docs/assets/images

# Generate all typestate diagrams
typestates dot src/ | csplit -f docs/assets/images/state- -b '%02d.dot' - '/^digraph/' '{*}'

# Convert each to SVG
for f in docs/assets/images/state-*.dot; do
  dot -Tsvg "$f" -o "${f%.dot}.svg"
done

Multiple Typestates

If your project has multiple typestates, the dot command outputs them all in a single unified graph with separate subgraphs. Bridges between typestates are shown as dashed purple edges.

Example: Authentication Flow with Session

This example shows two typestates with bridges connecting them:

# Session typestate
type
  Session = object
    userId: string
  Active = distinct Session
  Expired = distinct Session

typestate Session:
  states Active, Expired
  transitions:
    Active -> Expired

# AuthFlow typestate with bridges to Session
type
  AuthFlow = object
    userId: string
  Pending = distinct AuthFlow
  Authenticated = distinct AuthFlow
  Failed = distinct AuthFlow

typestate AuthFlow:
  states Pending, Authenticated, Failed
  transitions:
    Pending -> Authenticated
    Pending -> Failed
  bridges:
    Authenticated -> Session.Active
    Failed -> Session.Expired

Multiple Typestates with Bridges

The dashed purple edges show bridges connecting states across different typestates.