tons of code
This commit is contained in:
parent
3ebfa08350
commit
de8c9aedf7
35
kitcom/api/api.go
Normal file
35
kitcom/api/api.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
// todo check TInt size < 64
|
||||||
|
// todo check not float
|
||||||
|
|
||||||
|
type ValType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
TInt ValType = 1
|
||||||
|
TString ValType = 2
|
||||||
|
TBool ValType = 3
|
||||||
|
TBlob ValType = 4
|
||||||
|
TArray ValType = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
type Val struct {
|
||||||
|
Name string
|
||||||
|
Type ValType
|
||||||
|
Children []Val
|
||||||
|
}
|
||||||
|
|
||||||
|
type Method struct {
|
||||||
|
Name string
|
||||||
|
Params []Val
|
||||||
|
Ret []Val
|
||||||
|
}
|
||||||
|
|
||||||
|
type Endpoint struct {
|
||||||
|
Name string
|
||||||
|
Methods []Method
|
||||||
|
}
|
||||||
|
|
||||||
|
type Api struct {
|
||||||
|
Endpoints []Endpoint
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package main
|
package golang
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -7,21 +7,23 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"efprojects.com/kitten-ipc/kitcom/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type goGenData struct {
|
type goGenData struct {
|
||||||
PkgName string
|
PkgName string
|
||||||
Api *Api
|
Api *api.Api
|
||||||
}
|
}
|
||||||
|
|
||||||
type GoApiGenerator struct {
|
type GoApiGenerator struct {
|
||||||
pkgName string
|
PkgName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GoApiGenerator) Generate(api *Api, destFile string) error {
|
func (g *GoApiGenerator) Generate(apis *api.Api, destFile string) error {
|
||||||
tplCtx := goGenData{
|
tplCtx := goGenData{
|
||||||
PkgName: g.pkgName,
|
PkgName: g.PkgName,
|
||||||
Api: api,
|
Api: apis,
|
||||||
}
|
}
|
||||||
|
|
||||||
tpl := template.New("gogen")
|
tpl := template.New("gogen")
|
||||||
@ -29,22 +31,22 @@ func (g *GoApiGenerator) Generate(api *Api, destFile string) error {
|
|||||||
"receiver": func(name string) string {
|
"receiver": func(name string) string {
|
||||||
return strings.ToLower(name)[0:1]
|
return strings.ToLower(name)[0:1]
|
||||||
},
|
},
|
||||||
"typedef": func(t ValType) (string, error) {
|
"typedef": func(t api.ValType) (string, error) {
|
||||||
td, ok := map[ValType]string{
|
td, ok := map[api.ValType]string{
|
||||||
TInt: "int",
|
api.TInt: "int",
|
||||||
TString: "string",
|
api.TString: "string",
|
||||||
TBool: "bool",
|
api.TBool: "bool",
|
||||||
}[t]
|
}[t]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", fmt.Errorf("cannot generate type %v", t)
|
return "", fmt.Errorf("cannot generate type %v", t)
|
||||||
}
|
}
|
||||||
return td, nil
|
return td, nil
|
||||||
},
|
},
|
||||||
"zerovalue": func(t ValType) (string, error) {
|
"zerovalue": func(t api.ValType) (string, error) {
|
||||||
v, ok := map[ValType]string{
|
v, ok := map[api.ValType]string{
|
||||||
TInt: "0",
|
api.TInt: "0",
|
||||||
TString: `""`,
|
api.TString: `""`,
|
||||||
TBool: "false",
|
api.TBool: "false",
|
||||||
}[t]
|
}[t]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", fmt.Errorf("cannot generate zero value for type %v", t)
|
return "", fmt.Errorf("cannot generate zero value for type %v", t)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package main
|
package golang
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -6,6 +6,8 @@ import (
|
|||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"efprojects.com/kitten-ipc/kitcom/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
var decorComment = regexp.MustCompile(`^//\s?kittenipc:api$`)
|
var decorComment = regexp.MustCompile(`^//\s?kittenipc:api$`)
|
||||||
@ -13,9 +15,9 @@ var decorComment = regexp.MustCompile(`^//\s?kittenipc:api$`)
|
|||||||
type GoApiParser struct {
|
type GoApiParser struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GoApiParser) Parse(sourceFile string) (*Api, error) {
|
func (g *GoApiParser) Parse(sourceFile string) (*api.Api, error) {
|
||||||
|
|
||||||
var api Api
|
var apis api.Api
|
||||||
|
|
||||||
fileSet := token.NewFileSet()
|
fileSet := token.NewFileSet()
|
||||||
astFile, err := parser.ParseFile(fileSet, sourceFile, nil, parser.ParseComments|parser.SkipObjectResolution)
|
astFile, err := parser.ParseFile(fileSet, sourceFile, nil, parser.ParseComments|parser.SkipObjectResolution)
|
||||||
@ -50,12 +52,12 @@ func (g *GoApiParser) Parse(sourceFile string) (*Api, error) {
|
|||||||
}
|
}
|
||||||
_ = structType
|
_ = structType
|
||||||
|
|
||||||
api.Endpoints = append(api.Endpoints, Endpoint{
|
apis.Endpoints = append(apis.Endpoints, api.Endpoint{
|
||||||
Name: typeSpec.Name.Name,
|
Name: typeSpec.Name.Name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(api.Endpoints) == 0 {
|
if len(apis.Endpoints) == 0 {
|
||||||
return nil, fmt.Errorf("no api struct found")
|
return nil, fmt.Errorf("no api struct found")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,20 +88,20 @@ func (g *GoApiParser) Parse(sourceFile string) (*Api, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, endpoint := range api.Endpoints {
|
for i, endpoint := range apis.Endpoints {
|
||||||
if recvIdent.Name == endpoint.Name {
|
if recvIdent.Name == endpoint.Name {
|
||||||
var apiMethod Method
|
var apiMethod api.Method
|
||||||
apiMethod.Name = funcDecl.Name.Name
|
apiMethod.Name = funcDecl.Name.Name
|
||||||
for _, param := range funcDecl.Type.Params.List {
|
for _, param := range funcDecl.Type.Params.List {
|
||||||
var apiPar Val
|
var apiPar api.Val
|
||||||
ident := param.Type.(*ast.Ident)
|
ident := param.Type.(*ast.Ident)
|
||||||
switch ident.Name {
|
switch ident.Name {
|
||||||
case "int":
|
case "int":
|
||||||
apiPar.Type = TInt
|
apiPar.Type = api.TInt
|
||||||
case "string":
|
case "string":
|
||||||
apiPar.Type = TString
|
apiPar.Type = api.TString
|
||||||
case "bool":
|
case "bool":
|
||||||
apiPar.Type = TBool
|
apiPar.Type = api.TBool
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("parameter type %s is not supported yet", ident.Name)
|
return nil, fmt.Errorf("parameter type %s is not supported yet", ident.Name)
|
||||||
}
|
}
|
||||||
@ -110,15 +112,15 @@ func (g *GoApiParser) Parse(sourceFile string) (*Api, error) {
|
|||||||
apiMethod.Params = append(apiMethod.Params, apiPar)
|
apiMethod.Params = append(apiMethod.Params, apiPar)
|
||||||
}
|
}
|
||||||
for _, ret := range funcDecl.Type.Results.List {
|
for _, ret := range funcDecl.Type.Results.List {
|
||||||
var apiRet Val
|
var apiRet api.Val
|
||||||
ident := ret.Type.(*ast.Ident)
|
ident := ret.Type.(*ast.Ident)
|
||||||
switch ident.Name {
|
switch ident.Name {
|
||||||
case "int":
|
case "int":
|
||||||
apiRet.Type = TInt
|
apiRet.Type = api.TInt
|
||||||
case "string":
|
case "string":
|
||||||
apiRet.Type = TString
|
apiRet.Type = api.TString
|
||||||
case "bool":
|
case "bool":
|
||||||
apiRet.Type = TBool
|
apiRet.Type = api.TBool
|
||||||
case "error":
|
case "error":
|
||||||
// errors are processed other way
|
// errors are processed other way
|
||||||
continue
|
continue
|
||||||
@ -130,10 +132,10 @@ func (g *GoApiParser) Parse(sourceFile string) (*Api, error) {
|
|||||||
}
|
}
|
||||||
apiMethod.Ret = append(apiMethod.Ret, apiRet)
|
apiMethod.Ret = append(apiMethod.Ret, apiRet)
|
||||||
}
|
}
|
||||||
api.Endpoints[i].Methods = append(api.Endpoints[i].Methods, apiMethod)
|
apis.Endpoints[i].Methods = append(apis.Endpoints[i].Methods, apiMethod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &api, nil
|
return &apis, nil
|
||||||
}
|
}
|
||||||
@ -8,48 +8,18 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"efprojects.com/kitten-ipc/kitcom/api"
|
||||||
|
"efprojects.com/kitten-ipc/kitcom/golang"
|
||||||
|
"efprojects.com/kitten-ipc/kitcom/ts"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ValType int
|
|
||||||
|
|
||||||
// todo check TInt size < 64
|
|
||||||
// todo check not float
|
|
||||||
|
|
||||||
const (
|
|
||||||
TInt ValType = 1
|
|
||||||
TString ValType = 2
|
|
||||||
TBool ValType = 3
|
|
||||||
TBlob ValType = 4
|
|
||||||
TArray ValType = 5
|
|
||||||
)
|
|
||||||
|
|
||||||
type Val struct {
|
|
||||||
Name string
|
|
||||||
Type ValType
|
|
||||||
Children []Val
|
|
||||||
}
|
|
||||||
|
|
||||||
type Method struct {
|
|
||||||
Name string
|
|
||||||
Params []Val
|
|
||||||
Ret []Val
|
|
||||||
}
|
|
||||||
|
|
||||||
type Endpoint struct {
|
|
||||||
Name string
|
|
||||||
Methods []Method
|
|
||||||
}
|
|
||||||
|
|
||||||
type Api struct {
|
|
||||||
Endpoints []Endpoint
|
|
||||||
}
|
|
||||||
|
|
||||||
type ApiParser interface {
|
type ApiParser interface {
|
||||||
Parse(sourceFile string) (*Api, error)
|
Parse(sourceFile string) (*api.Api, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiGenerator interface {
|
type ApiGenerator interface {
|
||||||
Generate(api *Api, destFile string) error
|
Generate(api *api.Api, destFile string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -116,9 +86,9 @@ func checkIsFile(src string) error {
|
|||||||
func apiParserByExt(src string) (ApiParser, error) {
|
func apiParserByExt(src string) (ApiParser, error) {
|
||||||
switch path.Ext(src) {
|
switch path.Ext(src) {
|
||||||
case ".go":
|
case ".go":
|
||||||
return &GoApiParser{}, nil
|
return &golang.GoApiParser{}, nil
|
||||||
case ".ts":
|
case ".ts":
|
||||||
return &TypescriptApiParser{}, nil
|
return &ts.TypescriptApiParser{}, nil
|
||||||
case ".js":
|
case ".js":
|
||||||
return nil, fmt.Errorf("vanilla javascript is not supported and never will be")
|
return nil, fmt.Errorf("vanilla javascript is not supported and never will be")
|
||||||
case "":
|
case "":
|
||||||
@ -137,11 +107,11 @@ func apiGeneratorByExt(dest string, pkgName string) (ApiGenerator, error) {
|
|||||||
if !token.IsIdentifier(pkgName) {
|
if !token.IsIdentifier(pkgName) {
|
||||||
return nil, fmt.Errorf("invalid package name: %s", pkgName)
|
return nil, fmt.Errorf("invalid package name: %s", pkgName)
|
||||||
}
|
}
|
||||||
return &GoApiGenerator{
|
return &golang.GoApiGenerator{
|
||||||
pkgName: pkgName,
|
PkgName: pkgName,
|
||||||
}, nil
|
}, nil
|
||||||
case ".ts":
|
case ".ts":
|
||||||
return &TypescriptApiGenerator{}, nil
|
return &ts.TypescriptApiGenerator{}, nil
|
||||||
case ".js":
|
case ".js":
|
||||||
return nil, fmt.Errorf("vanilla javascript is not supported and never will be")
|
return nil, fmt.Errorf("vanilla javascript is not supported and never will be")
|
||||||
case "":
|
case "":
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
{{- /*gotype: efprojects.com/kitten-ipc/kitcom.tsGenData*/ -}}
|
|
||||||
|
|
||||||
import {ParentIPC, ChildIPC} from 'kitten-ipc';
|
import {ParentIPC, ChildIPC} from 'kitten-ipc';
|
||||||
|
|
||||||
|
{{- /*gotype: efprojects.com/kitten-ipc/kitcom/ts.tsGenData*/ -}}
|
||||||
{{range $e := .Api.Endpoints}}
|
{{range $e := .Api.Endpoints}}
|
||||||
export default class {{$e.Name}} {
|
export default class {{$e.Name}} {
|
||||||
private ipc: ParentIPC | ChildIPC;
|
private ipc: ParentIPC | ChildIPC;
|
||||||
@ -14,9 +13,10 @@ export default class {{$e.Name}} {
|
|||||||
async {{ $mtd.Name }}(
|
async {{ $mtd.Name }}(
|
||||||
{{ range $par := $mtd.Params }}{{$par.Name}}: {{$par.Type | typedef }}, {{end}}
|
{{ range $par := $mtd.Params }}{{$par.Name}}: {{$par.Type | typedef }}, {{end}}
|
||||||
): Promise<{{if len $mtd.Ret}}{{(index $mtd.Ret 0).Type | typedef }}{{else}}void{{end}}> {
|
): Promise<{{if len $mtd.Ret}}{{(index $mtd.Ret 0).Type | typedef }}{{else}}void{{end}}> {
|
||||||
return await this.ipc.call('{{$mtd.Name}}',
|
const results = await this.ipc.call('{{$mtd.Name}}',
|
||||||
{{range $par := $mtd.Params}}{{$par.Name}}, {{end}}
|
{{range $par := $mtd.Params}}{{$par.Name}}, {{end}}
|
||||||
);
|
);
|
||||||
|
return {{range $ret := $mtd.}}
|
||||||
}
|
}
|
||||||
{{end}}
|
{{end}}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package main
|
package ts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -7,27 +7,29 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"efprojects.com/kitten-ipc/kitcom/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type tsGenData struct {
|
type tsGenData struct {
|
||||||
Api *Api
|
Api *api.Api
|
||||||
}
|
}
|
||||||
|
|
||||||
type TypescriptApiGenerator struct {
|
type TypescriptApiGenerator struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *TypescriptApiGenerator) Generate(api *Api, destFile string) error {
|
func (g *TypescriptApiGenerator) Generate(apis *api.Api, destFile string) error {
|
||||||
tplCtx := tsGenData{
|
tplCtx := tsGenData{
|
||||||
Api: api,
|
Api: apis,
|
||||||
}
|
}
|
||||||
|
|
||||||
tpl := template.New("tsgen")
|
tpl := template.New("tsgen")
|
||||||
tpl = tpl.Funcs(map[string]any{
|
tpl = tpl.Funcs(map[string]any{
|
||||||
"typedef": func(t ValType) (string, error) {
|
"typedef": func(t api.ValType) (string, error) {
|
||||||
td, ok := map[ValType]string{
|
td, ok := map[api.ValType]string{
|
||||||
TInt: "number",
|
api.TInt: "number",
|
||||||
TString: "string",
|
api.TString: "string",
|
||||||
TBool: "boolean",
|
api.TBool: "boolean",
|
||||||
}[t]
|
}[t]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", fmt.Errorf("cannot generate type %v", t)
|
return "", fmt.Errorf("cannot generate type %v", t)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package main
|
package ts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"efprojects.com/kitten-ipc/kitcom/api"
|
||||||
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
|
||||||
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
|
||||||
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/parser"
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/parser"
|
||||||
@ -18,7 +19,7 @@ const TagComment = "api"
|
|||||||
type TypescriptApiParser struct {
|
type TypescriptApiParser struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TypescriptApiParser) Parse(sourceFilePath string) (*Api, error) {
|
func (t *TypescriptApiParser) Parse(sourceFilePath string) (*api.Api, error) {
|
||||||
|
|
||||||
f, err := os.Open(sourceFilePath)
|
f, err := os.Open(sourceFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,7 +41,7 @@ func (t *TypescriptApiParser) Parse(sourceFilePath string) (*Api, error) {
|
|||||||
}, string(fileContents), core.ScriptKindTS)
|
}, string(fileContents), core.ScriptKindTS)
|
||||||
_ = sourceFile
|
_ = sourceFile
|
||||||
|
|
||||||
var api Api
|
var apis api.Api
|
||||||
|
|
||||||
sourceFile.ForEachChild(func(node *ast.Node) bool {
|
sourceFile.ForEachChild(func(node *ast.Node) bool {
|
||||||
if node.Kind != ast.KindClassDeclaration {
|
if node.Kind != ast.KindClassDeclaration {
|
||||||
@ -74,7 +75,7 @@ func (t *TypescriptApiParser) Parse(sourceFilePath string) (*Api, error) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var endpoint Endpoint
|
var endpoint api.Endpoint
|
||||||
|
|
||||||
endpoint.Name = cls.Name().Text()
|
endpoint.Name = cls.Name().Text()
|
||||||
|
|
||||||
@ -84,42 +85,42 @@ func (t *TypescriptApiParser) Parse(sourceFilePath string) (*Api, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
method := member.AsMethodDeclaration()
|
method := member.AsMethodDeclaration()
|
||||||
var apiMethod Method
|
var apiMethod api.Method
|
||||||
apiMethod.Name = method.Name().Text()
|
apiMethod.Name = method.Name().Text()
|
||||||
for _, parNode := range method.ParameterList().Nodes {
|
for _, parNode := range method.ParameterList().Nodes {
|
||||||
par := parNode.AsParameterDeclaration()
|
par := parNode.AsParameterDeclaration()
|
||||||
var apiPar Val
|
var apiPar api.Val
|
||||||
apiPar.Name = par.Name().Text()
|
apiPar.Name = par.Name().Text()
|
||||||
switch par.Type.Kind {
|
switch par.Type.Kind {
|
||||||
case ast.KindNumberKeyword:
|
case ast.KindNumberKeyword:
|
||||||
apiPar.Type = TInt
|
apiPar.Type = api.TInt
|
||||||
case ast.KindStringKeyword:
|
case ast.KindStringKeyword:
|
||||||
apiPar.Type = TString
|
apiPar.Type = api.TString
|
||||||
case ast.KindBooleanKeyword:
|
case ast.KindBooleanKeyword:
|
||||||
apiPar.Type = TBool
|
apiPar.Type = api.TBool
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("parameter type %s is not supported yet", par.Type.Kind)
|
err = fmt.Errorf("parameter type %s is not supported yet", par.Type.Kind)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
apiMethod.Params = append(apiMethod.Params, apiPar)
|
apiMethod.Params = append(apiMethod.Params, apiPar)
|
||||||
}
|
}
|
||||||
var apiRet Val
|
var apiRet api.Val
|
||||||
switch method.Type.Kind {
|
switch method.Type.Kind {
|
||||||
case ast.KindNumberKeyword:
|
case ast.KindNumberKeyword:
|
||||||
apiRet.Type = TInt
|
apiRet.Type = api.TInt
|
||||||
case ast.KindStringKeyword:
|
case ast.KindStringKeyword:
|
||||||
apiRet.Type = TString
|
apiRet.Type = api.TString
|
||||||
case ast.KindBooleanKeyword:
|
case ast.KindBooleanKeyword:
|
||||||
apiRet.Type = TBool
|
apiRet.Type = api.TBool
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("return type %s is not supported yet", method.Type.Kind)
|
err = fmt.Errorf("return type %s is not supported yet", method.Type.Kind)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
apiMethod.Ret = []Val{apiRet}
|
apiMethod.Ret = []api.Val{apiRet}
|
||||||
endpoint.Methods = append(endpoint.Methods, apiMethod)
|
endpoint.Methods = append(endpoint.Methods, apiMethod)
|
||||||
}
|
}
|
||||||
|
|
||||||
api.Endpoints = append(api.Endpoints, endpoint)
|
apis.Endpoints = append(apis.Endpoints, endpoint)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
@ -128,9 +129,9 @@ func (t *TypescriptApiParser) Parse(sourceFilePath string) (*Api, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(api.Endpoints) == 0 {
|
if len(apis.Endpoints) == 0 {
|
||||||
return nil, fmt.Errorf("no api class found")
|
return nil, fmt.Errorf("no api class found")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &api, nil
|
return &apis, nil
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user