Skip to content

fix: discover transitive deps with skills and handle shim import errors#46

Merged
KyleAMathews merged 3 commits intomainfrom
fix/transitive-deps-and-shim-error
Mar 7, 2026
Merged

fix: discover transitive deps with skills and handle shim import errors#46
KyleAMathews merged 3 commits intomainfrom
fix/transitive-deps-and-shim-error

Conversation

@KyleAMathews
Copy link
Collaborator

Summary

Fix two bugs: the scanner misses transitive dependencies with skills in non-hoisted layouts (pnpm), and bunx @tanstack/intent install fails when a library's intent shim shadows the real package binary.

Root Cause

Transitive deps not found: scanForIntents only reads top-level node_modules/ entries. In pnpm, only direct dependencies are symlinked there — transitive deps like @tanstack/db (a dependency of @tanstack/react-db) live in .pnpm/ and are invisible to the flat scan.

Shim import failure: Libraries ship a bin/intent.mjs shim that does await import('@tanstack/intent/intent-library'). When a user runs bunx @tanstack/intent (without @latest), bun finds the local intent binary from the shim and runs it instead of downloading @tanstack/intent. The import then fails because @tanstack/intent isn't a project dependency.

Approach

Transitive dependency walking

Added a Phase 2 to scanForIntents that walks the dependency tree after the initial flat scan. A new resolveDepDir utility resolves packages by:

  1. Checking top-level node_modules/ (handles hoisted layouts — npm, yarn, bun)
  2. Following realpathSync to navigate the pnpm virtual store: from a package's real path, walk up by the number of segments in its name to reach the enclosing node_modules/, then find the dep as a sibling

The same resolveDepDir was also applied to library-scanner.ts so the library shim's intent list also finds non-hoisted deps.

A tryRegister helper was extracted to share the package registration logic (read package.json → validate intent → discover skills → push) between Phase 1 and Phase 2, eliminating ~40 lines of duplication.

Shim error handling

Updated the shim template to wrap the import in a try/catch. On ERR_MODULE_NOT_FOUND, it prints a clear message suggesting npm add -D @tanstack/intent or npx @tanstack/intent@latest list.

Documentation

All npx @tanstack/intent commands in README and docs now use @latest to avoid the local binary conflict.

Key Invariants

  • Phase 1 (flat scan) behavior is unchanged — no regression for hoisted layouts
  • walkVisited set prevents infinite recursion on circular deps
  • foundNames set (shared via tryRegister) prevents duplicate package entries
  • resolveDepDir returns null (not found) only for ENOENT/ENOTDIR; other errors are logged

Non-goals

  • Walking deps of non-intent packages to find deeply nested intent deps (would require scanning all transitive deps; covered by walking from direct deps and found skill packages)
  • Fixing already-published library shims (only newly generated shims get the error handling)

Verification

pnpm run --filter @tanstack/intent test:lib    # 127 tests pass
pnpm run --filter @tanstack/intent test:types  # Type checking passes

Files changed

File Change
src/utils.ts New getDeps and resolveDepDir shared utilities
src/scanner.ts Phase 2 dep walking, tryRegister extraction, proper error handling
src/library-scanner.ts Use shared getDeps and resolveDepDir (removed local duplicate)
src/setup.ts Shim template wraps import in try/catch with helpful error message
src/index.ts Export new utilities
src/cli.ts @latest in scaffold README suggestion
README.md All npx commands use @latest
docs/overview.md All npx commands use @latest
scripts/validate-skills.ts Fix allowed shell command pattern

🤖 Generated with Claude Code

KyleAMathews and others added 2 commits March 6, 2026 21:02
The scanner only checked top-level node_modules, missing transitive
dependencies with skills in non-hoisted layouts (pnpm). Add Phase 2
dependency walking that resolves packages through the pnpm virtual store
using realpathSync.

Also fix the library shim to catch ERR_MODULE_NOT_FOUND gracefully when
@tanstack/intent isn't installed, and update all docs to use @latest to
avoid the local binary conflict.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions bot mentioned this pull request Mar 7, 2026
@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 7, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@tanstack/intent@46

commit: aa00cd4

@KyleAMathews KyleAMathews merged commit 2964f75 into main Mar 7, 2026
5 checks passed
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.

2 participants