{"id":29871600,"url":"https://github.com/ertgl/tapable-tracer","last_synced_at":"2025-07-30T20:02:27.248Z","repository":{"id":302362001,"uuid":"1012085376","full_name":"ertgl/tapable-tracer","owner":"ertgl","description":"Trace the connections and flows between tapable hooks.","archived":false,"fork":false,"pushed_at":"2025-07-28T14:56:07.000Z","size":1866,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-28T16:35:20.209Z","etag":null,"topics":["javascript","tapable","tracing","typescript","uml","webpack"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ertgl.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2025-07-01T19:38:35.000Z","updated_at":"2025-07-28T14:56:05.000Z","dependencies_parsed_at":"2025-07-28T16:22:08.665Z","dependency_job_id":"c9d9d257-71b0-4893-824e-b078912dbbf4","html_url":"https://github.com/ertgl/tapable-tracer","commit_stats":null,"previous_names":["ertgl/tapable-tracer"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/ertgl/tapable-tracer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Ftapable-tracer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Ftapable-tracer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Ftapable-tracer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Ftapable-tracer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ertgl","download_url":"https://codeload.github.com/ertgl/tapable-tracer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Ftapable-tracer/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267552044,"owners_count":24105989,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"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":["javascript","tapable","tracing","typescript","uml","webpack"],"created_at":"2025-07-30T20:01:04.697Z","updated_at":"2025-07-30T20:02:27.223Z","avatar_url":"https://github.com/ertgl.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tapable-tracer\n\nTrace the connections and flows between\n[tapable](https://github.com/webpack/tapable) hooks in real-time.\n\nCollect structured stack traces, and optionally export them as UML diagrams.\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Features](#features)\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Initialize Tracer](#initialize-tracer)\n  - [Register Hooks](#register-hooks)\n  - [Export Frames](#export-frames)\n  - [Generate UML](#generate-uml)\n  - [Tracer Internals](#tracer-internals)\n- [Configuration](#configuration)\n  - [Global Options](#global-options)\n  - [Per-Hook Options](#per-hook-options)\n- [Technical Details](#technical-details)\n  - [Examples](#examples)\n- [License](#license)\n\n## Overview\n\nHave you ever wondered what the internals of webpack look like?\nBelow is a UML-style representation of webpack's internal hooks captured at\nruntime. This diagram was generated using the `tapable-tracer` and its\n[webpack plugin](src/extensions/webpack/plugin/TapableTracerPlugin.ts) by\ntracing dynamically every hook tap and call in the system.\n\n\u003cpicture\u003e\n  \u003csource\n    media=\"(prefers-color-scheme: dark)\"\n    srcset=\"./assets/webpack-graph-dark.svg\"\n  /\u003e\n  \u003cimg\n    alt=\"Webpack hook graph generated via tapable-tracer\"\n    src=\"./assets/webpack-graph-light.svg\"\n  /\u003e\n\u003c/picture\u003e\n\nView the full interactive version here:\n- [Mermaid Chart Playground](https://www.mermaidchart.com/play#pako:eNqlmttOKzcUhl8l4h4JcgQuKqEQukPJBhEQlTZblZk4icWMZ2p70E5L36aXfao-Sb2cAznYnlmrV1HGXt_YXr9Pv-bPoySf8KOLo-Pj4xeZ5HIqZhcvstFI2SIvzUWDp2_w1_64x42GtPXvU5bwjEszNooZPltcNL4OHp_vHn75bTwc3d8Ofn2RDjhTrJg3bh8gFAJPvn1rfLW_A_kuVC4BcZ-WMyEb3783jo9_-jCs-HA1T23NVz7NFX8ooXRNaNrnj6xgryl_VLYVKhDfsvUmueRboW376N9__l5XTViaLut2bAH_bFGdkK4tYFPD1cAb17PFgx-2WLJUB1p4ZuskeVaIdLuR5_Zpf17Kt3vFp9wkc_ub5mwSGqaTDYUZkW-P1CkMYT_PslzeaIe8zlXGggMOI2vmQvf9NBjQsWHKlIWDXfGCywmXieCaiGzvN_DWdlTIGREHaeynnMlQPCSNZ2I7UaeQqRv2znSiRGFG-aRMw_2JDDZk80bnkk6AzF9qzemNaELRQBq1uCugKEBonjq9b6rV0XskxlO0fJ8SsxlXH_GmbSjNdQVCv6timyDejL1tT7Qm9NWuLUZknPBKENtQTrm61AuZ0FMGmrxihj0pQYgG9V7bBYQWfbacf4UteBWpMJShB9V-YcrO4QV5EFpQdDm6IkSC9h7476VQ_EaPTTmdEiDNrXWIEA7igpUruBfFgturHZHadtDh5f2QENl1e1SRK6OtkPPLgiChFgjwmb8WLHkbWkySlhNO2KtaSylKbQixIMEnbUdQiYQQ3z751NCqBwTIlhAHUpeKwmh-MuxYGP6D0htQ4zCDtBKC25vgETeM3ghQ5XihDc8Iwd2dRhAAIMqnh1tCJMjwOVdv4akcP4O0QYtXfMrK1J6NmdHXLDE5ZU_rnOyR7DnQng0IoNMDkLBpJaxVnebuWckmBxYOAqjl9muYJe7YZ3U2EVCHsPp23DbOs_ydD7LCLByQwgHJjria8auySEVirzVkFAj4OmWz9XpIBoGQx8Jel6ZTnlgxWSaBcrZqzubEvlgt-wTW-QHrSbMZYbHrnrgDlOTqZ7gjEgCg6xGTs5STu9MFRS-PLVaDkHPJIgfnGMldj6xwTDzZ8eWjuzwNDOwd5U4OlMpVCNQFuep5XqaTwe6Npj4j1p2um1UsdVuANF-YpqTInQ6Yzq6FvQeLP_5Hos7cImaXrUxIoY1YnbiHEwrsfB_mckZi9VbLtJCEOdADCT9ypSmrcc85ITwrbIk9cjFDSFCv5dKc5GpC633bJVjJPrPnLy61XcXfOfke0Ou45ug8feeqz5I5J-7CoVtsb2PbLMG6VlBvHbRuWr0wkKzVlxFO-nVCQp7X_vPD63XMV6tuKcwHVdaqewZvUpxNlqqpNRJn0H4J3lO6lMbqUFQrtunU4s6h-ODWZuD6B0ZbOMrry-0-PcyA3_GrTnmFp-UvPnx9pdmHJ9Yy_PDYStMPjfSd2tGQ4AaOJkVWsWo5RPzBw6LDd1e6xyhahTmKY4UMUhwlaJKiMB7DEBfv8w5xhLh_iGP5PEQcwecj4ghhLxHHifiJKNCBp4iLjviKOJDXW8QhPP4iDuD3GHGMfZ8RFx3xGnGguN-IYx16jrh4v--IYsS8Rxwo7D_iOBEPEgfy-JA4QNyLxLE8fiQOEPAkcZB9XxIXXWUtomhV9iIOVmUx4mgVNiMOVm014nhxuxHHqrQccbgK2xEHi1mPOFK1_YjjVVmQKFrIhsRBwlYkjlNlR-JoESMQB4qZgThSlSGIo9UwBXHAamMQxfOZgziAxyDEAcImIY7jNwpxjFpmYfWXKL5vObaeoW57oS9HttwgaMgU5DAf7b40bCB11oYhwnWKGPoHJbS5HjYdfN9FbT3zXMMPP7WqHpXPT-Z2XxWO6K3agPAaPZ_9bT3yaCP4OeHRX_8BgPSABA)\n- [Mermaid Live Editor](https://mermaid.live/edit#pako:eNqlmttu4zYQhl_F0HWysGVLsn1RIHCcbtJ4N8gBW3S9KBiJlolIpEpRwXoPb9PLPlWfpBz6ECcWJQ975YTkfKI4v3j4we9eLBLqjb3T09M5jwVfsHQ8551ORlaiUuMOzZ7gX_1jijsdrtvfZCSmOeXqTkmiaLoadz5M7z99vP3tz7vL2c319Pc5N8BUkmLZub6FUAjsfv7c-aB_p_yZScEBcZNVKeOdL186p6e__FCk-GFa9nTLR7oQkt5WULsl-Lr8nhTkMaP3UvdCWuL7ul0iON0LHeiif__5e9s0Jlm2bhvoCvrSo2NCQl1BForKaW1cpKunX3U1J1lp6eFQt4lFXrBsv5MjXTpZVvzpRtIFVfFS_2aCJLZh6u4oRDGxP1I9GMKJyHPBr0qDvBAyJ9YBh5FVS1ZO6mkwoHeKSFUVBnZOC8oTymNGS0fk4G0Hr_WLMp464iCNk4wSbouHpNGc7SeqB5m6Is-kjCUr1EwkVWZ_n4bBhmxelYK7EyDzZ2VJ3TvhQ9WUK7n6WECVheD3jN53zY7Re0NMTdX6eZKlKZU_mru2o_jbBg7v3Rbrg3hz8rT_ofnwrnpuUSynDo8EsV3yBZVn5YrH7ikDTZ4TRR4kc4gG9V7oCcQterj-_gpd8cgyplyGHlT7nkj9Da-cB6EPVWezc4dI0N4t_atikl6Vd6paLBwg_t485BAO4oKZy7oWNQUPNiuia99Bh2c3lw6RoVmjCiFVqYUszgoHCfVBgJ_oY0Hip0uNibMqoQ5rVX8tRV4qh1iQ4EOpR1Cy2CF-0H3R0OYNHCB7QpzyspIuDP-FocdC0a8ubwNqvMwhrQ7Bg13wjCri3glQ5d2qVDR3CA5fdcIBAKJ8uL12iAQZfhLyyf4pN-9BBqDFc7ogVab3xkSVFyRWwmVNC7pvSHofqPcGDqDeAYjptDrMVYH_eq-kkwMThwOob9Zr-ErMtk_rLGHQxmH2DcwyTnPxTKd5oVYG6MIByc6oTOl5VWQs1scaZxQI-CIj6XY-dAaBkO-YPi4tFjTWYtJMB8pw053djn21mfYdWKMD1kNJUofJLuyaDRSn8lc4IzoAQNczwtOMOr9OCIpeb1u0BiHnnDRsnJtI5nikhaOak908fYTr3cBUn1E-8qmUQtpAIci1XIoqS6avTzTHM5peJzRfFcnMEsDVe1K6pMjsDkiZXzB9Dmbf_keihmYS09NWzjgrFdvsuC8TF9joLczkzIkVbaZpxh2-gQgkfE9l6TIbR8YJoXmha_SWiyiHBEV9k-ZYyMTt7QcmwZJPiN5_UV7qWfyZOp8DosB0pxTZM5UTEi-p4ypsO8VGO9tmDS6PCoq2QduuHRcGktX6UsxI_5gQm-f1tvzweN3kq7X3FL4HWR3VdghPkpQka9UcNRJD6D8H7ylbS2OzKToq1jdqMftQfHB_N3CTA6PNHlXry70uPcxAvePXnvIWT6u--vDxrWYfnniU4YfHtpp-aGTdrh0NsS7gaFLDLNYuhwZ_8LDq8Nmt7jGK1mKO4lg2gxRHsZqkKEyNYYiLr_MOcYRm_xDHqvMQcYQ6HxFHsHuJOE6Dn4gCHXiKuOgGXxEHqvUWcYgafxEHqPcYcYy3PiMuusFrxIGa_UYc69BzxMXX-44oRpP3iAPZ_Uccp8GDxIFqfEgcoNmLxLFq_EgcwOJJ4iBvfUlcdJu1iKK12Ys4WJvFiKO12Iw4WLvViOM12404VqvliMO12I44WJP1iCO12484XpsFiaLZbEgcxG5F4jhtdiSO1mAE4kBNZiCO1GYI4mhHmII4YLsxiOLVmYM4QI1BiAPYTUIcp94oxDGOMgvbb6LU3eXYK0Od9mw3R_bcIOjIAuSwnL1-qN1ACraGIcJ1ajD0D2rcvnW76VB3L2qvrOYYfnjVqn1UXq7MvX6UPSLa9AHhNdZc-9srqtGG9Tqhd-KlkiXeWMmKnni5nhQI_Ot9B_DcU0ua07k31n8mRD7NvTn_qWMKwv8QIt-GSVGlS2-8IFmp_6uKRH-H54ykkrw0gVVMS6Xiyhv7gUF44-_eV298OvCjd91uEASD3mjk94aRrl7pcj_svuv3gqg_GIZ9f9jzg58n3jfzXP9dEIa6ZRiORoNh0Iv6Jx7Vex4hZ-ubnubC58__AOIrwXM)\n- [GitHub Mermaid Preview](e2e/uml/webpack/basic/PREVIEW.md)\n\n## Features\n\n- **Real-time**: Observe hooks as they're tapped and called.\n- **Structured**: Frames represent a directed graph.\n- **Dynamic**: No patching or rewriting needed.\n- **UML Export**: Visualize traces via Mermaid diagrams.\n- **Configurable**: Include or exclude the triggers.\n- **Customizable**: Embed information to be visible on diagrams.\n- **Universal**: Works with any tapable-based code, not just webpack.\n\n## Installation\n\n```sh\nyarn add tapable-tracer\n```\n\n## Usage\n\n### Initialize Tracer\n\nTo start tracing hooks, first create a tracer:\n\n```ts\nimport { createTracer } from \"tapable-tracer\";\n\nconst tracer = createTracer();\n```\n\n### Register Hooks\n\nTo capture hook activity, register each hook with the tracer:\n\n```ts\nimport { traceHook } from \"tapable-tracer\";\n\ntraceHook(tracer, hook1);\ntraceHook(tracer, hook2);\n```\n\n### Export Frames\n\nExport the captured frames as encodable array:\n\n```ts\nimport { dumpStackTrace } from \"tapable-tracer\";\n\nconst frames = dumpStackTrace(tracer.trace);\n```\n\n### Generate UML\n\nGenerate a Mermaid-compatible diagram code:\n\n```ts\nimport { generateMermaidUML } from \"tapable-tracer/extensions/mermaid\";\n\nconst uml = generateMermaidUML(frames);\n```\n\n### Tracer Internals\n\n`tapable-tracer` exposes its own hooks (via tapable) for further\ninstrumentation:\n\n- [PreCallHook](src/tracer/hooks/pre-call/PreCallHook.ts): Before a `Tap.fn`\n  called.\n- [PostCallHook](src/tracer/hooks/post-call/PostCallHook.ts): After a `Tap.fn`\n  completes.\n- [HandleStackFrameHook](src/tracer/hooks/handle-stack-frame/HandleStackFrameHook.ts):\n  When a new stack frame is emitted.\n\n## Configuration\n\n### Global Options\n\nPass [`TracerOptions`](src/tracer/options/TracerOptions.ts) to\n`createTracer()`:\n\nThe available options are:\n\n- **interceptorName** (`string`): Name of the interceptor to use.\n- **labelHook** ([`HookLabellerFunction`](src/hook/label/HookLabellerFunction.ts)):\n  Function to label hooks.\n- **labelTap** ([`TapLabellerFunction`](src/tap/label/TapLabellerFunction.ts)):\n  Function to label taps.\n\n### Per-Hook Options\n\nPass [`HookTracingOptions`](src/tracer/options/HookTracingOptions.ts) to\n`traceHook()`:\n\nThe available options are:\n\n- **includeTrigger** (`boolean`): Whether to include the trigger in the trace.\n- **key** (`string`): The hook's identifier in a container data-structure\n  inside the system. Also used as the fallback label for the hook.\n\n## Technical Details\n\nThe tracer captures three different frame types:\n\n- [`TapFrame`](src/stack-frame/TapFrame.ts): A tap is registered to a hook.\n- [`TriggerFrame`](src/stack-frame/TriggerFrame.ts): A delegate is called\n  before the actual `Tap.fn`.\n- [`CallFrame`](src/stack-frame/CallFrame.ts): A `Tap.fn` is called.\n\nAdditionally, it uses a [`CallSite`](src/tracer/stack/CallSite.ts) context\nobject per tap, for storing the hook, tap, and the original callback function.\n\nTo capture the frames the tracer uses two separate states:\n\n1. Stack: A stack of `CallSite` objects that represents the current call stack.\n2. Trace: A list of frames that represents the entire trace of the flows.\n\nFor tracing a hook, the tracer intercepts the hook's `tap`, `call` and `loop`\nevents.\n\nWhen a tap is added:\n\n1. A `CallSite` object is created for further reference.\n2. A `TapFrame` is created and pushed onto the `trace` list.\n3. The `tap.fn` function is overridden to capture the call events, by keeping\n  the `CallSite` object in the closure.\n\nWhen a `call` or `loop` event occurs:\n\n1. Create and push a `TriggerFrame` onto the `trace` list, if the\n  `includeTrigger` options is set to `true` for the hook and the\n  call was caused by a tap.\n2. Push the `CallSite` object onto the `stack`.\n3. Execute the original callback function.\n4. Pop the `CallSite` object from the `stack`.\n5. Create and push a `CallFrame` onto the `trace` list.\n\n### Examples\n\n\u003cdetails\u003e\n  \u003csummary\u003e\n    \u003cb\u003eExample: Output without triggers\u003c/b\u003e\n  \u003c/summary\u003e\n\n  ```ts\n  [\n    { hook: 'hook1', tap: 'hook2', type: 'tap' },\n    { hook: 'hook2', tap: 'hook3', type: 'tap' },\n    { hook: 'hook3', tap: 'hook4', type: 'tap' },\n    { callee: 'hook1', caller: null, type: 'call' },\n    { callee: 'hook2', caller: 'hook1', type: 'call' },\n    { callee: 'hook3', caller: 'hook2', type: 'call' },\n    { callee: 'hook4', caller: 'hook3', type: 'call' }\n  ]\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\n    \u003cb\u003eExample: Graph visualization of the output without triggers\u003c/b\u003e\n  \u003c/summary\u003e\n\n  \u003cpicture\u003e\n    \u003csource\n      media=\"(prefers-color-scheme: dark)\"\n      srcset=\"./assets/hook-graph-dark.svg\"\n    /\u003e\n    \u003cimg\n      alt=\"Hook graph generated via tapable-tracer\"\n      src=\"./assets/hook-graph-light.svg\"\n    /\u003e\n  \u003c/picture\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\n    \u003cb\u003eExample: Output with triggers\u003c/b\u003e\n  \u003c/summary\u003e\n\n  ```ts\n  [\n    { hook: 'hook1', tap: 'Plugin2', type: 'tap' },\n    { hook: 'hook2', tap: 'Plugin3', type: 'tap' },\n    { hook: 'hook3', tap: 'Plugin4', type: 'tap' },\n    { callee: 'hook1', caller: null, type: 'call' },\n    { callee: 'Plugin2', caller: 'hook1', type: 'trigger' },\n    { callee: 'hook2', caller: 'Plugin2', type: 'call' },\n    { callee: 'Plugin3', caller: 'hook2', type: 'trigger' },\n    { callee: 'hook3', caller: 'Plugin3', type: 'call' },\n    { callee: 'Plugin4', caller: 'hook3', type: 'trigger' },\n    { callee: 'hook4', caller: 'Plugin4', type: 'call' }\n  ]\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\n    \u003cb\u003eExample: Graph visualization of the output with triggers\u003c/b\u003e\n  \u003c/summary\u003e\n\n  \u003cpicture\u003e\n    \u003csource\n      media=\"(prefers-color-scheme: dark)\"\n      srcset=\"./assets/plugin-graph-dark.svg\"\n    /\u003e\n    \u003cimg\n      alt=\"Plugin graph generated via tapable-tracer\"\n      src=\"./assets/plugin-graph-light.svg\"\n    /\u003e\n  \u003c/picture\u003e\n\u003c/details\u003e\n\n## License\n\nThis project is licensed under the\n[MIT License](https://opensource.org/license/mit).\nSee the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fertgl%2Ftapable-tracer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fertgl%2Ftapable-tracer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fertgl%2Ftapable-tracer/lists"}