Repository navigation
refactor(platform-api-docs): use ts-morph globbing for file discovery - #9990
Merged
Merged
Conversation
## Explanation
<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:
* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->
- Refactor and clean up `cli.ts`
- Update `cli.ts` to extract `parseArguments`, further clean `main`
- Revise `root-messenger-discovery.ts` (update terminology, JSDoc)
- Simplify `{Scan,RootMessenger}StrategyOptions`, enforce that
`generate` takes strategy
## References
<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?
For example:
* Fixes #12345
* Related to #67890
-->
## Checklist
- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Programmatic callers of `generate` must pass `strategy` (breaking for
library use); root-messenger discovery is heavily renamed but CLI-facing
behavior should stay the same.
>
> **Overview**
> Refactors **platform-api-docs** around clearer typing and naming for
the scan vs **root-messenger** discovery paths, without changing CLI
flags.
>
> **CLI (`cli.ts`)** pulls argument parsing into **`parseArguments`**,
models options as a discriminated union (`ParsedArguments`), and has
**`checkStrategyArgs`** return normalized scan or root-messenger args
instead of only validating. **`--root-actions`** / **`--root-events`**
are coerced via **`parseRootCapabilitiesTypeReference`** at parse time;
**`main`** calls **`generate`** in separate branches with typed options.
>
> **`generate`** now **requires** an explicit **`strategy: 'scan' |
'root-messenger'`** on **`GenerateOptions`** (scan and root-messenger
option shapes are a strict union). Scan tests pass **`strategy:
'scan'`** accordingly.
>
> **Root-messenger discovery** renames and restructures APIs:
**`RootTypeReference`** → **`RootCapabilitiesTypeReference`**,
**`parseRootTypeReference`** → **`parseRootCapabilitiesTypeReference`**,
**`discoverFromRootMessenger`** →
**`discoverFromRootMessengerCapabilitiesTypes`**, with result fields
**`capabilityPackets`** / **`skippedCapabilities`**
(**`unnamedCapabilities`**, **`unextractableCapabilities`**). Internal
helpers use object parameters and expanded JSDoc; extraction behavior is
unchanged.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
4f7745c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
cryptodev-2s
force-pushed
the
refactor/platform-api-docs-ts-morph-globbing
branch
from
August 27, 2026 15:48
0e0845d to
dfd99a2
Compare
Replaces the hand rolled file walking with addSourceFilesAtPaths, which takes glob patterns directly. Deletes discovery.ts, the per file add and extract loops, and the glob dependency. Collapses the two near identical Project factories into one createProject(), and drops the redundant getSourceFile() guard now that addSourceFileAtPath is known to be idempotent. Generated output is byte identical, verified by diffing full docs trees built before and after for this monorepo, metamask-mobile and metamask-extension. Generation over this monorepo drops from 114s to 8.6s, since files are added in bulk rather than one at a time. Two things worth knowing for anyone touching these patterns: Glob roots are resolved with realpath first. The matcher does not follow a symlinked ancestor of a pattern, so on macOS a project under /tmp or /var would otherwise match nothing at all. Exclusions are anchored to their pattern's root. An unanchored !**/*.test.ts resolves against the working directory, so it silently stops excluding anything when the scanned path is elsewhere, which is the normal case when invoked via yarn workspace.
cryptodev-2s
force-pushed
the
refactor/platform-api-docs-ts-morph-globbing
branch
from
August 27, 2026 15:51
dfd99a2 to
4734579
Compare
mcmire
reviewed
Aug 27, 2026
Base automatically changed from
feat/platform-api-docs-root-messenger-strategy
to
main
August 27, 2026 21:02
cryptodev-2s
marked this pull request as ready for review
August 28, 2026 08:08
cryptodev-2s
temporarily deployed
to
default-branch
August 28, 2026 08:08 — with
GitHub Actions
Inactive
…-docs-ts-morph-globbing # Conflicts: # packages/platform-api-docs/CHANGELOG.md # packages/platform-api-docs/src/generate.test.ts # packages/platform-api-docs/src/generate.ts # packages/platform-api-docs/src/root-messenger-discovery.ts
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4734579. Configure here.
Renames tsSourceExclusions and declarationFileExclusions to buildTsSourceExclusions and buildDeclarationFileExclusions, so the names read as the functions they are. Review feedback.
The exclusions were anchored at `packages` rather than at `packages/*/src`, which made the first path segment a package name. A workspace package called `test` or `dist` therefore matched `test/**` and was dropped whole, where the previous implementation rooted its ignores at each package's `src` and only skipped nested directories. No effect on this repo, which has no package by those names, so add a regression test that fails without the fix.
Sorting with localeCompare made the traversal order depend on the locale the process runs under, and deduplication keeps the first of two equally scored items, so the source link a capability gets could vary by machine. Compares code units instead. Note the order still differs from the previous implementation, which enumerated package directories via readdir and so depended on the filesystem. A global sort is deterministic where that was not. Docs output over this repo is unchanged either way.
…-docs-ts-morph-globbing
Mrtenz
requested changes
Sep 1, 2026
mcmire
reviewed
Sep 1, 2026
mcmire
left a comment
Collaborator
There was a problem hiding this comment.
Tried this out and it definitely speeds things up. Nice work! Just had a few comments below.
cryptodev-2s
enabled auto-merge
September 2, 2026 16:36
Mrtenz
approved these changes
Sep 2, 2026
cryptodev-2s
deleted the
refactor/platform-api-docs-ts-morph-globbing
branch
September 2, 2026 17:55
3 of 4 tasks
pull Bot
pushed a commit
to Reality2byte/core
that referenced
this pull request
Sep 23, 2026
…ating (MetaMask#10085) ## Explanation A capability declared in a package's source is also visible in the `dist` built from it, and a cross-package import resolves to that `dist` rather than to the sibling's source. Whichever was reached first won, so 83 of 1164 source links pointed at `.d.cts` build output instead of code you can read and edit. Deduplication now scores source above build output, so the outcome no longer depends on traversal order. All 1164 links point at source, and namespace, action and event counts are unchanged. Both clients generate byte-identical docs, since they only ever see published packages and score every candidate the same way. ## References * Follow up to MetaMask#9990, as promised in MetaMask#9990 (comment) ## Checklist - [x] I've updated the test suite for new or updated code as appropriate - [x] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [x] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md) - [ ] I've introduced [breaking changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Documentation generation and link selection only; no runtime API or security behavior changes. > > **Overview** > Generated platform API docs were linking many capabilities to **`dist`** declaration files (`.d.cts`) instead of editable **`.ts` source**, because monorepo scans see the same action/event twice and cross-package imports often resolve through **`node_modules`** to build output first—whichever duplicate was processed first won. > > **Deduplication scoring** now adds a **`sourceScore`** that favors paths outside **`/dist/`**, so when both source and build declarations exist, docs keep the source file for links and metadata. Published-package-only consumers are unchanged (every candidate still looks like **`dist`**). > > Tests cover scanning with **`node_modules`** under a broad scan dir and a monorepo-style **`a-controller` / `b-controller`** layout asserting **`actions.md`** points at **`packages/b-controller/src/...`** and not **`/dist/`**. The changelog records the fix under **Fixed**. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 38afbc9. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Stacked on #9913, targets its branch.
Replaces hand-rolled file discovery with
Project#addSourceFilesAtPaths, which takes glob patterns directly. Dropsdiscovery.ts, the per-file add/extract loops,listTargetSubdirectories, and theglobdependency. Also merges the twoProjectfactories (they differed by one field) and removes the redundantgetSourceFile()guard, closing #9913 (comment).Net 254 lines deleted. Generation over this monorepo: 114s to 8.6s.
Output is byte identical.
diff -ron full docs trees generated before and after, for core, mobile and extension: all empty, sidebars included.Two traps, if you touch these patterns
Both produced wrong output while the whole suite stayed green.
realpath. The matcher does not follow a symlinked ancestor. Under/var/folders/...the declaration glob returned 0 where/private/var/...returned 1980, so any project under/tmpor/varwould have emitted empty docs.!**/*.test.tsresolves against the process cwd, not against the pattern it accompanies. Sinceyarn workspacesets cwd to the package dir, every exclusion silently stopped matching and test fixtures leaked in (117 namespaces instead of 112).Related: declaration-file exclusions are deliberately narrower than the source ones. A blanket
dist/**matches the segment those files live under and drops all 1980.Behaviour change
A broken symlink used to emit a per-file parse warning. The matcher now resolves it away before ts-morph sees it, so it is skipped silently; valid files are still documented. One test rewritten to match.
Follow-up
Second step makes each strategy self contained, which is what #9913 (comment) asked for. Worth knowing before that review:
extraction.tsis a scan-only front end welded onto a shared core, so the split has to cut through it too, not justgenerate.ts.Checklist
Note
Low Risk
Internal tooling refactor with byte-identical output claimed; main risk is glob/exclusion edge cases on unusual filesystem layouts, now covered by new tests.
Overview
Speeds up doc generation by replacing per-file
globdiscovery andaddSourceFileAtPathloops with a single shared ts-morphProjectthat bulk-loads matches viaaddSourceFilesAtPaths. Removesdiscovery.ts, theglobdependency, and merges the two project factories into sharedcreateProject()ints-project.ts.The scan strategy now builds resolved, forward-slashed glob roots (
toGlobPath+realpath) and content-root–anchored exclusion negations so test/dist skips work when cwd ≠ project root and monorepo packages namedtest/distare not excluded wholesale. Added source files are sorted by path for stable dedup/source links; extraction uses a realpath’d project root for relative source paths.Behavior: unreadable paths (e.g. broken symlinks) are skipped without per-file parse warnings; valid files still document. Tests cover the
packages/testexclusion edge case and the symlink case.Reviewed by Cursor Bugbot for commit 55c4a26. Bugbot is set up for automated code reviews on this repo. Configure here.