Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add binding gen js for remote and local #12

Merged
merged 35 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a2c8c05
init check in for generating binding files based on flix
bthaile Sep 1, 2023
6f03fb0
add sub templates for js files, gen binding file in same dir as templ…
bthaile Sep 1, 2023
389069b
organization of files and ignores
bthaile Sep 1, 2023
7451e2a
ignore built file
bthaile Sep 1, 2023
4ab973f
ignore template files
bthaile Sep 1, 2023
016c059
ignore template files
bthaile Sep 1, 2023
5a50239
add file reader to config for unit testing
bthaile Sep 1, 2023
50d5bcb
verify that remote templates can gen js files
bthaile Sep 5, 2023
1b9b440
fix git ignore file
bthaile Sep 5, 2023
37a9f3d
ignore cmd dir and all .DS_Store files
bthaile Sep 5, 2023
6c242b7
remove .DS_Store files
bthaile Sep 5, 2023
f9d4bf4
add testing gen js binding with remote flix
bthaile Sep 5, 2023
d15e7ca
support array of simple types
bthaile Sep 5, 2023
d4848cf
first batch of changes based on feedback
bthaile Sep 6, 2023
2098974
collapse files and keep everything in flixkit package
bthaile Sep 7, 2023
530a385
clean up
bthaile Sep 7, 2023
b7a142c
add js docs to provide types for typescript
bthaile Sep 8, 2023
870b6ff
do not rely on message to be there and that us-en exists, update temp…
bthaile Sep 8, 2023
805a993
fix consistency for testing
bthaile Sep 8, 2023
dac9742
simplify conversion to js types, fcl uses strings for all numbers
bthaile Sep 14, 2023
4a9cf9a
add golden for unit tests
bthaile Sep 26, 2023
bd1a7a9
pass in generator method to generate code
bthaile Sep 26, 2023
5aef7f0
use interface and set specific port for testing remote and use golden…
bthaile Sep 27, 2023
e7cd1bc
fixed arguments key sorting issue, that was causing test failures
bthaile Sep 27, 2023
4932623
fix case typo in generator name
bthaile Sep 28, 2023
64e11a5
remove need to read from disk to get template
bthaile Sep 28, 2023
aa66b9f
tidy
bthaile Sep 29, 2023
9d27901
move js generator to bindings module and rename js generator to fcl j…
bthaile Oct 4, 2023
8c19379
formatting
bthaile Oct 16, 2023
0593679
pass in template directory to be more flexible
bthaile Oct 18, 2023
5a9f441
add comment that fcl version 1.3.0 or greater is needed to use templates
bthaile Oct 18, 2023
8857770
add helper func to create fcl js code generator
bthaile Oct 18, 2023
9cd4a66
removed todo: added named return values from method
bthaile Oct 21, 2023
5ad7e6a
update readme to include bindings module
bthaile Oct 21, 2023
6619788
use filepath.Walk to get files from template dir
bthaile Oct 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# ignore all .DS_Store files
.DS_Store
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,34 @@ fmt.Println(template)

Note: Remember to replace "transfer-flow" with the actual name of the template you wish to fetch.

To read more about Flow Interaction Templates, [see the docs](https://developers.flow.com/tooling/fcl-js/interaction-templates).
To read more about Flow Interaction Templates, [see the docs](https://developers.flow.com/tooling/fcl-js/interaction-templates).


## Bindings

> Binding files are code files that bind consuming code with FLIX. The `bindings` module in Flixkit generates code that calls the FLIX cadence code. FLIX cadence is primarily transactions and scripts.

### Usage

The `bindings` module has two public methods `Generate` and `NewFclJSGenerator`. `FclJSGenerator` takes a template directory. `bindings` has fcl-js templates.


- `NewFclJSGenerator() *FclJSGenerator` // uses default fcl-js vanilla javascript
- `Generate(flix *flixkit.FlowInteractionTemplate, templateLocation string, isLocal bool) (string, error)` // flix is the hydrated template struct, templateLocation is the file location of the flix json file, isLocal is a flag that indicates if the template is local or on remote server

### Example

```go

// uses default fcl-js templates
fclJsGen := bindings.NewFclJSGenerator()

output, err := fclJsGen.Generate(template, flixQuery, isLocal)
if err != nil {
log.Fatal(err)
}

// output is the javascript binding code
fmt.Println(output])

```
145 changes: 145 additions & 0 deletions bindings/fcl-js.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package bindings

import (
"bytes"
"os"
"path/filepath"
"runtime"
"sort"
"text/template"

"github.com/onflow/flixkit-go"
"github.com/stoewer/go-strcase"
)

type simpleParameter struct {
Name string
JsType string
Description string
FclType string
CadType string
}

type templateData struct {
Version string
Parameters []simpleParameter
Title string
Description string
Location string
IsScript bool
IsLocalTemplate bool
}

type FclJSGenerator struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be lowercased?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's publicly assessable. I thought it needed to be uppercase so calls can get to ti.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has to be uppercased for other packages to access it yes.

TemplateDir string
}

func NewFclJSGenerator() *FclJSGenerator {
_, currentFilePath, _, _ := runtime.Caller(0)
baseDir := filepath.Dir(currentFilePath)
templateDir := filepath.Join(baseDir, "templates")

return &FclJSGenerator{
TemplateDir: templateDir,
}
}

func (g FclJSGenerator) Generate(flix *flixkit.FlowInteractionTemplate, templateLocation string, isLocal bool) (string, error) {
templateFiles, err := getAllFiles(g.TemplateDir)
if err != nil {
return "", err
}
tmpl, err := template.ParseFiles(templateFiles...)
if err != nil {
return "", err
}

methodName := strcase.LowerCamelCase(flix.Data.Messages.GetTitleValue("Request"))
description := flix.GetDescription()
data := templateData{
Version: flix.FVersion,
Parameters: transformArguments(flix.Data.Arguments),
Title: methodName,
Description: description,
Location: templateLocation,
IsScript: flix.IsScript(),
IsLocalTemplate: isLocal,
}

var buf bytes.Buffer
err = tmpl.Execute(&buf, data)
return buf.String(), err
}

func transformArguments(args flixkit.Arguments) []simpleParameter {
simpleArgs := []simpleParameter{}
var keys []string
// get keys for sorting
for k := range args {
keys = append(keys, k)
}

sort.SliceStable(keys, func(i, j int) bool {
return args[keys[i]].Index < args[keys[j]].Index
})
for _, key := range keys {
arg := args[key]
isArray, cType, jsType := isArrayParameter(arg)
desciption := arg.Messages.GetTitleValue("")
if isArray {
simpleArgs = append(simpleArgs, simpleParameter{Name: key, CadType: cType, JsType: jsType, FclType: "Array(t." + cType + ")", Description: desciption})
} else {
jsType := convertCadenceTypeToJS(arg.Type)
simpleArgs = append(simpleArgs, simpleParameter{Name: key, CadType: arg.Type, JsType: jsType, FclType: arg.Type, Description: desciption})
}
}
return simpleArgs
}

func isArrayParameter(arg flixkit.Argument) (isArray bool, cType string, jsType string) {
if arg.Type == "" || arg.Type[0] != '[' {
return false, "", ""
}
cadenceType := arg.Type[1 : len(arg.Type)-1]
javascriptType := "Array<" + convertCadenceTypeToJS(cadenceType) + ">"
return true, cadenceType, javascriptType
}

func convertCadenceTypeToJS(cadenceType string) string {
// need to determine js type based on fcl supported types
// looking at fcl types and how arguments work as parameters
// https://github.com/onflow/fcl-js/blob/master/packages/types/src/types.js
switch cadenceType {
case "Bool":
return "boolean"
case "Void":
return "void"
case "Dictionary":
return "object"
case "Struct":
return "object"
case "Enum":
return "object"
default:
return "string"
}
}

func getAllFiles(dir string) ([]string, error) {
var files []string
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// If it's a directory, skip it
if info.IsDir() {
return nil
}
files = append(files, path)
return nil
})
if err != nil {
return nil, err
}
return files, nil
}
Loading