Skip to content

Commit

Permalink
Merge pull request #3 from draganm/js-interpolation
Browse files Browse the repository at this point in the history
added JS interpolation
  • Loading branch information
draganm authored Feb 24, 2022
2 parents e586d85 + a89c7d2 commit 4bc3069
Showing 1 changed file with 58 additions and 20 deletions.
78 changes: 58 additions & 20 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func main() {
}
}()

env := map[string]string{}
vm := goja.New()

for _, e := range os.Environ() {

Expand All @@ -38,11 +38,9 @@ func main() {
return fmt.Errorf("while splitting env %q - got %d parts", e, len(kv))
}

env[kv[0]] = kv[1]
vm.Set(kv[0], kv[1])
}

vm := goja.New()

for _, p := range c.StringSlice("processor") {
script, err := os.ReadFile(p)
if err != nil {
Expand All @@ -51,16 +49,25 @@ func main() {
vm.RunScript(p, string(script))
}

vm.Set("env", env)
YAML := map[string]interface{}{
"parse": func(docString string) (interface{}, error) {
var v interface{}
err = yaml.Unmarshal([]byte(docString), &v)
if err != nil {
return nil, err
}
return v, nil
},
"stringify": func(d interface{}) (string, error) {
enc, err := yaml.Marshal(d)
if err != nil {
return "", err
}
return string(enc), nil
},
}

vm.Set("parseYaml", func(docString string) (interface{}, error) {
var v interface{}
err := yaml.NewDecoder(strings.NewReader(docString)).Decode(&v)
if err != nil {
return nil, err
}
return v, nil
})
vm.Set("YAML", YAML)

vm.Set("base64Encode", func(val string) string {
return base64.StdEncoding.EncodeToString([]byte(val))
Expand All @@ -79,7 +86,7 @@ func main() {

for _, k := range vm.GlobalObject().Keys() {

if strings.HasPrefix(k, "pre") {
if strings.HasPrefix(k, "pre_") {
v := vm.GlobalObject().Get(k)

var fn func(interface{}) error
Expand All @@ -90,12 +97,11 @@ func main() {
preProcessors = append(preProcessors, wrap(k, fn))
}

if strings.HasPrefix(k, "post") {
if strings.HasPrefix(k, "post_") {
v := vm.GlobalObject().Get(k)
var fn func(interface{}) error
err = vm.ExportTo(v, &fn)
if err != nil {
fmt.Println("err", err)
continue
}
postProcessors = append(postProcessors, wrap(k, fn))
Expand All @@ -122,6 +128,8 @@ func main() {

dec := yaml.NewDecoder(bytes.NewReader(b))

in := interpolator{vm: vm}

for {
var obj interface{}
err = dec.Decode(&obj)
Expand All @@ -140,7 +148,7 @@ func main() {
}
}

iobj, err := interpolate(obj)
iobj, err := in.interpolate(obj)
if err != nil {
return fmt.Errorf("while interpolating values into %s: %w", f, err)
}
Expand All @@ -166,13 +174,17 @@ func main() {
app.Run(os.Args)
}

func interpolate(o interface{}) (interface{}, error) {
type interpolator struct {
vm *goja.Runtime
}

func (in *interpolator) interpolate(o interface{}) (interface{}, error) {

switch v := o.(type) {
case map[string]interface{}:
nm := make(map[string]interface{}, len(v))
for mk, mv := range v {
nv, err := interpolate(mv)
nv, err := in.interpolate(mv)
if err != nil {
return nil, fmt.Errorf("while interpolating map value for key %q: %w", mk, err)
}
Expand All @@ -182,16 +194,42 @@ func interpolate(o interface{}) (interface{}, error) {
case []interface{}:
ns := make([]interface{}, len(v))
for i, sv := range v {
nv, err := interpolate(sv)
nv, err := in.interpolate(sv)
if err != nil {
return nil, fmt.Errorf("while interpolating slice value with index %d: %w", i, err)
}
ns[i] = nv
}
return ns, nil
case string:
if strings.HasPrefix(v, "$$JS:") {
return in.interpolateJS(v[len("$$JS:"):])
}
return envsubst.EvalEnv(v)
default:
return o, nil
}
}

func (i *interpolator) interpolateJS(code string) (res interface{}, err error) {
defer func() {
p := recover()
if p != nil {
var ok bool
err, ok = p.(error)
if !ok {
err = fmt.Errorf("panic: %s", p)
}
}
if err != nil {
err = fmt.Errorf("while interpolating JS %q: %w", code, err)
}
}()

resVal, err := i.vm.RunString(code)
if err != nil {
return nil, err
}

return resVal.Export(), nil
}

0 comments on commit 4bc3069

Please sign in to comment.