Universe

Version Github Repo License Manual

Dati basati (“Based Data” in Italian) is a Typst package, built on CeTZ, to draw ER-diagrams as I did during university. I was never able to find a software that did it, so why not do it myself?

See the /docs directory for the manual and the documentation.

See this for a quick start. You need to import the package into your project:

#import "@preview/dati-basati:0.1.0" as db

basic dati-basati er diagram example with tiw theme

See the source code
// tiw

#set page(width: auto, height: auto, margin: 1cm)

#import "@preview/dati-basati:0.1.0" as db

#set text(font: "Barlow")

#show: db.dati-basati.with(..db.themes.tiw)

#let entities = (
  "user": (
    coordinates: (0, 0),
    attributes: (
      "north": ("user_id", "nickname", "password"),
      "west": ("name", "surname"),
    ),
    attributes-position: (
      north: (alignment: center),
    ),
    primary-key: "user_id",
    label: "user",
    name: "user",
  ),
  "playlist": (
    coordinates: (5, -5),
    attributes: (
      "south": ("title",),
      "north": ("creation_date",),
    ),
    attributes-position: (
      "north": (alignment: right),
      "south": (alignment: left),
    ),
    weak-entity: ("title", "west"),
    label: "playlist",
    name: "playlist",
  ),
  "track": (
    coordinates: (10, 0),
    attributes: (
      "north": ("track_id", "title", "artist", "album").rev(),
      "east": ("year", "image_path", "song_path"),
    ),
    attributes-position: (
      "north": (
        alignment: center,
        dir: "ltr",
      ),
    ),
    primary-key: "track_id",
    label: "track",
    name: "track",
  ),
)

#let relations = (
  "user-playlist": (
    coordinates: (0, -5),
    entities: ("user", "playlist"),
    label: "creates",
    name: "user-playlist",
    cardinality: ("(0,n)", "(1,1)"),
  ),
  "user-track": (
    entities: ("user", "track"),
    label: "uploads",
    name: "user-track",
    cardinality: ("(0,n)", "(1,1)"),
  ),
  "playlist-track": (
    coordinates: (10, -5),
    entities: ("playlist", "track"),
    label: "contains",
    name: "playlist-track",
    cardinality: ("(0,n)", "(0,n)"),
    attributes: ("east": ("custom_order",)),
  ),
)

#db.er-diagram({
  for entity in entities.values() {
    db.entity(
      entity.coordinates,
      label: entity.label,
      name: entity.name,
      attributes: entity.attributes,
      attributes-position: entity.at("attributes-position", default: none),
      primary-key: entity.at("primary-key", default: none),
      weak-entity: entity.at("weak-entity", default: none),
      misc: entity.at("misc", default: none),
    )
  }

  for relation in relations.values() {
    db.relation(
      coordinates: relation.at("coordinates", default: none),
      entities: relation.entities,
      label: relation.at("label", default: none),
      name: relation.name,
      cardinality: relation.cardinality,
      attributes: relation.at("attributes", default: none),
    )
  }
})

If you click on the images you can check the source code.

dati basati er diagram example for C62-48 theme

dati basati er diagram example for tiramisu theme

dati basati er diagram example for ghibli theme

dati basati er diagram example for C62-50 theme

dati basati er diagram example for polimi theme

dati basati er diagram example for futurama theme

See the examples directory for many exceptions and particular cases. Note that those files serve the only purpose to illustrate how the package works: as such, they may contain errors and are NOT intended to be applied for database development.

  • Type checking using valkyrie
  • Better options coordination (in order to avoid visual errors)
  • Local theming as opposed to the current global one

If you happen to have suggestions, ideas or anything else feel free to open issues and pull requests or contact me.