builder

package module
v1.0.9 Latest Latest
Warning

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

Go to latest
Published: May 2, 2019 License: MIT Imports: 15 Imported by: 0

README

Application Meta Builder (Library)

Build applications by copying, parsing and bundling files from a meta-source directory as described by a configuration data file.

Meta Programming

Programming on meta files combines the benefits of configuration files and template files to allow rapid development of applications and improved maintainability without sacrificing customisation or adding abstractions. Programming is done in a meta directory on files and templates that are used to generate the regular application source code. A configuration file contains all the data used for template parsing and file placement specification. Finally, commands can be executed on the generated files to compile, transpile or perform any other processes.

Meta programming add the benefits of:

  • having a reduced code base since templates can be shared by multiple files,
  • improve development speed with the ability to configure applications,
  • and allows quick switching of the generated source code between different environments.

A watch mode forms a critical part of the builder. This allows the programmer to work in the meta source directory instead of the regular source directory and having changes pull through seamlessly into the entire application.

Overview

The builder uses the meta.json configuration file and the template files (in the meta folder) to build the project.

The builder will transfer files from sources to destinations by:

  • stepping through directories recursively
  • parsing any templates available in the source specified by the "from" key.
  • stepping through files
  • use file key as source name if "source" field is empty
  • use file key as destination name
  • create destination file

Using as stand-alone

The builder can be executed with:

bin/meta-builder

Files that does not exist yet will be created. If files already exists, it will not be replaced. However, the flag -f forces the replacement of all files.

Your project might look like this:

project-root
|- meta
|  |- file.ext
|
|- meta.json

The meta folder contains the files and templates that will be used to build files. The meta.json file describes how to build the files and where to place them.

Files will by default be built from the meta folder into the project-root using meta.json. The -s, -d and -c flags can be used to change these defaults. A -w flag can be added to put the builder into watch mode where files will be automatically updated when the meta code is changed. Use the -h flag for help.

Implementing your own builder

meta.json Configuration Reference

The config file defines the project at the top level. The project structure is:

{
  "name": "project-name",
  "directories": {},
  "actions": {},
}

File structures (FSs) are specified within an object with key directories. The directories object can contain key-value pairs of multiple FSs that can each be viewed as a directory in the project.

{
  "directories": {
    ...
    "dir-name": {},
    "dir-name": {},
    ...
  }
}

The FSs can contain child FSs within an directories object, aswell as file objects as key-value pairs under an object with a files key. These are the files that will be built.

{
  "directories": {
    ...
    "dir-name": {
      "files": {
        ...
        "file-name.ext": {},
        "file-name.ext": {},
        ...
      },
      "directories": {
        "dir-name": {
          "files": {
            ...
          }
        }
      }
    },
    ...
  }
}

By default, a file in the meta directory will be parsed and written to a file (named with the file key) and placed under a directory (named with the FS key) in the project root directory.

{
  "directories": {
    "one": {
      "files": {
        "aaa.ext": {},
        "bbb.ext": {}
      }
    },
    "two": {
      "files": {
        "ccc.ext": {}
      },
      "directories": {
        "six": {
          "files": {
            "jjj.ext": {}
          }
        }
      }
    }
  }
}

will build to:

./meta/one/aaa.ext -> ./one/aaa.ext
./meta/one/bbb.ext -> ./one/bbb.ext
./meta/two/ccc.ext -> ./two/ccc.ext
./meta/two/six/jjj.ext -> ./two/six/jjj.ext
File Location Modifications

The source and destination paths can be modified with the from and dest keys. Consider the example:

{
  "directories": {
    "one": {
      "directories": {
        "two": {
          "dest": D,
          "files": {
            "aaa.ext": {}
          }
        }
      }
    }
  }
}

D can be replaced as follows to modify the destination location:

D = "" (no effect)
./meta/one/two/aaa.ext -> ./one/two/aaa.ext

D = "sub" (add sub directory)
./meta/one/two/aaa.ext -> ./one/two/sub/aaa.ext

D = "sub/sub" (add sub directories)
./meta/one/two/aaa.ext -> ./one/two/sub/sub/aaa.ext

D = "." (stay in current directory)
./meta/one/two/aaa.ext -> ./one/aaa.ext

D = "sub" (sub directory from current directory)
./meta/one/two/aaa.ext -> ./one/sub/aaa.ext

D = "/" (back to root directory)
./meta/one/two/aaa.ext -> ./aaa.ext

D = "/sub" (sub directory from current directory)
./meta/one/two/aaa.ext -> ./sub/aaa.ext

The from key can be used in the same way as the dest was use above to modify the source location.

Copying files only

The copy key can be used at directory and file level to copy files directly.

{
  "directories": {
    "one": {
      "copy": true,
      "files": {
        "aaa.ext": {},
        "bbb.ext": {}
      }
    },
    "two": {
      "files": {
        "ccc.ext": {},
        "ddd.ext": {"copy": true}
      }
    }
  }
}

In the example above, both files in directory one are copied but only ddd.ext in directory two is copied while ccc.ext is parsed as normal. By default the copy field will be false. If set to true, file parsing will be skipped.

Actions

Commands can be executed on the generated files. They are specified in the actions key will typically look like:

"actions": {
  "action-a": {
    "pattern": "some-regex",
    "command": ["program", "params", "..."]
  }
}

Whenever a filename matches the pattern, the command will be added to the actions list under the name of the action (action-a in the example above). After all files are generated, the builder will go through this list and execute the commands. The order is by default non-specific but can controlled with an optional dependant key.

"actions": {
  "a": {
    "pattern": "some-regex",
    "command": ["program", "params", "..."],
    "depends-on": ["b", "c"]
  },
  "b": {
    "pattern": "some-regex",
    "command": ["program", "params", "..."],
  },
  "c": {
    "pattern": "some-regex",
    "command": ["program", "params", "..."],
  }
}

In the example above action a will only be executed after b and c are executed.

Specifying timeouts are also optional and can be done with the timeout key and an integer (unsigned) giving the time in milliseconds.

"actions": {
  "a": {
    "pattern": "some-regex",
    "command": ["program", "params", "..."],
    "timeout": 100
  }
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ProcessFS added in v1.0.4

func ProcessFS(bb func(BranchSetter), fs *FSDirectory, m *refmap.RefMap)

Types

type Action added in v1.0.7

type Action struct {
	Pattern string   `json:"pattern"`
	Cmd     []string `json:"cmd"`
	Deps    []string `json:"depends-on"`
	Timeout uint     `json:"timeout"`
}

type BackRef

type BackRef interface {
	FileStructure() map[string]*FSDirectory
	CmdMatch() map[string]*Action
	Up() BackRef
}

type BranchSetter added in v1.0.4

type BranchSetter interface {
	SetBranch(...DataBranch) DataBranch
}

type Config

type Config struct {
	// contains filtered or unexported fields
}

func NewConfig

func NewConfig(l ...string) *Config

func (*Config) BuildAll

func (c *Config) BuildAll(force bool)

func (*Config) Destination

func (c *Config) Destination(dst ...string) string

func (*Config) Error

func (c *Config) Error(err ...error) error

func (*Config) Finish added in v1.0.8

func (c *Config) Finish()

func (*Config) Force

func (c *Config) Force(f ...bool) bool

func (*Config) Load

func (c *Config) Load(p ProjectLoader, mf ...string)

func (Config) RegisterCmd

func (c Config) RegisterCmd(name string, cmd, deps []string, timeoutOpt ...uint)

func (*Config) Source

func (c *Config) Source(src ...string) string

func (Config) StopWatching added in v1.0.8

func (c Config) StopWatching()

func (*Config) Watch added in v1.0.8

func (c *Config) Watch(throttling time.Duration)

func (Config) Watching added in v1.0.8

func (c Config) Watching() bool

type DataBranch

type DataBranch interface {
	Files() map[string]*FSDirectory
	SetFile(*FSFile)
	File() *FSFile
}

type Entity

type Entity struct {
	Name        string                  `json:"name"`
	Description string                  `json:"description"`
	Directories map[string]*FSDirectory `json:"directories"`
	Actions     map[string]*Action      `json:"actions"`
	Branch      DataBranch              `json:"-"`
	Parent      BackRef                 `json:"-"`
	Error       *error                  `json:"-"`
	// contains filtered or unexported fields
}

func (*Entity) CalculateHash

func (cd *Entity) CalculateHash(m interface{}) error

func (Entity) Change added in v1.0.5

func (cd Entity) Change(change ...uint8) uint8

func (Entity) CmdMatch

func (m Entity) CmdMatch() map[string]*Action

func (Entity) FileStructure

func (m Entity) FileStructure() map[string]*FSDirectory

func (Entity) Hash added in v1.0.5

func (cd Entity) Hash() string

func (Entity) Up

func (m Entity) Up() BackRef

type FSDirectory

type FSDirectory struct {
	Source          string             `json:"from"`
	Destination     string             `json:"dest"`
	Files           map[string]*FSFile `json:"files"`
	Copy            bool               `json:"copy"`
	Update          string             `json:"update"`
	Template        *utils.Templax     `json:"-"`
	SourcePath      string             `json:"-"`
	DestinationPath string             `json:"-"`
	Entity
}

func (*FSDirectory) CalculateHash

func (dir *FSDirectory) CalculateHash() error

func (FSDirectory) Change added in v1.0.5

func (cd FSDirectory) Change(change ...uint8) uint8

func (FSDirectory) Hash added in v1.0.5

func (cd FSDirectory) Hash() string

func (*FSDirectory) SetBranch

func (fs *FSDirectory) SetBranch(branch ...DataBranch) DataBranch

type FSFile

type FSFile struct {
	Name      string            `json:"name"`
	Copy      bool              `json:"copy"`
	Update    string            `json:"update"`
	Source    string            `json:"source"`
	Templates map[string]string `json:"templates"`
	Parent    BackRef           `json:"-"`
	// contains filtered or unexported fields
}

func (*FSFile) Build

func (file *FSFile) Build(c refmap.Config)

func (*FSFile) CalculateHash

func (file *FSFile) CalculateHash() error

func (FSFile) Change added in v1.0.5

func (cd FSFile) Change(change ...uint8) uint8

func (FSFile) Hash

func (cd FSFile) Hash() string

type FSTemplate

type FSTemplate struct {
	Name string `json:"name"`
	File string `json:"file"`
	Body string `json:"body"`
}

type PrjData

type PrjData struct {
	TemplateMethods
	Prj *Project
	FSF *FSFile
}

func (PrjData) File

func (d PrjData) File() *FSFile

func (PrjData) Files

func (d PrjData) Files() map[string]*FSDirectory

func (PrjData) Project

func (d PrjData) Project() *Project

func (*PrjData) SetFile

func (d *PrjData) SetFile(file *FSFile)

type Project

type Project struct {
	Repo    string   `json:"repository"`
	Mode    string   `json:"-"`
	Secrets []string `json:"-"`
	Entity
}

func NewProject

func NewProject(err ...*error) *Project

func (*Project) CalculateHash

func (p *Project) CalculateHash()

func (Project) Change added in v1.0.5

func (cd Project) Change(change ...uint8) uint8

func (Project) Hash added in v1.0.5

func (cd Project) Hash() string

func (*Project) Load

func (p *Project) Load(fn string)

func (*Project) LoadSecrets

func (p *Project) LoadSecrets(fn string)

func (*Project) Process

func (p *Project) Process(m *refmap.RefMap)

type ProjectLoader added in v1.0.4

type ProjectLoader interface {
	CalculateHash()
	Load(string)
	LoadSecrets(string)
	Process(*refmap.RefMap)
}

type TemplateMethods added in v1.0.5

type TemplateMethods struct {
}

func (TemplateMethods) Clean added in v1.0.5

func (TemplateMethods) Clean(s string) string

func (TemplateMethods) CleanUpper added in v1.0.5

func (TemplateMethods) CleanUpper(s string) string

func (TemplateMethods) Plural added in v1.0.5

func (TemplateMethods) Plural(s string) string

func (TemplateMethods) Title added in v1.0.5

func (TemplateMethods) Title(s string) string

func (TemplateMethods) Upper added in v1.0.5

func (TemplateMethods) Upper(s string) string

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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