Skip to content

refactor(shim): implement lite provider interface #74

@CalvinAllen

Description

@CalvinAllen

Refactor the shim to use a lightweight provider interface that excludes heavy dependencies.

Problem

The shim imports full runtime providers which pull in dependencies not needed at runtime:

  • net/http (~2MB) - used only by ListAvailable()
  • download package - used only by Install()
  • progressbar/v3 (~500KB) - used by download
  • Detection code for nvm/pyenv/fnm - used only by DetectInstalled()

Shim's Actual Needs

The shim only uses these provider methods:

type ShimProvider interface {
    Name() string
    DisplayName() string
    Shims() []string
    ExecutablePath(version string) (string, error)
    IsInstalled(version string) (bool, error)
    ShouldReshimAfter(shimName string, args []string) bool
}

It does not need:

  • Install() / Uninstall()
  • ListAvailable() / ListInstalled()
  • DetectInstalled()
  • GlobalPackages() / InstallGlobalPackages()

Proposed Solutions

Option A: Build Tags

Use //go:build !shim to exclude heavy methods from shim builds:

//go:build !shim

func (p *Provider) ListAvailable() ([]runtime.AvailableVersion, error) {
    // HTTP code here
}

Pros: Minimal code changes, single provider file
Cons: Build complexity, easy to forget tags

Option B: Interface Split

Create separate ShimProvider and FullProvider interfaces:

src/internal/runtime/
├── provider.go      # Full interface
└── shim_provider.go # Lite interface for shim

src/runtimes/node/
├── provider.go      # Core methods (both interfaces)
├── install.go       # Install/download (full only)
└── detect.go        # Detection code (full only)

Pros: Clean separation, explicit dependencies
Cons: More files, some duplication

Option C: Lazy Loading

Only import heavy packages when methods are called (using plugin or reflection).

Pros: No build changes
Cons: Complex, runtime overhead, not idiomatic Go

Expected Impact

  • Shim binary size: ~7.2MB → ~3-4MB (after symbol stripping)
  • Removes net/http initialization overhead
  • Faster cold starts

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions