bldr/web/bundler/web-pkg-refs.go
Rama master · réplica de lectura del repositorio original.
package bldr_web_bundler
import (
"slices"
"strings"
web_pkg "github.com/s4wave/spacewave/bldr/web/pkg"
)
// WebPkgRefConfigSlice is a slice of WebPkgRefConfig.
type WebPkgRefConfigSlice []*WebPkgRefConfig
// AppendWebPkgRef appends a web pkg ref to the slice.
// Merges with any existing definition for that web pkg id.
//
// Returns true if any changes were made.
func (sl WebPkgRefConfigSlice) AppendWebPkgRefConfig(addConf *WebPkgRefConfig) (WebPkgRefConfigSlice, bool) {
// Require a package ID before merging its reference configuration.
if addConf.GetId() == "" {
return sl, false
}
// check if the ref already exists
var ref *WebPkgRefConfig
var dirty bool
for _, sref := range sl {
if sref.GetId() == addConf.GetId() {
ref = sref
break
}
}
// Insert a new package reference or merge its exclusions and imports.
if ref == nil {
sl = append(sl, addConf.CloneVT())
slices.SortFunc(sl, func(a, b *WebPkgRefConfig) int {
return strings.Compare(a.GetId(), b.GetId())
})
dirty = true
} else {
if addConf.GetExclude() && !ref.GetExclude() {
dirty = true
ref.Exclude = true
}
for _, addImport := range addConf.GetImports() {
if !slices.Contains(ref.Imports, addImport) {
dirty = true
ref.Imports = append(ref.Imports, addImport)
}
}
if dirty {
slices.Sort(ref.Imports)
}
}
return sl, dirty
}
// MergeWebPkgRefConfigImports merges declared config imports into resolved web
// package refs. Config imports are package-root-relative entry files and apply
// everywhere a WebPkgRefConfig is consumed; callers that already resolved package
// roots call this instead of rebuilding the merge policy locally.
func MergeWebPkgRefConfigImports(refs web_pkg.WebPkgRefSlice, configs []*WebPkgRefConfig) web_pkg.WebPkgRefSlice {
if len(refs) == 0 || len(configs) == 0 {
return refs
}
for _, conf := range CompactWebPkgRefConfigs(slices.Clone(configs)) {
if conf.GetId() == "" || conf.GetExclude() || len(conf.GetImports()) == 0 {
continue
}
ref, _ := web_pkg.FindWebPkgRef(refs, conf.GetId())
if ref == nil {
continue
}
for _, imp := range conf.GetImports() {
refs, _ = refs.AppendWebPkgRef(conf.GetId(), ref.GetWebPkgRoot(), imp)
}
}
return refs
}
// ToIdList converts the list to the esbuild externalize list.
func (sl WebPkgRefConfigSlice) ToIdList() []string {
// Collect the package IDs for the externalize list.
out := make([]string, 0, len(sl))
for _, v := range sl {
out = append(out, v.GetId())
}
// Sort and deduplicate the external package IDs.
slices.Sort(out)
out = slices.Compact(out)
return out
}
// ExcludedWebPkgIDs returns the set of web pkg IDs that have exclude=true.
func ExcludedWebPkgIDs(refs []*WebPkgRefConfig) map[string]struct{} {
out := make(map[string]struct{})
for _, ref := range refs {
if ref.GetExclude() {
out[ref.GetId()] = struct{}{}
}
}
return out
}
// SortWebPkgRefConfigs sorts the list of ref configs by web pkg id.
func SortWebPkgRefConfigs(refs []*WebPkgRefConfig) {
slices.SortStableFunc(refs, func(a, b *WebPkgRefConfig) int {
return strings.Compare(a.GetId(), b.GetId())
})
}
// CompactWebPkgRefConfigs compacts the list of ref configs by web pkg id.
// Merges together entries with the same ID in-place.
func CompactWebPkgRefConfigs(refs []*WebPkgRefConfig) []*WebPkgRefConfig {
// Keep reference lists that cannot contain duplicate package IDs.
if len(refs) <= 1 {
return refs
}
// Sort by ID first to ensure we process duplicates together
SortWebPkgRefConfigs(refs)
// Iterate through the sorted slice, merging duplicates
writeIdx := 0
for readIdx := range refs {
// Skip empty IDs
if refs[readIdx].GetId() == "" {
continue
}
// If this is the first element or has a different ID than the previous one
if writeIdx == 0 || refs[writeIdx-1].GetId() != refs[readIdx].GetId() {
// If we're not at the same position, copy the current element
if writeIdx != readIdx {
refs[writeIdx] = refs[readIdx]
}
writeIdx++
} else {
// Same ID as previous element, merge with it
prev := refs[writeIdx-1]
curr := refs[readIdx]
// Merge exclude flag
if curr.GetExclude() {
prev.Exclude = true
}
// Merge imports
for _, imp := range curr.GetImports() {
if !slices.Contains(prev.Imports, imp) {
prev.Imports = append(prev.Imports, imp)
}
}
// Sort imports for consistency
slices.Sort(prev.Imports)
}
}
// Return the compacted slice
return refs[:writeIdx]
}