importresolve

package
v1.39.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package importresolve provides a unified import resolver shared by codegraph and analyze. It is a leaf package (path/filepath, strings, os, encoding/json) so both callers can import it without introducing dependency cycles.

Resolution strategy (in dispatch order):

  1. "$lib/…" / "$lib" — SvelteKit alias: resolved via each LibDir in Config.
  2. "@scope/pkg…" — Workspace scoped package: resolved via Config.Workspace.
  3. "./x" / "../x" — TS/JS/Svelte relative imports resolved against the importing file or package directory. See resolveRelative.
  4. everything else — Go-style absolute imports, longest-suffix-matched against the set of local package dirs. See localPkgDir.

A zero Config{} means "no aliases" — steps 1 and 2 are skipped, preserving the exact pre-alias behaviour for analyze callers that do not have config.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseExports added in v1.31.11

func ParseExports(raw json.RawMessage) map[string]string

ParseExports normalizes a package.json "exports" json.RawMessage into a map[string]string (normalized key → normalized target). Returns nil for empty or unparseable input. See readPackageManifest for the normalization rules.

Supported shapes:

  • string: "exports": "./index.ts" → {"": "index.ts"}
  • map: "exports": {"./foo": "./bar.ts"} → {"foo": "bar.ts"}
  • map wildcard: "exports": {"./*": "./src/*"} → {"*": "src/*"}
  • array value: "exports": {"./foo": ["./a.ts"]} → {"foo": "a.ts"}
  • cond object: "exports": {"./foo": {"import": "./a.mjs"}} → {"foo": "a.mjs"}

Types

type Config

type Config struct {
	// LibDirs is the list of SvelteKit project roots (repo-relative dirs that
	// contain a svelte.config.js or svelte.config.ts). For each LibDir, "$lib"
	// maps to "<libDir>/src/lib".
	LibDirs []string

	// Workspace maps a scoped package name (e.g. "@acme/mesh-core") to its
	// repo-relative directory (e.g. "packages/mesh-core"). Subpath imports like
	// "@acme/mesh-core/foo" are resolved by joining the mapped dir with "foo".
	Workspace map[string]string

	// WorkspaceExports maps a scoped package name to its package.json "exports"
	// map, normalized so that both keys and values have any leading "./" stripped
	// and use forward slashes (e.g. "./*" → "src/*"). Wildcard "*" is preserved.
	// Used by resolveWorkspaceAlias when the bare wsDir+subpath probe misses, to
	// honor subpath redirects like {"./*":"./src/*"} that move source under src/.
	// nil/empty for packages with no "exports" field — preserves pre-fix behavior.
	WorkspaceExports map[string]map[string]string

	// VirtualModules maps a project-local Vite virtual module id (e.g.
	// "virtual:guide/content") to the repo-relative directory of the package
	// that defines it (the package containing the Vite plugin's resolveId/load
	// code). This is the approach-2 stopgap from #423: it does NOT resolve to
	// the specific re-exported target file (that requires parsing the Vite
	// plugin's load() body and each app's astro.config — approach 1, deferred),
	// but it preserves the package-to-package IMPORTS edge so dep_graph /
	// dead_code / impact_analysis do not show the importing package as
	// orphaned. nil/empty when no virtual modules are found in the repo.
	VirtualModules map[string]string
}

Config carries alias configuration for the Resolver. A zero Config{} disables all alias resolution — relative and Go-style resolution still applies. This preserves exact pre-alias behaviour for analyze callers that do not have project config at hand.

func BuildConfig

func BuildConfig(root string) Config

BuildConfig walks the repository at root and produces a Config by:

  • recording the repo-relative dir of every svelte.config.js or svelte.config.ts as a LibDir (so "$lib" → "<libDir>/src/lib");
  • reading every package.json and mapping its "name" field to the repo-relative dir, building the Workspace alias map.

"node_modules" and any dot-directory (".git", ".svelte-kit", ".claude/worktrees", …) are skipped entirely via filepath.SkipDir (path-segment match, not substring). Skipping dot-dirs matters because some repos keep nested git worktrees (full repo copies) under e.g. .claude/worktrees/; descending into them would register a duplicate svelte.config / package.json and let a worktree copy win the $lib root or a Workspace name by last-write. Config files live in non-dot dirs, so this is safe. Files that cannot be read or parsed are silently skipped — one bad manifest must never fail the build.

BuildConfig is decoupled from ingest: it walks the repo from disk so that package.json files (which have no registered language and are excluded by the ingest language filter) are still discovered. This fixes the production bug where Config.Workspace was always empty because ingest.IngestRepo dropped .json files before BuildConfig could see them.

type Resolver

type Resolver struct {
	// contains filtered or unexported fields
}

Resolver resolves import paths to the repo-relative container directory of the package they refer to.

func New

func New(pkgDirs, fileSet map[string]struct{}, cfg Config) *Resolver

New builds a Resolver from pkgDirs (set of repo-relative package directories), fileSet (set of all indexed repo-relative file paths), and an alias Config. A zero Config{} means no aliases — relative and Go-style resolution only. Both maps must not be mutated after New returns.

func (*Resolver) Resolve

func (r *Resolver) Resolve(imp, importingDir string) (string, bool)

Resolve maps an import string to the repo-relative container directory of the package it refers to. Returns ("", false) for external (unresolvable) imports.

Dispatch order:

  1. "$lib/…" or "$lib" — SvelteKit alias (requires non-empty cfg.LibDirs).
  2. "@scope/pkg…" — workspace scoped package (requires cfg.Workspace entry).
  3. "virtual:…" — project-local Vite virtual module (requires cfg.VirtualModules entry). Stopgap (#423): resolves to the defining package dir, not the specific re-exported target file.
  4. "./x" / "../x" — relative import, resolved against importingDir. importingDir should be filepath.Dir(relFile) for file-level callers, or the package directory for package-level callers.
  5. everything else — Go-style absolute import, longest-suffix-matched.

Aliased imports that have no matching config entry fall through to external.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL