💰 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
HasFundingfor 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.
type FundingInfo struct {
Name string `json:"name"`
URLs []string `json:"urls"`
Funding bool `json:"funding"`
}| Field | Type | Description |
|---|---|---|
Name | string | Package name, e.g., symfony/console |
URLs | []string | List of funding links (GitHub Sponsors, Patreon, etc.) |
Funding | bool | Whether funding support is declared |
FundInfo / FundResult
Used by the parsing layer ParseFundOutput (text format parsing), distinct from FundingInfo above.
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
| Method | Signature | Description |
|---|---|---|
| 💰 Fund | func (c *Composer) Fund() (string, error) | composer fund text output |
| 📋 FundWithJSON | func (c *Composer) FundWithJSON() ([]FundingInfo, error) | composer fund --format=json and parse |
| 🎯 FundWithPackage | func (c *Composer) FundWithPackage(packageName string) (string, error) | Query funding info for a single package |
| 🔗 GetFundingURLs | func (c *Composer) GetFundingURLs() (map[string][]string, error) | Package name → funding URL mapping |
| ❓ HasFunding | func (c *Composer) HasFunding() (bool, error) | Whether the project has packages accepting donations |
| ⚙️ FundWithOptions | func (c *Composer) FundWithOptions(options map[string]string) (string, error) | Custom options |
Examples
List All Packages Accepting Donations and Links
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
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
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
out, err := comp.FundWithPackage("symfony/console")
if err != nil {
log.Fatal(err)
}
fmt.Println(out)Specify Format with FundWithOptions
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.