feat(module,app): basic module to list apps
This commit is contained in:
@ -9,11 +9,11 @@ import (
|
||||
type ID string
|
||||
|
||||
type Manifest struct {
|
||||
ID ID `yaml:"id"`
|
||||
Version string `yaml:"version"`
|
||||
Title string `yaml:"title"`
|
||||
Description string `yaml:"description"`
|
||||
Tags []string `yaml:"tags"`
|
||||
ID ID `yaml:"id" json:"id"`
|
||||
Version string `yaml:"version" json:"version"`
|
||||
Title string `yaml:"title" json:"title"`
|
||||
Description string `yaml:"description" json:"description"`
|
||||
Tags []string `yaml:"tags" json:"tags"`
|
||||
}
|
||||
|
||||
func LoadManifest(b bundle.Bundle) (*Manifest, error) {
|
||||
|
5
pkg/module/app/error.go
Normal file
5
pkg/module/app/error.go
Normal file
@ -0,0 +1,5 @@
|
||||
package app
|
||||
|
||||
import "errors"
|
||||
|
||||
var ErrNotFound = errors.New("not found")
|
58
pkg/module/app/memory/module_test.go
Normal file
58
pkg/module/app/memory/module_test.go
Normal file
@ -0,0 +1,58 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/app"
|
||||
"forge.cadoles.com/arcad/edge/pkg/module"
|
||||
appModule "forge.cadoles.com/arcad/edge/pkg/module/app"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func TestAppModuleWithMemoryRepository(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server := app.NewServer(
|
||||
module.ContextModuleFactory(),
|
||||
module.ConsoleModuleFactory(),
|
||||
appModule.ModuleFactory(NewRepository(
|
||||
func(ctx context.Context, id app.ID) (string, error) {
|
||||
return fmt.Sprintf("http//%s.example.com", id), nil
|
||||
},
|
||||
&app.Manifest{
|
||||
ID: "dummy1.arcad.app",
|
||||
Version: "0.0.0",
|
||||
Title: "Dummy 1",
|
||||
Description: "Dummy App 1",
|
||||
Tags: []string{"dummy", "first"},
|
||||
},
|
||||
&app.Manifest{
|
||||
ID: "dummy2.arcad.app",
|
||||
Version: "0.0.0",
|
||||
Title: "Dummy 2",
|
||||
Description: "Dummy App 2",
|
||||
Tags: []string{"dummy", "second"},
|
||||
},
|
||||
)),
|
||||
)
|
||||
|
||||
file := "testdata/app.js"
|
||||
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := server.Load(file, string(data)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer server.Stop()
|
||||
|
||||
if err := server.Start(); err != nil {
|
||||
t.Fatalf("%+v", errors.WithStack(err))
|
||||
}
|
||||
}
|
50
pkg/module/app/memory/repository.go
Normal file
50
pkg/module/app/memory/repository.go
Normal file
@ -0,0 +1,50 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/app"
|
||||
module "forge.cadoles.com/arcad/edge/pkg/module/app"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type GetURLFunc func(context.Context, app.ID) (string, error)
|
||||
|
||||
type Repository struct {
|
||||
getURL GetURLFunc
|
||||
apps []*app.Manifest
|
||||
}
|
||||
|
||||
// GetURL implements app.Repository
|
||||
func (r *Repository) GetURL(ctx context.Context, id app.ID) (string, error) {
|
||||
url, err := r.getURL(ctx, id)
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
return url, nil
|
||||
}
|
||||
|
||||
// Get implements app.Repository
|
||||
func (r *Repository) Get(ctx context.Context, id app.ID) (*app.Manifest, error) {
|
||||
for _, app := range r.apps {
|
||||
if app.ID != id {
|
||||
continue
|
||||
}
|
||||
|
||||
return app, nil
|
||||
}
|
||||
|
||||
return nil, module.ErrNotFound
|
||||
}
|
||||
|
||||
// List implements app.Repository
|
||||
func (r *Repository) List(ctx context.Context) ([]*app.Manifest, error) {
|
||||
return r.apps, nil
|
||||
}
|
||||
|
||||
func NewRepository(getURL GetURLFunc, manifests ...*app.Manifest) *Repository {
|
||||
return &Repository{getURL, manifests}
|
||||
}
|
||||
|
||||
var _ module.Repository = &Repository{}
|
17
pkg/module/app/memory/testdata/app.js
vendored
Normal file
17
pkg/module/app/memory/testdata/app.js
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
var ctx = context.new();
|
||||
|
||||
var manifests = app.list(ctx);
|
||||
|
||||
if (manifests.length !== 2) {
|
||||
throw new Error("apps.length: expected '2', got '"+manifests.length+"'");
|
||||
}
|
||||
|
||||
var manifest = app.get(ctx, 'dummy2.arcad.app');
|
||||
|
||||
if (!manifest) {
|
||||
throw new Error("manifest should not be null");
|
||||
}
|
||||
|
||||
if (manifest.id !== "dummy2.arcad.app") {
|
||||
throw new Error("manifest.id: expected 'dummy2.arcad.app', got '"+manifest.id+"'");
|
||||
}
|
117
pkg/module/app/module.go
Normal file
117
pkg/module/app/module.go
Normal file
@ -0,0 +1,117 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/app"
|
||||
"forge.cadoles.com/arcad/edge/pkg/module/util"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Module struct {
|
||||
repository Repository
|
||||
}
|
||||
|
||||
type gojaManifest struct {
|
||||
ID string `goja:"id" json:"id"`
|
||||
Version string `goja:"version" json:"version"`
|
||||
Title string `goja:"title" json:"title"`
|
||||
Description string `goja:"description" json:"description"`
|
||||
Tags []string `goja:"tags" json:"tags"`
|
||||
}
|
||||
|
||||
func toGojaManifest(manifest *app.Manifest) *gojaManifest {
|
||||
return &gojaManifest{
|
||||
ID: string(manifest.ID),
|
||||
Version: manifest.Version,
|
||||
Title: manifest.Title,
|
||||
Description: manifest.Description,
|
||||
Tags: manifest.Tags,
|
||||
}
|
||||
}
|
||||
|
||||
func toGojaManifests(manifests []*app.Manifest) []*gojaManifest {
|
||||
gojaManifests := make([]*gojaManifest, len(manifests))
|
||||
|
||||
for i, m := range manifests {
|
||||
gojaManifests[i] = toGojaManifest(m)
|
||||
}
|
||||
|
||||
return gojaManifests
|
||||
}
|
||||
|
||||
func (m *Module) Name() string {
|
||||
return "app"
|
||||
}
|
||||
|
||||
func (m *Module) Export(export *goja.Object) {
|
||||
if err := export.Set("list", m.list); err != nil {
|
||||
panic(errors.Wrap(err, "could not set 'list' function"))
|
||||
}
|
||||
|
||||
if err := export.Set("get", m.get); err != nil {
|
||||
panic(errors.Wrap(err, "could not set 'get' function"))
|
||||
}
|
||||
|
||||
if err := export.Set("getUrl", m.getURL); err != nil {
|
||||
panic(errors.Wrap(err, "could not set 'list' function"))
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Module) list(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
|
||||
ctx := util.AssertContext(call.Argument(0), rt)
|
||||
|
||||
manifests, err := m.repository.List(ctx)
|
||||
if err != nil {
|
||||
panic(rt.ToValue(errors.WithStack(err)))
|
||||
}
|
||||
|
||||
return rt.ToValue(toGojaManifests(manifests))
|
||||
}
|
||||
|
||||
func (m *Module) get(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
|
||||
ctx := util.AssertContext(call.Argument(0), rt)
|
||||
appID := assertAppID(call.Argument(1), rt)
|
||||
|
||||
manifest, err := m.repository.Get(ctx, appID)
|
||||
if err != nil {
|
||||
panic(rt.ToValue(errors.WithStack(err)))
|
||||
}
|
||||
|
||||
return rt.ToValue(toGojaManifest(manifest))
|
||||
}
|
||||
|
||||
func (m *Module) getURL(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
|
||||
ctx := util.AssertContext(call.Argument(0), rt)
|
||||
appID := assertAppID(call.Argument(1), rt)
|
||||
|
||||
url, err := m.repository.GetURL(ctx, appID)
|
||||
if err != nil {
|
||||
panic(rt.ToValue(errors.WithStack(err)))
|
||||
}
|
||||
|
||||
return rt.ToValue(url)
|
||||
}
|
||||
|
||||
func ModuleFactory(repository Repository) app.ServerModuleFactory {
|
||||
return func(server *app.Server) app.ServerModule {
|
||||
return &Module{
|
||||
repository: repository,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func assertAppID(value goja.Value, rt *goja.Runtime) app.ID {
|
||||
appID, ok := value.Export().(app.ID)
|
||||
if !ok {
|
||||
rawAppID, ok := value.Export().(string)
|
||||
if !ok {
|
||||
panic(rt.NewTypeError(fmt.Sprintf("app id must be an appid or a string, got '%T'", value.Export())))
|
||||
}
|
||||
|
||||
appID = app.ID(rawAppID)
|
||||
}
|
||||
|
||||
return appID
|
||||
}
|
13
pkg/module/app/repository.go
Normal file
13
pkg/module/app/repository.go
Normal file
@ -0,0 +1,13 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/app"
|
||||
)
|
||||
|
||||
type Repository interface {
|
||||
List(context.Context) ([]*app.Manifest, error)
|
||||
Get(context.Context, app.ID) (*app.Manifest, error)
|
||||
GetURL(context.Context, app.ID) (string, error)
|
||||
}
|
Reference in New Issue
Block a user