mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-03-24 15:32:04 +01:00
update BlockService to use the new type union feature of tsgen. strongly type the arguments to BlockService.SendCommand
This commit is contained in:
parent
605b9ea048
commit
083e00227e
cmd/generate
frontend
pkg
blockcontroller
service
tsgen
@ -14,14 +14,13 @@ import (
|
||||
"github.com/wavetermdev/thenextwave/pkg/util/utilfn"
|
||||
)
|
||||
|
||||
func generateTypesFile() error {
|
||||
func generateTypesFile(tsTypesMap map[reflect.Type]string) error {
|
||||
fd, err := os.Create("frontend/types/gotypes.d.ts")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fd.Close()
|
||||
fmt.Fprintf(os.Stderr, "generating types file to %s\n", fd.Name())
|
||||
tsTypesMap := make(map[reflect.Type]string)
|
||||
tsgen.GenerateWaveObjTypes(tsTypesMap)
|
||||
err = tsgen.GenerateServiceTypes(tsTypesMap)
|
||||
if err != nil {
|
||||
@ -37,8 +36,8 @@ func generateTypesFile() error {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
iname, _ := tsgen.TypeToTSType(keys[i])
|
||||
jname, _ := tsgen.TypeToTSType(keys[j])
|
||||
iname, _ := tsgen.TypeToTSType(keys[i], tsTypesMap)
|
||||
jname, _ := tsgen.TypeToTSType(keys[j], tsTypesMap)
|
||||
return iname < jname
|
||||
})
|
||||
for _, key := range keys {
|
||||
@ -51,7 +50,7 @@ func generateTypesFile() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateServicesFile() error {
|
||||
func generateServicesFile(tsTypesMap map[reflect.Type]string) error {
|
||||
fd, err := os.Create("frontend/app/store/services.ts")
|
||||
if err != nil {
|
||||
return err
|
||||
@ -65,7 +64,7 @@ func generateServicesFile() error {
|
||||
orderedKeys := utilfn.GetOrderedMapKeys(service.ServiceMap)
|
||||
for _, serviceName := range orderedKeys {
|
||||
serviceObj := service.ServiceMap[serviceName]
|
||||
svcStr := tsgen.GenerateServiceClass(serviceName, serviceObj)
|
||||
svcStr := tsgen.GenerateServiceClass(serviceName, serviceObj, tsTypesMap)
|
||||
fmt.Fprint(fd, svcStr)
|
||||
fmt.Fprint(fd, "\n")
|
||||
}
|
||||
@ -78,12 +77,13 @@ func main() {
|
||||
fmt.Fprintf(os.Stderr, "Error validating service map: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = generateTypesFile()
|
||||
tsTypesMap := make(map[reflect.Type]string)
|
||||
err = generateTypesFile(tsTypesMap)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error generating types file: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = generateServicesFile()
|
||||
err = generateServicesFile(tsTypesMap)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error generating services file: %v\n", err)
|
||||
os.Exit(1)
|
||||
|
@ -49,7 +49,7 @@ const Block = ({ blockId, onClose }: BlockProps) => {
|
||||
} else if (blockData.view === "plot") {
|
||||
blockElem = <PlotView />;
|
||||
} else if (blockData.view === "codeedit") {
|
||||
blockElem = <CodeEditView />;
|
||||
blockElem = <CodeEditView text={null} />;
|
||||
}
|
||||
return (
|
||||
<div className="block" ref={blockRef}>
|
||||
|
@ -8,7 +8,7 @@ import * as WOS from "./wos";
|
||||
// blockservice.BlockService (block)
|
||||
class BlockServiceType {
|
||||
// send command to block
|
||||
SendCommand(blockid: string, command: MetaType): Promise<void> {
|
||||
SendCommand(blockid: string, cmd: BlockCommand): Promise<void> {
|
||||
return WOS.callBackendService("block", "SendCommand", Array.from(arguments))
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,10 @@ function handleResize(fitAddon: FitAddon, blockId: string, term: Terminal) {
|
||||
const oldCols = term.cols;
|
||||
fitAddon.fit();
|
||||
if (oldRows !== term.rows || oldCols !== term.cols) {
|
||||
const resizeCommand = { command: "controller:input", termsize: { rows: term.rows, cols: term.cols } };
|
||||
const resizeCommand: BlockInputCommand = {
|
||||
command: "controller:input",
|
||||
termsize: { rows: term.rows, cols: term.cols },
|
||||
};
|
||||
services.BlockService.SendCommand(blockId, resizeCommand);
|
||||
}
|
||||
}
|
||||
@ -78,17 +81,13 @@ const TerminalView = ({ blockId }: { blockId: string }) => {
|
||||
newTerm.loadAddon(newFitAddon);
|
||||
newTerm.open(connectElemRef.current);
|
||||
newFitAddon.fit();
|
||||
// BlockService.SendCommand(blockId, {
|
||||
// command: "controller:input",
|
||||
// termsize: { rows: newTerm.rows, cols: newTerm.cols },
|
||||
// });
|
||||
services.BlockService.SendCommand(blockId, {
|
||||
command: "controller:input",
|
||||
termsize: { rows: newTerm.rows, cols: newTerm.cols },
|
||||
});
|
||||
newTerm.onData((data) => {
|
||||
const b64data = btoa(data);
|
||||
const inputCmd = { command: "controller:input", blockid: blockId, inputdata64: b64data };
|
||||
const inputCmd: BlockInputCommand = { command: "controller:input", inputdata64: b64data };
|
||||
services.BlockService.SendCommand(blockId, inputCmd);
|
||||
});
|
||||
|
||||
|
32
frontend/types/gotypes.d.ts
vendored
32
frontend/types/gotypes.d.ts
vendored
@ -14,6 +14,10 @@ declare global {
|
||||
meta: MetaType;
|
||||
};
|
||||
|
||||
type BlockCommand = {
|
||||
command: string;
|
||||
} & ( BlockMessageCommand | BlockInputCommand | BlockSetViewCommand | BlockSetMetaCommand );
|
||||
|
||||
// wstore.BlockDef
|
||||
type BlockDef = {
|
||||
controller?: string;
|
||||
@ -22,6 +26,32 @@ declare global {
|
||||
meta?: MetaType;
|
||||
};
|
||||
|
||||
// blockcontroller.BlockInputCommand
|
||||
type BlockInputCommand = {
|
||||
command: "controller:input";
|
||||
inputdata64?: string;
|
||||
signame?: string;
|
||||
termsize?: TermSize;
|
||||
};
|
||||
|
||||
// blockcontroller.BlockMessageCommand
|
||||
type BlockMessageCommand = {
|
||||
command: "message";
|
||||
message: string;
|
||||
};
|
||||
|
||||
// blockcontroller.BlockSetMetaCommand
|
||||
type BlockSetMetaCommand = {
|
||||
command: "setmeta";
|
||||
meta: MetaType;
|
||||
};
|
||||
|
||||
// blockcontroller.BlockSetViewCommand
|
||||
type BlockSetViewCommand = {
|
||||
command: "setview";
|
||||
view: string;
|
||||
};
|
||||
|
||||
// wstore.Client
|
||||
type Client = WaveObj & {
|
||||
mainwindowid: string;
|
||||
@ -62,7 +92,7 @@ declare global {
|
||||
|
||||
type MetaType = {[key: string]: any}
|
||||
|
||||
// servicemeta.MethodMeta
|
||||
// tsgenmeta.MethodMeta
|
||||
type MethodMeta = {
|
||||
Desc: string;
|
||||
ArgNames: string[];
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"reflect"
|
||||
|
||||
"github.com/wavetermdev/thenextwave/pkg/shellexec"
|
||||
"github.com/wavetermdev/thenextwave/pkg/tsgen/tsgenmeta"
|
||||
)
|
||||
|
||||
const CommandKey = "command"
|
||||
@ -21,16 +22,33 @@ const (
|
||||
)
|
||||
|
||||
var CommandToTypeMap = map[string]reflect.Type{
|
||||
BlockCommand_Message: reflect.TypeOf(MessageCommand{}),
|
||||
BlockCommand_Input: reflect.TypeOf(InputCommand{}),
|
||||
BlockCommand_SetView: reflect.TypeOf(SetViewCommand{}),
|
||||
BlockCommand_SetMeta: reflect.TypeOf(SetMetaCommand{}),
|
||||
BlockCommand_Message: reflect.TypeOf(BlockMessageCommand{}),
|
||||
BlockCommand_Input: reflect.TypeOf(BlockInputCommand{}),
|
||||
BlockCommand_SetView: reflect.TypeOf(BlockSetViewCommand{}),
|
||||
BlockCommand_SetMeta: reflect.TypeOf(BlockSetMetaCommand{}),
|
||||
}
|
||||
|
||||
func CommandTypeUnionMeta() tsgenmeta.TypeUnionMeta {
|
||||
return tsgenmeta.TypeUnionMeta{
|
||||
BaseType: reflect.TypeOf((*BlockCommand)(nil)).Elem(),
|
||||
TypeFieldName: "command",
|
||||
Types: []reflect.Type{
|
||||
reflect.TypeOf(BlockMessageCommand{}),
|
||||
reflect.TypeOf(BlockInputCommand{}),
|
||||
reflect.TypeOf(BlockSetViewCommand{}),
|
||||
reflect.TypeOf(BlockSetMetaCommand{}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type BlockCommand interface {
|
||||
GetCommand() string
|
||||
}
|
||||
|
||||
type BlockCommandWrapper struct {
|
||||
BlockCommand
|
||||
}
|
||||
|
||||
func ParseCmdMap(cmdMap map[string]any) (BlockCommand, error) {
|
||||
cmdType, ok := cmdMap[CommandKey].(string)
|
||||
if !ok {
|
||||
@ -52,40 +70,40 @@ func ParseCmdMap(cmdMap map[string]any) (BlockCommand, error) {
|
||||
return cmd.(BlockCommand), nil
|
||||
}
|
||||
|
||||
type MessageCommand struct {
|
||||
Command string `json:"command"`
|
||||
type BlockMessageCommand struct {
|
||||
Command string `json:"command" tstype:"\"message\""`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (mc *MessageCommand) GetCommand() string {
|
||||
func (mc *BlockMessageCommand) GetCommand() string {
|
||||
return BlockCommand_Message
|
||||
}
|
||||
|
||||
type InputCommand struct {
|
||||
Command string `json:"command"`
|
||||
InputData64 string `json:"inputdata64"`
|
||||
type BlockInputCommand struct {
|
||||
Command string `json:"command" tstype:"\"controller:input\""`
|
||||
InputData64 string `json:"inputdata64,omitempty"`
|
||||
SigName string `json:"signame,omitempty"`
|
||||
TermSize *shellexec.TermSize `json:"termsize,omitempty"`
|
||||
}
|
||||
|
||||
func (ic *InputCommand) GetCommand() string {
|
||||
func (ic *BlockInputCommand) GetCommand() string {
|
||||
return BlockCommand_Input
|
||||
}
|
||||
|
||||
type SetViewCommand struct {
|
||||
Command string `json:"command"`
|
||||
type BlockSetViewCommand struct {
|
||||
Command string `json:"command" tstype:"\"setview\""`
|
||||
View string `json:"view"`
|
||||
}
|
||||
|
||||
func (svc *SetViewCommand) GetCommand() string {
|
||||
func (svc *BlockSetViewCommand) GetCommand() string {
|
||||
return BlockCommand_SetView
|
||||
}
|
||||
|
||||
type SetMetaCommand struct {
|
||||
Command string `json:"command"`
|
||||
type BlockSetMetaCommand struct {
|
||||
Command string `json:"command" tstype:"\"setmeta\""`
|
||||
Meta map[string]any `json:"meta"`
|
||||
}
|
||||
|
||||
func (smc *SetMetaCommand) GetCommand() string {
|
||||
func (smc *BlockSetMetaCommand) GetCommand() string {
|
||||
return BlockCommand_SetMeta
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ type BlockController struct {
|
||||
Status string
|
||||
|
||||
ShellProc *shellexec.ShellProc
|
||||
ShellInputCh chan *InputCommand
|
||||
ShellInputCh chan *BlockInputCommand
|
||||
}
|
||||
|
||||
func (bc *BlockController) WithLock(f func()) {
|
||||
@ -149,7 +149,7 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts) error {
|
||||
bc.ShellProc.Close()
|
||||
return err
|
||||
}
|
||||
shellInputCh := make(chan *InputCommand)
|
||||
shellInputCh := make(chan *BlockInputCommand)
|
||||
bc.ShellInputCh = shellInputCh
|
||||
go func() {
|
||||
defer func() {
|
||||
@ -234,7 +234,7 @@ func (bc *BlockController) Run(bdata *wstore.Block) {
|
||||
|
||||
for genCmd := range bc.InputCh {
|
||||
switch cmd := genCmd.(type) {
|
||||
case *InputCommand:
|
||||
case *BlockInputCommand:
|
||||
fmt.Printf("INPUT: %s | %q\n", bc.BlockId, cmd.InputData64)
|
||||
if bc.ShellInputCh != nil {
|
||||
bc.ShellInputCh <- cmd
|
||||
@ -293,10 +293,10 @@ func ProcessStaticCommand(blockId string, cmdGen BlockCommand) error {
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
|
||||
defer cancelFn()
|
||||
switch cmd := cmdGen.(type) {
|
||||
case *MessageCommand:
|
||||
case *BlockMessageCommand:
|
||||
log.Printf("MESSAGE: %s | %q\n", blockId, cmd.Message)
|
||||
return nil
|
||||
case *SetViewCommand:
|
||||
case *BlockSetViewCommand:
|
||||
log.Printf("SETVIEW: %s | %q\n", blockId, cmd.View)
|
||||
block, err := wstore.DBGet[*wstore.Block](ctx, blockId)
|
||||
if err != nil {
|
||||
@ -308,7 +308,7 @@ func ProcessStaticCommand(blockId string, cmdGen BlockCommand) error {
|
||||
return fmt.Errorf("error updating block: %w", err)
|
||||
}
|
||||
return nil
|
||||
case *SetMetaCommand:
|
||||
case *BlockSetMetaCommand:
|
||||
log.Printf("SETMETA: %s | %v\n", blockId, cmd.Meta)
|
||||
block, err := wstore.DBGet[*wstore.Block](ctx, blockId)
|
||||
if err != nil {
|
||||
|
@ -9,25 +9,21 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/wavetermdev/thenextwave/pkg/blockcontroller"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/servicemeta"
|
||||
"github.com/wavetermdev/thenextwave/pkg/tsgen/tsgenmeta"
|
||||
)
|
||||
|
||||
type BlockService struct{}
|
||||
|
||||
const DefaultTimeout = 2 * time.Second
|
||||
|
||||
func (bs *BlockService) SendCommand_Meta() servicemeta.MethodMeta {
|
||||
return servicemeta.MethodMeta{
|
||||
func (bs *BlockService) SendCommand_Meta() tsgenmeta.MethodMeta {
|
||||
return tsgenmeta.MethodMeta{
|
||||
Desc: "send command to block",
|
||||
ArgNames: []string{"blockid", "command"},
|
||||
ArgNames: []string{"blockid", "cmd"},
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BlockService) SendCommand(blockId string, cmdMap map[string]any) error {
|
||||
cmd, err := blockcontroller.ParseCmdMap(cmdMap)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing command map: %w", err)
|
||||
}
|
||||
func (bs *BlockService) SendCommand(blockId string, cmd blockcontroller.BlockCommand) error {
|
||||
if strings.HasPrefix(cmd.GetCommand(), "controller:") {
|
||||
bc := blockcontroller.GetBlockController(blockId)
|
||||
if bc == nil {
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/wavetermdev/thenextwave/pkg/blockcontroller"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/servicemeta"
|
||||
"github.com/wavetermdev/thenextwave/pkg/tsgen/tsgenmeta"
|
||||
"github.com/wavetermdev/thenextwave/pkg/waveobj"
|
||||
"github.com/wavetermdev/thenextwave/pkg/wstore"
|
||||
)
|
||||
@ -29,8 +29,8 @@ func parseORef(oref string) (*waveobj.ORef, error) {
|
||||
return &waveobj.ORef{OType: fields[0], OID: fields[1]}, nil
|
||||
}
|
||||
|
||||
func (svc *ObjectService) GetObject_Meta() servicemeta.MethodMeta {
|
||||
return servicemeta.MethodMeta{
|
||||
func (svc *ObjectService) GetObject_Meta() tsgenmeta.MethodMeta {
|
||||
return tsgenmeta.MethodMeta{
|
||||
Desc: "get wave object by oref",
|
||||
ArgNames: []string{"oref"},
|
||||
}
|
||||
@ -50,8 +50,8 @@ func (svc *ObjectService) GetObject(orefStr string) (waveobj.WaveObj, error) {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (svc *ObjectService) GetObjects_Meta() servicemeta.MethodMeta {
|
||||
return servicemeta.MethodMeta{
|
||||
func (svc *ObjectService) GetObjects_Meta() tsgenmeta.MethodMeta {
|
||||
return tsgenmeta.MethodMeta{
|
||||
ArgNames: []string{"orefs"},
|
||||
ReturnDesc: "objects",
|
||||
}
|
||||
@ -92,8 +92,8 @@ func updatesRtn(ctx context.Context, rtnVal map[string]any) (any, error) {
|
||||
return rtnVal, nil
|
||||
}
|
||||
|
||||
func (svc *ObjectService) AddTabToWorkspace_Meta() servicemeta.MethodMeta {
|
||||
return servicemeta.MethodMeta{
|
||||
func (svc *ObjectService) AddTabToWorkspace_Meta() tsgenmeta.MethodMeta {
|
||||
return tsgenmeta.MethodMeta{
|
||||
ArgNames: []string{"uiContext", "tabName", "activateTab"},
|
||||
ReturnDesc: "tabId",
|
||||
}
|
||||
@ -120,8 +120,8 @@ func (svc *ObjectService) AddTabToWorkspace(uiContext wstore.UIContext, tabName
|
||||
return tab.OID, wstore.ContextGetUpdatesRtn(ctx), nil
|
||||
}
|
||||
|
||||
func (svc *ObjectService) SetActiveTab_Meta() servicemeta.MethodMeta {
|
||||
return servicemeta.MethodMeta{
|
||||
func (svc *ObjectService) SetActiveTab_Meta() tsgenmeta.MethodMeta {
|
||||
return tsgenmeta.MethodMeta{
|
||||
ArgNames: []string{"uiContext", "tabId"},
|
||||
}
|
||||
}
|
||||
@ -158,8 +158,8 @@ func (svc *ObjectService) SetActiveTab(uiContext wstore.UIContext, tabId string)
|
||||
return updates, nil
|
||||
}
|
||||
|
||||
func (svc *ObjectService) CreateBlock_Meta() servicemeta.MethodMeta {
|
||||
return servicemeta.MethodMeta{
|
||||
func (svc *ObjectService) CreateBlock_Meta() tsgenmeta.MethodMeta {
|
||||
return tsgenmeta.MethodMeta{
|
||||
ArgNames: []string{"uiContext", "blockDef", "rtOpts"},
|
||||
ReturnDesc: "blockId",
|
||||
}
|
||||
@ -185,8 +185,8 @@ func (svc *ObjectService) CreateBlock(uiContext wstore.UIContext, blockDef *wsto
|
||||
return blockData.OID, wstore.ContextGetUpdatesRtn(ctx), nil
|
||||
}
|
||||
|
||||
func (svc *ObjectService) DeleteBlock_Meta() servicemeta.MethodMeta {
|
||||
return servicemeta.MethodMeta{
|
||||
func (svc *ObjectService) DeleteBlock_Meta() tsgenmeta.MethodMeta {
|
||||
return tsgenmeta.MethodMeta{
|
||||
ArgNames: []string{"uiContext", "blockId"},
|
||||
}
|
||||
}
|
||||
@ -203,8 +203,8 @@ func (svc *ObjectService) DeleteBlock(uiContext wstore.UIContext, blockId string
|
||||
return wstore.ContextGetUpdatesRtn(ctx), nil
|
||||
}
|
||||
|
||||
func (svc *ObjectService) CloseTab_Meta() servicemeta.MethodMeta {
|
||||
return servicemeta.MethodMeta{
|
||||
func (svc *ObjectService) CloseTab_Meta() tsgenmeta.MethodMeta {
|
||||
return tsgenmeta.MethodMeta{
|
||||
ArgNames: []string{"uiContext", "tabId"},
|
||||
}
|
||||
}
|
||||
@ -244,8 +244,8 @@ func (svc *ObjectService) CloseTab(uiContext wstore.UIContext, tabId string) (ws
|
||||
return wstore.ContextGetUpdatesRtn(ctx), nil
|
||||
}
|
||||
|
||||
func (svc *ObjectService) UpdateObjectMeta_Meta() servicemeta.MethodMeta {
|
||||
return servicemeta.MethodMeta{
|
||||
func (svc *ObjectService) UpdateObjectMeta_Meta() tsgenmeta.MethodMeta {
|
||||
return tsgenmeta.MethodMeta{
|
||||
ArgNames: []string{"uiContext", "oref", "meta"},
|
||||
}
|
||||
}
|
||||
@ -265,8 +265,8 @@ func (svc *ObjectService) UpdateObjectMeta(uiContext wstore.UIContext, orefStr s
|
||||
return wstore.ContextGetUpdatesRtn(ctx), nil
|
||||
}
|
||||
|
||||
func (svc *ObjectService) UpdateObject_Meta() servicemeta.MethodMeta {
|
||||
return servicemeta.MethodMeta{
|
||||
func (svc *ObjectService) UpdateObject_Meta() tsgenmeta.MethodMeta {
|
||||
return tsgenmeta.MethodMeta{
|
||||
ArgNames: []string{"uiContext", "waveObj", "returnUpdates"},
|
||||
}
|
||||
}
|
||||
|
@ -9,11 +9,12 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/wavetermdev/thenextwave/pkg/blockcontroller"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/blockservice"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/clientservice"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/fileservice"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/objectservice"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/servicemeta"
|
||||
"github.com/wavetermdev/thenextwave/pkg/tsgen/tsgenmeta"
|
||||
"github.com/wavetermdev/thenextwave/pkg/waveobj"
|
||||
"github.com/wavetermdev/thenextwave/pkg/wstore"
|
||||
)
|
||||
@ -31,9 +32,10 @@ var updatesRType = reflect.TypeOf(([]wstore.WaveObjUpdate{}))
|
||||
var waveObjRType = reflect.TypeOf((*waveobj.WaveObj)(nil)).Elem()
|
||||
var waveObjSliceRType = reflect.TypeOf([]waveobj.WaveObj{})
|
||||
var waveObjMapRType = reflect.TypeOf(map[string]waveobj.WaveObj{})
|
||||
var methodMetaRType = reflect.TypeOf(servicemeta.MethodMeta{})
|
||||
var methodMetaRType = reflect.TypeOf(tsgenmeta.MethodMeta{})
|
||||
var waveObjUpdateRType = reflect.TypeOf(wstore.WaveObjUpdate{})
|
||||
var uiContextRType = reflect.TypeOf((*wstore.UIContext)(nil)).Elem()
|
||||
var blockCommandRType = reflect.TypeOf((*blockcontroller.BlockCommand)(nil)).Elem()
|
||||
|
||||
type WebCallType struct {
|
||||
Service string `json:"service"`
|
||||
@ -89,12 +91,25 @@ func convertComplex(argType reflect.Type, jsonArg any) (any, error) {
|
||||
}
|
||||
|
||||
func isSpecialWaveArgType(argType reflect.Type) bool {
|
||||
return argType == waveObjRType || argType == waveObjSliceRType || argType == waveObjMapRType
|
||||
return argType == waveObjRType || argType == waveObjSliceRType || argType == waveObjMapRType || argType == blockCommandRType
|
||||
}
|
||||
|
||||
func convertBlockCommand(argType reflect.Type, jsonArg any) (any, error) {
|
||||
if _, ok := jsonArg.(map[string]any); !ok {
|
||||
return nil, fmt.Errorf("cannot convert %T to %s", jsonArg, argType)
|
||||
}
|
||||
cmd, err := blockcontroller.ParseCmdMap(jsonArg.(map[string]any))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing command map: %w", err)
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func convertSpecial(argType reflect.Type, jsonArg any) (any, error) {
|
||||
jsonType := reflect.TypeOf(jsonArg)
|
||||
if argType == waveObjRType {
|
||||
if argType == blockCommandRType {
|
||||
return convertBlockCommand(argType, jsonArg)
|
||||
} else if argType == waveObjRType {
|
||||
if jsonType.Kind() != reflect.Map {
|
||||
return nil, fmt.Errorf("cannot convert %T to %s", jsonArg, argType)
|
||||
}
|
||||
|
@ -1,10 +0,0 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package servicemeta
|
||||
|
||||
type MethodMeta struct {
|
||||
Desc string
|
||||
ArgNames []string
|
||||
ReturnDesc string
|
||||
}
|
@ -10,9 +10,10 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/wavetermdev/thenextwave/pkg/blockcontroller"
|
||||
"github.com/wavetermdev/thenextwave/pkg/eventbus"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/servicemeta"
|
||||
"github.com/wavetermdev/thenextwave/pkg/tsgen/tsgenmeta"
|
||||
"github.com/wavetermdev/thenextwave/pkg/waveobj"
|
||||
"github.com/wavetermdev/thenextwave/pkg/wstore"
|
||||
)
|
||||
@ -69,7 +70,7 @@ func isFieldOmitEmpty(field reflect.StructField) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func TypeToTSType(t reflect.Type) (string, []reflect.Type) {
|
||||
func TypeToTSType(t reflect.Type, tsTypesMap map[reflect.Type]string) (string, []reflect.Type) {
|
||||
switch t.Kind() {
|
||||
case reflect.String:
|
||||
return "string", nil
|
||||
@ -80,7 +81,7 @@ func TypeToTSType(t reflect.Type) (string, []reflect.Type) {
|
||||
case reflect.Bool:
|
||||
return "boolean", nil
|
||||
case reflect.Slice, reflect.Array:
|
||||
elemType, subTypes := TypeToTSType(t.Elem())
|
||||
elemType, subTypes := TypeToTSType(t.Elem(), tsTypesMap)
|
||||
if elemType == "" {
|
||||
return "", nil
|
||||
}
|
||||
@ -92,7 +93,7 @@ func TypeToTSType(t reflect.Type) (string, []reflect.Type) {
|
||||
if t == metaRType {
|
||||
return "MetaType", nil
|
||||
}
|
||||
elemType, subTypes := TypeToTSType(t.Elem())
|
||||
elemType, subTypes := TypeToTSType(t.Elem(), tsTypesMap)
|
||||
if elemType == "" {
|
||||
return "", nil
|
||||
}
|
||||
@ -100,10 +101,10 @@ func TypeToTSType(t reflect.Type) (string, []reflect.Type) {
|
||||
case reflect.Struct:
|
||||
return t.Name(), []reflect.Type{t}
|
||||
case reflect.Ptr:
|
||||
return TypeToTSType(t.Elem())
|
||||
return TypeToTSType(t.Elem(), tsTypesMap)
|
||||
case reflect.Interface:
|
||||
if t == waveObjRType {
|
||||
return "WaveObj", nil
|
||||
if _, ok := tsTypesMap[t]; ok {
|
||||
return t.Name(), nil
|
||||
}
|
||||
return "any", nil
|
||||
default:
|
||||
@ -115,7 +116,7 @@ var tsRenameMap = map[string]string{
|
||||
"Window": "WaveWindow",
|
||||
}
|
||||
|
||||
func generateTSTypeInternal(rtype reflect.Type) (string, []reflect.Type) {
|
||||
func generateTSTypeInternal(rtype reflect.Type, tsTypesMap map[reflect.Type]string) (string, []reflect.Type) {
|
||||
var buf bytes.Buffer
|
||||
waveObjType := reflect.TypeOf((*waveobj.WaveObj)(nil)).Elem()
|
||||
tsTypeName := rtype.Name()
|
||||
@ -149,10 +150,10 @@ func generateTSTypeInternal(rtype reflect.Type) (string, []reflect.Type) {
|
||||
}
|
||||
tsTypeTag := field.Tag.Get("tstype")
|
||||
if tsTypeTag != "" {
|
||||
buf.WriteString(fmt.Sprintf(" %s%s: %s;\n", fieldName, optMarker, tsTypeTag))
|
||||
buf.WriteString(fmt.Sprintf(" %s%s: %s;\n", fieldName, optMarker, tsTypeTag))
|
||||
continue
|
||||
}
|
||||
tsType, fieldSubTypes := TypeToTSType(field.Type)
|
||||
tsType, fieldSubTypes := TypeToTSType(field.Type, tsTypesMap)
|
||||
if tsType == "" {
|
||||
continue
|
||||
}
|
||||
@ -179,7 +180,32 @@ func GenerateWaveObjTSType() string {
|
||||
|
||||
func GenerateMetaType() string {
|
||||
return "type MetaType = {[key: string]: any}\n"
|
||||
}
|
||||
|
||||
func GenerateTSTypeUnion(unionMeta tsgenmeta.TypeUnionMeta, tsTypeMap map[reflect.Type]string) {
|
||||
rtn := generateTSTypeUnionInternal(unionMeta)
|
||||
tsTypeMap[unionMeta.BaseType] = rtn
|
||||
for _, rtype := range unionMeta.Types {
|
||||
GenerateTSType(rtype, tsTypeMap)
|
||||
}
|
||||
}
|
||||
|
||||
func generateTSTypeUnionInternal(unionMeta tsgenmeta.TypeUnionMeta) string {
|
||||
var buf bytes.Buffer
|
||||
if unionMeta.Desc != "" {
|
||||
buf.WriteString(fmt.Sprintf("// %s\n", unionMeta.Desc))
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf("type %s = {\n", unionMeta.BaseType.Name()))
|
||||
buf.WriteString(fmt.Sprintf(" %s: string;\n", unionMeta.TypeFieldName))
|
||||
buf.WriteString("} & ( ")
|
||||
for idx, rtype := range unionMeta.Types {
|
||||
if idx > 0 {
|
||||
buf.WriteString(" | ")
|
||||
}
|
||||
buf.WriteString(rtype.Name())
|
||||
}
|
||||
buf.WriteString(" );\n")
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func GenerateTSType(rtype reflect.Type, tsTypesMap map[reflect.Type]string) {
|
||||
@ -212,7 +238,7 @@ func GenerateTSType(rtype reflect.Type, tsTypesMap map[reflect.Type]string) {
|
||||
if rtype.Kind() != reflect.Struct {
|
||||
return
|
||||
}
|
||||
tsType, subTypes := generateTSTypeInternal(rtype)
|
||||
tsType, subTypes := generateTSTypeInternal(rtype, tsTypesMap)
|
||||
tsTypesMap[rtype] = tsType
|
||||
for _, subType := range subTypes {
|
||||
GenerateTSType(subType, tsTypesMap)
|
||||
@ -229,7 +255,7 @@ func hasUpdatesReturn(method reflect.Method) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func GenerateMethodSignature(serviceName string, method reflect.Method, meta servicemeta.MethodMeta, isFirst bool) string {
|
||||
func GenerateMethodSignature(serviceName string, method reflect.Method, meta tsgenmeta.MethodMeta, isFirst bool, tsTypesMap map[reflect.Type]string) string {
|
||||
var sb strings.Builder
|
||||
mayReturnUpdates := hasUpdatesReturn(method)
|
||||
if (meta.Desc != "" || meta.ReturnDesc != "" || mayReturnUpdates) && !isFirst {
|
||||
@ -260,7 +286,7 @@ func GenerateMethodSignature(serviceName string, method reflect.Method, meta ser
|
||||
if inType == contextRType || inType == uiContextRType {
|
||||
continue
|
||||
}
|
||||
tsTypeName, _ := TypeToTSType(inType)
|
||||
tsTypeName, _ := TypeToTSType(inType, tsTypesMap)
|
||||
var argName string
|
||||
if idx-1 < len(meta.ArgNames) {
|
||||
argName = meta.ArgNames[idx-1] // subtract 1 for receiver
|
||||
@ -280,7 +306,7 @@ func GenerateMethodSignature(serviceName string, method reflect.Method, meta ser
|
||||
if outType == updatesRtnRType {
|
||||
continue
|
||||
}
|
||||
tsTypeName, _ := TypeToTSType(outType)
|
||||
tsTypeName, _ := TypeToTSType(outType, tsTypesMap)
|
||||
sb.WriteString(fmt.Sprintf("Promise<%s>", tsTypeName))
|
||||
wroteRtn = true
|
||||
}
|
||||
@ -291,11 +317,11 @@ func GenerateMethodSignature(serviceName string, method reflect.Method, meta ser
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func GenerateMethodBody(serviceName string, method reflect.Method, meta servicemeta.MethodMeta) string {
|
||||
func GenerateMethodBody(serviceName string, method reflect.Method, meta tsgenmeta.MethodMeta) string {
|
||||
return fmt.Sprintf(" return WOS.callBackendService(%q, %q, Array.from(arguments))\n", serviceName, method.Name)
|
||||
}
|
||||
|
||||
func GenerateServiceClass(serviceName string, serviceObj any) string {
|
||||
func GenerateServiceClass(serviceName string, serviceObj any, tsTypesMap map[reflect.Type]string) string {
|
||||
serviceType := reflect.TypeOf(serviceObj)
|
||||
var sb strings.Builder
|
||||
tsServiceName := serviceType.Elem().Name()
|
||||
@ -309,14 +335,14 @@ func GenerateServiceClass(serviceName string, serviceObj any) string {
|
||||
if strings.HasSuffix(method.Name, "_Meta") {
|
||||
continue
|
||||
}
|
||||
var meta servicemeta.MethodMeta
|
||||
var meta tsgenmeta.MethodMeta
|
||||
metaMethod, found := serviceType.MethodByName(method.Name + "_Meta")
|
||||
if found {
|
||||
serviceObjVal := reflect.ValueOf(serviceObj)
|
||||
metaVal := metaMethod.Func.Call([]reflect.Value{serviceObjVal})
|
||||
meta = metaVal[0].Interface().(servicemeta.MethodMeta)
|
||||
meta = metaVal[0].Interface().(tsgenmeta.MethodMeta)
|
||||
}
|
||||
sb.WriteString(GenerateMethodSignature(serviceName, method, meta, isFirst))
|
||||
sb.WriteString(GenerateMethodSignature(serviceName, method, meta, isFirst, tsTypesMap))
|
||||
sb.WriteString(GenerateMethodBody(serviceName, method, meta))
|
||||
sb.WriteString(" }\n")
|
||||
isFirst = false
|
||||
@ -327,6 +353,7 @@ func GenerateServiceClass(serviceName string, serviceObj any) string {
|
||||
}
|
||||
|
||||
func GenerateWaveObjTypes(tsTypesMap map[reflect.Type]string) {
|
||||
GenerateTSTypeUnion(blockcontroller.CommandTypeUnionMeta(), tsTypesMap)
|
||||
GenerateTSType(reflect.TypeOf(waveobj.ORef{}), tsTypesMap)
|
||||
GenerateTSType(reflect.TypeOf((*waveobj.WaveObj)(nil)).Elem(), tsTypesMap)
|
||||
GenerateTSType(reflect.TypeOf(map[string]any{}), tsTypesMap)
|
||||
|
19
pkg/tsgen/tsgenmeta/tsgenmeta.go
Normal file
19
pkg/tsgen/tsgenmeta/tsgenmeta.go
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package tsgenmeta
|
||||
|
||||
import "reflect"
|
||||
|
||||
type MethodMeta struct {
|
||||
Desc string
|
||||
ArgNames []string
|
||||
ReturnDesc string
|
||||
}
|
||||
|
||||
type TypeUnionMeta struct {
|
||||
BaseType reflect.Type
|
||||
Desc string
|
||||
TypeFieldName string
|
||||
Types []reflect.Type
|
||||
}
|
Loading…
Reference in New Issue
Block a user