updated cobra.Command constructor and update structConstructor to use goja.Object.Set
This commit is contained in:
parent
fc311a8d28
commit
21607f0f66
|
@ -14,7 +14,7 @@ const heading = `
|
|||
// baseBinds
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
declare var $app: core.App
|
||||
declare var $app: pocketbase.PocketBase
|
||||
|
||||
interface Record extends models.Record{} // merge
|
||||
declare class Record implements models.Record {
|
||||
|
@ -41,11 +41,16 @@ declare class SchemaField implements schema.SchemaField {
|
|||
constructor(data?: Partial<schema.SchemaField>)
|
||||
}
|
||||
|
||||
interface Mail extends mailer.Message{} // merge
|
||||
interface MailerMessage extends mailer.Message{} // merge
|
||||
declare class Mail implements mailer.Message {
|
||||
constructor(message?: Partial<mailer.Message>)
|
||||
}
|
||||
|
||||
interface Command extends cobra.Command{} // merge
|
||||
declare class Mail implements cobra.Command {
|
||||
constructor(cmd?: Partial<cobra.Command>)
|
||||
}
|
||||
|
||||
interface ValidationError extends ozzo_validation.Error{} // merge
|
||||
declare class ValidationError implements ozzo_validation.Error {
|
||||
constructor(code?: number, message?: string)
|
||||
|
@ -270,7 +275,7 @@ func main() {
|
|||
"github.com/pocketbase/pocketbase/tokens": {"*"},
|
||||
"github.com/pocketbase/pocketbase/apis": {"*"},
|
||||
"github.com/pocketbase/pocketbase/forms": {"*"},
|
||||
"github.com/pocketbase/pocketbase/core": {"*"},
|
||||
"github.com/pocketbase/pocketbase": {"*"},
|
||||
},
|
||||
FieldNameFormatter: func(s string) string {
|
||||
return mapper.FieldName(nil, reflect.StructField{Name: s})
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,7 @@ package jsvm
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
@ -38,6 +39,7 @@ import (
|
|||
"github.com/pocketbase/pocketbase/tools/mailer"
|
||||
"github.com/pocketbase/pocketbase/tools/security"
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func baseBinds(vm *goja.Runtime) {
|
||||
|
@ -66,19 +68,6 @@ func baseBinds(vm *goja.Runtime) {
|
|||
}
|
||||
`)
|
||||
|
||||
vm.Set("unmarshal", func(src map[string]any, dest any) (any, error) {
|
||||
raw, err := json.Marshal(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(raw, &dest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dest, nil
|
||||
})
|
||||
|
||||
vm.Set("DynamicModel", func(call goja.ConstructorCall) *goja.Object {
|
||||
shape, ok := call.Argument(0).Export().(map[string]any)
|
||||
if !ok || len(shape) == 0 {
|
||||
|
@ -113,9 +102,7 @@ func baseBinds(vm *goja.Runtime) {
|
|||
instance = models.NewRecord(collection)
|
||||
data, ok := call.Argument(1).Export().(map[string]any)
|
||||
if ok {
|
||||
if raw, err := json.Marshal(data); err == nil {
|
||||
json.Unmarshal(raw, instance)
|
||||
}
|
||||
instance.Load(data)
|
||||
}
|
||||
} else {
|
||||
instance = &models.Record{}
|
||||
|
@ -129,26 +116,31 @@ func baseBinds(vm *goja.Runtime) {
|
|||
|
||||
vm.Set("Collection", func(call goja.ConstructorCall) *goja.Object {
|
||||
instance := &models.Collection{}
|
||||
return structConstructor(vm, call, instance)
|
||||
return structConstructorUnmarshal(vm, call, instance)
|
||||
})
|
||||
|
||||
vm.Set("Admin", func(call goja.ConstructorCall) *goja.Object {
|
||||
instance := &models.Admin{}
|
||||
return structConstructor(vm, call, instance)
|
||||
return structConstructorUnmarshal(vm, call, instance)
|
||||
})
|
||||
|
||||
vm.Set("Schema", func(call goja.ConstructorCall) *goja.Object {
|
||||
instance := &schema.Schema{}
|
||||
return structConstructor(vm, call, instance)
|
||||
return structConstructorUnmarshal(vm, call, instance)
|
||||
})
|
||||
|
||||
vm.Set("SchemaField", func(call goja.ConstructorCall) *goja.Object {
|
||||
instance := &schema.SchemaField{}
|
||||
return structConstructorUnmarshal(vm, call, instance)
|
||||
})
|
||||
|
||||
vm.Set("MailerMessage", func(call goja.ConstructorCall) *goja.Object {
|
||||
instance := &mailer.Message{}
|
||||
return structConstructor(vm, call, instance)
|
||||
})
|
||||
|
||||
vm.Set("Mail", func(call goja.ConstructorCall) *goja.Object {
|
||||
instance := &mailer.Message{}
|
||||
vm.Set("Command", func(call goja.ConstructorCall) *goja.Object {
|
||||
instance := &cobra.Command{}
|
||||
return structConstructor(vm, call, instance)
|
||||
})
|
||||
|
||||
|
@ -307,8 +299,8 @@ func apisBinds(vm *goja.Runtime) {
|
|||
obj.Set("unauthorizedError", apis.NewUnauthorizedError)
|
||||
|
||||
vm.Set("Route", func(call goja.ConstructorCall) *goja.Object {
|
||||
instance := echo.Route{}
|
||||
return structConstructor(vm, call, &instance)
|
||||
instance := &echo.Route{}
|
||||
return structConstructor(vm, call, instance)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -339,7 +331,25 @@ func registerFactoryAsConstructor(vm *goja.Runtime, constructorName string, fact
|
|||
}
|
||||
|
||||
// structConstructor wraps the provided struct with a native JS constructor.
|
||||
//
|
||||
// If the constructor argument is a map, each entry of the map will be loaded into the wrapped goja.Object.
|
||||
func structConstructor(vm *goja.Runtime, call goja.ConstructorCall, instance any) *goja.Object {
|
||||
data, _ := call.Argument(0).Export().(map[string]any)
|
||||
|
||||
instanceValue := vm.ToValue(instance).(*goja.Object)
|
||||
for k, v := range data {
|
||||
instanceValue.Set(k, v)
|
||||
}
|
||||
|
||||
instanceValue.SetPrototype(call.This.Prototype())
|
||||
|
||||
return instanceValue
|
||||
}
|
||||
|
||||
// structConstructorUnmarshal wraps the provided struct with a native JS constructor.
|
||||
//
|
||||
// The constructor first argument will be loaded via json.Unmarshal into the instance.
|
||||
func structConstructorUnmarshal(vm *goja.Runtime, call goja.ConstructorCall, instance any) *goja.Object {
|
||||
if data := call.Argument(0).Export(); data != nil {
|
||||
if raw, err := json.Marshal(data); err == nil {
|
||||
json.Unmarshal(raw, instance)
|
||||
|
@ -460,3 +470,42 @@ func newDynamicModel(shape map[string]any) any {
|
|||
|
||||
return elem.Addr().Interface()
|
||||
}
|
||||
|
||||
func loadMapFields(data any, instance any) error {
|
||||
if reflect.TypeOf(data).Kind() != reflect.Map {
|
||||
return errors.New("data must be map")
|
||||
}
|
||||
|
||||
if reflect.TypeOf(instance).Kind() != reflect.Pointer {
|
||||
return errors.New("instance must be pointer")
|
||||
}
|
||||
|
||||
iv := reflect.ValueOf(instance).Elem()
|
||||
if iv.Kind() != reflect.Struct {
|
||||
return errors.New("value must be a pointer to a struct/interface")
|
||||
}
|
||||
|
||||
dv := reflect.ValueOf(data)
|
||||
|
||||
for _, k := range dv.MapKeys() {
|
||||
name := strings.Title(k.String()) // @todo reverse mapping
|
||||
field := iv.FieldByName(name)
|
||||
|
||||
if !field.CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
v := dv.MapIndex(k)
|
||||
|
||||
if !v.CanInterface() {
|
||||
continue
|
||||
}
|
||||
|
||||
// if v.Type().Kind() == reflect.Func {
|
||||
// }
|
||||
|
||||
// field.Set(reflect.ValueOf(v.Interface()))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -27,25 +27,6 @@ func TestBaseBindsCount(t *testing.T) {
|
|||
testBindsCount(vm, "this", 14, t)
|
||||
}
|
||||
|
||||
func TestBaseBindsUnmarshal(t *testing.T) {
|
||||
vm := goja.New()
|
||||
baseBinds(vm)
|
||||
|
||||
v, err := vm.RunString(`unmarshal({ name: "test" }, new Collection())`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
m, ok := v.Export().(*models.Collection)
|
||||
if !ok {
|
||||
t.Fatalf("Expected models.Collection, got %v", m)
|
||||
}
|
||||
|
||||
if m.Name != "test" {
|
||||
t.Fatalf("Expected collection with name %q, got %q", "test", m.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBaseBindsRecord(t *testing.T) {
|
||||
app, _ := tests.NewTestApp()
|
||||
defer app.Cleanup()
|
||||
|
@ -168,11 +149,11 @@ func TestBaseBindsSchemaField(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBaseBindsMail(t *testing.T) {
|
||||
func TestBaseBindsMailerMessage(t *testing.T) {
|
||||
vm := goja.New()
|
||||
baseBinds(vm)
|
||||
|
||||
v, err := vm.RunString(`new Mail({
|
||||
v, err := vm.RunString(`new MailerMessage({
|
||||
from: {name: "test_from", address: "test_from@example.com"},
|
||||
to: [
|
||||
{name: "test_to1", address: "test_to1@example.com"},
|
||||
|
@ -212,6 +193,35 @@ func TestBaseBindsMail(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBaseBindsCommand(t *testing.T) {
|
||||
vm := goja.New()
|
||||
baseBinds(vm)
|
||||
|
||||
_, err := vm.RunString(`
|
||||
let runCalls = 0;
|
||||
|
||||
let cmd = new Command({
|
||||
use: "test",
|
||||
run: (c, args) => {
|
||||
runCalls++;
|
||||
}
|
||||
});
|
||||
|
||||
cmd.run(null, []);
|
||||
|
||||
if (cmd.use != "test") {
|
||||
throw new Error('Expected cmd.use "test", got: ' + cmd.use);
|
||||
}
|
||||
|
||||
if (runCalls != 1) {
|
||||
throw new Error('Expected runCalls 1, got: ' + runCalls);
|
||||
}
|
||||
`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBaseBindsValidationError(t *testing.T) {
|
||||
vm := goja.New()
|
||||
baseBinds(vm)
|
||||
|
|
Loading…
Reference in New Issue