Skip to content

💰 Funding

List packages in the project that accept funding and their funding links, making it easy to support open-source maintainers.

Composer's composer fund command reads the funding field from each installed package's composer.json and aggregates the display. Composer Skills wraps this into four layers: raw text output, JSON structured list, query by package, and a boolean check for "whether the project has any funding entries".

When to Use

  • 💖 Display "which open-source packages this project depends on that accept sponsorship" in your CLI tool or dashboard.
  • 📊 Include funding links in dependency reports to remind teams to support upstream maintainers.
  • 🤝 Decide whether to print a "consider sponsoring" prompt at the end of CI — use HasFunding for conditional checks.
  • 🎯 Query funding info for a specific package (e.g., symfony/console).

Structured Types

FundingInfo

Element returned by FundWithJSON, corresponds to an item in the composer fund --format=json array.

go
type FundingInfo struct {
	Name    string   `json:"name"`
	URLs    []string `json:"urls"`
	Funding bool     `json:"funding"`
}
FieldTypeDescription
NamestringPackage name, e.g., symfony/console
URLs[]stringList of funding links (GitHub Sponsors, Patreon, etc.)
FundingboolWhether funding support is declared

FundInfo / FundResult

Used by the parsing layer ParseFundOutput (text format parsing), distinct from FundingInfo above.

go
type FundInfo struct {
	Package string `json:"package"`
	Type    string `json:"type,omitempty"` // "github", "patreon", "tidelift", etc.
	URL     string `json:"url,omitempty"`
}

type FundResult struct {
	Funds []FundInfo `json:"funds,omitempty"`
}

Method Signatures

MethodSignatureDescription
💰 Fundfunc (c *Composer) Fund() (string, error)composer fund text output
📋 FundWithJSONfunc (c *Composer) FundWithJSON() ([]FundingInfo, error)composer fund --format=json and parse
🎯 FundWithPackagefunc (c *Composer) FundWithPackage(packageName string) (string, error)Query funding info for a single package
🔗 GetFundingURLsfunc (c *Composer) GetFundingURLs() (map[string][]string, error)Package name → funding URL mapping
❓ HasFundingfunc (c *Composer) HasFunding() (bool, error)Whether the project has packages accepting donations
⚙️ FundWithOptionsfunc (c *Composer) FundWithOptions(options map[string]string) (string, error)Custom options

Examples

go
package main

import (
	"fmt"
	"log"

	"github.com/scagogogo/composer-skills/pkg/composer"
)

func main() {
	comp, err := composer.New(composer.DefaultOptions())
	if err != nil {
		log.Fatalf("Initialization failed: %v", err)
	}

	urls, err := comp.GetFundingURLs()
	if err != nil {
		log.Fatalf("Failed to get funding links: %v", err)
	}

	for pkg, links := range urls {
		fmt.Printf("📦 %s\n", pkg)
		for _, u := range links {
			fmt.Printf("   -> %s\n", u)
		}
	}
}

Get Complete Structure with JSON

go
infos, err := comp.FundWithJSON()
if err != nil {
	log.Fatal(err)
}
for _, info := range infos {
	if info.Funding {
		fmt.Printf("%-30s %d funding links\n", info.Name, len(info.URLs))
	}
}

Conditional Sponsorship Prompt

go
has, err := comp.HasFunding()
if err != nil {
	log.Fatal(err)
}
if has {
	fmt.Println("💖 This project depends on open-source packages accepting sponsorship; run `composer fund` for details")
}

Query a Single Package

go
out, err := comp.FundWithPackage("symfony/console")
if err != nil {
	log.Fatal(err)
}
fmt.Println(out)

Specify Format with FundWithOptions

go
out, err := comp.FundWithOptions(map[string]string{
	"format": "json",
	"no-dev": "",
})
if err != nil {
	log.Fatal(err)
}
fmt.Println(out)

Advanced

HasFunding Determination Logic

HasFunding executes composer fund --format=text and returns true when the output doesn't contain the string "No funding". This is based on Composer's wording convention; future Composer wording changes may affect this check.

Don't Confuse the Two FundInfo Types

FundingInfo (fund.go) comes from --format=json, contains URLs slice; FundInfo (result_types.go) comes from ParseFundOutput parsing text output, contains Type field. The two have different fields; choose as needed.

Released under the MIT License