fix(trace): output imports and scopes in single and batch modes#21
Conversation
📝 WalkthroughWalkthroughThe PR adds Resolver.ResolveSpecifiers and changes tracing to call it directly for traced bare specifiers. Single-file and batch trace paths now use a shared baseResolver to produce per-file imports via ResolveSpecifiers while still deriving scopes from a full resolve. Changes
Sequence Diagram(s)sequenceDiagram
participant CLI as mappa trace (main)
participant Worker as traceFile / worker
participant Parser as HTML parser (bareSpec discovery)
participant BaseR as baseResolver (Resolver)
participant FullR as full resolve (for scopes)
CLI->>Worker: start trace (single or batch)
Worker->>Parser: parse file -> bareSpecs
Worker->>BaseR: ResolveSpecifiers(workspaceRoot, bareSpecs)
BaseR-->>Worker: map[baredSpecifier]=resolvedURL (imports)
Worker->>FullR: perform full resolve (to collect scopes)
FullR-->>Worker: scopes map
Worker->>CLI: emit result {file, imports, scopes}
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
✏️ Tip: You can disable this entire section by setting Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
main.go (1)
522-531: Consider reusing resolver across batch workers for efficiency.Each worker creates a new resolver per file with the same configuration (
templateArg,conditions). While this is thread-safe, creating the resolver once and sharing it across workers would be slightly more efficient:♻️ Optional: Share resolver across workers
In
runTraceBatch, create the resolver once before spawning workers:// In runTraceBatch, before worker creation: resolver := local.New(osfs, nil) resolver, err = resolver.WithTemplate(templateArg) if err != nil { return fmt.Errorf("invalid template: %w", err) } if len(conditions) > 0 { resolver = resolver.WithConditions(conditions) } // Pass resolver to traceFile instead of templateArg and conditionsThen update
traceFilesignature to accept the resolver directly. TheResolvertype and its methods appear to be safe for concurrent use sinceResolveSpecifiersonly reads configuration.main_test.go (1)
410-438: LGTM – valid regression test for issue#15.The test correctly verifies that deep imports not listed in package exports are resolved in single-file trace mode. The assertion logic is sound.
Optional: Consider adding an
expected.jsongolden file intestdata/trace/unresolvable/and usingcompareOrUpdateGoldenfor more comprehensive output validation, consistent withTestTraceandTestTraceWithTemplate. This would catch unexpected regressions in other output fields.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
testdata/trace/unresolvable/node_modules/@example/core/button/button.jsis excluded by!**/node_modules/**testdata/trace/unresolvable/node_modules/@example/core/index.jsis excluded by!**/node_modules/**testdata/trace/unresolvable/node_modules/@example/core/package.jsonis excluded by!**/node_modules/**
📒 Files selected for processing (6)
main.gomain_test.goresolve/local/local.gotestdata/trace/unresolvable/package.jsontestdata/trace/unresolvable/page.htmltestdata/trace/unresolvable/page2.html
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.go: Getter methods should be namedFoo(), notGetFoo()
Rungo vetto surface gopls suggestions, including: replaceinterface{}withany, replaceif/elsewithmin, replacem[k]=vloop withmaps.Copy, and simplify loops usingslices.Contains
Always use the pluggable FileSystem interface: never useos.ReadFile,os.Stat,os.ReadDir, etc. directly; all functions that read from disk must accept aFileSystemparameter
UseNewOSFileSystem()only at the top level (CLI entry point), not throughout the codebase
Files:
resolve/local/local.gomain_test.gomain.go
**/testdata/**
📄 CodeRabbit inference engine (CLAUDE.md)
Each test fixture scenario should be a subdirectory containing required input files (input.json, index.html, module.js, or package.json) and expected.json for assertions
Files:
testdata/trace/unresolvable/package.jsontestdata/trace/unresolvable/page.htmltestdata/trace/unresolvable/page2.html
**/*_test.go
📄 CodeRabbit inference engine (CLAUDE.md)
**/*_test.go: Practice TDD and use fixture/golden patterns for tests: place input test data intestdata/directories and expected output files (e.g.,expected.json) for comparison; tests should support--updateflag to regenerate golden files
Always usetestutil.NewFixtureFSfor tests to load fixtures into MapFileSystem, never useNewOSFileSystem()in tests
For unit tests that don't need fixtures, create an empty MapFileSystem usingimportmaps.NewMapFileSystem()instead of using the OS filesystem
Don't inline source code in tests; use fixture files instead with input files and expected output inexpected.json
UseNewMapFileSystem()andNewFixtureFS()in tests for testability with mock filesystems and integration with cem
Files:
main_test.go
🧠 Learnings (4)
📚 Learning: 2026-01-14T10:24:30.377Z
Learnt from: CR
Repo: bennypowers/mappa PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T10:24:30.377Z
Learning: Applies to **/*_test.go : Don't inline source code in tests; use fixture files instead with input files and expected output in `expected.json`
Applied to files:
main_test.go
📚 Learning: 2026-01-14T10:24:30.377Z
Learnt from: CR
Repo: bennypowers/mappa PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T10:24:30.377Z
Learning: Applies to **/*_test.go : Practice TDD and use fixture/golden patterns for tests: place input test data in `testdata/` directories and expected output files (e.g., `expected.json`) for comparison; tests should support `--update` flag to regenerate golden files
Applied to files:
main_test.go
📚 Learning: 2026-01-14T10:24:30.377Z
Learnt from: CR
Repo: bennypowers/mappa PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T10:24:30.377Z
Learning: Applies to **/*_test.go : Use `NewMapFileSystem()` and `NewFixtureFS()` in tests for testability with mock filesystems and integration with cem
Applied to files:
main_test.go
📚 Learning: 2026-01-14T10:24:30.377Z
Learnt from: CR
Repo: bennypowers/mappa PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T10:24:30.377Z
Learning: Applies to **/*_test.go : For unit tests that don't need fixtures, create an empty MapFileSystem using `importmaps.NewMapFileSystem()` instead of using the OS filesystem
Applied to files:
main_test.go
🧬 Code graph analysis (2)
resolve/local/local.go (1)
resolve/resolve.go (2)
Resolver(30-33)FindWorkspaceRoot(49-77)
main.go (1)
importmap/importmap.go (1)
ImportMap(27-37)
🔇 Additional comments (6)
testdata/trace/unresolvable/package.json (1)
1-6: LGTM!The package manifest correctly declares the
@example/coredependency needed for the unresolvable import test scenario.testdata/trace/unresolvable/page.html (1)
1-10: LGTM!The test file clearly documents its purpose with an inline comment explaining that this deep import exists as a file but is not in the package's exports. This is a good testing practice that makes the test scenario self-documenting.
main.go (2)
340-366: LGTM - Single trace mode correctly combines Resolve and ResolveSpecifiers.The approach of using
Resolvefor scopes (transitive dependencies) while usingResolveSpecifiersfor direct imports handles the deep import scenario correctly. This ensures that:
- Deep imports not in package exports are resolved via
ResolveSpecifiers- Scopes for transitive dependencies are still computed via full
Resolve
533-535: This is not an inconsistency—single mode and batch mode use entirely different output types by design.Single mode (
runTraceSingle) outputs a completeimportmap.ImportMap(with both Imports and Scopes) for a single file. Batch mode (runTraceBatch→traceFile) outputstraceResultrecords (one per file) with only File, Imports, Error, and Warnings fields. ThetraceResultstruct was never designed to include scopes—it's intentionally minimal for per-file NDJSON output.Likely an incorrect or invalid review comment.
testdata/trace/unresolvable/page2.html (1)
1-10: Test fixture correctly structured for programmatic test validation.The HTML file properly sets up a test case for deep module imports (
@example/core/button/button.js). The testdata/trace/unresolvable directory appropriately provides the necessary input files: page.html, page2.html, package.json, and mock node_modules. The test validates output through programmatic assertions on CLI stdout (JSON/NDJSON parsing), not through expected.json comparison, which is the established pattern in this test suite.main_test.go (1)
440-476: LGTM – valid regression test for issue#20.The test correctly verifies that batch mode resolves deep imports across multiple HTML files. Fixtures are properly structured with both
page.htmlandpage2.htmlimporting@example/core/button/button.jsfrom the mock@example/corepackage. The NDJSON parsing and validation pattern aligns with existing batch tests.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
Fixes #20
Fixes #15
Summary by CodeRabbit
Bug Fixes
Refactor
Tests
✏️ Tip: You can customize this high-level summary in your review settings.