github.com/snyk/vervet/v5@v5.11.1-0.20240202085829-ad4dd7fb6101/generate/generate.go (about)

     1  package generate
     2  
     3  import (
     4  	"fmt"
     5  	"io/fs"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  	"text/template"
    10  
    11  	"github.com/snyk/vervet/v5/config"
    12  	"github.com/snyk/vervet/v5/internal/generator"
    13  )
    14  
    15  // GeneratorParams contains the metadata needed to execute code generators.
    16  type GeneratorParams struct {
    17  	ProjectDir     string
    18  	ConfigFile     string
    19  	Generators     []string
    20  	GeneratorsFile string
    21  	Force          bool
    22  	Debug          bool
    23  	DryRun         bool
    24  	FS             fs.FS
    25  	Functions      template.FuncMap
    26  }
    27  
    28  // Generate executes code generators against OpenAPI specs.
    29  func Generate(params GeneratorParams) error {
    30  	f, err := os.Open(params.ConfigFile)
    31  	if err != nil {
    32  		return err
    33  	}
    34  	defer f.Close()
    35  	proj, err := config.Load(f)
    36  	if err != nil {
    37  		return err
    38  	}
    39  
    40  	selectedGenerators := map[string]struct{}{}
    41  	for _, generator := range params.Generators {
    42  		selectedGenerators[generator] = struct{}{}
    43  	}
    44  
    45  	// Ensure a default FS if one isn't provided.
    46  	basePath := ""
    47  	if params.FS == nil {
    48  		basePath = "/"
    49  		params.FS = os.DirFS(basePath)
    50  	}
    51  
    52  	// Option to load generators and overlay onto project config
    53  	generatorsHere := map[string]string{}
    54  	if params.GeneratorsFile != "" {
    55  		genFile := strings.TrimPrefix(params.GeneratorsFile, "/")
    56  		f, err := params.FS.Open(genFile)
    57  		if err != nil {
    58  			return err
    59  		}
    60  		defer f.Close()
    61  		generators, err := config.LoadGenerators(f)
    62  		if err != nil {
    63  			return err
    64  		}
    65  		for k, v := range generators {
    66  			proj.Generators[k] = v
    67  			generatorsHere[k] = filepath.Dir(filepath.Join(basePath, genFile))
    68  		}
    69  	}
    70  	// If a list of specific generators were specified, only instantiate those.
    71  	if len(selectedGenerators) > 0 {
    72  		for k := range proj.Generators {
    73  			if _, ok := selectedGenerators[k]; !ok {
    74  				delete(proj.Generators, k)
    75  			}
    76  		}
    77  	}
    78  
    79  	options := []generator.Option{generator.Force(true)}
    80  	if params.Debug {
    81  		options = append(options, generator.Debug(true))
    82  	}
    83  	if params.DryRun {
    84  		options = append(options, generator.DryRun(true))
    85  	}
    86  	if params.FS != nil {
    87  		options = append(options, generator.Filesystem(params.FS))
    88  	}
    89  	if len(params.Functions) > 0 {
    90  		options = append(options, generator.Functions(params.Functions))
    91  	}
    92  	generators := map[string]*generator.Generator{}
    93  	for k, genConf := range proj.Generators {
    94  		genHere, ok := generatorsHere[k]
    95  		if !ok {
    96  			genHere = params.ProjectDir
    97  		}
    98  		genHere, err = filepath.Abs(genHere)
    99  		if err != nil {
   100  			return err
   101  		}
   102  		gen, err := generator.New(genConf, append(options, generator.Here(genHere))...)
   103  		if err != nil {
   104  			return err
   105  		}
   106  		generators[k] = gen
   107  	}
   108  
   109  	err = os.Chdir(params.ProjectDir)
   110  	if err != nil {
   111  		return err
   112  	}
   113  
   114  	resources, err := generator.MapResources(proj)
   115  	if err != nil {
   116  		return err
   117  	}
   118  
   119  	var allGeneratedFiles []string
   120  	for _, gen := range generators {
   121  		generatedFiles, err := gen.Execute(resources)
   122  		if err != nil {
   123  			return err
   124  		}
   125  		allGeneratedFiles = append(allGeneratedFiles, generatedFiles...)
   126  	}
   127  
   128  	for _, generatedFile := range allGeneratedFiles {
   129  		fmt.Println(generatedFile)
   130  	}
   131  
   132  	return nil
   133  }