Skip to content

fix(js,ts): an import from the app's root maps through the app's own tsconfig paths - #2740

Merged
colbymchenry merged 1 commit into
mainfrom
claude/meteor-root-imports
Oct 21, 2026
Merged

colbymchenry merged 1 commit into
mainfrom
claude/meteor-root-imports

Conversation

@colbymchenry

Copy link
Copy Markdown
Owner

Follow-up to #2738. An import written from the app's root with a leading slash — bigbluebutton's import Icon from '/imports/ui/components/common/icon/component', a style its client kept from its Meteor days — is mapped by the app's own config:

// bigbluebutton-html5/tsconfig.json
"baseUrl": ".",
"paths": {
  /* Support absolute /imports/* with a leading '/' */
  "/*": ["*"]
}

tsc maps a rooted name through paths (its paths test treats only ./ and ../ as relative), but never reads one from baseUrl. codegraph read neither: ownConfigCandidates returned nothing for any specifier starting with /. So all 2,375 of bigbluebutton's rooted imports parked unresolved, and every name they import linked by bare-name matching:

Now a rooted specifier goes through the nearest config's paths patterns only, as tsc does; baseUrl is still never applied to it. A protocol-relative //host/x stays out.

A/B

Both arms are on main ada1445 with main's kernel; the change is resolution-only. Nodes are identical.

bigbluebutton

  • Unresolved refs: 26,189 → 22,565. Rooted imports left unresolved: 2,375 → 1, which names /imports/api/breakouts, a module that isn't in the repository.
  • Edges: 31,637 → 35,476. Gained:
  • Lost: the 2,753 name-matched import edges above, 1,197 exact-match calls, and 8 others:
    • 4 isMobile references. The file imports export const isMobile = isPhone || isTablet from /imports/utils/deviceInfo, and main had bound it to an unrelated isMobile() in layout/utils.js.
    • 4 JSX children of app/component.jsx's render, which renders more than the 30 children a parent keeps (MAX_JSX_CHILDREN). More of its tags now resolve, so 4 later ones fall off; one of them, PollingContainer, was bound on main to a styled namesake in polling/styles.ts.
  • Every edge whose target changed or is new was checked against the file its rooted import names: 2,449 land on that file. The other 181 land where that file forwards them:
    • Session.setItem reaches ObservableStorage.setItem because in-memory.ts is export default new ObservableStorage(new InMemoryStorage());
    • PollContainer reaches PollCreationPanelContainer through poll/container.jsx's import X from './component'; export default X.

Controls (13, byte-identical): outline, SigNoz, excalidraw, berry, mastodon, matx, mantis, minimal-kit, bulletproof-react, next-saas-starter, proshop, create-t3-turbo, and Rocket.Chat's apps/meteor. Rocket.Chat's tsconfig declares the same "/*": ["./*"] mapping, but its sources have since moved to relative imports.

Tests

tsconfig-baseurl-imports.test.ts:

  • a rooted specifier maps through paths, and is never read from baseUrl (a protocol-relative one neither);
  • a bigbluebutton-shaped app with its JSONC tsconfig and a namesake Icon in a folder that sorts first. The rooted import links its file; the tag renders, and the call reaches, what the import binds; a styled(Icon) wrapper renders it;
  • a sync that adds the modules equals a fresh index.

All but the baseUrl / protocol-relative case fail on main.

Full suite (--maxWorkers=4, kernel built, CODEGRAPH_KERNEL_EXPECT=1) on the branch merged with ada1445: 689 of 689 files; 8,260 tests, 8,178 passed, 0 failed, 82 skipped.

🤖 Generated with Claude Code

…tsconfig paths

bigbluebutton's client imports nearly everything from its root,
`import Icon from '/imports/ui/components/common/icon/component'`, which its
tsconfig maps with `"paths": { "/*": ["*"] }`. tsc maps a rooted name through
`paths` (only `./` and `../` count as relative there) and never reads it
from `baseUrl`. ownConfigCandidates refused every specifier starting with
`/`, so all 2,375 of these imports stayed unresolved and every name they
import linked by bare-name matching, often to the wrong one of several
same-named components.

A rooted specifier now goes through the nearest config's `paths` patterns
only; `baseUrl` is still never applied to it, and a protocol-relative
`//host/x` stays out. On bigbluebutton the unresolved refs fall from 26,189
to 22,565 and its rooted imports from 2,375 unresolved to 1 (a module that
isn't in the repository); 13 control repos are byte-identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@colbymchenry
colbymchenry merged commit aa01692 into main Oct 21, 2026
@colbymchenry
colbymchenry deleted the claude/meteor-root-imports branch October 21, 2026 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant