Effect-TS / effect

An ecosystem of tools for building production-grade applications in TypeScript.
https://effect.website
MIT License
6.95k stars 217 forks source link

Generate Mermaid class diagram (or expose DAG) from schema #3304

Open ingun37 opened 1 month ago

ingun37 commented 1 month ago

What is the problem this feature would solve?

Developers want to visualize and document their data schema, likely in UML Class diagram. For those who define their type in the traditional way would have to draw the diagram manually, and it's a big maintenance cost.

What is the feature you are proposing to solve the problem?

A function that takes a schema and generate Mermaid Class Diagram. It will be particularly useful for developers who document their domain logic in GitHub Markdown because they supports Mermaid.

What alternatives have you considered?

writing manually

ingun37 commented 1 month ago

I would love to make a PR myself if you'd approve making this feature and give me some guidance.

gcanti commented 1 month ago

Could you please provide an example including the schemas and the expected diagram?

ingun37 commented 1 month ago

@gcanti Here are some rules I'm thinking

const Person = Struct({
  name: Schema.Number,
  age: Schema.String,
  religion: Schema.optional(Schema),
  degrees: Schema.Array(Degree),
}).annotations({ title: "Person" })

const Religion = Struct({
  name: Schema.String
}).annotations({ title: "Religion" })

const Bachelor = Schema.Struct({
  kind: Schema.Literal("bachelor"),
}).annotations({ title: "Bachelor" })

const Master = Schema.Struct({
  kind: Schema.Literal("master"),
  thesis: Thesis
}).annotations({ title: "Master" });

const Thesis = Schema.Struct({}).annotations({ title: "Thesis" })

const Degree = Schema.Union(Bachelor, Square).annotations({ title: "Degree" })
classDiagram
class Person {
  name: string
  age: number
  religion?: Religion
  degrees: Degree[]
}
class Religion {
 name: string
}
namespace Degrees {
class Degree {
  kind: "master" | "bachelor"
}
class Master {
  kind: "master"
  thesis: Thesis
}
class Bachelor {
  kind: "bachelor"
}
}
class Thesis
Person --> Religion
Person "1" --> "*" Degree
Degree <|-- Master
Degree <|-- Bachelor
Master --> Thesis

(I notated cardinatily but it's not rendering. I guess it's a current bug.)

fubhy commented 1 month ago

That's a DAG. So we first need graph data structures in Effect. Deriving a mermaid representation from a DAG is trivial

gcanti commented 1 month ago

@fubhy It depends on the meaning assigned to the edges. For instance, if the directed edge represents the relation "this schema uses this schema" then it's not acyclic (counterexamples: recursive schemas, mutually recursive schemas)

fubhy commented 1 month ago

True. I was just refering to this specific example. My point is, I would like to have graph data structures in effect modules. For various types of graphs. Once we have those, rendering them with mermaid is trivial, whether it is a DAG or not. My second point was that, from an api design standpoint, I think it would be desirable to go schema -> graph -> mermaid instead of schema -> mermaid.

ingun37 commented 1 month ago

If you could expose underlying graph data structure then I guess I could achieve the same thing. I'll appreciate that too.