github.com/octohelm/cuemod@v0.9.4/pkg/cuemod/build.go (about)

     1  package cuemod
     2  
     3  import (
     4  	"path/filepath"
     5  	"strconv"
     6  	"strings"
     7  
     8  	cueast "cuelang.org/go/cue/ast"
     9  	"cuelang.org/go/cue/build"
    10  	"cuelang.org/go/cue/load"
    11  	"cuelang.org/go/cue/parser"
    12  	"github.com/octohelm/cuemod/pkg/cuemod/builtin"
    13  )
    14  
    15  type OptionFunc = func(c *load.Config)
    16  
    17  func OptRoot(dir string) OptionFunc {
    18  	return func(c *load.Config) {
    19  		c.Dir = dir
    20  	}
    21  }
    22  
    23  func OptOverlay(overlay map[string]load.Source) OptionFunc {
    24  	return func(c *load.Config) {
    25  		c.Overlay = overlay
    26  	}
    27  }
    28  
    29  type ImportFunc = func(importPath string, importedAt string) (resolvedDir string, err error)
    30  
    31  func OptImportFunc(importFunc ImportFunc) OptionFunc {
    32  	return func(c *load.Config) {
    33  		c.ParseFile = func(filename string, src any) (*cueast.File, error) {
    34  			f, err := parser.ParseFile(filename, src, parser.ParseComments)
    35  			if err != nil {
    36  				return nil, err
    37  			}
    38  
    39  			for i := range f.Imports {
    40  				importPath, _ := strconv.Unquote(f.Imports[i].Path.Value)
    41  
    42  				// skip abs path and rel path
    43  				if filepath.IsAbs(importPath) {
    44  					continue
    45  				}
    46  
    47  				// "xxx/xxxx:xxx"
    48  				importPath = strings.Split(importPath, ":")[0]
    49  
    50  				// skip builtin
    51  				if builtin.IsBuiltIn(importPath) {
    52  					continue
    53  				}
    54  
    55  				_, err := importFunc(importPath, filename)
    56  				if err != nil {
    57  					return nil, err
    58  				}
    59  			}
    60  
    61  			return f, nil
    62  		}
    63  	}
    64  }
    65  
    66  type Instance = build.Instance
    67  
    68  func BuildConfig(optionFns ...OptionFunc) *load.Config {
    69  	c := &load.Config{}
    70  	for i := range optionFns {
    71  		optionFns[i](c)
    72  	}
    73  	return c
    74  }
    75  
    76  func BuildInstances(c *load.Config, inputs []string) []*Instance {
    77  	files := make([]string, len(inputs))
    78  
    79  	for i, f := range inputs {
    80  		if filepath.IsAbs(f) {
    81  			rel, _ := filepath.Rel(c.Dir, f)
    82  			files[i] = "./" + rel
    83  		} else {
    84  			files[i] = f
    85  		}
    86  	}
    87  
    88  	return load.Instances(files, c)
    89  }
    90  
    91  func Build(inputs []string, optionFns ...OptionFunc) *Instance {
    92  	c := BuildConfig(optionFns...)
    93  	// load only support related path
    94  	return BuildInstances(c, inputs)[0]
    95  }