diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index f689c0e..e33d6d8 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -12,7 +12,7 @@ jobs:
go-version: ^1.17
id: go
- name: check out
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Cache
uses: actions/cache@v2.1.0
@@ -26,7 +26,7 @@ jobs:
needs: setup
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: build
run: go build ./...
@@ -34,7 +34,7 @@ jobs:
needs: setup
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: test
run: go test ./... -v
@@ -42,7 +42,7 @@ jobs:
needs: setup
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
diff --git a/README.md b/README.md
index da91ee6..faf3b0d 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
This command has a fzf-like UI that allows you to find and run the file version used by the [hasura cli command](https://hasura.io/docs/latest/graphql/core/hasura-cli/index.html).
-
+
## install
diff --git a/cmd/hasura/hasura.go b/cmd/hasura/hasura.go
index 3389712..9526170 100644
--- a/cmd/hasura/hasura.go
+++ b/cmd/hasura/hasura.go
@@ -1,9 +1,10 @@
package hasura
import (
+ "bufio"
"errors"
"fmt"
- "io/ioutil"
+ "os"
"os/exec"
"regexp"
"strconv"
@@ -20,23 +21,28 @@ const (
var versionRegex *regexp.Regexp
-type Cmd struct {
- called string
- command []string
- fileNames []string
- options map[string]interface{}
- target string
+type HasuraCmd struct {
+ called string
+ command []string
+ options map[string]interface{}
+ files []fileInfo
+ applyTarget string
}
-func NewHasuraCmd(called string, options map[string]interface{}) *Cmd {
+type fileInfo struct {
+ name string
+ headline string
+}
+
+func NewHasuraCmd(called string, options map[string]interface{}) *HasuraCmd {
if called == calledMigrateApply || called == calledMigrateDelete {
setRegex()
}
- return &Cmd{called: called, options: options}
+ return &HasuraCmd{called: called, options: options}
}
-func (h *Cmd) Run() (string, error) {
+func (h *HasuraCmd) Run() (string, error) {
if err := h.setFileNames(); err != nil {
return "", err
}
@@ -48,7 +54,7 @@ func (h *Cmd) Run() (string, error) {
return h.setCommand().exec()
}
-func (h *Cmd) exec() (string, error) {
+func (h *HasuraCmd) exec() (string, error) {
fmt.Println("running... ", "hasura", strings.Join(h.command, " "))
fmt.Println("")
@@ -57,15 +63,14 @@ func (h *Cmd) exec() (string, error) {
return string(r), err
}
-func (h *Cmd) setCommand() *Cmd {
+func (h *HasuraCmd) setCommand() *HasuraCmd {
switch h.called {
case CalledSeedApply:
- h.command = append(strings.Split(h.called, " "), []string{"--file", h.target}...)
+ h.command = append(strings.Split(h.called, " "), []string{"--file", h.applyTarget}...)
case calledMigrateApply, calledMigrateDelete:
- h.command = append(strings.Split(h.called, " "), []string{"--version", h.target}...)
+ h.command = append(strings.Split(h.called, " "), []string{"--version", h.applyTarget}...)
}
-
- if h.target == "" {
+ if h.applyTarget == "" {
h.command = strings.Split(h.called, " ")
}
@@ -83,8 +88,8 @@ func (h *Cmd) setCommand() *Cmd {
return h
}
-func (h *Cmd) setTarget() error {
- if len(h.fileNames) == 0 {
+func (h *HasuraCmd) setTarget() error {
+ if len(h.files) == 0 {
return nil
}
@@ -94,15 +99,15 @@ func (h *Cmd) setTarget() error {
}
if h.called == calledMigrateApply || h.called == calledMigrateDelete {
- h.target = trimVersion(fileName)
+ h.applyTarget = trimVersion(fileName)
} else {
- h.target = fileName
+ h.applyTarget = fileName
}
return nil
}
-func (h *Cmd) setFileNames() error {
+func (h *HasuraCmd) setFileNames() error {
var filePath string
switch h.called {
@@ -114,47 +119,57 @@ func (h *Cmd) setFileNames() error {
return nil
}
- files, err := ioutil.ReadDir(filePath)
+ files, err := os.ReadDir(filePath)
if err != nil {
return err
}
if len(files) == 0 {
- return errors.New("no file")
+ return errors.New("no such file or directory")
}
for _, file := range files {
if file.IsDir() {
if h.called == calledMigrateApply || h.called == calledMigrateDelete {
- h.fileNames = append(h.fileNames, file.Name())
+ headline, err := readFileHeadline("./migrations/default/" + file.Name() + "/up.sql")
+ if err != nil {
+ return err
+ }
+ h.files = append(h.files, fileInfo{name: file.Name(), headline: headline})
}
}
if !file.IsDir() && h.called == CalledSeedApply {
- h.fileNames = append(h.fileNames, file.Name())
+ headline, err := readFileHeadline("./seeds/default/" + file.Name())
+ if err != nil {
+ return err
+ }
+ h.files = append(h.files, fileInfo{name: file.Name(), headline: headline})
}
}
return nil
}
-func (h *Cmd) findOne() (string, error) {
- type fileName struct {
- name string
- }
-
- fileNames := make([]fileName, 0, len(h.fileNames))
-
- for _, f := range h.fileNames {
- fileNames = append(fileNames, fileName{f})
- }
+func (h *HasuraCmd) findOne() (string, error) {
+ i, err := fuzzyfinder.Find(
+ h.files,
+ func(i int) string { return h.files[i].name },
+ fuzzyfinder.WithPreviewWindow(func(i, width, height int) string {
+ if i == -1 {
+ return ""
+ }
+ return fmt.Sprintf(`📝 Applied SQL file
- i, err := fuzzyfinder.Find(fileNames, func(i int) string { return fileNames[i].name })
+ %s
+ ...
+ `, h.files[i].headline)
+ }),
+ )
if err != nil {
return "", err
}
-
- return fileNames[i].name, nil
+ return h.files[i].name, nil
}
func trimVersion(fileName string) string {
@@ -164,3 +179,26 @@ func trimVersion(fileName string) string {
func setRegex() {
versionRegex = regexp.MustCompile(`^[0-9]+`)
}
+
+// readFileHeadline
+// Opens a file in the path passed as an argument, reads the first three lines, and returns them as a string.
+func readFileHeadline(path string) (string, error) {
+ var headline string
+ f, err := os.Open(path)
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+ scanner := bufio.NewScanner(f)
+
+ var count int
+ for scanner.Scan() {
+ if count == 4 {
+ headline += scanner.Text()
+ break
+ }
+ headline += fmt.Sprintln(scanner.Text())
+ count++
+ }
+ return headline, nil
+}
diff --git a/cmd/hasura/hasura_test.go b/cmd/hasura/hasura_test.go
index fdf7901..555eff3 100644
--- a/cmd/hasura/hasura_test.go
+++ b/cmd/hasura/hasura_test.go
@@ -10,24 +10,24 @@ func TestCmd_setCommand(t *testing.T) {
t.Parallel()
type fields struct {
- called string
- command []string
- fileNames []string
- options map[string]interface{}
- target string
+ called string
+ command []string
+ files []fileInfo
+ options map[string]interface{}
+ target string
}
tests := []struct {
name string
fields fields
- want *Cmd
+ want *HasuraCmd
}{
{
name: "case: not set h.target",
fields: fields{
called: "seed apply",
},
- want: &Cmd{
+ want: &HasuraCmd{
called: "seed apply",
command: []string{"seed", "apply"},
},
@@ -38,10 +38,10 @@ func TestCmd_setCommand(t *testing.T) {
called: "seed apply",
target: "xxx.sql",
},
- want: &Cmd{
- called: "seed apply",
- target: "xxx.sql",
- command: []string{"seed", "apply", "--file", "xxx.sql"},
+ want: &HasuraCmd{
+ called: "seed apply",
+ applyTarget: "xxx.sql",
+ command: []string{"seed", "apply", "--file", "xxx.sql"},
},
},
{
@@ -53,10 +53,10 @@ func TestCmd_setCommand(t *testing.T) {
"admin-secret": "secret",
},
},
- want: &Cmd{
- called: "seed apply",
- target: "xxx.sql",
- command: []string{"seed", "apply", "--file", "xxx.sql", "--admin-secret", "secret"},
+ want: &HasuraCmd{
+ called: "seed apply",
+ applyTarget: "xxx.sql",
+ command: []string{"seed", "apply", "--file", "xxx.sql", "--admin-secret", "secret"},
options: map[string]interface{}{
"admin-secret": "secret",
},
@@ -71,10 +71,10 @@ func TestCmd_setCommand(t *testing.T) {
"no-color": false,
},
},
- want: &Cmd{
- called: "seed apply",
- target: "xxx.sql",
- command: []string{"seed", "apply", "--file", "xxx.sql", "--no-color", "false"},
+ want: &HasuraCmd{
+ called: "seed apply",
+ applyTarget: "xxx.sql",
+ command: []string{"seed", "apply", "--file", "xxx.sql", "--no-color", "false"},
options: map[string]interface{}{
"no-color": false,
},
@@ -90,10 +90,10 @@ func TestCmd_setCommand(t *testing.T) {
"admin-secret": "secret",
},
},
- want: &Cmd{
- called: "seed apply",
- target: "xxx.sql",
- command: []string{"seed", "apply", "--file", "xxx.sql", "--admin-secret", "secret", "--no-color", "false"},
+ want: &HasuraCmd{
+ called: "seed apply",
+ applyTarget: "xxx.sql",
+ command: []string{"seed", "apply", "--file", "xxx.sql", "--admin-secret", "secret", "--no-color", "false"},
options: map[string]interface{}{
"no-color": false,
"admin-secret": "secret",
@@ -106,9 +106,9 @@ func TestCmd_setCommand(t *testing.T) {
called: "migrate",
target: "xxx.sql",
},
- want: &Cmd{
- called: "migrate",
- target: "xxx.sql",
+ want: &HasuraCmd{
+ called: "migrate",
+ applyTarget: "xxx.sql",
},
},
{
@@ -117,10 +117,10 @@ func TestCmd_setCommand(t *testing.T) {
called: "migrate apply",
target: "xxx",
},
- want: &Cmd{
- called: "migrate apply",
- target: "xxx",
- command: []string{"migrate", "apply", "--version", "xxx"},
+ want: &HasuraCmd{
+ called: "migrate apply",
+ applyTarget: "xxx",
+ command: []string{"migrate", "apply", "--version", "xxx"},
},
},
{
@@ -132,10 +132,10 @@ func TestCmd_setCommand(t *testing.T) {
"admin-secret": "secret",
},
},
- want: &Cmd{
- called: "migrate apply",
- target: "xxx",
- command: []string{"migrate", "apply", "--version", "xxx", "--admin-secret", "secret"},
+ want: &HasuraCmd{
+ called: "migrate apply",
+ applyTarget: "xxx",
+ command: []string{"migrate", "apply", "--version", "xxx", "--admin-secret", "secret"},
options: map[string]interface{}{
"admin-secret": "secret",
},
@@ -150,10 +150,10 @@ func TestCmd_setCommand(t *testing.T) {
"no-color": false,
},
},
- want: &Cmd{
- called: "migrate apply",
- target: "xxx",
- command: []string{"migrate", "apply", "--version", "xxx", "--no-color", "false"},
+ want: &HasuraCmd{
+ called: "migrate apply",
+ applyTarget: "xxx",
+ command: []string{"migrate", "apply", "--version", "xxx", "--no-color", "false"},
options: map[string]interface{}{
"no-color": false,
},
@@ -169,10 +169,10 @@ func TestCmd_setCommand(t *testing.T) {
"admin-secret": "secret",
},
},
- want: &Cmd{
- called: "migrate apply",
- target: "xxx",
- command: []string{"migrate", "apply", "--version", "xxx", "--admin-secret", "secret", "--no-color", "false"},
+ want: &HasuraCmd{
+ called: "migrate apply",
+ applyTarget: "xxx",
+ command: []string{"migrate", "apply", "--version", "xxx", "--admin-secret", "secret", "--no-color", "false"},
options: map[string]interface{}{
"no-color": false,
"admin-secret": "secret",
@@ -185,10 +185,10 @@ func TestCmd_setCommand(t *testing.T) {
called: "migrate delete",
target: "xxx",
},
- want: &Cmd{
- called: "migrate delete",
- target: "xxx",
- command: []string{"migrate", "delete", "--version", "xxx"},
+ want: &HasuraCmd{
+ called: "migrate delete",
+ applyTarget: "xxx",
+ command: []string{"migrate", "delete", "--version", "xxx"},
},
},
{
@@ -200,10 +200,10 @@ func TestCmd_setCommand(t *testing.T) {
"admin-secret": "secret",
},
},
- want: &Cmd{
- called: "migrate delete",
- target: "xxx",
- command: []string{"migrate", "delete", "--version", "xxx", "--admin-secret", "secret"},
+ want: &HasuraCmd{
+ called: "migrate delete",
+ applyTarget: "xxx",
+ command: []string{"migrate", "delete", "--version", "xxx", "--admin-secret", "secret"},
options: map[string]interface{}{
"admin-secret": "secret",
},
@@ -218,10 +218,10 @@ func TestCmd_setCommand(t *testing.T) {
"no-color": false,
},
},
- want: &Cmd{
- called: "migrate delete",
- target: "xxx",
- command: []string{"migrate", "delete", "--version", "xxx", "--no-color", "false"},
+ want: &HasuraCmd{
+ called: "migrate delete",
+ applyTarget: "xxx",
+ command: []string{"migrate", "delete", "--version", "xxx", "--no-color", "false"},
options: map[string]interface{}{
"no-color": false,
},
@@ -237,10 +237,10 @@ func TestCmd_setCommand(t *testing.T) {
"admin-secret": "secret",
},
},
- want: &Cmd{
- called: "migrate delete",
- target: "xxx",
- command: []string{"migrate", "delete", "--version", "xxx", "--admin-secret", "secret", "--no-color", "false"},
+ want: &HasuraCmd{
+ called: "migrate delete",
+ applyTarget: "xxx",
+ command: []string{"migrate", "delete", "--version", "xxx", "--admin-secret", "secret", "--no-color", "false"},
options: map[string]interface{}{
"no-color": false,
"admin-secret": "secret",
@@ -253,9 +253,9 @@ func TestCmd_setCommand(t *testing.T) {
called: "hoge",
target: "xxx",
},
- want: &Cmd{
- called: "hoge",
- target: "xxx",
+ want: &HasuraCmd{
+ called: "hoge",
+ applyTarget: "xxx",
},
},
}
@@ -263,30 +263,28 @@ func TestCmd_setCommand(t *testing.T) {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
- h := &Cmd{
- called: tt.fields.called,
- command: tt.fields.command,
- fileNames: tt.fields.fileNames,
- options: tt.fields.options,
- target: tt.fields.target,
+ h := &HasuraCmd{
+ called: tt.fields.called,
+ command: tt.fields.command,
+ files: tt.fields.files,
+ options: tt.fields.options,
+ applyTarget: tt.fields.target,
}
got := h.setCommand()
sort.Strings(got.command)
sort.Strings(tt.want.command)
- sort.Strings(got.fileNames)
- sort.Strings(tt.want.fileNames)
if !reflect.DeepEqual(got.called, tt.want.called) {
t.Errorf("Cmd.setCommand() = %v, want.called %v", got.called, tt.want.called)
}
- if !reflect.DeepEqual(got.target, tt.want.target) {
- t.Errorf("Cmd.setCommand() = %v, want.target %v", got.target, tt.want.target)
+ if !reflect.DeepEqual(got.applyTarget, tt.want.applyTarget) {
+ t.Errorf("HasuraCmd.setCommand() = %v, want.target %v", got.applyTarget, tt.want.applyTarget)
}
if !reflect.DeepEqual(got.command, tt.want.command) {
t.Errorf("Cmd.setCommand() = %v, want.command %v", got.command, tt.want.command)
}
- if !reflect.DeepEqual(got.fileNames, tt.want.fileNames) {
- t.Errorf("Cmd.setCommand() = %v, want.fileNames %v", got.fileNames, tt.want.fileNames)
+ if !reflect.DeepEqual(got.files, tt.want.files) {
+ t.Errorf("HasuraCmd.setCommand() = %v, want.files %v", got.files, tt.want.files)
}
if !reflect.DeepEqual(got.options, tt.want.options) {
for _, set := range tt.want.options {