parser

package
v1.0.0-beta.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2025 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package parser provides a bunch of functions to be wrapped with generate.Parser function signature.

Examples:

type config struct { ... }

func ParserNode(ctx context.Context, destdir string, c *config) error {
	var jsonfile parser.PackageJSON
	jsonpath := filepath.Join(destdir, parser.FilePackageJSON)
	if err := files.ReadJSON(jsonpath, &jsonfile, os.ReadFile); err != nil {
		if errors.Is(err, fs.ErrNotExist) {
			return nil
		}
		return fmt.Errorf("read json: %w", err)
	}
	engine.GetLogger().Infof("node detected, a '%s' is present and valid", parser.FilePackageJSON)

	if err := jsonfile.Validate(); err != nil {
		return fmt.Errorf("validate '%s': %w", parser.FilePackageJSON, err)
	}
	// do something with parsed jsonfile (e.g. update config since it's a pointer)
	return nil
}

var _ generate.Parser[config] = ParserNode // ensure interface is implemented

// single parser call
func main() {
	var c config
	err := parser.ParserNode(ctx, "path/to/dir", &c)
	// handle err
}

// fully used with engine.Generate
func main() {
	destdir, _ := os.Getwd()

	var c config
	err := engine.Generate(ctx, destdir, c, []engine.Parser[config]{ParserNode}, ...)
	// handle err
}

Index

Constants

View Source
const (
	// FolderCMD represents the cmd folder where go main.go should be placed according to go layout.
	FolderCMD = "cmd"

	// FileGomod represents the go.mod filename.
	FileGomod = "go.mod"

	// FileMain represents the main.go filename.
	FileMain = "main.go"
)
View Source
const (
	// Bitbucket is just the bitbucket constant.
	Bitbucket = "bitbucket"
	// Gitea is just the gitea constant.
	Gitea = "gitea"
	// GitHub is just the github constant.
	GitHub = "github"
	// GitLab is just the gitlab constant.
	GitLab = "gitlab"
)
View Source
const FilePackageJSON = "package.json"

FilePackageJSON represents package.json filename.

Variables

View Source
var (
	// ErrMissingModuleStatement is the error returned when module statement is missing from go.mod.
	ErrMissingModuleStatement = errors.New("invalid go.mod, module statement is missing")

	// ErrMissingGoStatement is the error returned when go statement is missing from go.mod.
	ErrMissingGoStatement = errors.New("invalid go.mod, go statement is missing")
)
View Source
var (
	// ErrMissingPackageName is the error returned when package.json name is missing.
	ErrMissingPackageName = errors.New("package.json 'name' is missing")

	// ErrInvalidPackageManager is the error returned when packageManager is missing or invalid in package.json.
	ErrInvalidPackageManager = errors.New("package.json 'packageManager' is missing or isn't valid")
)

Functions

func MergeValues

func MergeValues(values any, filepaths ...string) (map[string]any, error)

MergeValues merges all input values files into one and only map.

It also takes an input values struct / map that could have been read beforehand and marshals it with JSON as base values.

All successive merges are made with override strategy, meaning that a value can be overridden by the next values file. See mergo.Merge for more details.

In case of error, merges stops on the first error and returns it.

It can be used as a simple function, calling it directly, but can also be used as its expected usage with engine.Generate:

type config struct { ... }

func ParserChart(ctx context.Context, destdir string, c *config) error {
	chartdir := filepath.Join(destdir, "chart")
	if config.CI != nil && config.CI.Deployment != nil && config.CI.Deployment.Helm {
		engine.GetLogger().Infof("skipping helm chart, configuration has 'exclude' key with 'chart' in it")
		if err := os.RemoveAll(chartdir); err != nil {
			return fmt.Errorf("remove chart dir: %w", err)
		}
		return nil
	}
	engine.GetLogger().Infof("helm chart detected, configuration doesn't have 'exclude' key or 'chart' isn't present in it")

	values, err := parser.MergeValues(c,
		filepath.Join(chartdir, "values.custom1.yaml"),
		filepath.Join(chartdir, "values.custom2.yaml"))
	if err != nil {
		return fmt.Errorf("merge values: %w", err)
	}
	// do something with values (e.g. update config since it's a pointer)
	return nil
}

Types

type Executables

type Executables struct {
	// Clis is a map of CLI names without value (empty struct).
	Clis map[string]struct{} `json:"clis,omitempty"`

	// Crons is a map of cronjob names without value (empty struct).
	Crons map[string]struct{} `json:"crons,omitempty"`

	// Jobs is a map of job names without value (empty struct).
	Jobs map[string]struct{} `json:"jobs,omitempty"`

	// Workers is a map of workers names without value (empty struct).
	Workers map[string]struct{} `json:"workers,omitempty"`
}

Executables represents a collection of executables (clis, cronjobs, jobs, workers).

func ReadGoCmd

func ReadGoCmd(destdir string) (Executables, error)

ReadGoCmd reads cmd folder at destdir and returns all executables found.

An executable is a main.go present in a subfolder of cmd. For instance cmd/<name>/main.go.

Executables are categorized as CLI, Cron, Job and Worker. The prefix of <name> indicates in which category the executable belongs:

  • <name> for CLI executables
  • cron-<name> for cron executables
  • job-<name> for job executables
  • worker-<name> for worker executables

It can be used as a simple function, calling it directly, but can also be used as its expected usage with engine.Generate:

type config struct { ... }

func ParserGolang(ctx context.Context, destdir string, c *config) error {
	gomod, err := parser.ReadGomod(destdir)
	if err != nil {
		if errors.Is(err, fs.ErrNotExist) {
			return nil
		}
		return fmt.Errorf("read go.mod: %w", err)
	}

	engine.GetLogger().Infof("golang detected, file '%s' is present and valid", parser.FileGomod)
	// do something with gomod (e.g. update config since it's a pointer)

	executables, err := parser.ReadGoCmd(destdir)
	if err != nil {
		if errors.Is(err, fs.ErrNotExist) {
			return nil
		}
		return fmt.Errorf("read cmd: %w", err)
	}
	// do something with executables (e.g. update config since it's a pointer)
	return nil
}

func (*Executables) AddCLI

func (g *Executables) AddCLI(name string)

AddCLI sets a CLI with its name. In case a CLI with the name same already exists, it is replaced.

func (*Executables) AddCron

func (g *Executables) AddCron(name string)

AddCron sets a cronjob with its name. In case a cronjob with the name same already exists, it is replaced.

func (*Executables) AddJob

func (g *Executables) AddJob(name string)

AddJob sets a job with its name. In case a job with the name same already exists, it is replaced.

func (*Executables) AddWorker

func (g *Executables) AddWorker(name string)

AddWorker sets a worker with its name. In case a worker with the name same already exists, it is replaced.

func (Executables) Binaries

func (g Executables) Binaries() int

Binaries returns the sum of all executables (clis, cronjobs, jobs, workers).

type Gomod

type Gomod struct {
	// Go is the go statement,
	// i.e. "go 1.23.4" without "go" (and space) part.
	Go string

	// Module is the module statement,
	// i.e. "module github.com/kilianpaquier/craft" without "module" (and space) part.
	Module string

	// Toolchain is the toolchain statement,
	// i.e. "toolchain go1.23.4" without "toolchain go" part.
	Toolchain string

	// Tools is the slice of tools present in go.mod file.
	// Nothing is done on it like formatting, as such the path of each tool is the full path given in go.mod.
	Tools []string
}

Gomod represents the parsed struct for go.mod file.

func ReadGomod

func ReadGomod(destdir string) (Gomod, error)

ReadGomod reads the go.mod file at destdir and returns its representation.

It will return an error if the go.mod file is missing the following properties:

  • module statement
  • go statement

It can be used as a simple function, calling it directly, but can also be used as its expected usage with engine.Generate:

type config struct { ... }

func Golang(ctx context.Context, destdir string, c *config) error {
	gomod, err := parser.ReadGomod(destdir)
	if err != nil {
		if errors.Is(err, fs.ErrNotExist) {
			return nil
		}
		return fmt.Errorf("read go.mod: %w", err)
	}
	engine.GetLogger().Infof("golang detected, file '%s' is present and valid", parser.FileGomod)
	// do something with gomod (e.g. update config since it's a pointer)
	return nil
}

func (Gomod) AsVCS

func (g Gomod) AsVCS() VCS

AsVCS returns the vcs configuration associated to module statement in go.mod.

type HugoConfig

type HugoConfig struct {
	// IsTheme expresses whether a theme.* configuration is present,
	// meaning current hugo repository is a theme one.
	IsTheme bool
}

HugoConfig represents the parse'd hugo.* or theme.* file associated to hugo configuration file.

func Hugo

func Hugo(destdir string) (HugoConfig, bool)

Hugo detects if the project is a Hugo project.

Detection consists of looking for hugo.* or theme.* files in the given destdir.

It can be used as a simple function, calling it directly, but can also be used as its expected usage with engine.Generate:

type config struct { ... }

func ParserHugo(ctx context.Context, destdir string, c *config) error {
	hugoc, ok := parser.Hugo(destdir)
	if !ok {
		return nil
	}
	engine.GetLogger().Infof("hugo detected, theme or hugo files are present")
	// do something with hugo config (e.g. update config since it's a pointer)
	return nil
}

type PackageJSON

type PackageJSON struct {
	Author         *string  `json:"author,omitempty"`
	Description    *string  `json:"description,omitempty"`
	Files          []string `json:"files,omitempty"`
	Keywords       []string `json:"keywords,omitempty"`
	License        *string  `json:"license,omitempty"`
	Main           *string  `json:"main,omitempty"`
	Module         string   `json:"module,omitempty"`
	Name           string   `json:"name,omitempty"`
	PackageManager string   `json:"packageManager,omitempty"`
	Private        bool     `json:"private,omitempty"`
	PublishConfig  struct {
		Access     string `json:"access,omitempty"`
		Provenance bool   `json:"provenance,omitempty"`
		Registry   string `json:"registry,omitempty"`
		Tag        string `json:"tag,omitempty"`
	} `json:"publishConfig,omitzero"`
	Repository *struct {
		URL string `json:"url,omitempty"`
	} `json:"repository,omitempty"`
	Scripts map[string]string `json:"scripts,omitempty"`
	Version string            `json:"version,omitempty"`
}

PackageJSON represents the node package json file.

func (*PackageJSON) Validate

func (p *PackageJSON) Validate() error

Validate validates the given PackageJSON struct.

type VCS

type VCS struct {
	// Name is the version control system name.
	Name string `json:"name,omitempty" yaml:"-"`

	// Platform represents the vcs platform hosting the project.
	Platform string `json:"-" yaml:"platform,omitempty"`

	// ProjectHost represents the host where the project is hosted.
	ProjectHost string `json:"projectHost,omitempty" yaml:"-"`

	// ProjectName is the project name being generated.
	ProjectName string `json:"projectName,omitempty" yaml:"-"`

	// ProjectPath is the project path.
	ProjectPath string `json:"projectPath,omitempty" yaml:"-"`
}

VCS structure contains all properties related to VCS (Version Control System).

func Git

func Git(destdir string) (VCS, error)

Git reads the input destdir directory remote.origin.url to retrieve various project information (git host, project name, etc.).

It can be used as a simple function, calling it directly, but can also be used as its expected usage with engine.Generate:

type config struct { ... }

func ParserGit(ctx context.Context, destdir string, c *config) error {
	vcs, err := parser.Git(destdir)
	if err != nil {
		engine.GetLogger().Warnf("failed to retrieve git vcs configuration: %v", err)
		return nil // a repository may not be a git repository
	}
	engine.GetLogger().Infof("git repository detected")
	// do something with vcs (e.g. update config since it's a pointer)
	return nil
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL