diff --git a/shortcuts/base/base_shortcut_helpers.go b/shortcuts/base/base_shortcut_helpers.go index 06b21e005..925c0b300 100644 --- a/shortcuts/base/base_shortcut_helpers.go +++ b/shortcuts/base/base_shortcut_helpers.go @@ -5,19 +5,29 @@ package base import ( "encoding/json" + "errors" "fmt" + "io" "strings" - "github.com/larksuite/cli/internal/validate" - "github.com/larksuite/cli/internal/vfs" + "github.com/larksuite/cli/extension/fileio" "github.com/larksuite/cli/shortcuts/common" ) +// parseCtx carries file I/O dependency for JSON/file parsing helpers. +type parseCtx struct { + fio fileio.FileIO +} + +func newParseCtx(runtime *common.RuntimeContext) *parseCtx { + return &parseCtx{fio: runtime.FileIO()} +} + func baseTableID(runtime *common.RuntimeContext) string { return strings.TrimSpace(runtime.Str("table-id")) } -func loadJSONInput(raw string, flagName string) (string, error) { +func loadJSONInput(pc *parseCtx, raw string, flagName string) (string, error) { raw = strings.TrimSpace(raw) if raw == "" { return "", common.FlagErrorf("--%s cannot be empty", flagName) @@ -29,11 +39,19 @@ func loadJSONInput(raw string, flagName string) (string, error) { if path == "" { return "", common.FlagErrorf("--%s file path cannot be empty after @", flagName) } - safePath, err := validate.SafeInputPath(path) + if pc.fio == nil { + return "", common.FlagErrorf("--%s @file inputs require a FileIO provider", flagName) + } + f, err := pc.fio.Open(path) if err != nil { - return "", common.FlagErrorf("--%s invalid JSON file path %q: %v", flagName, path, err) + var pathErr *fileio.PathValidationError + if errors.As(err, &pathErr) { + return "", common.FlagErrorf("--%s invalid JSON file path %q: %v", flagName, path, pathErr.Err) + } + return "", common.FlagErrorf("--%s cannot open JSON file %q: %v", flagName, path, err) } - data, err := vfs.ReadFile(safePath) + defer f.Close() + data, err := io.ReadAll(f) if err != nil { return "", common.FlagErrorf("--%s cannot read JSON file %q: %v", flagName, path, err) } @@ -86,18 +104,18 @@ func baseAction(runtime *common.RuntimeContext, boolFlags []string, stringFlags return active[0], nil } -func parseObjectList(raw string, flagName string) ([]map[string]interface{}, error) { +func parseObjectList(pc *parseCtx, raw string, flagName string) ([]map[string]interface{}, error) { raw = strings.TrimSpace(raw) if raw == "" { return nil, nil } var err error - raw, err = loadJSONInput(raw, flagName) + raw, err = loadJSONInput(pc, raw, flagName) if err != nil { return nil, err } if strings.HasPrefix(raw, "[") { - arr, err := parseJSONArray(raw, flagName) + arr, err := parseJSONArray(pc, raw, flagName) if err != nil { return nil, err } @@ -111,16 +129,16 @@ func parseObjectList(raw string, flagName string) ([]map[string]interface{}, err } return items, nil } - obj, err := parseJSONObject(raw, flagName) + obj, err := parseJSONObject(pc, raw, flagName) if err != nil { return nil, err } return []map[string]interface{}{obj}, nil } -func parseJSONValue(raw string, flagName string) (interface{}, error) { +func parseJSONValue(pc *parseCtx, raw string, flagName string) (interface{}, error) { var err error - raw, err = loadJSONInput(raw, flagName) + raw, err = loadJSONInput(pc, raw, flagName) if err != nil { return nil, err } diff --git a/shortcuts/base/base_shortcuts_test.go b/shortcuts/base/base_shortcuts_test.go index a6f1c61d0..001aaf7ba 100644 --- a/shortcuts/base/base_shortcuts_test.go +++ b/shortcuts/base/base_shortcuts_test.go @@ -70,22 +70,22 @@ func TestBaseAction(t *testing.T) { } func TestParseObjectList(t *testing.T) { - items, err := parseObjectList("", "view") + items, err := parseObjectList(testPC, "", "view") if err != nil || items != nil { t.Fatalf("items=%v err=%v", items, err) } - items, err = parseObjectList(`{"name":"grid"}`, "view") + items, err = parseObjectList(testPC, `{"name":"grid"}`, "view") if err != nil || len(items) != 1 || items[0]["name"] != "grid" { t.Fatalf("items=%v err=%v", items, err) } - items, err = parseObjectList(`[{"name":"grid"}]`, "view") + items, err = parseObjectList(testPC, `[{"name":"grid"}]`, "view") if err != nil || len(items) != 1 || items[0]["name"] != "grid" { t.Fatalf("items=%v err=%v", items, err) } - _, err = parseObjectList(`[1]`, "view") + _, err = parseObjectList(testPC, `[1]`, "view") if err == nil || !strings.Contains(err.Error(), "must be an object") { t.Fatalf("err=%v", err) } diff --git a/shortcuts/base/dashboard_block_create.go b/shortcuts/base/dashboard_block_create.go index 9b663d33b..12a0efe79 100644 --- a/shortcuts/base/dashboard_block_create.go +++ b/shortcuts/base/dashboard_block_create.go @@ -29,6 +29,7 @@ var BaseDashboardBlockCreate = common.Shortcut{ {Name: "no-validate", Type: "bool", Desc: "skip local data_config validation"}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { + pc := newParseCtx(runtime) if runtime.Bool("no-validate") { return nil } @@ -36,7 +37,7 @@ var BaseDashboardBlockCreate = common.Shortcut{ if strings.TrimSpace(raw) == "" { return nil // 允许无 data_config 的创建(某些类型可先创建后配置) } - cfg, err := parseJSONObject(raw, "data-config") + cfg, err := parseJSONObject(pc, raw, "data-config") if err != nil { return err } @@ -50,6 +51,7 @@ var BaseDashboardBlockCreate = common.Shortcut{ return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { + pc := newParseCtx(runtime) body := map[string]interface{}{} if name := runtime.Str("name"); name != "" { body["name"] = name @@ -58,7 +60,7 @@ var BaseDashboardBlockCreate = common.Shortcut{ body["type"] = t } if raw := runtime.Str("data-config"); raw != "" { - if parsed, err := parseJSONObject(raw, "data-config"); err == nil { + if parsed, err := parseJSONObject(pc, raw, "data-config"); err == nil { body["data_config"] = parsed } } diff --git a/shortcuts/base/dashboard_block_update.go b/shortcuts/base/dashboard_block_update.go index 3a6cc59e0..55af8f1c0 100644 --- a/shortcuts/base/dashboard_block_update.go +++ b/shortcuts/base/dashboard_block_update.go @@ -29,6 +29,7 @@ var BaseDashboardBlockUpdate = common.Shortcut{ {Name: "no-validate", Type: "bool", Desc: "skip local data_config validation"}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { + pc := newParseCtx(runtime) if runtime.Bool("no-validate") { return nil } @@ -36,7 +37,7 @@ var BaseDashboardBlockUpdate = common.Shortcut{ if strings.TrimSpace(raw) == "" { return nil } - cfg, err := parseJSONObject(raw, "data-config") + cfg, err := parseJSONObject(pc, raw, "data-config") if err != nil { return err } @@ -49,12 +50,13 @@ var BaseDashboardBlockUpdate = common.Shortcut{ return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { + pc := newParseCtx(runtime) body := map[string]interface{}{} if name := runtime.Str("name"); name != "" { body["name"] = name } if raw := runtime.Str("data-config"); raw != "" { - if parsed, err := parseJSONObject(raw, "data-config"); err == nil { + if parsed, err := parseJSONObject(pc, raw, "data-config"); err == nil { body["data_config"] = parsed } } diff --git a/shortcuts/base/dashboard_ops.go b/shortcuts/base/dashboard_ops.go index c319fde59..12dca1d7a 100644 --- a/shortcuts/base/dashboard_ops.go +++ b/shortcuts/base/dashboard_ops.go @@ -95,6 +95,7 @@ func dryRunDashboardBlockGet(_ context.Context, runtime *common.RuntimeContext) } func dryRunDashboardBlockCreate(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { + pc := newParseCtx(runtime) body := map[string]interface{}{} if name := strings.TrimSpace(runtime.Str("name")); name != "" { body["name"] = name @@ -103,7 +104,7 @@ func dryRunDashboardBlockCreate(_ context.Context, runtime *common.RuntimeContex body["type"] = blockType } if raw := runtime.Str("data-config"); raw != "" { - if parsed, err := parseJSONObject(raw, "data-config"); err == nil { + if parsed, err := parseJSONObject(pc, raw, "data-config"); err == nil { body["data_config"] = parsed } } @@ -119,12 +120,13 @@ func dryRunDashboardBlockCreate(_ context.Context, runtime *common.RuntimeContex } func dryRunDashboardBlockUpdate(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { + pc := newParseCtx(runtime) body := map[string]interface{}{} if name := strings.TrimSpace(runtime.Str("name")); name != "" { body["name"] = name } if raw := runtime.Str("data-config"); raw != "" { - if parsed, err := parseJSONObject(raw, "data-config"); err == nil { + if parsed, err := parseJSONObject(pc, raw, "data-config"); err == nil { body["data_config"] = parsed } } @@ -240,6 +242,7 @@ func executeDashboardBlockGet(runtime *common.RuntimeContext) error { } func executeDashboardBlockCreate(runtime *common.RuntimeContext) error { + pc := newParseCtx(runtime) body := map[string]interface{}{} if name := strings.TrimSpace(runtime.Str("name")); name != "" { body["name"] = name @@ -248,7 +251,7 @@ func executeDashboardBlockCreate(runtime *common.RuntimeContext) error { body["type"] = blockType } if raw := runtime.Str("data-config"); raw != "" { - parsed, err := parseJSONObject(raw, "data-config") + parsed, err := parseJSONObject(pc, raw, "data-config") if err != nil { return err } @@ -269,12 +272,13 @@ func executeDashboardBlockCreate(runtime *common.RuntimeContext) error { } func executeDashboardBlockUpdate(runtime *common.RuntimeContext) error { + pc := newParseCtx(runtime) body := map[string]interface{}{} if name := strings.TrimSpace(runtime.Str("name")); name != "" { body["name"] = name } if raw := runtime.Str("data-config"); raw != "" { - parsed, err := parseJSONObject(raw, "data-config") + parsed, err := parseJSONObject(pc, raw, "data-config") if err != nil { return err } diff --git a/shortcuts/base/field_ops.go b/shortcuts/base/field_ops.go index 0976c90d2..7daaa6dbd 100644 --- a/shortcuts/base/field_ops.go +++ b/shortcuts/base/field_ops.go @@ -32,7 +32,8 @@ func dryRunFieldGet(_ context.Context, runtime *common.RuntimeContext) *common.D } func dryRunFieldCreate(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { - body, _ := parseJSONObject(runtime.Str("json"), "json") + pc := newParseCtx(runtime) + body, _ := parseJSONObject(pc, runtime.Str("json"), "json") return common.NewDryRunAPI(). POST("/open-apis/base/v3/bases/:base_token/tables/:table_id/fields"). Body(body). @@ -41,7 +42,8 @@ func dryRunFieldCreate(_ context.Context, runtime *common.RuntimeContext) *commo } func dryRunFieldUpdate(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { - body, _ := parseJSONObject(runtime.Str("json"), "json") + pc := newParseCtx(runtime) + body, _ := parseJSONObject(pc, runtime.Str("json"), "json") return common.NewDryRunAPI(). PUT("/open-apis/base/v3/bases/:base_token/tables/:table_id/fields/:field_id"). Body(body). @@ -78,7 +80,8 @@ func dryRunFieldSearchOptions(_ context.Context, runtime *common.RuntimeContext) } func validateFieldJSON(runtime *common.RuntimeContext) (map[string]interface{}, error) { - raw, _ := loadJSONInput(runtime.Str("json"), "json") + pc := newParseCtx(runtime) + raw, _ := loadJSONInput(pc, runtime.Str("json"), "json") if raw == "" { return nil, nil } @@ -148,7 +151,8 @@ func executeFieldGet(runtime *common.RuntimeContext) error { } func executeFieldCreate(runtime *common.RuntimeContext) error { - body, err := parseJSONObject(runtime.Str("json"), "json") + pc := newParseCtx(runtime) + body, err := parseJSONObject(pc, runtime.Str("json"), "json") if err != nil { return err } @@ -161,9 +165,10 @@ func executeFieldCreate(runtime *common.RuntimeContext) error { } func executeFieldUpdate(runtime *common.RuntimeContext) error { + pc := newParseCtx(runtime) baseToken := runtime.Str("base-token") tableIDValue := baseTableID(runtime) - body, err := parseJSONObject(runtime.Str("json"), "json") + body, err := parseJSONObject(pc, runtime.Str("json"), "json") if err != nil { return err } diff --git a/shortcuts/base/helpers.go b/shortcuts/base/helpers.go index 9032ab5a2..915c88265 100644 --- a/shortcuts/base/helpers.go +++ b/shortcuts/base/helpers.go @@ -29,8 +29,8 @@ type fieldTypeSpec struct { Extra map[string]interface{} } -func parseJSONObject(raw string, flagName string) (map[string]interface{}, error) { - resolved, err := loadJSONInput(raw, flagName) +func parseJSONObject(pc *parseCtx, raw string, flagName string) (map[string]interface{}, error) { + resolved, err := loadJSONInput(pc, raw, flagName) if err != nil { return nil, err } @@ -41,8 +41,8 @@ func parseJSONObject(raw string, flagName string) (map[string]interface{}, error return result, nil } -func parseJSONArray(raw string, flagName string) ([]interface{}, error) { - resolved, err := loadJSONInput(raw, flagName) +func parseJSONArray(pc *parseCtx, raw string, flagName string) ([]interface{}, error) { + resolved, err := loadJSONInput(pc, raw, flagName) if err != nil { return nil, err } @@ -53,12 +53,12 @@ func parseJSONArray(raw string, flagName string) ([]interface{}, error) { return result, nil } -func parseStringListFlexible(raw string, flagName string) ([]string, error) { +func parseStringListFlexible(pc *parseCtx, raw string, flagName string) ([]string, error) { raw = strings.TrimSpace(raw) if raw == "" { return nil, nil } - resolved, err := loadJSONInput(raw, flagName) + resolved, err := loadJSONInput(pc, raw, flagName) if err != nil { return nil, err } @@ -82,8 +82,19 @@ func parseStringListFlexible(raw string, flagName string) ([]string, error) { } func parseStringList(raw string) []string { - items, _ := parseStringListFlexible(raw, "fields") - return items + raw = strings.TrimSpace(raw) + if raw == "" { + return nil + } + parts := strings.Split(raw, ",") + result := make([]string, 0, len(parts)) + for _, part := range parts { + item := strings.TrimSpace(part) + if item != "" { + result = append(result, item) + } + } + return result } func deepMergeMaps(dst, src map[string]interface{}) map[string]interface{} { diff --git a/shortcuts/base/helpers_test.go b/shortcuts/base/helpers_test.go index 61806c4ae..2640998ae 100644 --- a/shortcuts/base/helpers_test.go +++ b/shortcuts/base/helpers_test.go @@ -10,8 +10,12 @@ import ( "strings" "testing" "time" + + "github.com/larksuite/cli/internal/vfs/localfileio" ) +var testPC = &parseCtx{fio: &localfileio.LocalFileIO{}} + func TestParseHelpers(t *testing.T) { tmpDir := t.TempDir() cwd, err := os.Getwd() @@ -30,36 +34,36 @@ func TestParseHelpers(t *testing.T) { t.Fatalf("write temp file err=%v", err) } _ = tmp.Close() - obj, err := parseJSONObject(`{"name":"demo"}`, "json") + obj, err := parseJSONObject(testPC, `{"name":"demo"}`, "json") if err != nil || obj["name"] != "demo" { t.Fatalf("obj=%v err=%v", obj, err) } - if _, err := parseJSONObject(`[1]`, "json"); err == nil || !strings.Contains(err.Error(), "invalid JSON object") { + if _, err := parseJSONObject(testPC, `[1]`, "json"); err == nil || !strings.Contains(err.Error(), "invalid JSON object") { t.Fatalf("err=%v", err) } - obj, err = parseJSONObject("@"+tmp.Name(), "json") + obj, err = parseJSONObject(testPC, "@"+tmp.Name(), "json") if err != nil || obj["name"] != "from-file" { t.Fatalf("file obj=%v err=%v", obj, err) } - arr, err := parseJSONArray(`[1,2]`, "items") + arr, err := parseJSONArray(testPC, `[1,2]`, "items") if err != nil || len(arr) != 2 { t.Fatalf("arr=%v err=%v", arr, err) } - if _, err := parseJSONArray(`{"a":1}`, "items"); err == nil || !strings.Contains(err.Error(), "invalid JSON array") { + if _, err := parseJSONArray(testPC, `{"a":1}`, "items"); err == nil || !strings.Contains(err.Error(), "invalid JSON array") { t.Fatalf("err=%v", err) } - list, err := parseStringListFlexible("a, b, ,c", "fields") + list, err := parseStringListFlexible(testPC, "a, b, ,c", "fields") if err != nil || !reflect.DeepEqual(list, []string{"a", "b", "c"}) { t.Fatalf("list=%v err=%v", list, err) } - list, err = parseStringListFlexible(`["x","y"]`, "fields") + list, err = parseStringListFlexible(testPC, `["x","y"]`, "fields") if err != nil || !reflect.DeepEqual(list, []string{"x", "y"}) { t.Fatalf("list=%v err=%v", list, err) } - if _, err := parseStringListFlexible(`[1]`, "fields"); err == nil || !strings.Contains(err.Error(), "invalid JSON string array") { + if _, err := parseStringListFlexible(testPC, `[1]`, "fields"); err == nil || !strings.Contains(err.Error(), "invalid JSON string array") { t.Fatalf("err=%v", err) } - if _, err := parseJSONValue("{", "json"); err == nil || !strings.Contains(err.Error(), "tip: pass a JSON object/array directly") { + if _, err := parseJSONValue(testPC, "{", "json"); err == nil || !strings.Contains(err.Error(), "tip: pass a JSON object/array directly") { t.Fatalf("err=%v", err) } if !reflect.DeepEqual(parseStringList("m,n"), []string{"m", "n"}) { @@ -262,10 +266,10 @@ func TestFilterAndSortHelpers(t *testing.T) { } func TestJSONInputHelpers(t *testing.T) { - if got, err := loadJSONInput(`{"name":"demo"}`, "json"); err != nil || got != `{"name":"demo"}` { + if got, err := loadJSONInput(testPC, `{"name":"demo"}`, "json"); err != nil || got != `{"name":"demo"}` { t.Fatalf("got=%q err=%v", got, err) } - if _, err := loadJSONInput("@", "json"); err == nil || !strings.Contains(err.Error(), "file path cannot be empty") { + if _, err := loadJSONInput(testPC, "@", "json"); err == nil || !strings.Contains(err.Error(), "file path cannot be empty") { t.Fatalf("err=%v", err) } tmp := t.TempDir() @@ -281,7 +285,7 @@ func TestJSONInputHelpers(t *testing.T) { if err := os.WriteFile(emptyPath, []byte(" \n"), 0o644); err != nil { t.Fatalf("write empty file err=%v", err) } - if _, err := loadJSONInput("@"+emptyPath, "json"); err == nil || !strings.Contains(err.Error(), "is empty") { + if _, err := loadJSONInput(testPC, "@"+emptyPath, "json"); err == nil || !strings.Contains(err.Error(), "is empty") { t.Fatalf("err=%v", err) } syntaxErr := formatJSONError("json", "object", &json.SyntaxError{Offset: 7}) diff --git a/shortcuts/base/record_ops.go b/shortcuts/base/record_ops.go index 280b1c580..bcaec01f5 100644 --- a/shortcuts/base/record_ops.go +++ b/shortcuts/base/record_ops.go @@ -35,7 +35,8 @@ func dryRunRecordGet(_ context.Context, runtime *common.RuntimeContext) *common. } func dryRunRecordUpsert(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { - body, _ := parseJSONObject(runtime.Str("json"), "json") + pc := newParseCtx(runtime) + body, _ := parseJSONObject(pc, runtime.Str("json"), "json") if recordID := runtime.Str("record-id"); recordID != "" { return common.NewDryRunAPI(). PATCH("/open-apis/base/v3/bases/:base_token/tables/:table_id/records/:record_id"). @@ -106,7 +107,8 @@ func executeRecordGet(runtime *common.RuntimeContext) error { } func executeRecordUpsert(runtime *common.RuntimeContext) error { - body, err := parseJSONObject(runtime.Str("json"), "json") + pc := newParseCtx(runtime) + body, err := parseJSONObject(pc, runtime.Str("json"), "json") if err != nil { return err } diff --git a/shortcuts/base/record_upload_attachment.go b/shortcuts/base/record_upload_attachment.go index 31d0ffc51..b744327e2 100644 --- a/shortcuts/base/record_upload_attachment.go +++ b/shortcuts/base/record_upload_attachment.go @@ -14,10 +14,9 @@ import ( larkcore "github.com/larksuite/oapi-sdk-go/v3/core" + "github.com/larksuite/cli/extension/fileio" "github.com/larksuite/cli/internal/output" "github.com/larksuite/cli/internal/util" - "github.com/larksuite/cli/internal/validate" - "github.com/larksuite/cli/internal/vfs" "github.com/larksuite/cli/shortcuts/common" ) @@ -91,15 +90,16 @@ func dryRunRecordUploadAttachment(_ context.Context, runtime *common.RuntimeCont func executeRecordUploadAttachment(runtime *common.RuntimeContext) error { filePath := runtime.Str("file") - safeFilePath, err := validate.SafeInputPath(filePath) - if err != nil { - return output.ErrValidation("unsafe file path: %s", err) + fio := runtime.FileIO() + if fio == nil { + return output.ErrValidation("file operations require a FileIO provider") } - filePath = safeFilePath - - fileInfo, err := vfs.Stat(filePath) + fileInfo, err := fio.Stat(filePath) if err != nil { - return output.ErrValidation("file not found: %s", filePath) + if errors.Is(err, fileio.ErrPathValidation) { + return output.ErrValidation("unsafe file path: %s", err) + } + return output.ErrValidation("file not accessible: %s: %v", filePath, err) } if fileInfo.Size() > baseAttachmentUploadMaxFileSize { return output.ErrValidation("file %.1fMB exceeds 20MB limit", float64(fileInfo.Size())/1024/1024) @@ -209,7 +209,7 @@ func normalizeAttachmentForPatch(attachment map[string]interface{}) map[string]i } func uploadAttachmentToBase(runtime *common.RuntimeContext, filePath, fileName, baseToken string, fileSize int64) (map[string]interface{}, error) { - f, err := vfs.Open(filePath) + f, err := runtime.FileIO().Open(filePath) if err != nil { return nil, output.ErrValidation("cannot open file: %v", err) } diff --git a/shortcuts/base/table_ops.go b/shortcuts/base/table_ops.go index 044823965..d44b9c9f2 100644 --- a/shortcuts/base/table_ops.go +++ b/shortcuts/base/table_ops.go @@ -107,8 +107,9 @@ func executeTableCreate(runtime *common.RuntimeContext) error { } result := map[string]interface{}{"table": created} tableIDValue := tableID(created) + pc := newParseCtx(runtime) if tableIDValue != "" && runtime.Str("fields") != "" { - fieldItems, err := parseJSONArray(runtime.Str("fields"), "fields") + fieldItems, err := parseJSONArray(pc, runtime.Str("fields"), "fields") if err != nil { return err } @@ -139,7 +140,7 @@ func executeTableCreate(runtime *common.RuntimeContext) error { result["fields"] = createdFields } if tableIDValue != "" && runtime.Str("view") != "" { - viewItems, err := parseObjectList(runtime.Str("view"), "view") + viewItems, err := parseObjectList(pc, runtime.Str("view"), "view") if err != nil { return err } diff --git a/shortcuts/base/view_ops.go b/shortcuts/base/view_ops.go index 53211cf1c..7331891b0 100644 --- a/shortcuts/base/view_ops.go +++ b/shortcuts/base/view_ops.go @@ -35,8 +35,9 @@ func dryRunViewGet(_ context.Context, runtime *common.RuntimeContext) *common.Dr } func dryRunViewCreate(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { + pc := newParseCtx(runtime) api := dryRunViewBase(runtime) - bodyList, err := parseObjectList(runtime.Str("json"), "json") + bodyList, err := parseObjectList(pc, runtime.Str("json"), "json") if err != nil || len(bodyList) == 0 { return api.POST("/open-apis/base/v3/bases/:base_token/tables/:table_id/views") } @@ -57,14 +58,16 @@ func dryRunViewGetProperty(runtime *common.RuntimeContext, segment string) *comm } func dryRunViewSetJSONObject(runtime *common.RuntimeContext, segment string) *common.DryRunAPI { - body, _ := parseJSONObject(runtime.Str("json"), "json") + pc := newParseCtx(runtime) + body, _ := parseJSONObject(pc, runtime.Str("json"), "json") return dryRunViewBase(runtime). PUT(fmt.Sprintf("/open-apis/base/v3/bases/:base_token/tables/:table_id/views/:view_id/%s", url.PathEscape(segment))). Body(body) } func dryRunViewSetWrapped(runtime *common.RuntimeContext, segment string, wrapper string) *common.DryRunAPI { - raw, err := parseJSONValue(runtime.Str("json"), "json") + pc := newParseCtx(runtime) + raw, err := parseJSONValue(pc, runtime.Str("json"), "json") if err != nil { raw = nil } @@ -168,9 +171,10 @@ func executeViewGet(runtime *common.RuntimeContext) error { } func executeViewCreate(runtime *common.RuntimeContext) error { + pc := newParseCtx(runtime) baseToken := runtime.Str("base-token") tableIDValue := baseTableID(runtime) - viewItems, err := parseObjectList(runtime.Str("json"), "json") + viewItems, err := parseObjectList(pc, runtime.Str("json"), "json") if err != nil { return err } @@ -211,10 +215,11 @@ func executeViewGetProperty(runtime *common.RuntimeContext, segment string, key } func executeViewSetJSONObject(runtime *common.RuntimeContext, segment string, key string) error { + pc := newParseCtx(runtime) baseToken := runtime.Str("base-token") tableIDValue := baseTableID(runtime) viewRef := runtime.Str("view-id") - body, err := parseJSONObject(runtime.Str("json"), "json") + body, err := parseJSONObject(pc, runtime.Str("json"), "json") if err != nil { return err } @@ -227,10 +232,11 @@ func executeViewSetJSONObject(runtime *common.RuntimeContext, segment string, ke } func executeViewSetWrapped(runtime *common.RuntimeContext, segment string, wrapper string, key string) error { + pc := newParseCtx(runtime) baseToken := runtime.Str("base-token") tableIDValue := baseTableID(runtime) viewRef := runtime.Str("view-id") - raw, err := parseJSONValue(runtime.Str("json"), "json") + raw, err := parseJSONValue(pc, runtime.Str("json"), "json") if err != nil { return err } diff --git a/shortcuts/base/workflow_create.go b/shortcuts/base/workflow_create.go index 0bba5bbeb..b4d9b683e 100644 --- a/shortcuts/base/workflow_create.go +++ b/shortcuts/base/workflow_create.go @@ -25,19 +25,21 @@ var BaseWorkflowCreate = common.Shortcut{ if strings.TrimSpace(runtime.Str("base-token")) == "" { return common.FlagErrorf("--base-token must not be blank") } - raw, err := loadJSONInput(runtime.Str("json"), "json") + pc := newParseCtx(runtime) + raw, err := loadJSONInput(pc, runtime.Str("json"), "json") if err != nil { return err } - if _, err := parseJSONObject(raw, "json"); err != nil { + if _, err := parseJSONObject(pc, raw, "json"); err != nil { return err } return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { + pc := newParseCtx(runtime) var body map[string]interface{} - if raw, err := loadJSONInput(runtime.Str("json"), "json"); err == nil { - body, _ = parseJSONObject(raw, "json") + if raw, err := loadJSONInput(pc, runtime.Str("json"), "json"); err == nil { + body, _ = parseJSONObject(pc, raw, "json") } return common.NewDryRunAPI(). POST("/open-apis/base/v3/bases/:base_token/workflows"). @@ -45,11 +47,12 @@ var BaseWorkflowCreate = common.Shortcut{ Set("base_token", runtime.Str("base-token")) }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { - raw, err := loadJSONInput(runtime.Str("json"), "json") + pc := newParseCtx(runtime) + raw, err := loadJSONInput(pc, runtime.Str("json"), "json") if err != nil { return err } - body, err := parseJSONObject(raw, "json") + body, err := parseJSONObject(pc, raw, "json") if err != nil { return err } diff --git a/shortcuts/base/workflow_update.go b/shortcuts/base/workflow_update.go index 0b316e4fd..2fe2e38cc 100644 --- a/shortcuts/base/workflow_update.go +++ b/shortcuts/base/workflow_update.go @@ -29,20 +29,16 @@ var BaseWorkflowUpdate = common.Shortcut{ if strings.TrimSpace(runtime.Str("workflow-id")) == "" { return common.FlagErrorf("--workflow-id must not be blank") } - raw, err := loadJSONInput(runtime.Str("json"), "json") - if err != nil { - return err - } - if _, err := parseJSONObject(raw, "json"); err != nil { + pc := newParseCtx(runtime) + if _, err := parseJSONObject(pc, runtime.Str("json"), "json"); err != nil { return err } return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { + pc := newParseCtx(runtime) var body map[string]interface{} - if raw, err := loadJSONInput(runtime.Str("json"), "json"); err == nil { - body, _ = parseJSONObject(raw, "json") - } + body, _ = parseJSONObject(pc, runtime.Str("json"), "json") return common.NewDryRunAPI(). PUT("/open-apis/base/v3/bases/:base_token/workflows/:workflow_id"). Body(body). @@ -50,11 +46,8 @@ var BaseWorkflowUpdate = common.Shortcut{ Set("workflow_id", runtime.Str("workflow-id")) }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { - raw, err := loadJSONInput(runtime.Str("json"), "json") - if err != nil { - return err - } - body, err := parseJSONObject(raw, "json") + pc := newParseCtx(runtime) + body, err := parseJSONObject(pc, runtime.Str("json"), "json") if err != nil { return err }