⚡ Convenience Methods
A set of high-level wrappers that consolidate common operations like "determine project status", "read composer.json/lock", "list installed packages/direct dependencies", "filter by type/abandoned", "namespace/script queries", and "directory location" into one-line calls.
Most of these methods directly read files or combine multiple composer subcommands, saving you from hand-writing parsing logic. They fall into three categories: 🩺 status checks, 📊 project summaries, 🔍 directory and config queries.
When to Use
- 🩺 Quickly determine if the current directory is a Composer project and whether dependencies are installed at startup.
- 📊 Generate a project health report: dependency count, outdated package count, vulnerability count, Composer/PHP version — all in one
GetProjectSummarycall. - 📋 List installed package names or direct dependency names for dependency analysis scripts.
- 🎯 Filter packages by type (find all
composer-plugin) or find abandoned packages. - 🗂️ Get vendor/bin/cache/home directory paths to plan cache or artifacts.
Structured Types
ProjectSummary
Returned by GetProjectSummary, a project health report aggregating multi-source information.
type ProjectSummary struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Type string `json:"type,omitempty"`
License string `json:"license,omitempty"`
DirectDependencyCount int `json:"direct_dependency_count"`
DevDependencyCount int `json:"dev_dependency_count"`
TotalInstalledCount int `json:"total_installed_count"`
OutdatedCount int `json:"outdated_count"`
VulnerabilityCount int `json:"vulnerability_count"`
ComposerVersion string `json:"composer_version,omitempty"`
PHPVersion string `json:"php_version,omitempty"`
}ProjectDependencies
Returned by GetProjectDependencies, dependency counts and package name lists.
type ProjectDependencies struct {
DirectCount int `json:"direct_count"`
DevCount int `json:"dev_count"`
TotalInstalled int `json:"total_installed"`
DirectPackages []string `json:"direct_packages,omitempty"`
DevPackages []string `json:"dev_packages,omitempty"`
InstalledPackages []string `json:"installed_packages,omitempty"`
}Method Signatures
🩺 Status Checks
| Method | Signature | Description |
|---|---|---|
| 📦 IsProject | func (c *Composer) IsProject() bool | Whether current working directory has composer.json |
| 📂 IsProjectIn | func (c *Composer) IsProjectIn(dir string) bool | Whether specified directory has composer.json |
| 🔒 HasComposerLock | func (c *Composer) HasComposerLock() bool | Whether composer.lock exists |
| 📁 HasVendorDir | func (c *Composer) HasVendorDir() bool | Whether vendor directory exists |
| ✅ IsPackageInstalled | func (c *Composer) IsPackageInstalled(packageName string) bool | Whether a package is installed |
| 🧪 IsPackageDev | func (c *Composer) IsPackageDev(packageName string) (bool, error) | Whether a package is in require-dev |
📊 Project Summary and Dependencies
| Method | Signature | Description |
|---|---|---|
| 📋 GetInstalledPackageNames | func (c *Composer) GetInstalledPackageNames() ([]string, error) | All installed package names |
| 🎯 GetDirectDependencyNames | func (c *Composer) GetDirectDependencyNames() ([]string, error) | Direct dependency package names |
| 🔢 GetPackageVersionsList | func (c *Composer) GetPackageVersionsList(packageName string) ([]string, error) | All available versions of a package |
| 📊 GetProjectDependencies | func (c *Composer) GetProjectDependencies() (*ProjectDependencies, error) | Dependency summary |
| 📈 GetProjectSummary | func (c *Composer) GetProjectSummary() (*ProjectSummary, error) | Project health report |
| 🔖 GetRequireWithVersion | func (c *Composer) GetRequireWithVersion(packageName string) (string, error) | Installed version of a package |
| 🏷️ GetPackagesByType | func (c *Composer) GetPackagesByType(packageType string) ([]string, error) | Filter packages by type |
| ⚠️ GetAbandonedPackagesFromLock | func (c *Composer) GetAbandonedPackagesFromLock() ([]string, error) | Find abandoned packages from lock |
| 🗺️ GetNamespaceMap | func (c *Composer) GetNamespaceMap() (map[string]string, error) | PSR-4 namespace → directory mapping |
| 📜 GetScripts | func (c *Composer) GetScripts() (map[string]interface{}, error) | composer.json scripts |
🗂️ Directory and File Reading
| Method | Signature | Description |
|---|---|---|
| 🏠 GetComposerHomeDir | func (c *Composer) GetComposerHomeDir() (string, error) | composer config home |
| 💾 GetCacheDir | func (c *Composer) GetCacheDir() (string, error) | composer config cache-dir |
| 📦 GetVendorDir | func (c *Composer) GetVendorDir() (string, error) | vendor directory (with fallback default) |
| 🗂️ GetBinDir | func (c *Composer) GetBinDir() (string, error) | bin directory (with fallback default) |
🔧 Package-level Parse Functions
| Method | Signature | Description |
|---|---|---|
| 📋 ParsePackageList | func ParsePackageList(output string) []string | Parse composer show text output |
| 🔢 ParsePackageVersions | func ParsePackageVersions(output string) ([]string, error) | Parse versions from show --all --format=json |
Examples
Project Health Report
package main
import (
"fmt"
"log"
"github.com/scagogogo/composer-skills/pkg/composer"
)
func main() {
comp, err := composer.New(composer.DefaultOptions())
if err != nil {
log.Fatal(err)
}
summary, err := comp.GetProjectSummary()
if err != nil {
log.Fatal(err)
}
fmt.Printf("📦 %s (%s)\n", summary.Name, summary.Type)
fmt.Printf(" Direct deps %d / Dev deps %d / Installed %d\n",
summary.DirectDependencyCount, summary.DevDependencyCount, summary.TotalInstalledCount)
fmt.Printf(" Outdated %d / Vulnerabilities %d\n", summary.OutdatedCount, summary.VulnerabilityCount)
fmt.Printf(" Composer %s / PHP %s\n", summary.ComposerVersion, summary.PHPVersion)
}List All Installed Package Names
pkgs, err := comp.GetInstalledPackageNames()
if err != nil {
log.Fatal(err)
}
for _, p := range pkgs {
fmt.Println(p)
}Filter Packages by Type
plugins, err := comp.GetPackagesByType("composer-plugin")
if err != nil {
log.Fatal(err)
}
for _, p := range plugins {
fmt.Println("🔌", p)
}Find Abandoned Packages
abandoned, err := comp.GetAbandonedPackagesFromLock()
if err != nil {
log.Fatal(err)
}
if len(abandoned) > 0 {
fmt.Println("⚠️ The following packages are abandoned, consider replacing:")
for _, p := range abandoned {
fmt.Println(" -", p)
}
}Query Installed Version of a Package
v, err := comp.GetRequireWithVersion("symfony/console")
if err != nil {
log.Fatal(err)
}
fmt.Println("symfony/console version:", v)Determine Project Status
if !comp.IsProject() {
log.Fatal("Current directory is not a Composer project")
}
if !comp.HasComposerLock() {
fmt.Println("⚠️ Missing composer.lock, recommend running composer install")
}
if !comp.HasVendorDir() {
fmt.Println("⚠️ Missing vendor directory, dependencies not installed")
}
if comp.IsPackageInstalled("phpunit/phpunit") {
fmt.Println("✅ PHPUnit installed")
}Get Directory Paths
home, _ := comp.GetComposerHomeDir()
cache, _ := comp.GetCacheDir()
vendor, _ := comp.GetVendorDir()
bin, _ := comp.GetBinDir()
fmt.Printf("home=%s\ncache=%s\nvendor=%s\nbin=%s\n", home, cache, vendor, bin)Using Parse Functions Independently
// You can run composer show yourself to get output, then use ParsePackageList to extract
output := `symfony/console v5.4.0 Eases...
monolog/monolog 2.5.0 Sends...`
for _, name := range composer.ParsePackageList(output) {
fmt.Println(name)
}Advanced
GetProjectSummary Fault Tolerance
GetProjectSummary internally does err == nil checks on each sub-call — any single failure (e.g., no lock file) only leaves the corresponding field empty, without interrupting the overall report. This makes it suitable for "best-effort" health checks.
Two Abandoned Package Methods
GetAbandonedPackagesFromLock (this file) directly reads the abandoned field from composer.lock, no command execution needed; audit.go's GetAbandonedPackages goes through the composer audit command and returns []Vulnerability. The former is faster, the latter is more complete (includes extra info like abandonment reasons).
GetVendorDir / GetBinDir Fallback
When composer config vendor-dir fails (e.g., uninitialized project), they fall back to <working directory>/vendor and <working directory>/vendor/bin, not returning an error. This is intentional design, so reasonable default paths can be obtained even when the project is unconfigured.
IsPackageInstalled Determination
IsPackageInstalled executes composer show <pkg>; success means installed. Note that Composer may also return non-zero exit code when a package exists but has version issues, so this check is "optimistic".