{"id":51166305,"url":"https://github.com/escherize/gleam-type-graph","last_synced_at":"2026-06-26T19:02:04.533Z","repository":{"id":358536249,"uuid":"1241831812","full_name":"escherize/gleam-type-graph","owner":"escherize","description":"Static type-graph extractor for Gleam codebases. Maps types to the functions that transform them, rendered as mermaid / graphviz / json / interactive HTML.","archived":false,"fork":false,"pushed_at":"2026-05-17T21:59:33.000Z","size":0,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-17T22:22:59.749Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Gleam","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/escherize.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-17T21:42:08.000Z","updated_at":"2026-05-17T21:59:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/escherize/gleam-type-graph","commit_stats":null,"previous_names":["escherize/gleam-type-graph"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/escherize/gleam-type-graph","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escherize%2Fgleam-type-graph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escherize%2Fgleam-type-graph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escherize%2Fgleam-type-graph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escherize%2Fgleam-type-graph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/escherize","download_url":"https://codeload.github.com/escherize/gleam-type-graph/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escherize%2Fgleam-type-graph/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34829415,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-26T02:00:06.560Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-26T19:02:00.665Z","updated_at":"2026-06-26T19:02:04.527Z","avatar_url":"https://github.com/escherize.png","language":"Gleam","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gleam-type-graph\n\nStatically extract a directed graph of **types** and **the functions that\ntransform them** from a Gleam codebase.\n\n- **Nodes** = types (`Order`, `OrderSnapshot`, `Json`, `String`, ...)\n- **Edges** = functions that turn one type into another (`order.snapshot`,\n  `json.to_string`, ...)\n\nRead the resulting graph as: *to convert an `X` into a `Y`, here's the path\nof functions to compose.*\n\n## Quick start\n\n```sh\ncd /your/gleam/project\nnpx gleam-type-graph --open\n```\n\nThat's it. From inside any Gleam project (or any subdirectory of one), this\nwalks up to find your `gleam.toml`, scans `src/`, renders an interactive\nmermaid diagram, and opens it in your browser.\n\nNo `gleam` toolchain required on your machine — the tool ships pre-compiled\nto JavaScript.\n\n## Other invocations\n\n```sh\n# Mermaid to stdout (good for piping into a markdown file)\nnpx gleam-type-graph\n\n# Sorted plain-text edge list, easiest to grep / diff\nnpx gleam-type-graph --format text\n\n# Drop edges between stdlib / primitive types — show just the domain core\nnpx gleam-type-graph --domain-only --open\n\n# Graphviz dot (for `dot -Tpng -o graph.png`)\nnpx gleam-type-graph --format=dot \u003e graph.dot\ndot -Tpng graph.dot -o graph.png\n\n# JSON for downstream tooling\nnpx gleam-type-graph --format=json \u003e graph.json\n\n# Point at a specific src/ tree\nnpx gleam-type-graph /some/other/project/src --open\n```\n\n## Example output\n\nGiven a project with `Order`, `OrderSnapshot`, `Money`, `CustomerId`, and a\nJSON encoder:\n\n```sh\n$ npx gleam-type-graph --format text\nInt                  --[money.from_cents]--\u003e money.Money\nString               --[customer.new_id]--\u003e customer.CustomerId\nString               --[order.new_id]--\u003e order.OrderId\nmoney.Money          --[money.to_cents]--\u003e Int\nmoney.Money          --[money.to_json]--\u003e json.Json\norder.Order          --[order.order_to_json]--\u003e json.Json\norder.Order          --[order.snapshot]--\u003e order.OrderSnapshot\norder.OrderSnapshot  --[order.restore]--\u003e order.Order\n```\n\nTwo seconds of reading and you know:\n\n- `String → OrderId` and `String → CustomerId` are smart constructors\n- `Order ↔ OrderSnapshot` is a symmetric snapshot/restore pair\n- The path to put an `Order` on disk is\n  `Order → snapshot → OrderSnapshot → order_to_json → Json → ...`\n\nWith `--domain-only` the same project collapses to just the user-defined\ncore:\n\n```sh\n$ npx gleam-type-graph --format text --domain-only\norder.Order          --[order.snapshot]--\u003e order.OrderSnapshot\norder.OrderSnapshot  --[order.restore]--\u003e order.Order\n```\n\nWhen a function takes multiple typed parameters — say\n`make_order(c: CustomerId, id: OrderId, total: Money) -\u003e Order` — the\noutput groups the inputs to make the *and*-relation visible:\n\n```\n{customer.CustomerId, money.Money, order.OrderId} --[order.make_order]--\u003e order.Order\n```\n\nIn mermaid / dot this renders as a single fan-in node that all inputs flow\ninto and the return type flows out of, so a reader can see at a glance that\nall three inputs are required.\n\n## CLI\n\n```\nUsage: gleam-type-graph [PATH] [OPTIONS]\n\nArguments:\n  PATH                Directory to scan. If omitted, walks up from cwd\n                      looking for gleam.toml and uses its src/.\n\nOptions:\n  --format \u003cFMT\u003e      Output format: mermaid|dot|json|text|html\n                      (default: html when --open, mermaid otherwise)\n  --open              Render to a temp file and open in your browser\n  --include \u003cPAT\u003e     Module substring to include (repeatable)\n  --exclude \u003cPAT\u003e     Module substring to exclude (repeatable)\n  --domain-only       Drop edges touching stdlib / primitives\n  -h, --help          Show this help\n```\n\n`--include` and `--exclude` match the substring against either endpoint\nmodule *or* the function label, so `--include order` keeps every edge\ninvolving the `order` module on either side.\n\n## How edges are derived\n\nFor a single-arg public function `module.fn(p: T) -\u003e R`:\n\n- One edge `T → R`, labelled `module.fn`\n\nFor a multi-arg public function `module.fn(p1: T1, p2: T2, ...) -\u003e R`:\n\n- A synthetic *fan-in node* `module.fn()` is introduced (rendered as a\n  stadium in mermaid, an ellipse in dot, `{...}` braces in text).\n- Each typed parameter type flows *into* the fan-in node; the return type\n  flows *out*. Reads as: \"you need T1 **and** T2 **and** ... to produce R.\"\n- Duplicate input types are deduped, so `merge(Order, Order, String) -\u003e Order`\n  shows `{Order, String}` flowing into the fan-in, with Order also flowing\n  out as a self-cycle.\n\nAcross both cases:\n\n- `Result(T, E)` returns are unwrapped to `T` (the success path is the\n  transformation; the error type is metadata)\n- `Option(T)` returns are unwrapped to `T`\n- `List(T) → List(S)` is unwrapped to `T → S` (container-preserving)\n\nType references are resolved through the module's import table:\n\n- `import app/order.{type OrderSnapshot}` — `OrderSnapshot` resolves to\n  `app/order.OrderSnapshot`\n- `import app/order as o` — `o.OrderSnapshot` resolves to\n  `app/order.OrderSnapshot`\n- `import app/order` — `order.OrderSnapshot` resolves the same way\n\nUnresolvable qualified references show up as `Unknown(module.Type)` rather\nthan crashing the run.\n\n## Limitations (MVP scope)\n\n- Only `src/` is parsed. `test/` and `build/packages/\u003cdep\u003e/src/` aren't\n  crawled yet.\n- Only public functions are included.\n- Type aliases are treated as opaque — `pub type UserId = String` shows up\n  as `UserId`, not `String`.\n- Generic types collapse to their base name — `List(Order)` and\n  `List(OrderSnapshot)` aren't distinguished beyond the container-preserving\n  rule.\n\nThese are tracked as stretch goals in `../type_graph_tool.md`.\n\n## Development\n\n```sh\ngleam build                                # Compile (requires Gleam ≥ 1.x)\ngleam test                                 # Run tests (none yet)\n./bin/gleam-type-graph.mjs ./src           # Run the local binary\nnpm pack \u0026\u0026 npx ./gleam-type-graph-*.tgz   # Smoke-test the npm package\n```\n\nThe pipeline is small enough to read top-to-bottom:\n\n```\nsrc/type_graph.gleam              # CLI + pipeline\nsrc/type_graph/parse.gleam        # walk src/, parse with `glance`\nsrc/type_graph/extract.gleam      # AST → edges, with import resolution\nsrc/type_graph/filter.gleam       # primitive / stdlib / pattern filters\nsrc/type_graph/render.gleam       # mermaid | dot | json | text | html\nsrc/type_graph/sys.gleam          # tmp file + open-in-browser\nsrc/type_graph_ffi.mjs            # JS FFI for sys\nbin/gleam-type-graph.mjs          # npm bin shim\n```\n\n## License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fescherize%2Fgleam-type-graph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fescherize%2Fgleam-type-graph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fescherize%2Fgleam-type-graph/lists"}