Skip to content

Bug: D2.js does not route SQL table relationships to column ports with ELK, while the CLI does #2781

Description

@afohlmeister-june

Summary

When rendering SQL tables with the ELK layout engine, the D2 CLI correctly routes relationships from column to column (e.g. primary key to foreign key). However, the JavaScript package @terrastruct/d2 produces table-to-table connections for the same input and layout.

This appears to be a discrepancy between the CLI and D2.js rather than an ELK configuration issue.

Environment

  • D2.js package: @terrastruct/d2 0.1.33
  • Embedded D2 engine: v0.7.0-HEAD (reported by await d2.version())
  • JS version: 0.1.33 (reported by await d2.jsVersion())
  • Layout engine: ELK

Minimal example

users: {
  shape: sql_table
  id: int {constraint: primary_key}
  name: string
  email: string
}

orders: {
  shape: sql_table
  id: int {constraint: primary_key}
  user_id: int {constraint: foreign_key}
}

users.id -> orders.user_id

D2.js code

import { D2 } from "@terrastruct/d2";

const d2 = new D2();

const { diagram, renderOptions } = await d2.compile(source, {
  options: { layout: "elk" },
});

const svg = await d2.render(diagram, renderOptions);

Expected behavior

The relationship should connect from the users.id row to the orders.user_id row, matching the behavior of the D2 CLI.

Actual behavior

The relationship connects from table to table rather than row to row.

Image

Comparison with the CLI

Running the exact same D2 source via the CLI:

d2 --layout elk schema.d2 schema.svg

produces the expected row-to-row connections.

Image

Additional investigation

  • Both use the ELK layout engine.
  • Calling await d2.version() returns v0.7.0-HEAD.
  • Calling await d2.jsVersion() returns 0.1.33.
  • Inspecting the object returned by d2.compile() shows no explicit port definitions for SQL table rows, although it is unclear whether these are expected to be generated during compilation or later in the rendering pipeline.

Conclusion

There appears to be a behavioral difference between the D2 CLI and the @terrastruct/d2 JavaScript package when rendering SQL tables with ELK. The CLI correctly performs row-to-row routing, while D2.js renders the same diagram as table-to-table.

If this behavior is intentional, it would be helpful to document any additional API calls or options required to enable SQL table port routing in D2.js. Otherwise, this appears to be a bug or feature parity issue between the CLI and the JavaScript renderer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions