diff --git a/v2/pkg/commands/build/internal/backendjs/backendjs.go b/v2/pkg/commands/build/internal/backendjs/backendjs.go index 77f0e4f95..cfb0448e6 100644 --- a/v2/pkg/commands/build/internal/backendjs/backendjs.go +++ b/v2/pkg/commands/build/internal/backendjs/backendjs.go @@ -1,3 +1,5 @@ +// Package backendjs deals with generating the `backend` Javascript module +// used by the frontend to interact with Go package backendjs import ( diff --git a/v2/pkg/commands/build/internal/backendjs/conversion.go b/v2/pkg/commands/build/internal/backendjs/conversion.go new file mode 100644 index 000000000..0214599a1 --- /dev/null +++ b/v2/pkg/commands/build/internal/backendjs/conversion.go @@ -0,0 +1,43 @@ +package backendjs + +import "reflect" + +// JSType represents a javascript type +type JSType string + +const ( + // JsString is a JS string + JsString JSType = "string" + // JsBoolean is a JS bool + JsBoolean = "boolean" + // JsInt is a JS number + JsInt = "number" + // JsFloat is a JS number + JsFloat = "number" + // JsArray is a JS array + JsArray = "Array" + // JsObject is a JS object + JsObject = "Object" + // JsUnsupported represents a type that cannot be converted + JsUnsupported = "*" +) + +func goTypeToJS(input reflect.Kind) JSType { + switch input { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return JsInt + case reflect.String: + return JsString + case reflect.Float32, reflect.Float64, reflect.Complex64: + return JsFloat + case reflect.Bool: + return JsBoolean + case reflect.Array, reflect.Slice: + return JsArray + case reflect.Ptr, reflect.Struct, reflect.Map, reflect.Interface: + return JsObject + default: + return JsUnsupported + } +} diff --git a/v2/pkg/commands/build/internal/backendjs/index.template b/v2/pkg/commands/build/internal/backendjs/index.template new file mode 100644 index 000000000..019e459ba --- /dev/null +++ b/v2/pkg/commands/build/internal/backendjs/index.template @@ -0,0 +1,9 @@ +// index.js +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT +{{range .}} +const {{.Name}} = require('./{{.Name}}'); +{{end}} +module.exports = { + {{range .}}{{.Name}}: {{.Name}},{{end}} +} \ No newline at end of file diff --git a/v2/pkg/commands/build/internal/backendjs/package.template b/v2/pkg/commands/build/internal/backendjs/package.template index 019e459ba..ca5850b31 100644 --- a/v2/pkg/commands/build/internal/backendjs/package.template +++ b/v2/pkg/commands/build/internal/backendjs/package.template @@ -1,9 +1,22 @@ -// index.js // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT -{{range .}} -const {{.Name}} = require('./{{.Name}}'); + +// {{.Name}}.js +{{range .Comments}}// {{.}}{{end}} + +{{range .Methods}} +/**{{if .Comments }} +{{range .Comments}} * {{ . }}{{end}} + *{{end}} + * @function {{.Name}} +{{range .Inputs}} * @param {{"{"}}{{.JSType}}{{"}"}} {{.Name}} +{{end}} * + * @returns {Promise} + */ +function {{.Name}}({{.InputsAsJSText}}) { + return window.backend.{{$.Name}}.{{.Name}}(); +} {{end}} module.exports = { - {{range .}}{{.Name}}: {{.Name}},{{end}} -} \ No newline at end of file + {{range .Methods}}{{.Name}}: {{.Name}},{{end}} +} diff --git a/v2/pkg/commands/build/internal/backendjs/packages.go b/v2/pkg/commands/build/internal/backendjs/packages.go index e3e5a5300..eab40e02c 100644 --- a/v2/pkg/commands/build/internal/backendjs/packages.go +++ b/v2/pkg/commands/build/internal/backendjs/packages.go @@ -3,6 +3,7 @@ package backendjs import ( "bytes" "io/ioutil" + "reflect" "text/template" "github.com/pkg/errors" @@ -38,10 +39,40 @@ func parsePackages() ([]*Package, error) { result = append(result, &Package{ Name: "mypackage", - Comments: []string{"// mypackage is awesome"}, + Comments: []string{"mypackage is awesome"}, Methods: []*Method{ { - Name: "Naked", + Name: "Naked", + Comments: []string{"Naked is a method that does nothing"}, + }, + }, + }) + result = append(result, &Package{ + Name: "otherpackage", + Comments: []string{"otherpackage is awesome"}, + Methods: []*Method{ + { + Name: "OneInput", + Comments: []string{"OneInput does stuff"}, + Inputs: []*Parameter{ + { + Name: "name", + Type: reflect.String, + }, + }, + }, + { + Name: "TwoInputs", + Inputs: []*Parameter{ + { + Name: "name", + Type: reflect.String, + }, + { + Name: "age", + Type: reflect.Uint8, + }, + }, }, }, }) @@ -55,17 +86,23 @@ func generateJSFiles(packages []*Package) error { if err != nil { return errors.Wrap(err, "Error generating index.js file") } + + err = generatePackageFiles(packages) + if err != nil { + return errors.Wrap(err, "Error generating packages") + } + return nil } func generateIndexJS(packages []*Package) error { // Get path to local file - templateFile := fs.RelativePath("./package.template") + templateFile := fs.RelativePath("./index.template") // Load template templateData := fs.MustLoadString(templateFile) - packagesTemplate, err := template.New("packages").Parse(templateData) + packagesTemplate, err := template.New("index").Parse(templateData) if err != nil { return errors.Wrap(err, "Error creating template") } @@ -80,7 +117,7 @@ func generateIndexJS(packages []*Package) error { // Calculate target filename indexJS, err := fs.RelativeToCwd("./frontend/backend/index.js") if err != nil { - return errors.Wrap(err, "Error creating backend js directory") + return errors.Wrap(err, "Error calculating index js path") } err = ioutil.WriteFile(indexJS, buffer.Bytes(), 0755) @@ -90,3 +127,40 @@ func generateIndexJS(packages []*Package) error { return nil } + +func generatePackageFiles(packages []*Package) error { + + // Get path to local file + templateFile := fs.RelativePath("./package.template") + + // Load template + templateData := fs.MustLoadString(templateFile) + packagesTemplate, err := template.New("package").Parse(templateData) + if err != nil { + return errors.Wrap(err, "Error creating template") + } + + // Iterate over each package + for _, thisPackage := range packages { + + // Execute template + var buffer bytes.Buffer + err = packagesTemplate.Execute(&buffer, thisPackage) + if err != nil { + return errors.Wrap(err, "Error generating code") + } + + // Calculate target filename + packageFile, err := fs.RelativeToCwd("./frontend/backend/" + thisPackage.Name + ".js") + if err != nil { + return errors.Wrap(err, "Error calculating package path") + } + + err = ioutil.WriteFile(packageFile, buffer.Bytes(), 0755) + if err != nil { + return errors.Wrap(err, "Error writing backend package file") + } + } + + return nil +} diff --git a/v2/pkg/commands/build/internal/backendjs/structs.go b/v2/pkg/commands/build/internal/backendjs/structs.go index 030fe6c36..a4366f98b 100644 --- a/v2/pkg/commands/build/internal/backendjs/structs.go +++ b/v2/pkg/commands/build/internal/backendjs/structs.go @@ -2,12 +2,19 @@ package backendjs import ( "reflect" + "strings" ) // Parameter defines a parameter used by a struct method type Parameter struct { Name string - Type reflect.Type + Type reflect.Kind +} + +// JSType returns the Javascript equivalent of the +// parameter type +func (p *Parameter) JSType() string { + return string(goTypeToJS(p.Type)) } // Method defines a struct method @@ -18,6 +25,18 @@ type Method struct { Comments []string } +// InputsAsJSText generates a string with the method inputs +// formatted in a way acceptable to Javascript +func (m *Method) InputsAsJSText() string { + var inputs []string + + for _, input := range m.Inputs { + inputs = append(inputs, input.Name) + } + + return strings.Join(inputs, ", ") +} + // func generateStructFile() { // // Create string buffer // var result bytes.Buffer