wsh edit working (#252)

This commit is contained in:
Mike Sawka
2024-08-20 14:56:48 -07:00
committed by GitHub
parent 5c00fc6e78
commit 037497e7f1
35 changed files with 828 additions and 520 deletions
+3 -2
View File
@@ -22,6 +22,7 @@ import (
"github.com/wavetermdev/thenextwave/pkg/telemetry"
"github.com/wavetermdev/thenextwave/pkg/util/shellutil"
"github.com/wavetermdev/thenextwave/pkg/wavebase"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/wcloud"
"github.com/wavetermdev/thenextwave/pkg/wconfig"
"github.com/wavetermdev/thenextwave/pkg/web"
@@ -116,7 +117,7 @@ func sendTelemetryWrapper() {
}()
ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
defer cancelFn()
client, err := wstore.DBGetSingleton[*wstore.Client](ctx)
client, err := wstore.DBGetSingleton[*waveobj.Client](ctx)
if err != nil {
log.Printf("[error] getting client data for telemetry: %v\n", err)
return
@@ -133,7 +134,7 @@ func startupActivityUpdate() {
activity := telemetry.ActivityUpdate{
Startup: 1,
}
activity.NumTabs, _ = wstore.DBGetCount[*wstore.Tab](ctx)
activity.NumTabs, _ = wstore.DBGetCount[*waveobj.Tab](ctx)
err := telemetry.UpdateActivity(ctx, activity) // set at least one record into activity (don't use go routine wrap here)
if err != nil {
log.Printf("error updating startup activity: %v\n", err)
+69
View File
@@ -0,0 +1,69 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
"io/fs"
"os"
"path/filepath"
"github.com/spf13/cobra"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/wshrpc"
"github.com/wavetermdev/thenextwave/pkg/wshrpc/wshclient"
)
var editCmd = &cobra.Command{
Use: "edit",
Short: "edit a file",
Args: cobra.ExactArgs(1),
Run: editRun,
PreRunE: preRunSetupRpcClient,
}
func init() {
rootCmd.AddCommand(editCmd)
}
func editRun(cmd *cobra.Command, args []string) {
fileArg := args[0]
wshCmd := wshrpc.CommandCreateBlockData{
BlockDef: &waveobj.BlockDef{
Meta: map[string]any{
waveobj.MetaKey_View: "preview",
waveobj.MetaKey_File: fileArg,
},
},
}
if RpcContext.Conn != "" {
wshCmd.BlockDef.Meta[waveobj.MetaKey_Connection] = RpcContext.Conn
}
absFile, err := filepath.Abs(fileArg)
if err != nil {
WriteStderr("[error] getting absolute path: %v\n", err)
return
}
_, err = os.Stat(absFile)
if err == fs.ErrNotExist {
WriteStderr("[error] file does not exist: %q\n", absFile)
return
}
if err != nil {
WriteStderr("[error] getting file info: %v\n", err)
return
}
blockRef, err := wshclient.CreateBlockCommand(RpcClient, wshCmd, &wshrpc.RpcOpts{Timeout: 2000})
if err != nil {
WriteStderr("[error] running view command: %v\r\n", err)
return
}
doneCh := make(chan bool)
RpcClient.EventListener.On("blockclose", func(event *wshrpc.WaveEvent) {
if event.HasScope(blockRef.String()) {
close(doneCh)
}
})
wshclient.EventSubCommand(RpcClient, wshrpc.SubscriptionRequest{Event: "blockclose", Scopes: []string{blockRef.String()}}, nil)
<-doneCh
}
+8
View File
@@ -9,6 +9,7 @@ import (
"log"
"os"
"regexp"
"runtime/debug"
"strconv"
"strings"
"time"
@@ -33,6 +34,7 @@ var (
var usingHtmlMode bool
var WrappedStdin io.Reader = os.Stdin
var RpcClient *wshutil.WshRpc
var RpcContext wshrpc.RpcContext
var UsingTermWshMode bool
func extraShutdownFn() {
@@ -78,6 +80,11 @@ func setupRpcClient(serverImpl wshutil.ServerImpl) error {
RpcClient, WrappedStdin = wshutil.SetupTerminalRpcClient(serverImpl)
return nil
}
rpcCtx, err := wshutil.ExtractUnverifiedRpcContext(jwtToken)
if err != nil {
return fmt.Errorf("error extracting rpc context from %s: %v", wshutil.WaveJwtTokenVarName, err)
}
RpcContext = *rpcCtx
sockName, err := wshutil.ExtractUnverifiedSocketName(jwtToken)
if err != nil {
return fmt.Errorf("error extracting socket name from %s: %v", wshutil.WaveJwtTokenVarName, err)
@@ -162,6 +169,7 @@ func Execute() {
r := recover()
if r != nil {
WriteStderr("[panic] %v\n", r)
debug.PrintStack()
wshutil.DoShutdown("", 1, true)
} else {
wshutil.DoShutdown("", 0, false)
+8 -5
View File
@@ -9,9 +9,9 @@ import (
"github.com/spf13/cobra"
"github.com/wavetermdev/thenextwave/pkg/wavebase"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/wshrpc"
"github.com/wavetermdev/thenextwave/pkg/wshrpc/wshclient"
"github.com/wavetermdev/thenextwave/pkg/wstore"
)
var termCmd = &cobra.Command{
@@ -46,14 +46,17 @@ func termRun(cmd *cobra.Command, args []string) {
return
}
createBlockData := wshrpc.CommandCreateBlockData{
BlockDef: &wstore.BlockDef{
BlockDef: &waveobj.BlockDef{
Meta: map[string]interface{}{
wstore.MetaKey_View: "term",
wstore.MetaKey_CmdCwd: cwd,
wstore.MetaKey_Controller: "shell",
waveobj.MetaKey_View: "term",
waveobj.MetaKey_CmdCwd: cwd,
waveobj.MetaKey_Controller: "shell",
},
},
}
if RpcContext.Conn != "" {
createBlockData.BlockDef.Meta[waveobj.MetaKey_Connection] = RpcContext.Conn
}
oref, err := wshclient.CreateBlockCommand(RpcClient, createBlockData, nil)
if err != nil {
WriteStderr("[error] creating new terminal block: %v\n", err)
+12 -8
View File
@@ -10,8 +10,8 @@ import (
"strings"
"github.com/spf13/cobra"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/wshrpc"
"github.com/wavetermdev/thenextwave/pkg/wstore"
)
var viewNewBlock bool
@@ -31,13 +31,14 @@ func init() {
func viewRun(cmd *cobra.Command, args []string) {
fileArg := args[0]
conn := RpcContext.Conn
var wshCmd *wshrpc.CommandCreateBlockData
if strings.HasPrefix(fileArg, "http://") || strings.HasPrefix(fileArg, "https://") {
wshCmd = &wshrpc.CommandCreateBlockData{
BlockDef: &wstore.BlockDef{
Meta: map[string]interface{}{
wstore.MetaKey_View: "web",
wstore.MetaKey_Url: fileArg,
BlockDef: &waveobj.BlockDef{
Meta: map[string]any{
waveobj.MetaKey_View: "web",
waveobj.MetaKey_Url: fileArg,
},
},
}
@@ -57,13 +58,16 @@ func viewRun(cmd *cobra.Command, args []string) {
return
}
wshCmd = &wshrpc.CommandCreateBlockData{
BlockDef: &wstore.BlockDef{
BlockDef: &waveobj.BlockDef{
Meta: map[string]interface{}{
wstore.MetaKey_View: "preview",
wstore.MetaKey_File: absFile,
waveobj.MetaKey_View: "preview",
waveobj.MetaKey_File: absFile,
},
},
}
if conn != "" {
wshCmd.BlockDef.Meta[waveobj.MetaKey_Connection] = conn
}
}
_, err := RpcClient.SendRpcRequest(wshrpc.Command_CreateBlock, wshCmd, &wshrpc.RpcOpts{Timeout: 2000})
if err != nil {
+1 -1
View File
@@ -13,7 +13,7 @@ class WshServerType {
}
// command "authenticate" [call]
AuthenticateCommand(data: string, opts?: RpcOpts): Promise<void> {
AuthenticateCommand(data: string, opts?: RpcOpts): Promise<CommandAuthenticateRtnData> {
return WOS.wshServerRpcHelper_call("authenticate", data, opts);
}
+23 -18
View File
@@ -22,7 +22,7 @@ declare global {
installonquit: boolean;
};
// wstore.Block
// waveobj.Block
type Block = WaveObj & {
blockdef: BlockDef;
runtimeopts?: RuntimeOpts;
@@ -36,7 +36,7 @@ declare global {
shellprocstatus?: string;
};
// wstore.BlockDef
// waveobj.BlockDef
type BlockDef = {
files?: {[key: string]: FileDef};
meta?: MetaType;
@@ -54,7 +54,7 @@ declare global {
inputdata64: string;
};
// wstore.Client
// waveobj.Client
type Client = WaveObj & {
windowids: string[];
tosagreed?: number;
@@ -67,6 +67,11 @@ declare global {
data: {[key: string]: any};
};
// wshrpc.CommandAuthenticateRtnData
type CommandAuthenticateRtnData = {
routeid: string;
};
// wshrpc.CommandBlockInputData
type CommandBlockInputData = {
blockid: string;
@@ -158,7 +163,7 @@ declare global {
count: number;
};
// wstore.FileDef
// waveobj.FileDef
type FileDef = {
filetype?: string;
path?: string;
@@ -194,13 +199,13 @@ declare global {
data64: string;
};
// wstore.LayoutState
// waveobj.LayoutState
type LayoutState = WaveObj & {
rootnode?: any;
magnifiednodeid?: string;
};
// wstore.MetaTSType
// waveobj.MetaTSType
type MetaType = {
view?: string;
controller?: string;
@@ -297,7 +302,7 @@ declare global {
prompt: OpenAIPromptMessageType[];
};
// wstore.Point
// waveobj.Point
type Point = {
x: number;
y: number;
@@ -325,7 +330,7 @@ declare global {
route?: string;
};
// wstore.RuntimeOpts
// waveobj.RuntimeOpts
type RuntimeOpts = {
termsize?: TermSize;
winsize?: WinSize;
@@ -355,20 +360,20 @@ declare global {
presets?: {[key: string]: MetaType};
};
// wstore.StickerClickOptsType
// waveobj.StickerClickOptsType
type StickerClickOptsType = {
sendinput?: string;
createblock?: BlockDef;
};
// wstore.StickerDisplayOptsType
// waveobj.StickerDisplayOptsType
type StickerDisplayOptsType = {
icon: string;
imgsrc: string;
svgblob?: string;
};
// wstore.StickerType
// waveobj.StickerType
type StickerType = {
stickertype: string;
style: {[key: string]: any};
@@ -383,7 +388,7 @@ declare global {
allscopes?: boolean;
};
// wstore.Tab
// waveobj.Tab
type Tab = WaveObj & {
name: string;
layoutstate: string;
@@ -395,7 +400,7 @@ declare global {
enabled: boolean;
};
// wstore.TermSize
// waveobj.TermSize
type TermSize = {
rows: number;
cols: number;
@@ -440,7 +445,7 @@ declare global {
values: {[key: string]: number};
};
// wstore.UIContext
// waveobj.UIContext
type UIContext = {
windowid: string;
activetabid: string;
@@ -558,7 +563,7 @@ declare global {
meta: MetaType;
};
// wstore.WaveObjUpdate
// waveobj.WaveObjUpdate
type WaveObjUpdate = {
updatetype: string;
otype: string;
@@ -566,7 +571,7 @@ declare global {
obj?: WaveObj;
};
// wstore.Window
// waveobj.Window
type WaveWindow = WaveObj & {
workspaceid: string;
activetabid: string;
@@ -607,7 +612,7 @@ declare global {
blockdef: BlockDef;
};
// wstore.WinSize
// waveobj.WinSize
type WinSize = {
width: number;
height: number;
@@ -622,7 +627,7 @@ declare global {
reducedmotion: boolean;
};
// wstore.Workspace
// waveobj.Workspace
type Workspace = WaveObj & {
name: string;
tabids: string[];
+29 -29
View File
@@ -54,9 +54,9 @@ var globalLock = &sync.Mutex{}
var blockControllerMap = make(map[string]*BlockController)
type BlockInputUnion struct {
InputData []byte `json:"inputdata,omitempty"`
SigName string `json:"signame,omitempty"`
TermSize *wstore.TermSize `json:"termsize,omitempty"`
InputData []byte `json:"inputdata,omitempty"`
SigName string `json:"signame,omitempty"`
TermSize *waveobj.TermSize `json:"termsize,omitempty"`
}
type BlockController struct {
@@ -64,7 +64,7 @@ type BlockController struct {
ControllerType string
TabId string
BlockId string
BlockDef *wstore.BlockDef
BlockDef *waveobj.BlockDef
Status string
CreatedHtmlFile bool
ShellProc *shellexec.ShellProc
@@ -115,7 +115,7 @@ func (bc *BlockController) getShellProc() *shellexec.ShellProc {
}
type RunShellOpts struct {
TermSize wstore.TermSize `json:"termsize,omitempty"`
TermSize waveobj.TermSize `json:"termsize,omitempty"`
}
func (bc *BlockController) UpdateControllerAndSendUpdate(updateFn func() bool) {
@@ -127,7 +127,7 @@ func (bc *BlockController) UpdateControllerAndSendUpdate(updateFn func() bool) {
log.Printf("sending blockcontroller update %#v\n", bc.GetRuntimeStatus())
go eventbus.SendEvent(eventbus.WSEventType{
EventType: eventbus.WSEvent_BlockControllerStatus,
ORef: waveobj.MakeORef(wstore.OType_Block, bc.BlockId).String(),
ORef: waveobj.MakeORef(waveobj.OType_Block, bc.BlockId).String(),
Data: bc.GetRuntimeStatus(),
})
}
@@ -145,7 +145,7 @@ func HandleTruncateBlockFile(blockId string, blockFile string) error {
}
eventbus.SendEvent(eventbus.WSEventType{
EventType: eventbus.WSEvent_BlockFile,
ORef: waveobj.MakeORef(wstore.OType_Block, blockId).String(),
ORef: waveobj.MakeORef(waveobj.OType_Block, blockId).String(),
Data: &eventbus.WSFileEventData{
ZoneId: blockId,
FileName: blockFile,
@@ -165,7 +165,7 @@ func HandleAppendBlockFile(blockId string, blockFile string, data []byte) error
}
eventbus.SendEvent(eventbus.WSEventType{
EventType: eventbus.WSEvent_BlockFile,
ORef: waveobj.MakeORef(wstore.OType_Block, blockId).String(),
ORef: waveobj.MakeORef(waveobj.OType_Block, blockId).String(),
Data: &eventbus.WSFileEventData{
ZoneId: blockId,
FileName: blockFile,
@@ -180,9 +180,9 @@ func (bc *BlockController) resetTerminalState() {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
var shouldTruncate bool
blockData, getBlockDataErr := wstore.DBMustGet[*wstore.Block](ctx, bc.BlockId)
blockData, getBlockDataErr := wstore.DBMustGet[*waveobj.Block](ctx, bc.BlockId)
if getBlockDataErr == nil {
shouldTruncate = blockData.Meta.GetBool(wstore.MetaKey_CmdClearOnRestart, false)
shouldTruncate = blockData.Meta.GetBool(waveobj.MetaKey_CmdClearOnRestart, false)
}
if shouldTruncate {
err := HandleTruncateBlockFile(bc.BlockId, BlockFile_Term)
@@ -231,7 +231,7 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts, blockMeta waveobj
if shellProcErr != nil {
return shellProcErr
}
remoteName := blockMeta.GetString(wstore.MetaKey_Connection, "")
remoteName := blockMeta.GetString(waveobj.MetaKey_Connection, "")
var cmdStr string
cmdOpts := shellexec.CommandOptsType{
Env: make(map[string]string),
@@ -239,22 +239,22 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts, blockMeta waveobj
if bc.ControllerType == BlockController_Shell {
cmdOpts.Interactive = true
cmdOpts.Login = true
cmdOpts.Cwd = blockMeta.GetString(wstore.MetaKey_CmdCwd, "")
cmdOpts.Cwd = blockMeta.GetString(waveobj.MetaKey_CmdCwd, "")
if cmdOpts.Cwd != "" {
cmdOpts.Cwd = wavebase.ExpandHomeDir(cmdOpts.Cwd)
}
} else if bc.ControllerType == BlockController_Cmd {
cmdStr = blockMeta.GetString(wstore.MetaKey_Cmd, "")
cmdStr = blockMeta.GetString(waveobj.MetaKey_Cmd, "")
if cmdStr == "" {
return fmt.Errorf("missing cmd in block meta")
}
cmdOpts.Cwd = blockMeta.GetString(wstore.MetaKey_CmdCwd, "")
cmdOpts.Cwd = blockMeta.GetString(waveobj.MetaKey_CmdCwd, "")
if cmdOpts.Cwd != "" {
cmdOpts.Cwd = wavebase.ExpandHomeDir(cmdOpts.Cwd)
}
cmdOpts.Interactive = blockMeta.GetBool(wstore.MetaKey_CmdInteractive, false)
cmdOpts.Login = blockMeta.GetBool(wstore.MetaKey_CmdLogin, false)
cmdEnv := blockMeta.GetMap(wstore.MetaKey_CmdEnv)
cmdOpts.Interactive = blockMeta.GetBool(waveobj.MetaKey_CmdInteractive, false)
cmdOpts.Login = blockMeta.GetBool(waveobj.MetaKey_CmdLogin, false)
cmdEnv := blockMeta.GetMap(waveobj.MetaKey_CmdEnv)
for k, v := range cmdEnv {
if v == nil {
continue
@@ -282,8 +282,8 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts, blockMeta waveobj
if err != nil {
return err
}
if !blockMeta.GetBool(wstore.MetaKey_CmdNoWsh, false) {
jwtStr, err := wshutil.MakeClientJWTToken(wshrpc.RpcContext{TabId: bc.TabId, BlockId: bc.BlockId}, conn.SockName)
if !blockMeta.GetBool(waveobj.MetaKey_CmdNoWsh, false) {
jwtStr, err := wshutil.MakeClientJWTToken(wshrpc.RpcContext{TabId: bc.TabId, BlockId: bc.BlockId, Conn: conn.Opts.String()}, conn.SockName)
if err != nil {
return fmt.Errorf("error making jwt token: %w", err)
}
@@ -294,7 +294,7 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts, blockMeta waveobj
return err
}
} else {
if !blockMeta.GetBool(wstore.MetaKey_CmdNoWsh, false) {
if !blockMeta.GetBool(waveobj.MetaKey_CmdNoWsh, false) {
jwtStr, err := wshutil.MakeClientJWTToken(wshrpc.RpcContext{TabId: bc.TabId, BlockId: bc.BlockId}, wavebase.GetDomainSocketName())
if err != nil {
return fmt.Errorf("error making jwt token: %w", err)
@@ -404,18 +404,18 @@ func getBoolFromMeta(meta map[string]any, key string, def bool) bool {
return def
}
func getTermSize(bdata *wstore.Block) wstore.TermSize {
func getTermSize(bdata *waveobj.Block) waveobj.TermSize {
if bdata.RuntimeOpts != nil {
return bdata.RuntimeOpts.TermSize
} else {
return wstore.TermSize{
return waveobj.TermSize{
Rows: 25,
Cols: 80,
}
}
}
func (bc *BlockController) run(bdata *wstore.Block, blockMeta map[string]any) {
func (bc *BlockController) run(bdata *waveobj.Block, blockMeta map[string]any) {
defer func() {
bc.UpdateControllerAndSendUpdate(func() bool {
if bc.Status == Status_Running {
@@ -432,18 +432,18 @@ func (bc *BlockController) run(bdata *wstore.Block, blockMeta map[string]any) {
bc.Status = Status_Running
return true
})
controllerName := bdata.Meta.GetString(wstore.MetaKey_Controller, "")
controllerName := bdata.Meta.GetString(waveobj.MetaKey_Controller, "")
if controllerName != BlockController_Shell && controllerName != BlockController_Cmd {
log.Printf("unknown controller %q\n", controllerName)
return
}
if getBoolFromMeta(blockMeta, wstore.MetaKey_CmdClearOnStart, false) {
if getBoolFromMeta(blockMeta, waveobj.MetaKey_CmdClearOnStart, false) {
err := HandleTruncateBlockFile(bc.BlockId, BlockFile_Term)
if err != nil {
log.Printf("error truncating term blockfile: %v\n", err)
}
}
runOnStart := getBoolFromMeta(blockMeta, wstore.MetaKey_CmdRunOnStart, true)
runOnStart := getBoolFromMeta(blockMeta, waveobj.MetaKey_CmdRunOnStart, true)
if runOnStart {
go func() {
err := bc.DoRunShellCommand(&RunShellOpts{TermSize: getTermSize(bdata)}, bdata.Meta)
@@ -466,7 +466,7 @@ func (bc *BlockController) SendInput(inputUnion *BlockInputUnion) error {
func (bc *BlockController) RestartController() error {
// TODO: if shell command is already running
// we probably want to kill it off, wait, and then restart it
bdata, err := wstore.DBMustGet[*wstore.Block](context.Background(), bc.BlockId)
bdata, err := wstore.DBMustGet[*waveobj.Block](context.Background(), bc.BlockId)
if err != nil {
return fmt.Errorf("error getting block: %w", err)
}
@@ -479,11 +479,11 @@ func (bc *BlockController) RestartController() error {
func StartBlockController(ctx context.Context, tabId string, blockId string) error {
log.Printf("start blockcontroller %q\n", blockId)
blockData, err := wstore.DBMustGet[*wstore.Block](ctx, blockId)
blockData, err := wstore.DBMustGet[*waveobj.Block](ctx, blockId)
if err != nil {
return fmt.Errorf("error getting block: %w", err)
}
controllerName := blockData.Meta.GetString(wstore.MetaKey_Controller, "")
controllerName := blockData.Meta.GetString(waveobj.MetaKey_Controller, "")
if controllerName == "" {
// nothing to start
return nil
+2 -1
View File
@@ -83,7 +83,8 @@ func (conn *SSHConn) StartConnServer() error {
}
wshPath := remote.GetWshPath(conn.Client)
rpcCtx := wshrpc.RpcContext{
Conn: conn.Opts.String(),
ClientType: wshrpc.ClientType_ConnServer,
Conn: conn.Opts.String(),
}
jwtToken, err := wshutil.MakeClientJWTToken(rpcCtx, conn.SockName)
if err != nil {
+4 -3
View File
@@ -12,6 +12,7 @@ import (
"github.com/wavetermdev/thenextwave/pkg/blockcontroller"
"github.com/wavetermdev/thenextwave/pkg/filestore"
"github.com/wavetermdev/thenextwave/pkg/tsgen/tsgenmeta"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/wshrpc"
"github.com/wavetermdev/thenextwave/pkg/wstore"
)
@@ -41,7 +42,7 @@ func (bs *BlockService) GetControllerStatus(ctx context.Context, blockId string)
}
func (bs *BlockService) SaveTerminalState(ctx context.Context, blockId string, state string, stateType string, ptyOffset int64) error {
_, err := wstore.DBMustGet[*wstore.Block](ctx, blockId)
_, err := wstore.DBMustGet[*waveobj.Block](ctx, blockId)
if err != nil {
return err
}
@@ -62,11 +63,11 @@ func (bs *BlockService) SaveTerminalState(ctx context.Context, blockId string, s
}
func (bs *BlockService) SaveWaveAiData(ctx context.Context, blockId string, history []wshrpc.OpenAIPromptMessageType) error {
block, err := wstore.DBMustGet[*wstore.Block](ctx, blockId)
block, err := wstore.DBMustGet[*waveobj.Block](ctx, blockId)
if err != nil {
return err
}
viewName := block.Meta.GetString(wstore.MetaKey_View, "")
viewName := block.Meta.GetString(waveobj.MetaKey_View, "")
if viewName != "waveai" {
return fmt.Errorf("invalid view type: %s", viewName)
}
+41 -40
View File
@@ -12,6 +12,7 @@ import (
"github.com/wavetermdev/thenextwave/pkg/eventbus"
"github.com/wavetermdev/thenextwave/pkg/service/objectservice"
"github.com/wavetermdev/thenextwave/pkg/util/utilfn"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/wstore"
)
@@ -19,47 +20,47 @@ type ClientService struct{}
const DefaultTimeout = 2 * time.Second
func (cs *ClientService) GetClientData() (*wstore.Client, error) {
func (cs *ClientService) GetClientData() (*waveobj.Client, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
clientData, err := wstore.DBGetSingleton[*wstore.Client](ctx)
clientData, err := wstore.DBGetSingleton[*waveobj.Client](ctx)
if err != nil {
return nil, fmt.Errorf("error getting client data: %w", err)
}
return clientData, nil
}
func (cs *ClientService) GetWorkspace(workspaceId string) (*wstore.Workspace, error) {
func (cs *ClientService) GetWorkspace(workspaceId string) (*waveobj.Workspace, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
ws, err := wstore.DBGet[*wstore.Workspace](ctx, workspaceId)
ws, err := wstore.DBGet[*waveobj.Workspace](ctx, workspaceId)
if err != nil {
return nil, fmt.Errorf("error getting workspace: %w", err)
}
return ws, nil
}
func (cs *ClientService) GetTab(tabId string) (*wstore.Tab, error) {
func (cs *ClientService) GetTab(tabId string) (*waveobj.Tab, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
tab, err := wstore.DBGet[*wstore.Tab](ctx, tabId)
tab, err := wstore.DBGet[*waveobj.Tab](ctx, tabId)
if err != nil {
return nil, fmt.Errorf("error getting tab: %w", err)
}
return tab, nil
}
func (cs *ClientService) GetWindow(windowId string) (*wstore.Window, error) {
func (cs *ClientService) GetWindow(windowId string) (*waveobj.Window, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
window, err := wstore.DBGet[*wstore.Window](ctx, windowId)
window, err := wstore.DBGet[*waveobj.Window](ctx, windowId)
if err != nil {
return nil, fmt.Errorf("error getting window: %w", err)
}
return window, nil
}
func (cs *ClientService) MakeWindow(ctx context.Context) (*wstore.Window, error) {
func (cs *ClientService) MakeWindow(ctx context.Context) (*waveobj.Window, error) {
return wstore.CreateWindow(ctx, nil)
}
@@ -77,9 +78,9 @@ func (cs *ClientService) FocusWindow(ctx context.Context, windowId string) error
return wstore.DBUpdate(ctx, client)
}
func (cs *ClientService) AgreeTos(ctx context.Context) (wstore.UpdatesRtnType, error) {
ctx = wstore.ContextWithUpdates(ctx)
clientData, err := wstore.DBGetSingleton[*wstore.Client](ctx)
func (cs *ClientService) AgreeTos(ctx context.Context) (waveobj.UpdatesRtnType, error) {
ctx = waveobj.ContextWithUpdates(ctx)
clientData, err := wstore.DBGetSingleton[*waveobj.Client](ctx)
if err != nil {
return nil, fmt.Errorf("error getting client data: %w", err)
}
@@ -90,19 +91,19 @@ func (cs *ClientService) AgreeTos(ctx context.Context) (wstore.UpdatesRtnType, e
return nil, fmt.Errorf("error updating client data: %w", err)
}
cs.BootstrapStarterLayout(ctx)
return wstore.ContextGetUpdatesRtn(ctx), nil
return waveobj.ContextGetUpdatesRtn(ctx), nil
}
type PortableLayout []struct {
IndexArr []int
Size uint
BlockDef *wstore.BlockDef
BlockDef *waveobj.BlockDef
}
func (cs *ClientService) BootstrapStarterLayout(ctx context.Context) error {
ctx, cancelFn := context.WithTimeout(ctx, 2*time.Second)
defer cancelFn()
client, err := wstore.DBGetSingleton[*wstore.Client](ctx)
client, err := wstore.DBGetSingleton[*waveobj.Client](ctx)
if err != nil {
log.Printf("unable to find client: %v\n", err)
return fmt.Errorf("unable to find client: %w", err)
@@ -114,7 +115,7 @@ func (cs *ClientService) BootstrapStarterLayout(ctx context.Context) error {
windowId := client.WindowIds[0]
window, err := wstore.DBMustGet[*wstore.Window](ctx, windowId)
window, err := wstore.DBMustGet[*waveobj.Window](ctx, windowId)
if err != nil {
return fmt.Errorf("error getting window: %w", err)
}
@@ -122,43 +123,43 @@ func (cs *ClientService) BootstrapStarterLayout(ctx context.Context) error {
tabId := window.ActiveTabId
starterLayout := PortableLayout{
{IndexArr: []int{0}, BlockDef: &wstore.BlockDef{
Meta: wstore.MetaMapType{
wstore.MetaKey_View: "term",
wstore.MetaKey_Controller: "shell",
{IndexArr: []int{0}, BlockDef: &waveobj.BlockDef{
Meta: waveobj.MetaMapType{
waveobj.MetaKey_View: "term",
waveobj.MetaKey_Controller: "shell",
},
}},
{IndexArr: []int{1}, BlockDef: &wstore.BlockDef{
Meta: wstore.MetaMapType{
wstore.MetaKey_View: "cpuplot",
{IndexArr: []int{1}, BlockDef: &waveobj.BlockDef{
Meta: waveobj.MetaMapType{
waveobj.MetaKey_View: "cpuplot",
},
}},
{IndexArr: []int{1, 1}, BlockDef: &wstore.BlockDef{
Meta: wstore.MetaMapType{
wstore.MetaKey_View: "web",
wstore.MetaKey_Url: "https://github.com/wavetermdev/waveterm",
{IndexArr: []int{1, 1}, BlockDef: &waveobj.BlockDef{
Meta: waveobj.MetaMapType{
waveobj.MetaKey_View: "web",
waveobj.MetaKey_Url: "https://github.com/wavetermdev/waveterm",
},
}},
{IndexArr: []int{1, 2}, BlockDef: &wstore.BlockDef{
Meta: wstore.MetaMapType{
wstore.MetaKey_View: "preview",
wstore.MetaKey_File: "~",
{IndexArr: []int{1, 2}, BlockDef: &waveobj.BlockDef{
Meta: waveobj.MetaMapType{
waveobj.MetaKey_View: "preview",
waveobj.MetaKey_File: "~",
},
}},
{IndexArr: []int{2}, BlockDef: &wstore.BlockDef{
Meta: wstore.MetaMapType{
wstore.MetaKey_View: "help",
{IndexArr: []int{2}, BlockDef: &waveobj.BlockDef{
Meta: waveobj.MetaMapType{
waveobj.MetaKey_View: "help",
},
}},
{IndexArr: []int{2, 1}, BlockDef: &wstore.BlockDef{
Meta: wstore.MetaMapType{
wstore.MetaKey_View: "waveai",
{IndexArr: []int{2, 1}, BlockDef: &waveobj.BlockDef{
Meta: waveobj.MetaMapType{
waveobj.MetaKey_View: "waveai",
},
}},
// {IndexArr: []int{2, 2}, BlockDef: &wstore.BlockDef{
// Meta: wstore.MetaMapType{
// wstore.MetaKey_View: "web",
// wstore.MetaKey_Url: "https://www.youtube.com/embed/cKqsw_sAsU8",
// waveobj.MetaKey_View: "web",
// waveobj.MetaKey_Url: "https://www.youtube.com/embed/cKqsw_sAsU8",
// },
// }},
}
@@ -168,7 +169,7 @@ func (cs *ClientService) BootstrapStarterLayout(ctx context.Context) error {
for i := 0; i < len(starterLayout); i++ {
layoutAction := starterLayout[i]
blockData, err := objsvc.CreateBlock_NoUI(ctx, tabId, layoutAction.BlockDef, &wstore.RuntimeOpts{})
blockData, err := objsvc.CreateBlock_NoUI(ctx, tabId, layoutAction.BlockDef, &waveobj.RuntimeOpts{})
if err != nil {
return fmt.Errorf("unable to create block for starter layout: %w", err)
+32 -32
View File
@@ -13,6 +13,7 @@ import (
"github.com/wavetermdev/thenextwave/pkg/blockcontroller"
"github.com/wavetermdev/thenextwave/pkg/tsgen/tsgenmeta"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/wcore"
"github.com/wavetermdev/thenextwave/pkg/wstore"
)
@@ -78,11 +79,11 @@ func (svc *ObjectService) AddTabToWorkspace_Meta() tsgenmeta.MethodMeta {
}
}
func (svc *ObjectService) AddTabToWorkspace(uiContext wstore.UIContext, tabName string, activateTab bool) (string, wstore.UpdatesRtnType, error) {
func (svc *ObjectService) AddTabToWorkspace(uiContext waveobj.UIContext, tabName string, activateTab bool) (string, waveobj.UpdatesRtnType, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
ctx = wstore.ContextWithUpdates(ctx)
windowData, err := wstore.DBMustGet[*wstore.Window](ctx, uiContext.WindowId)
ctx = waveobj.ContextWithUpdates(ctx)
windowData, err := wstore.DBMustGet[*waveobj.Window](ctx, uiContext.WindowId)
if err != nil {
return "", nil, fmt.Errorf("error getting window: %w", err)
}
@@ -96,7 +97,7 @@ func (svc *ObjectService) AddTabToWorkspace(uiContext wstore.UIContext, tabName
return "", nil, fmt.Errorf("error setting active tab: %w", err)
}
}
return tab.OID, wstore.ContextGetUpdatesRtn(ctx), nil
return tab.OID, waveobj.ContextGetUpdatesRtn(ctx), nil
}
func (svc *ObjectService) UpdateWorkspaceTabIds_Meta() tsgenmeta.MethodMeta {
@@ -105,15 +106,15 @@ func (svc *ObjectService) UpdateWorkspaceTabIds_Meta() tsgenmeta.MethodMeta {
}
}
func (svc *ObjectService) UpdateWorkspaceTabIds(uiContext wstore.UIContext, workspaceId string, tabIds []string) (wstore.UpdatesRtnType, error) {
func (svc *ObjectService) UpdateWorkspaceTabIds(uiContext waveobj.UIContext, workspaceId string, tabIds []string) (waveobj.UpdatesRtnType, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
ctx = wstore.ContextWithUpdates(ctx)
ctx = waveobj.ContextWithUpdates(ctx)
err := wstore.UpdateWorkspaceTabIds(ctx, workspaceId, tabIds)
if err != nil {
return nil, fmt.Errorf("error updating workspace tab ids: %w", err)
}
return wstore.ContextGetUpdatesRtn(ctx), nil
return waveobj.ContextGetUpdatesRtn(ctx), nil
}
func (svc *ObjectService) SetActiveTab_Meta() tsgenmeta.MethodMeta {
@@ -122,16 +123,16 @@ func (svc *ObjectService) SetActiveTab_Meta() tsgenmeta.MethodMeta {
}
}
func (svc *ObjectService) SetActiveTab(uiContext wstore.UIContext, tabId string) (wstore.UpdatesRtnType, error) {
func (svc *ObjectService) SetActiveTab(uiContext waveobj.UIContext, tabId string) (waveobj.UpdatesRtnType, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
ctx = wstore.ContextWithUpdates(ctx)
ctx = waveobj.ContextWithUpdates(ctx)
err := wstore.SetActiveTab(ctx, uiContext.WindowId, tabId)
if err != nil {
return nil, fmt.Errorf("error setting active tab: %w", err)
}
// check all blocks in tab and start controllers (if necessary)
tab, err := wstore.DBMustGet[*wstore.Tab](ctx, tabId)
tab, err := wstore.DBMustGet[*waveobj.Tab](ctx, tabId)
if err != nil {
return nil, fmt.Errorf("error getting tab: %w", err)
}
@@ -148,9 +149,9 @@ func (svc *ObjectService) SetActiveTab(uiContext wstore.UIContext, tabId string)
if err != nil {
return nil, fmt.Errorf("error getting tab blocks: %w", err)
}
updates := wstore.ContextGetUpdatesRtn(ctx)
updates = append(updates, wstore.MakeUpdate(tab))
updates = append(updates, wstore.MakeUpdates(blocks)...)
updates := waveobj.ContextGetUpdatesRtn(ctx)
updates = append(updates, waveobj.MakeUpdate(tab))
updates = append(updates, waveobj.MakeUpdates(blocks)...)
return updates, nil
}
@@ -160,15 +161,15 @@ func (svc *ObjectService) UpdateTabName_Meta() tsgenmeta.MethodMeta {
}
}
func (svc *ObjectService) UpdateTabName(uiContext wstore.UIContext, tabId, name string) (wstore.UpdatesRtnType, error) {
func (svc *ObjectService) UpdateTabName(uiContext waveobj.UIContext, tabId, name string) (waveobj.UpdatesRtnType, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
ctx = wstore.ContextWithUpdates(ctx)
ctx = waveobj.ContextWithUpdates(ctx)
err := wstore.UpdateTabName(ctx, tabId, name)
if err != nil {
return nil, fmt.Errorf("error updating tab name: %w", err)
}
return wstore.ContextGetUpdatesRtn(ctx), nil
return waveobj.ContextGetUpdatesRtn(ctx), nil
}
func (svc *ObjectService) CreateBlock_Meta() tsgenmeta.MethodMeta {
@@ -178,12 +179,12 @@ func (svc *ObjectService) CreateBlock_Meta() tsgenmeta.MethodMeta {
}
}
func (svc *ObjectService) CreateBlock_NoUI(ctx context.Context, tabId string, blockDef *wstore.BlockDef, rtOpts *wstore.RuntimeOpts) (*wstore.Block, error) {
func (svc *ObjectService) CreateBlock_NoUI(ctx context.Context, tabId string, blockDef *waveobj.BlockDef, rtOpts *waveobj.RuntimeOpts) (*waveobj.Block, error) {
blockData, err := wstore.CreateBlock(ctx, tabId, blockDef, rtOpts)
if err != nil {
return nil, fmt.Errorf("error creating block: %w", err)
}
controllerName := blockData.Meta.GetString(wstore.MetaKey_Controller, "")
controllerName := blockData.Meta.GetString(waveobj.MetaKey_Controller, "")
if controllerName != "" {
err = blockcontroller.StartBlockController(ctx, tabId, blockData.OID)
if err != nil {
@@ -194,20 +195,20 @@ func (svc *ObjectService) CreateBlock_NoUI(ctx context.Context, tabId string, bl
return blockData, nil
}
func (svc *ObjectService) CreateBlock(uiContext wstore.UIContext, blockDef *wstore.BlockDef, rtOpts *wstore.RuntimeOpts) (string, wstore.UpdatesRtnType, error) {
func (svc *ObjectService) CreateBlock(uiContext waveobj.UIContext, blockDef *waveobj.BlockDef, rtOpts *waveobj.RuntimeOpts) (string, waveobj.UpdatesRtnType, error) {
if uiContext.ActiveTabId == "" {
return "", nil, fmt.Errorf("no active tab")
}
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
ctx = wstore.ContextWithUpdates(ctx)
ctx = waveobj.ContextWithUpdates(ctx)
blockData, err := svc.CreateBlock_NoUI(ctx, uiContext.ActiveTabId, blockDef, rtOpts)
if err != nil {
return "", nil, err
}
return blockData.OID, wstore.ContextGetUpdatesRtn(ctx), nil
return blockData.OID, waveobj.ContextGetUpdatesRtn(ctx), nil
}
func (svc *ObjectService) DeleteBlock_Meta() tsgenmeta.MethodMeta {
@@ -216,16 +217,15 @@ func (svc *ObjectService) DeleteBlock_Meta() tsgenmeta.MethodMeta {
}
}
func (svc *ObjectService) DeleteBlock(uiContext wstore.UIContext, blockId string) (wstore.UpdatesRtnType, error) {
func (svc *ObjectService) DeleteBlock(uiContext waveobj.UIContext, blockId string) (waveobj.UpdatesRtnType, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
ctx = wstore.ContextWithUpdates(ctx)
err := wstore.DeleteBlock(ctx, uiContext.ActiveTabId, blockId)
ctx = waveobj.ContextWithUpdates(ctx)
err := wcore.DeleteBlock(ctx, uiContext.ActiveTabId, blockId)
if err != nil {
return nil, fmt.Errorf("error deleting block: %w", err)
}
blockcontroller.StopBlockController(blockId)
return wstore.ContextGetUpdatesRtn(ctx), nil
return waveobj.ContextGetUpdatesRtn(ctx), nil
}
func (svc *ObjectService) CloseTab_Meta() tsgenmeta.MethodMeta {
@@ -240,10 +240,10 @@ func (svc *ObjectService) UpdateObjectMeta_Meta() tsgenmeta.MethodMeta {
}
}
func (svc *ObjectService) UpdateObjectMeta(uiContext wstore.UIContext, orefStr string, meta wstore.MetaMapType) (wstore.UpdatesRtnType, error) {
func (svc *ObjectService) UpdateObjectMeta(uiContext waveobj.UIContext, orefStr string, meta waveobj.MetaMapType) (waveobj.UpdatesRtnType, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
ctx = wstore.ContextWithUpdates(ctx)
ctx = waveobj.ContextWithUpdates(ctx)
oref, err := parseORef(orefStr)
if err != nil {
return nil, fmt.Errorf("error parsing object reference: %w", err)
@@ -252,7 +252,7 @@ func (svc *ObjectService) UpdateObjectMeta(uiContext wstore.UIContext, orefStr s
if err != nil {
return nil, fmt.Errorf("error updateing %q meta: %w", orefStr, err)
}
return wstore.ContextGetUpdatesRtn(ctx), nil
return waveobj.ContextGetUpdatesRtn(ctx), nil
}
func (svc *ObjectService) UpdateObject_Meta() tsgenmeta.MethodMeta {
@@ -261,10 +261,10 @@ func (svc *ObjectService) UpdateObject_Meta() tsgenmeta.MethodMeta {
}
}
func (svc *ObjectService) UpdateObject(uiContext wstore.UIContext, waveObj waveobj.WaveObj, returnUpdates bool) (wstore.UpdatesRtnType, error) {
func (svc *ObjectService) UpdateObject(uiContext waveobj.UIContext, waveObj waveobj.WaveObj, returnUpdates bool) (waveobj.UpdatesRtnType, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
ctx = wstore.ContextWithUpdates(ctx)
ctx = waveobj.ContextWithUpdates(ctx)
if waveObj == nil {
return nil, fmt.Errorf("update wavobj is nil")
}
@@ -281,7 +281,7 @@ func (svc *ObjectService) UpdateObject(uiContext wstore.UIContext, waveObj waveo
return nil, fmt.Errorf("error updating object: %w", err)
}
if returnUpdates {
return wstore.ContextGetUpdatesRtn(ctx), nil
return waveobj.ContextGetUpdatesRtn(ctx), nil
}
return nil, nil
}
+12 -13
View File
@@ -19,7 +19,6 @@ import (
"github.com/wavetermdev/thenextwave/pkg/util/utilfn"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/web/webcmd"
"github.com/wavetermdev/thenextwave/pkg/wstore"
)
var ServiceMap = map[string]any{
@@ -33,28 +32,28 @@ var ServiceMap = map[string]any{
var contextRType = reflect.TypeOf((*context.Context)(nil)).Elem()
var errorRType = reflect.TypeOf((*error)(nil)).Elem()
var updatesRType = reflect.TypeOf(([]wstore.WaveObjUpdate{}))
var updatesRType = reflect.TypeOf(([]waveobj.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(tsgenmeta.MethodMeta{})
var waveObjUpdateRType = reflect.TypeOf(wstore.WaveObjUpdate{})
var uiContextRType = reflect.TypeOf((*wstore.UIContext)(nil)).Elem()
var waveObjUpdateRType = reflect.TypeOf(waveobj.WaveObjUpdate{})
var uiContextRType = reflect.TypeOf((*waveobj.UIContext)(nil)).Elem()
var wsCommandRType = reflect.TypeOf((*webcmd.WSCommandType)(nil)).Elem()
var orefRType = reflect.TypeOf((*waveobj.ORef)(nil)).Elem()
type WebCallType struct {
Service string `json:"service"`
Method string `json:"method"`
UIContext *wstore.UIContext `json:"uicontext,omitempty"`
Args []any `json:"args"`
Service string `json:"service"`
Method string `json:"method"`
UIContext *waveobj.UIContext `json:"uicontext,omitempty"`
Args []any `json:"args"`
}
type WebReturnType struct {
Success bool `json:"success,omitempty"`
Error string `json:"error,omitempty"`
Data any `json:"data,omitempty"`
Updates []wstore.WaveObjUpdate `json:"updates,omitempty"`
Success bool `json:"success,omitempty"`
Error string `json:"error,omitempty"`
Data any `json:"data,omitempty"`
Updates []waveobj.WaveObjUpdate `json:"updates,omitempty"`
}
func convertNumber(argType reflect.Type, jsonArg float64) (any, error) {
@@ -289,7 +288,7 @@ func convertReturnValues(rtnVals []reflect.Value) *WebReturnType {
}
if valType == updatesRType {
// has a special MarshalJSON method
rtn.Updates = val.Interface().([]wstore.WaveObjUpdate)
rtn.Updates = val.Interface().([]waveobj.WaveObjUpdate)
continue
}
if isSpecialWaveArgType(valType) {
+24 -22
View File
@@ -13,6 +13,8 @@ import (
"github.com/wavetermdev/thenextwave/pkg/eventbus"
"github.com/wavetermdev/thenextwave/pkg/tsgen/tsgenmeta"
"github.com/wavetermdev/thenextwave/pkg/util/utilfn"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/wcore"
"github.com/wavetermdev/thenextwave/pkg/wstore"
)
@@ -20,12 +22,12 @@ const DefaultTimeout = 2 * time.Second
type WindowService struct{}
func (ws *WindowService) SetWindowPosAndSize(ctx context.Context, windowId string, pos *wstore.Point, size *wstore.WinSize) (wstore.UpdatesRtnType, error) {
func (ws *WindowService) SetWindowPosAndSize(ctx context.Context, windowId string, pos *waveobj.Point, size *waveobj.WinSize) (waveobj.UpdatesRtnType, error) {
if pos == nil && size == nil {
return nil, nil
}
ctx = wstore.ContextWithUpdates(ctx)
win, err := wstore.DBMustGet[*wstore.Window](ctx, windowId)
ctx = waveobj.ContextWithUpdates(ctx)
win, err := wstore.DBMustGet[*waveobj.Window](ctx, windowId)
if err != nil {
return nil, err
}
@@ -39,20 +41,20 @@ func (ws *WindowService) SetWindowPosAndSize(ctx context.Context, windowId strin
if err != nil {
return nil, err
}
return wstore.ContextGetUpdatesRtn(ctx), nil
return waveobj.ContextGetUpdatesRtn(ctx), nil
}
func (svc *WindowService) CloseTab(ctx context.Context, uiContext wstore.UIContext, tabId string) (wstore.UpdatesRtnType, error) {
ctx = wstore.ContextWithUpdates(ctx)
window, err := wstore.DBMustGet[*wstore.Window](ctx, uiContext.WindowId)
func (svc *WindowService) CloseTab(ctx context.Context, uiContext waveobj.UIContext, tabId string) (waveobj.UpdatesRtnType, error) {
ctx = waveobj.ContextWithUpdates(ctx)
window, err := wstore.DBMustGet[*waveobj.Window](ctx, uiContext.WindowId)
if err != nil {
return nil, fmt.Errorf("error getting window: %w", err)
}
tab, err := wstore.DBMustGet[*wstore.Tab](ctx, tabId)
tab, err := wstore.DBMustGet[*waveobj.Tab](ctx, tabId)
if err != nil {
return nil, fmt.Errorf("error getting tab: %w", err)
}
ws, err := wstore.DBMustGet[*wstore.Workspace](ctx, window.WorkspaceId)
ws, err := wstore.DBMustGet[*waveobj.Workspace](ctx, window.WorkspaceId)
if err != nil {
return nil, fmt.Errorf("error getting workspace: %w", err)
}
@@ -66,7 +68,7 @@ func (svc *WindowService) CloseTab(ctx context.Context, uiContext wstore.UIConte
for _, blockId := range tab.BlockIds {
blockcontroller.StopBlockController(blockId)
}
if err := wstore.DeleteTab(ctx, window.WorkspaceId, tabId); err != nil {
if err := wcore.DeleteTab(ctx, window.WorkspaceId, tabId); err != nil {
return nil, fmt.Errorf("error closing tab: %w", err)
}
if window.ActiveTabId == tabId && tabIndex != -1 {
@@ -85,7 +87,7 @@ func (svc *WindowService) CloseTab(ctx context.Context, uiContext wstore.UIConte
}
}
}
return wstore.ContextGetUpdatesRtn(ctx), nil
return waveobj.ContextGetUpdatesRtn(ctx), nil
}
func (svc *WindowService) MoveBlockToNewWindow_Meta() tsgenmeta.MethodMeta {
@@ -95,14 +97,14 @@ func (svc *WindowService) MoveBlockToNewWindow_Meta() tsgenmeta.MethodMeta {
}
}
func (svc *WindowService) MoveBlockToNewWindow(ctx context.Context, currentTabId string, blockId string) (wstore.UpdatesRtnType, error) {
func (svc *WindowService) MoveBlockToNewWindow(ctx context.Context, currentTabId string, blockId string) (waveobj.UpdatesRtnType, error) {
log.Printf("MoveBlockToNewWindow(%s, %s)", currentTabId, blockId)
ctx = wstore.ContextWithUpdates(ctx)
ctx = waveobj.ContextWithUpdates(ctx)
curWindowId, err := wstore.DBFindWindowForTabId(ctx, currentTabId)
if err != nil {
return nil, fmt.Errorf("error finding window for current-tab: %w", err)
}
tab, err := wstore.DBMustGet[*wstore.Tab](ctx, currentTabId)
tab, err := wstore.DBMustGet[*waveobj.Tab](ctx, currentTabId)
if err != nil {
return nil, fmt.Errorf("error getting tab: %w", err)
}
@@ -149,35 +151,35 @@ func (svc *WindowService) MoveBlockToNewWindow(ctx context.Context, currentTabId
BlockId: blockId,
},
})
return wstore.ContextGetUpdatesRtn(ctx), nil
return waveobj.ContextGetUpdatesRtn(ctx), nil
}
func (svc *WindowService) CloseWindow(ctx context.Context, windowId string) error {
ctx = wstore.ContextWithUpdates(ctx)
window, err := wstore.DBMustGet[*wstore.Window](ctx, windowId)
ctx = waveobj.ContextWithUpdates(ctx)
window, err := wstore.DBMustGet[*waveobj.Window](ctx, windowId)
if err != nil {
return fmt.Errorf("error getting window: %w", err)
}
workspace, err := wstore.DBMustGet[*wstore.Workspace](ctx, window.WorkspaceId)
workspace, err := wstore.DBMustGet[*waveobj.Workspace](ctx, window.WorkspaceId)
if err != nil {
return fmt.Errorf("error getting workspace: %w", err)
}
for _, tabId := range workspace.TabIds {
uiContext := wstore.UIContext{WindowId: windowId}
uiContext := waveobj.UIContext{WindowId: windowId}
_, err := svc.CloseTab(ctx, uiContext, tabId)
if err != nil {
return fmt.Errorf("error closing tab: %w", err)
}
}
err = wstore.DBDelete(ctx, wstore.OType_Workspace, window.WorkspaceId)
err = wstore.DBDelete(ctx, waveobj.OType_Workspace, window.WorkspaceId)
if err != nil {
return fmt.Errorf("error deleting workspace: %w", err)
}
err = wstore.DBDelete(ctx, wstore.OType_Window, windowId)
err = wstore.DBDelete(ctx, waveobj.OType_Window, windowId)
if err != nil {
return fmt.Errorf("error deleting window: %w", err)
}
client, err := wstore.DBGetSingleton[*wstore.Client](ctx)
client, err := wstore.DBGetSingleton[*waveobj.Client](ctx)
if err != nil {
return fmt.Errorf("error getting client: %w", err)
}
+4 -4
View File
@@ -22,8 +22,8 @@ import (
"github.com/wavetermdev/thenextwave/pkg/remote"
"github.com/wavetermdev/thenextwave/pkg/util/shellutil"
"github.com/wavetermdev/thenextwave/pkg/wavebase"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/wshutil"
"github.com/wavetermdev/thenextwave/pkg/wstore"
"golang.org/x/crypto/ssh"
)
@@ -150,7 +150,7 @@ func (pp *PipePty) WriteString(s string) (n int, err error) {
return pp.Write([]byte(s))
}
func StartRemoteShellProc(termSize wstore.TermSize, cmdStr string, cmdOpts CommandOptsType, client *ssh.Client) (*ShellProc, error) {
func StartRemoteShellProc(termSize waveobj.TermSize, cmdStr string, cmdOpts CommandOptsType, client *ssh.Client) (*ShellProc, error) {
shellPath, err := remote.DetectShell(client)
if err != nil {
return nil, err
@@ -266,7 +266,7 @@ func isBashShell(shellPath string) bool {
return strings.Contains(shellBase, "bash")
}
func StartShellProc(termSize wstore.TermSize, cmdStr string, cmdOpts CommandOptsType) (*ShellProc, error) {
func StartShellProc(termSize waveobj.TermSize, cmdStr string, cmdOpts CommandOptsType) (*ShellProc, error) {
shellutil.InitCustomShellStartupFiles()
var ecmd *exec.Cmd
var shellOpts []string
@@ -328,7 +328,7 @@ func StartShellProc(termSize wstore.TermSize, cmdStr string, cmdOpts CommandOpts
return &ShellProc{Cmd: CmdWrap{ecmd, cmdPty}, CloseOnce: &sync.Once{}, DoneCh: make(chan any)}, nil
}
func RunSimpleCmdInPty(ecmd *exec.Cmd, termSize wstore.TermSize) ([]byte, error) {
func RunSimpleCmdInPty(ecmd *exec.Cmd, termSize waveobj.TermSize) ([]byte, error) {
ecmd.Env = os.Environ()
shellutil.UpdateCmdEnv(ecmd, shellutil.WaveshellLocalEnvVars(shellutil.DefaultTermType))
if termSize.Rows == 0 || termSize.Cols == 0 {
+6 -7
View File
@@ -21,7 +21,6 @@ import (
"github.com/wavetermdev/thenextwave/pkg/web/webcmd"
"github.com/wavetermdev/thenextwave/pkg/wshrpc"
"github.com/wavetermdev/thenextwave/pkg/wshutil"
"github.com/wavetermdev/thenextwave/pkg/wstore"
)
// add extra types to generate here
@@ -31,7 +30,7 @@ var ExtraTypes = []any{
map[string]any{},
service.WebCallType{},
service.WebReturnType{},
wstore.UIContext{},
waveobj.UIContext{},
eventbus.WSEventType{},
eventbus.WSFileEventData{},
eventbus.WSLayoutActionData{},
@@ -45,7 +44,7 @@ var ExtraTypes = []any{
vdom.Elem{},
vdom.VDomFuncType{},
vdom.VDomRefType{},
wstore.MetaTSType{},
waveobj.MetaTSType{},
}
// add extra type unions to generate here
@@ -56,10 +55,10 @@ var TypeUnions = []tsgenmeta.TypeUnionMeta{
var contextRType = reflect.TypeOf((*context.Context)(nil)).Elem()
var errorRType = reflect.TypeOf((*error)(nil)).Elem()
var anyRType = reflect.TypeOf((*interface{})(nil)).Elem()
var metaRType = reflect.TypeOf((*wstore.MetaMapType)(nil)).Elem()
var uiContextRType = reflect.TypeOf((*wstore.UIContext)(nil)).Elem()
var metaRType = reflect.TypeOf((*waveobj.MetaMapType)(nil)).Elem()
var uiContextRType = reflect.TypeOf((*waveobj.UIContext)(nil)).Elem()
var waveObjRType = reflect.TypeOf((*waveobj.WaveObj)(nil)).Elem()
var updatesRtnRType = reflect.TypeOf(wstore.UpdatesRtnType{})
var updatesRtnRType = reflect.TypeOf(waveobj.UpdatesRtnType{})
var orefRType = reflect.TypeOf((*waveobj.ORef)(nil)).Elem()
var wshRpcInterfaceRType = reflect.TypeOf((*wshrpc.WshRpcInterface)(nil)).Elem()
@@ -471,7 +470,7 @@ func GenerateWaveObjTypes(tsTypesMap map[reflect.Type]string) {
for _, extraType := range ExtraTypes {
GenerateTSType(reflect.TypeOf(extraType), tsTypesMap)
}
for _, rtype := range wstore.AllWaveObjTypes() {
for _, rtype := range waveobj.AllWaveObjTypes() {
GenerateTSType(rtype, tsTypesMap)
}
}
+3 -3
View File
@@ -19,7 +19,7 @@ import (
"github.com/wavetermdev/thenextwave/pkg/util/utilfn"
"github.com/wavetermdev/thenextwave/pkg/wavebase"
"github.com/wavetermdev/thenextwave/pkg/wstore"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
)
const DefaultTermType = "xterm-256color"
@@ -126,8 +126,8 @@ func internalMacUserShell() string {
return m[1]
}
func DefaultTermSize() wstore.TermSize {
return wstore.TermSize{Rows: DefaultTermRows, Cols: DefaultTermCols}
func DefaultTermSize() waveobj.TermSize {
return waveobj.TermSize{Rows: DefaultTermRows, Cols: DefaultTermCols}
}
func WaveshellLocalEnvVars(termType string) map[string]string {
+137
View File
@@ -0,0 +1,137 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package waveobj
import (
"bytes"
"context"
"fmt"
"log"
)
var waveObjUpdateKey = struct{}{}
type contextUpdatesType struct {
UpdatesStack []map[ORef]WaveObjUpdate
}
func dumpUpdateStack(updates *contextUpdatesType) {
log.Printf("dumpUpdateStack len:%d\n", len(updates.UpdatesStack))
for idx, update := range updates.UpdatesStack {
var buf bytes.Buffer
buf.WriteString(fmt.Sprintf(" [%d]:", idx))
for k := range update {
buf.WriteString(fmt.Sprintf(" %s:%s", k.OType, k.OID))
}
buf.WriteString("\n")
log.Print(buf.String())
}
}
func ContextWithUpdates(ctx context.Context) context.Context {
updatesVal := ctx.Value(waveObjUpdateKey)
if updatesVal != nil {
return ctx
}
return context.WithValue(ctx, waveObjUpdateKey, &contextUpdatesType{
UpdatesStack: []map[ORef]WaveObjUpdate{make(map[ORef]WaveObjUpdate)},
})
}
func ContextGetUpdates(ctx context.Context) map[ORef]WaveObjUpdate {
updatesVal := ctx.Value(waveObjUpdateKey)
if updatesVal == nil {
return nil
}
updates := updatesVal.(*contextUpdatesType)
if len(updates.UpdatesStack) == 1 {
return updates.UpdatesStack[0]
}
rtn := make(map[ORef]WaveObjUpdate)
for _, update := range updates.UpdatesStack {
for k, v := range update {
rtn[k] = v
}
}
return rtn
}
func ContextGetUpdate(ctx context.Context, oref ORef) *WaveObjUpdate {
updatesVal := ctx.Value(waveObjUpdateKey)
if updatesVal == nil {
return nil
}
updates := updatesVal.(*contextUpdatesType)
for idx := len(updates.UpdatesStack) - 1; idx >= 0; idx-- {
if obj, ok := updates.UpdatesStack[idx][oref]; ok {
return &obj
}
}
return nil
}
func ContextAddUpdate(ctx context.Context, update WaveObjUpdate) {
updatesVal := ctx.Value(waveObjUpdateKey)
if updatesVal == nil {
return
}
updates := updatesVal.(*contextUpdatesType)
oref := ORef{
OType: update.OType,
OID: update.OID,
}
updates.UpdatesStack[len(updates.UpdatesStack)-1][oref] = update
}
func ContextUpdatesBeginTx(ctx context.Context) context.Context {
updatesVal := ctx.Value(waveObjUpdateKey)
if updatesVal == nil {
return ctx
}
updates := updatesVal.(*contextUpdatesType)
updates.UpdatesStack = append(updates.UpdatesStack, make(map[ORef]WaveObjUpdate))
return ctx
}
func ContextUpdatesCommitTx(ctx context.Context) {
updatesVal := ctx.Value(waveObjUpdateKey)
if updatesVal == nil {
return
}
updates := updatesVal.(*contextUpdatesType)
if len(updates.UpdatesStack) <= 1 {
panic(fmt.Errorf("no updates transaction to commit"))
}
// merge the last two updates
curUpdateMap := updates.UpdatesStack[len(updates.UpdatesStack)-1]
prevUpdateMap := updates.UpdatesStack[len(updates.UpdatesStack)-2]
for k, v := range curUpdateMap {
prevUpdateMap[k] = v
}
updates.UpdatesStack = updates.UpdatesStack[:len(updates.UpdatesStack)-1]
}
func ContextUpdatesRollbackTx(ctx context.Context) {
updatesVal := ctx.Value(waveObjUpdateKey)
if updatesVal == nil {
return
}
updates := updatesVal.(*contextUpdatesType)
if len(updates.UpdatesStack) <= 1 {
panic(fmt.Errorf("no updates transaction to rollback"))
}
updates.UpdatesStack = updates.UpdatesStack[:len(updates.UpdatesStack)-1]
}
func ContextGetUpdatesRtn(ctx context.Context) UpdatesRtnType {
updatesMap := ContextGetUpdates(ctx)
if updatesMap == nil {
return nil
}
rtn := make(UpdatesRtnType, 0, len(updatesMap))
for _, v := range updatesMap {
rtn = append(rtn, v)
}
return rtn
}
@@ -1,16 +1,16 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package wstore
package waveobj
import (
"encoding/json"
"fmt"
"reflect"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
)
type UpdatesRtnType = []WaveObjUpdate
type UIContext struct {
WindowId string `json:"windowid"`
ActiveTabId string `json:"activetabid"`
@@ -31,10 +31,10 @@ const (
)
type WaveObjUpdate struct {
UpdateType string `json:"updatetype"`
OType string `json:"otype"`
OID string `json:"oid"`
Obj waveobj.WaveObj `json:"obj,omitempty"`
UpdateType string `json:"updatetype"`
OType string `json:"otype"`
OID string `json:"oid"`
Obj WaveObj `json:"obj,omitempty"`
}
func (update WaveObjUpdate) MarshalJSON() ([]byte, error) {
@@ -44,7 +44,7 @@ func (update WaveObjUpdate) MarshalJSON() ([]byte, error) {
rtn["oid"] = update.OID
if update.Obj != nil {
var err error
rtn["obj"], err = waveobj.ToJsonMap(update.Obj)
rtn["obj"], err = ToJsonMap(update.Obj)
if err != nil {
return nil, err
}
@@ -52,16 +52,16 @@ func (update WaveObjUpdate) MarshalJSON() ([]byte, error) {
return json.Marshal(rtn)
}
func MakeUpdate(obj waveobj.WaveObj) WaveObjUpdate {
func MakeUpdate(obj WaveObj) WaveObjUpdate {
return WaveObjUpdate{
UpdateType: UpdateType_Update,
OType: obj.GetOType(),
OID: waveobj.GetOID(obj),
OID: GetOID(obj),
Obj: obj,
}
}
func MakeUpdates(objs []waveobj.WaveObj) []WaveObjUpdate {
func MakeUpdates(objs []WaveObj) []WaveObjUpdate {
rtn := make([]WaveObjUpdate, 0, len(objs))
for _, obj := range objs {
rtn = append(rtn, MakeUpdate(obj))
@@ -102,7 +102,7 @@ func (update *WaveObjUpdate) UnmarshalJSON(data []byte) error {
if !ok {
return fmt.Errorf("in WaveObjUpdate bad obj type %T", objMap["obj"])
}
waveObj, err := waveobj.FromJsonMap(objMap)
waveObj, err := FromJsonMap(objMap)
if err != nil {
return fmt.Errorf("in WaveObjUpdate error decoding obj: %w", err)
}
@@ -167,10 +167,10 @@ func (*Tab) GetOType() string {
return OType_Tab
}
func (t *Tab) GetBlockORefs() []waveobj.ORef {
rtn := make([]waveobj.ORef, 0, len(t.BlockIds))
func (t *Tab) GetBlockORefs() []ORef {
rtn := make([]ORef, 0, len(t.BlockIds))
for _, blockId := range t.BlockIds {
rtn = append(rtn, waveobj.ORef{OType: OType_Block, OID: blockId})
rtn = append(rtn, ORef{OType: OType_Block, OID: blockId})
}
return rtn
}
@@ -1,18 +1,14 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package wstore
package waveobj
import (
"strings"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
)
const Entity_Any = "any"
type MetaMapType = waveobj.MetaMapType
// well known meta keys
// to add a new key, add it here and add it to MetaTSType (make sure the keys match)
// TODO: will code generate one side of this so we don't need to add the keys in two places

Some files were not shown because too many files have changed in this diff Show More