Skip to content

fix(imports): resolve workspace subpath exports (#1308)#1541

Closed
guyoron1 wants to merge 1 commit into
Graphify-Labs:v8from
guyoron1:v8
Closed

fix(imports): resolve workspace subpath exports (#1308)#1541
guyoron1 wants to merge 1 commit into
Graphify-Labs:v8from
guyoron1:v8

Conversation

@guyoron1

@guyoron1 guyoron1 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Workspace imports with subpath exports (e.g. import { value } from "@example/pkg-a/browser") now resolve through the package.json exports map instead of falling back to a bare path string
  • Supports string values, condition objects (source > import > module > default > require > svelte > types), nested conditions, and wildcard patterns ("./*": "./src/*.ts")
  • Normalizes import node IDs to use _file_stem instead of full paths across JS/Svelte/Astro/Vue extractors

Closes #1308

Test plan

  • 4 new tests: string subpath, condition object, wildcard, filesystem fallback
  • All 10 workspace tests pass
  • All 38 import extension resolution tests pass
  • Full 34-test JS import resolution suite passes — 0 regressions

…node IDs (Graphify-Labs#1308)

Workspace imports with subpath exports (e.g. `@pkg/foo/browser`) now
resolve through the package.json `exports` map instead of falling back
to a bare path string. Also normalizes import node IDs to use _file_stem
instead of full paths for consistency across JS/Svelte/Astro/Vue extractors.
safishamsi pushed a commit that referenced this pull request Jun 29, 2026
…orts map (#1308)

Workspace imports with subpath exports (e.g.
`import { x } from "@scope/pkg/browser"`) now resolve through the
package's `exports` map instead of falling back to a bare path. Supports
string values, condition objects, nested conditions, and single-`*`
wildcard patterns (`"./*": "./src/*.js"`), falling back to the existing
bare-path/index resolution when there is no exports map or no match.

Adapted from #1541, taking only the exports-map resolver and not that
PR's competing import-node-ID normalization (current v8 already resolves
the node-ID mismatch via the #1529 id-remap post-pass, and the PR's
_file_stem approach regressed the relative-input alias case). Two
hardening changes over the original:
- `default` is consulted LAST in the condition priority (it is Node's
  catch-all), so a matching `import`/`module`/`svelte` condition wins.
- Export targets that escape the package directory are rejected
  (`_contained_in_package`), so a malicious `exports` value like
  `"./x": "../../../etc/..."` cannot resolve to a file outside the package.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@safishamsi

Copy link
Copy Markdown
Collaborator

Thanks for this — the exports-map subpath resolver is a genuinely useful addition and it shipped on v8 (e8dabad) with your authorship. It resolves @scope/pkg/subpath imports through the package's exports map (string values, condition objects, nested conditions, ./* wildcards), which graphify couldn't do before.

I landed the resolver portion only, with two changes:

  • Dropped the import-node-ID normalization (_make_id(str(...))_make_id(_file_stem(...))) that the PR also included. Current v8 already fixes the node-ID mismatch a different, more complete way — commit 2133539 (import edges silently dropped on Next.js codebase — short IDs vs full-path node IDs (regression of #256) #1529), whose id-remap post-pass registers the absolute-resolved forms and handles the relative-input alias case. Keeping the _file_stem change on top regressed test_alias_import_edge_resolves_with_relative_input_paths (it changed the key the post-pass matches on, silently disabling the remap), so it was left out.
  • Two hardening tweaks: default is now consulted LAST in the condition priority (Node's catch-all), and export targets that escape the package dir are rejected (a "./x": "../../../etc/..." value can no longer resolve to a file outside the package).

Brought your 4 subpath tests plus two more (path-escape, default-last). Full suite green (2551), and the #1529 test still passes. Closing as shipped — credit for #1308 is yours. Thank you.

@safishamsi safishamsi closed this Jun 29, 2026
safishamsi added a commit that referenced this pull request Jun 29, 2026
Covers #1499 (Ruby type-aware resolution), #1308/#1541 (workspace
exports map), #1529 (alias/workspace import-edge regression), #1531
(tsconfig paths fallbacks), #1527 (semantic cache pruning), #1475 (three
ObjC fixes), #1533 (Swift static-call confidence), #1442 (secondary LLM
timeout), #1502 (GraphML null coercion + save-result --answer-file),
#1530 (host-generic skill wording), and the Dependabot dep bumps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mathieucarbou-ibm pushed a commit to mathieucarbou-ibm/graphify that referenced this pull request Jun 29, 2026
…orts map (Graphify-Labs#1308)

Workspace imports with subpath exports (e.g.
`import { x } from "@scope/pkg/browser"`) now resolve through the
package's `exports` map instead of falling back to a bare path. Supports
string values, condition objects, nested conditions, and single-`*`
wildcard patterns (`"./*": "./src/*.js"`), falling back to the existing
bare-path/index resolution when there is no exports map or no match.

Adapted from Graphify-Labs#1541, taking only the exports-map resolver and not that
PR's competing import-node-ID normalization (current v8 already resolves
the node-ID mismatch via the Graphify-Labs#1529 id-remap post-pass, and the PR's
_file_stem approach regressed the relative-input alias case). Two
hardening changes over the original:
- `default` is consulted LAST in the condition priority (it is Node's
  catch-all), so a matching `import`/`module`/`svelte` condition wins.
- Export targets that escape the package directory are rejected
  (`_contained_in_package`), so a malicious `exports` value like
  `"./x": "../../../etc/..."` cannot resolve to a file outside the package.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mathieucarbou-ibm pushed a commit to mathieucarbou-ibm/graphify that referenced this pull request Jun 29, 2026
Covers safishamsi#1499 (Ruby type-aware resolution), safishamsi#1308/safishamsi#1541 (workspace
exports map), safishamsi#1529 (alias/workspace import-edge regression), safishamsi#1531
(tsconfig paths fallbacks), safishamsi#1527 (semantic cache pruning), safishamsi#1475 (three
ObjC fixes), safishamsi#1533 (Swift static-call confidence), safishamsi#1442 (secondary LLM
timeout), safishamsi#1502 (GraphML null coercion + save-result --answer-file),
safishamsi#1530 (host-generic skill wording), and the Dependabot dep bumps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

TypeScript workspace imports do not resolve package subpath exports

2 participants