{"id":49606065,"url":"https://github.com/jonathan-pap/powerbi-lineage","last_synced_at":"2026-05-04T13:01:31.867Z","repository":{"id":351983785,"uuid":"1212731032","full_name":"jonathan-pap/PowerBI-Lineage","owner":"jonathan-pap","description":"Generate documentation from Power BI PBIP projects — runs in your browser (nothing uploaded) or as a local CLI. Outputs a searchable dashboard plus 9 Markdown docs ready for ADO Wiki or GitHub. Measures, pages, lineage, and a model-health audit.","archived":false,"fork":false,"pushed_at":"2026-04-24T12:24:46.000Z","size":51106,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-24T12:26:03.262Z","etag":null,"topics":["azure-devops","browser-tool","data-dictionary","dax","documentation","file-system-access-api","lineage","markdown","pbip","power-bi","powerbi","semantic-model","tmdl","typescript","wiki","zero-dependencies"],"latest_commit_sha":null,"homepage":"https://jonathan-pap.github.io/PowerBI-Lineage/","language":"TypeScript","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/jonathan-pap.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-04-16T17:13:36.000Z","updated_at":"2026-04-24T12:24:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jonathan-pap/PowerBI-Lineage","commit_stats":null,"previous_names":["jonathan-pap/powerbi-lineage"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jonathan-pap/PowerBI-Lineage","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathan-pap%2FPowerBI-Lineage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathan-pap%2FPowerBI-Lineage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathan-pap%2FPowerBI-Lineage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathan-pap%2FPowerBI-Lineage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonathan-pap","download_url":"https://codeload.github.com/jonathan-pap/PowerBI-Lineage/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathan-pap%2FPowerBI-Lineage/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32608309,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"ssl_error","status_checked_at":"2026-05-04T10:08:02.005Z","response_time":58,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["azure-devops","browser-tool","data-dictionary","dax","documentation","file-system-access-api","lineage","markdown","pbip","power-bi","powerbi","semantic-model","tmdl","typescript","wiki","zero-dependencies"],"created_at":"2026-05-04T13:01:30.385Z","updated_at":"2026-05-04T13:01:31.855Z","avatar_url":"https://github.com/jonathan-pap.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Power BI Documenter\n\n\u003e **Lineage · Audit · Wiki-ready Markdown**\n\nOpen a PBIP project folder — get a searchable dashboard plus nine Markdown docs ready for ADO Wiki or GitHub. Runs **entirely in your browser** (nothing uploads) or as a **local CLI**.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://jonathan-pap.github.io/PowerBI-Lineage/\"\u003e\u003cimg alt=\"Try it — no install needed\" src=\"https://img.shields.io/badge/Try%20it-no%20install%20needed-f59e0b?style=for-the-badge\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Tests 276/276\" src=\"https://img.shields.io/badge/tests-276%2F276-22c55e?style=flat-square\"\u003e\n  \u003cimg alt=\"Runtime deps 0\" src=\"https://img.shields.io/badge/runtime%20deps-0-64748b?style=flat-square\"\u003e\n  \u003cimg alt=\"Node ≥18\" src=\"https://img.shields.io/badge/node-%E2%89%A518-5E6A7B?style=flat-square\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/01-landing.png\" alt=\"Power BI Documenter landing page\" width=\"640\"\u003e\n\u003c/p\u003e\n\n## What you get\n\n- **Interactive dashboard** — 11 tabs: Sources, Tables, Columns, Relationships, Measures, Calc Groups, Functions, Pages (with layout wireframe), Unused, Lineage (search-driven), Documentation\n- **Wiki-ready Markdown** — up to 9 generated docs, paste-ready for ADO Wiki or GitHub. **Lite / Detailed toggle** per doc — paste-into-wiki summary for stakeholders, full reference for engineers. Cross-doc links between them resolve in the dashboard, on GitHub, and on ADO Wiki\n- **Improvements audit** — 16 checks across five severity tiers (high / medium / low / info / strengths) including broken-DAX-reference detection\n- **Source Map** — flat PBI-column → physical-source lineage with CSV export\n- **Page layout wireframe** — SVG thumbnail of each page showing visuals at true canvas positions\n- **Privacy by default** — browser-mode files never leave your machine; CLI binds to loopback only\n\n## Tour\n\n### Inspect the model\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/06-measures.png\" alt=\"Measures tab\"\u003e\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/04-columns.png\" alt=\"Columns tab\"\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003eMeasures\u003c/b\u003e — DAX dependencies, where-used per visual + page, direct/indirect/unused status, descriptions inline. CSV export honours filters.\u003c/td\u003e\n\u003ctd\u003e\u003cb\u003eColumns\u003c/b\u003e — types, usage counts, status, sortable + searchable. Same CSV export pattern.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/03-tables.png\" alt=\"Tables tab\"\u003e\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/03-tablesB.png\" alt=\"Tables tab — drill-down\"\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003eTables\u003c/b\u003e — grouped by role (Fact / Dimension / Bridge / Calc Group). Per-table stats for columns, measures, keys, FKs.\u003c/td\u003e\n\u003ctd\u003e\u003cb\u003eTables drill-down\u003c/b\u003e — expand any table to see columns, measures, and per-relationship cardinality chips (\u003ccode\u003e*:1\u003c/code\u003e, \u003ccode\u003e↔\u003c/code\u003e for bidi).\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Relationships, sources \u0026 lineage\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/05-relationships.png\" alt=\"Relationships tab\"\u003e\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/02-sources.png\" alt=\"Sources tab\"\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003eRelationships\u003c/b\u003e — active + inactive, cardinality (one/many on each side), cross-filter direction (single → / both ↔). CSV export.\u003c/td\u003e\n\u003ctd\u003e\u003cb\u003eSources\u003c/b\u003e — connection buckets, partition modes, \u003cb\u003ephysical-source index\u003c/b\u003e (what breaks if this source goes away?), hand-written SQL from \u003ccode\u003eValue.NativeQuery\u003c/code\u003e, M-step breakdown classifying every ETL step, raw M expressions on demand.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/11-lineage.png\" alt=\"Lineage view\"\u003e\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/10-Unused.png\" alt=\"Unused tab\"\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003eLineage\u003c/b\u003e — search any measure or column from the tab itself, or click an entity from any other tab. Shows upstream DAX dependencies + source tables + functions, and downstream visuals + measures that feed into it.\u003c/td\u003e\n\u003ctd\u003e\u003cb\u003eUnused\u003c/b\u003e — orphan measures, dead-chain measures, indirect-use detection. Pairs with the Improvements audit's broken-reference detection.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Pages, functions, calc groups\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/09-pages.png\" alt=\"Pages tab — overview\"\u003e\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/09-pagesB.png\" alt=\"Pages tab — wireframe\"\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003ePages overview\u003c/b\u003e — every page in the report with visual count, slicers, measure / column bindings.\u003c/td\u003e\n\u003ctd\u003e\u003cb\u003eSVG wireframe\u003c/b\u003e — each page's visuals at true canvas positions. Charts, cards, slicers, tables, maps — shapes and buttons deliberately filtered.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/09-pagesC.png\" alt=\"Pages tab — bindings\"\u003e\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\u003cimg src=\"docs/screenshots/07-functions.png\" alt=\"Functions tab\"\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cb\u003ePer-visual bindings\u003c/b\u003e — every measure + column each visual consumes, with type chips. Hover the wireframe for field-well tooltips.\u003c/td\u003e\n\u003ctd\u003e\u003cb\u003eUDF reference\u003c/b\u003e — parameters, body, and every measure that calls each function. Tabular 1702+.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\" colspan=\"2\" align=\"center\"\u003e\u003cimg src=\"docs/screenshots/13-calcgroups.png\" alt=\"Calc Groups tab\" width=\"720\"\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd colspan=\"2\" align=\"center\"\u003e\u003cb\u003eCalc Groups\u003c/b\u003e — items, precedence, format-string expressions per item.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Wiki-ready Markdown\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/12-modeldocuments.png\" alt=\"Documentation tab with Model technical specification\" width=\"720\"\u003e\n\u003c/p\u003e\n\nNine Markdown documents — paste-ready for ADO Wiki or GitHub, anchor-stable, with cross-doc links that resolve everywhere.\n\n| Doc | What's in it |\n|---|---|\n| **Model** | Technical spec — front matter, schema summary, per-table breakdown, relationships, pages roll-up |\n| **Data Dictionary** | Per-table column catalog with PK / FK / CALC / HIDDEN badges + textual star-schema fragments (FK targets, role tags) |\n| **Sources** | Data-sources catalog, partition modes, field parameters, composite-model proxies |\n| **Measures** | A–Z reference with DAX, dependencies (Depends on / Used by), per-visual + per-page bindings |\n| **Functions** | UDF reference — parameters, description, body |\n| **Calc Groups** | Calculation-group reference with per-item descriptions |\n| **Pages** | Per-page visual catalog — type, title, field bindings for every visual |\n| **Improvements** | Prioritised action list — severity-tiered with rationale |\n| **Index** | Alphabetical glossary — every named entity links to its full reference in the companion docs |\n\nPlus a **Changelog** tab exposing the project's release history.\n\n## Try it\n\n### Browser (no install)\n\n**[→ Open the browser build](https://jonathan-pap.github.io/PowerBI-Lineage/)** — requires Chrome, Edge, or Opera (File System Access API).\n\n1. Click **Open folder** — pick the PBIP project parent folder (the one that contains both `\u003cName\u003e.Report` and `\u003cName\u003e.SemanticModel`). Or click **Try a sample** for a one-click demo.\n2. When multiple project pairs exist under one parent, a pair-picker lets you choose which Report + Semantic Model to load. Report-only and Model-only modes are also supported.\n3. Dashboard renders in the same page.\n\nFirefox / Safari users: run the CLI ([see below](#running)) — the File System Access API is Chromium-only.\n\n### Running — CLI mode\n\nRequires Node.js 18+ and a `.Report` folder with its `.SemanticModel` sibling.\n\n**Double-click (Windows):**\n\n```\nlaunch.bat\n```\n\nFirst run does `npm install` + `npm run build`, then starts the app and opens your browser.\n\n**From the terminal:**\n\n```sh\nnpm install\nnpm run build\nnode dist/app.js\n```\n\nThe app listens on `http://127.0.0.1:5679` (loopback only — nothing leaves your machine). Paste the `.Report` path or use the picker. Recent reports are remembered.\n\n## How it works\n\n### Browser mode\n\nThe same parser + data-builder that power the CLI run client-side via three small shims:\n\n- `src/browser/fs-shim.ts` — pretends to be `fs` but reads from an in-memory Map\n- `src/browser/path-shim.ts` — POSIX-style `path` replacement\n- `src/browser/fsa-walk.ts` — walks a `FileSystemDirectoryHandle` into the Map\n\nAn import-map in `docs/index.html` redirects bare `import … from \"fs\"` / `\"path\"` to the shims. The parser never knows the difference.\n\n### Build + deploy\n\n```sh\nnpm run build:browser    # → ./docs/\nnpm run serve:browser    # → 127.0.0.1:5700\n```\n\n`.github/workflows/pages.yml` auto-publishes `docs/` to GitHub Pages on every push to `main`.\n\n## Project layout\n\n```\nsrc/\n  pbir-reader.ts       Read-only access to PBIR report/page/visual JSON\n  model-parser.ts      findSemanticModelPath + TMDL + BIM parsers\n  report-scanner.ts    Walks visuals/filters/objects to extract field bindings + positions\n  data-builder.ts      Cross-references model + report into FullData\n  md-generator.ts      9 MD docs (Lite + Detailed modes), ADO Wiki-safe anchors, cross-doc xref links\n  improvements.ts      16-check audit (incl. broken-ref detection) — severity-tiered\n  html-generator.ts    Dashboard HTML template\n  client/              Dashboard runtime (tabs, search, sort, lineage view, wireframe)\n                         main.ts · render/escape.ts · render/md.ts · globals.d.ts\n  render/              Shared server-side escape helpers\n  app.ts               CLI HTTP server + landing page\n  browser/             FSA walker + shims + entry shell + pair-picker logic\n                         entry.ts · fsa-walk.ts · fs-shim.ts · path-shim.ts · pair-picker.ts\n\nscripts/\n  build-browser.mjs    Assembles docs/ from dist/ + browser TS output\n  bake-sample.mjs      Bakes a sample PBIP into docs/sample-data.json\n  serve-browser.mjs    Tiny static server for local testing\n\nchangelog/             Per-version release notes (one file per release)\ntests/                 node:test suites — 276 tests, zero framework deps\n```\n\n## Zero runtime dependencies\n\nRuntime deps: none. Only Node builtins (`fs`, `path`, `http`, `crypto`, `child_process`). Dev-deps are `typescript` + `@types/node` only — needed to build.\n\n## Developing\n\n```sh\nnpm run typecheck    # tsc --noEmit\nnpm test             # compile + run Node's built-in test runner\nnpm run build        # compile CLI to dist/\nnpm run build:browser  # compile + assemble docs/ + bake sample\n```\n\nTests use the stdlib `node:test` module. `.github/workflows/ci.yml` runs typecheck + tests + build on every push and PR across Node 18 / 20 / 22.\n\n## Publishing to Azure DevOps Wiki\n\nEach of the nine generated MDs starts with an HTML comment suggesting its wiki page name:\n\n```markdown\n\u003c!-- Suggested ADO Wiki page name: Health_and_Safety/Measures --\u003e\n# Measures Reference\n```\n\n**To publish:**\n\n1. Open the dashboard for your report, switch to the **Documentation** tab\n2. For each doc (Model / Data Dictionary / Sources / Measures / Functions / Calc Groups / Pages / Improvements / Index):\n   - Click **⎘ Copy** to copy the markdown\n   - In ADO Wiki, create a new page with the name from the `\u003c!-- Suggested ADO Wiki page name: ... --\u003e` hint\n   - Paste\n3. If you want ADO's auto-TOC instead of the hand-rolled one, type `[[_TOC_]]` at the top of the page\n\n### Compatibility\n\n| Feature | ADO Wiki | GitHub | Dashboard |\n|---|---|---|---|\n| Anchors (jump-to nav, cross-references) | ✅ via `adoSlug` algorithm | ✅ | ✅ |\n| Same-doc anchor links (`[text](#anchor)`) | ✅ | ✅ | ✅ scrolls within doc |\n| Cross-doc links (`[text](DocName.md#anchor)`) | ⚠ rename `.md` → page-path on paste | ✅ if files share a folder | ✅ tab-switches + scrolls |\n| `\u003cdetails\u003e` / `\u003csummary\u003e` collapsibles | ✅ native | ✅ native | ✅ native |\n| Pipe tables | ✅ | ✅ | ✅ |\n| Fenced `dax` code blocks | ✅ syntax-highlighted | ✅ | ✅ syntax-highlighted |\n| ```` ```mermaid ```` lineage / star fragments | ⛔ not emitted (render-quality wasn't reliable across targets) | ⛔ not emitted | ⛔ not emitted |\n| Badge `\u003cspan\u003e` styling | ⚠ CSS stripped — emoji-prefixed plain text (`🔑 PK`) | ⚠ same fallback | ✅ styled pill |\n| Auto-anchor from heading | ✅ | ✅ | ✅ |\n\nEvery anchor link is verified by `tests/md-anchors.test.ts` — drift fires CI.\n\n## Changelog\n\n[`changelog/`](changelog/) — one file per release. Full index in [`changelog/README.md`](changelog/README.md). Future direction is open-ended; feature requests welcome via Issues.\n\nLatest release: **[v0.11.7](changelog/0.11.7.md)** — Default tab on first load is now **Sources** (was Measures), and Measures + Columns sort no longer flips to ascending on report reload. Small UX defaults that were quietly wrong.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonathan-pap%2Fpowerbi-lineage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonathan-pap%2Fpowerbi-lineage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonathan-pap%2Fpowerbi-lineage/lists"}