mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
implement ijson commands
This commit is contained in:
parent
e044487489
commit
41fe49a54c
@ -22,8 +22,10 @@ function formatPath(path: PathType): string {
|
||||
} else {
|
||||
pathStr += "[" + JSON.stringify(pathPart) + "]";
|
||||
}
|
||||
} else {
|
||||
} else if (typeof pathPart === "number") {
|
||||
pathStr += "[" + pathPart + "]";
|
||||
} else {
|
||||
pathStr += ".*";
|
||||
}
|
||||
}
|
||||
return pathStr;
|
||||
@ -82,6 +84,18 @@ function combineFn_arrayAppend(oldVal: any, newVal: any, opts: SetPathOpts): any
|
||||
return oldVal;
|
||||
}
|
||||
|
||||
function checkPath(path: PathType): boolean {
|
||||
if (!isArray(path)) {
|
||||
return false;
|
||||
}
|
||||
for (let pathPart of path) {
|
||||
if (typeof pathPart !== "string" && typeof pathPart !== "number") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function setPath(obj: any, path: PathType, value: any, opts: SetPathOpts) {
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
@ -89,6 +103,12 @@ function setPath(obj: any, path: PathType, value: any, opts: SetPathOpts) {
|
||||
if (opts.remove && value != null) {
|
||||
throw new Error("Cannot set value and remove at the same time");
|
||||
}
|
||||
if (path == null) {
|
||||
path = [];
|
||||
}
|
||||
if (!checkPath(path)) {
|
||||
throw new Error("Invalid path: " + formatPath(path));
|
||||
}
|
||||
return setPathInternal(obj, path, value, opts);
|
||||
}
|
||||
|
||||
@ -194,5 +214,42 @@ function setPathInternal(obj: any, path: PathType, value: any, opts: SetPathOpts
|
||||
}
|
||||
}
|
||||
|
||||
function getCommandPath(command: object): PathType {
|
||||
if (command["path"] == null) {
|
||||
return [];
|
||||
}
|
||||
return command["path"];
|
||||
}
|
||||
|
||||
function applyCommand(data: any, command: any): any {
|
||||
if (command == null) {
|
||||
throw new Error("Invalid command (null)");
|
||||
}
|
||||
if (!isObject(command)) {
|
||||
throw new Error("Invalid command (not an object): " + command);
|
||||
}
|
||||
const commandType = command.type;
|
||||
if (commandType == null) {
|
||||
throw new Error("Invalid command (no type): " + command);
|
||||
}
|
||||
const path = getCommandPath(command);
|
||||
if (!checkPath(path)) {
|
||||
throw new Error("Invalid command path: " + formatPath(path));
|
||||
}
|
||||
switch (commandType) {
|
||||
case "set":
|
||||
return setPath(data, path, command.value, null);
|
||||
|
||||
case "del":
|
||||
return setPath(data, path, null, { remove: true });
|
||||
|
||||
case "append":
|
||||
return setPath(data, path, command.value, { combinefn: combineFn_arrayAppend });
|
||||
|
||||
default:
|
||||
throw new Error("Invalid command type: " + commandType);
|
||||
}
|
||||
}
|
||||
|
||||
export type { PathType, SetPathOpts };
|
||||
export { getPath, setPath, combineFn_arrayAppend };
|
||||
export { getPath, setPath, applyCommand, combineFn_arrayAppend };
|
||||
|
@ -22,44 +22,10 @@ const (
|
||||
AppendCommandStr = "append"
|
||||
)
|
||||
|
||||
var _ = CommandType(SetCommand{})
|
||||
var _ = CommandType(DelCommand{})
|
||||
var _ = CommandType(AppendCommand{})
|
||||
|
||||
type CommandType interface {
|
||||
GetCommandType() string
|
||||
}
|
||||
|
||||
type SetCommand struct {
|
||||
Type string `json:"type"` // "set"
|
||||
Path []any `json:"path"` // each path entry must be either a string or int
|
||||
Data any `json:"data"` // data must be a valid JSON structure
|
||||
}
|
||||
|
||||
func (c SetCommand) GetCommandType() string {
|
||||
return SetCommandStr
|
||||
}
|
||||
|
||||
// removes values from the state
|
||||
type DelCommand struct {
|
||||
Type string `json:"type"` // "del"
|
||||
Path []any `json:"path"`
|
||||
}
|
||||
|
||||
func (c DelCommand) GetCommandType() string {
|
||||
return DelCommandStr
|
||||
}
|
||||
|
||||
// appends to an array
|
||||
type AppendCommand struct {
|
||||
Type string `json:"type"` // "append"
|
||||
Path []any `json:"path"`
|
||||
Data any `json:"data"`
|
||||
}
|
||||
|
||||
func (c AppendCommand) GetCommandType() string {
|
||||
return AppendCommandStr
|
||||
}
|
||||
// instead of defining structs for commands, we just define a command shape
|
||||
// set: type, path, value
|
||||
// del: type, path
|
||||
// arrayappend: type, path, value
|
||||
|
||||
type PathError struct {
|
||||
Err string
|
||||
@ -498,15 +464,50 @@ func DeepEqual(v1 any, v2 any) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func ApplyCommand(data any, command CommandType, budget int) (any, error) {
|
||||
switch command := command.(type) {
|
||||
case SetCommand:
|
||||
return SetPath(data, command.Path, command.Data, &SetPathOpts{Budget: budget})
|
||||
case DelCommand:
|
||||
return SetPath(data, command.Path, nil, &SetPathOpts{Remove: true, Budget: budget})
|
||||
case AppendCommand:
|
||||
return SetPath(data, command.Path, command.Data, &SetPathOpts{CombineFn: CombineFn_ArrayAppend, Budget: budget})
|
||||
func getCommandType(command map[string]any) string {
|
||||
typeVal, ok := command["type"]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
typeStr, ok := typeVal.(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return typeStr
|
||||
}
|
||||
|
||||
func getCommandPath(command map[string]any) []any {
|
||||
pathVal, ok := command["path"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
path, ok := pathVal.([]any)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
func ApplyCommand(data any, command any, budget int) (any, error) {
|
||||
mapVal, ok := command.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("ApplyCommand: expected map, but got %T", command)
|
||||
}
|
||||
commandType := getCommandType(mapVal)
|
||||
if commandType == "" {
|
||||
return nil, fmt.Errorf("ApplyCommand: missing type field")
|
||||
}
|
||||
switch commandType {
|
||||
case SetCommandStr:
|
||||
path := getCommandPath(mapVal)
|
||||
return SetPath(data, path, mapVal["data"], &SetPathOpts{Budget: budget})
|
||||
case DelCommandStr:
|
||||
path := getCommandPath(mapVal)
|
||||
return SetPath(data, path, nil, &SetPathOpts{Remove: true, Budget: budget})
|
||||
case AppendCommandStr:
|
||||
path := getCommandPath(mapVal)
|
||||
return SetPath(data, path, mapVal["data"], &SetPathOpts{CombineFn: CombineFn_ArrayAppend, Budget: budget})
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown command type %T", command)
|
||||
return nil, fmt.Errorf("ApplyCommand: unknown command type %q", commandType)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user