Skip to content

Commit

Permalink
feat(go-scaffolding): simplify Go layout (#521)
Browse files Browse the repository at this point in the history
Also added a README to the template to explain the directory structure.
  • Loading branch information
alecthomas authored Oct 26, 2023
1 parent 090f67d commit 287cef3
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 51 deletions.
35 changes: 15 additions & 20 deletions cmd/ftl/cmd_init.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"archive/zip"
"os"
"path/filepath"

Expand All @@ -18,28 +19,15 @@ type initCmd struct {
}

type initGoCmd struct {
Dir string `arg:"" default:"." type:"dir" help:"Directory to initialize the module in."`
Name string `short:"n" help:"Name of the FTL module (defaults to name of directory)."`
GoModule string `short:"G" required:"" help:"Go module import path."`
Dir string `arg:"" default:"." type:"dir" help:"Directory to initialize the module in."`
Name string `short:"n" help:"Name of the FTL module (defaults to name of directory)."`
}

func (i initGoCmd) Run(parent *initCmd) error {
if i.Name == "" {
i.Name = filepath.Base(i.Dir)
}
err := internal.UnzipDir(goruntime.Files, i.Dir)
if err != nil {
return errors.WithStack(err)
}
if err := internal.Scaffold(i.Dir, i); err != nil {
return errors.WithStack(err)
}
if !parent.Hermit {
if err := os.RemoveAll(filepath.Join(i.Dir, "bin")); err != nil {
return errors.WithStack(err)
}
}
return nil
return errors.WithStack(scaffold(goruntime.Files, parent.Hermit, i.Dir, i))
}

type initKotlinCmd struct {
Expand All @@ -51,15 +39,22 @@ func (i *initKotlinCmd) Run(parent *initCmd) error {
if i.Name == "" {
i.Name = filepath.Base(i.Dir)
}
err := internal.UnzipDir(kotlinruntime.Files, i.Dir)
return errors.WithStack(scaffold(kotlinruntime.Files, parent.Hermit, i.Dir, i))
}

func scaffold(reader *zip.Reader, hermit bool, dir string, ctx any) error {
err := internal.UnzipDir(reader, dir)
if err != nil {
return errors.WithStack(err)
}
if err := internal.Scaffold(i.Dir, i); err != nil {
if err := os.Remove(filepath.Join(dir, "go.mod")); err != nil {
return errors.WithStack(err)
}
if err := internal.Scaffold(dir, ctx); err != nil {
return errors.WithStack(err)
}
if !parent.Hermit {
if err := os.RemoveAll(filepath.Join(i.Dir, "bin")); err != nil {
if !hermit {
if err := os.RemoveAll(filepath.Join(dir, "bin")); err != nil {
return errors.WithStack(err)
}
}
Expand Down
17 changes: 17 additions & 0 deletions go-runtime/scaffolding/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# FTL modules

Each subdirectory represents an FTL module. Remote modules will be
code-generated into their own directories, one module per directory. Note that
this is a temporary solution.

For example given an `echo` module written in Go that calls a `time` module
written in Kotlin, the filesystem might look like this once the FTL tooling is
started:

```
README.md
go.mod
echo/ftl.toml
echo/echo.go
time/generated_ftl_module.go
```
2 changes: 0 additions & 2 deletions go-runtime/scaffolding/ftl.toml

This file was deleted.

4 changes: 0 additions & 4 deletions go-runtime/scaffolding/go.mod

This file was deleted.

2 changes: 1 addition & 1 deletion go-runtime/scaffolding/go.mod.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module {{ .GoModule }}
module ftl

go 1.21.0

Expand Down
3 changes: 3 additions & 0 deletions go-runtime/scaffolding/{{ .Name | camel | lower }}/ftl.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module = "{{ .Name }}"
language = "go"
deploy = ["build/main", "build/schema.pb"]
5 changes: 5 additions & 0 deletions go-runtime/scaffolding/{{ .Name | camel | lower }}/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module ftl/{{ .Name | camel | lower }}

go 1.21.0

require github.com/TBD54566975/ftl latest
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package {{ .Name | camel | lower }}

import (
"context"
"fmt"

_ "github.com/TBD54566975/ftl/go-runtime/sdk" // Import the FTL SDK.
)

type EchoRequest struct {
Name string `json:"name'`
}

type EchoResponse struct {
Message string `json:"message"`
}

//ftl:verb
func echo(ctx context.Context, req EchoRequest) (EchoResponse, error) {
return EchoResponse{Message: fmt.Sprintf("Hello, %s!", req.Name)}, nil
}
18 changes: 0 additions & 18 deletions go-runtime/scaffolding/{{ .Name | lower }}.go.tmpl

This file was deleted.

19 changes: 13 additions & 6 deletions internal/scaffolder.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import (
//
// The functions "snake", "camel", "lowerCamel", "kebab", "upper", and "lower"
// are available.
//
// This is inspired by [cookiecutter].
//
// [cookiecutter]: https://github.com/cookiecutter/cookiecutter
func Scaffold(destination string, ctx any) error {
return errors.WithStack(walkDir(destination, func(path string, d fs.DirEntry) error {
info, err := d.Info()
Expand Down Expand Up @@ -98,12 +102,15 @@ func walkDir(dir string, fn func(path string, d fs.DirEntry) error) error {
func evaluate(tmpl string, ctx any) (string, error) {
t, err := template.New("scaffolding").Funcs(
template.FuncMap{
"snake": strcase.ToSnake,
"camel": strcase.ToCamel,
"lowerCamel": strcase.ToLowerCamel,
"kebab": strcase.ToKebab,
"upper": strings.ToUpper,
"lower": strings.ToLower,
"snake": strcase.ToSnake,
"screamingSnake": strcase.ToScreamingSnake,
"camel": strcase.ToCamel,
"lowerCamel": strcase.ToLowerCamel,
"kebab": strcase.ToKebab,
"screamingKebab": strcase.ToScreamingKebab,
"upper": strings.ToUpper,
"lower": strings.ToLower,
"title": strings.Title,
"typename": func(v any) string {
return reflect.Indirect(reflect.ValueOf(v)).Type().Name()
},
Expand Down

0 comments on commit 287cef3

Please sign in to comment.