// Copyright (c) 2026 Lark Technologies Pte. Ltd. // SPDX-License-Identifier: MIT package base import ( "context" "strings" "github.com/larksuite/cli/shortcuts/common" ) func dryRunFieldList(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { offset := runtime.Int("offset") if offset < 0 { offset = 0 } limit := common.ParseIntBounded(runtime, "limit", 1, 200) return common.NewDryRunAPI(). GET("/open-apis/base/v3/bases/:base_token/tables/:table_id/fields"). Params(map[string]interface{}{"offset": offset, "limit": limit}). Set("base_token", runtime.Str("base-token")). Set("table_id", baseTableID(runtime)) } func dryRunFieldGet(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { return common.NewDryRunAPI(). GET("/open-apis/base/v3/bases/:base_token/tables/:table_id/fields/:field_id"). Set("base_token", runtime.Str("base-token")). Set("table_id", baseTableID(runtime)). Set("field_id", runtime.Str("field-id")) } func dryRunFieldCreate(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { 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). Set("base_token", runtime.Str("base-token")). Set("table_id", baseTableID(runtime)) } func dryRunFieldUpdate(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { 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). Set("base_token", runtime.Str("base-token")). Set("table_id", baseTableID(runtime)). Set("field_id", runtime.Str("field-id")) } func dryRunFieldDelete(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { return common.NewDryRunAPI(). DELETE("/open-apis/base/v3/bases/:base_token/tables/:table_id/fields/:field_id"). Set("base_token", runtime.Str("base-token")). Set("table_id", baseTableID(runtime)). Set("field_id", runtime.Str("field-id")) } func dryRunFieldSearchOptions(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { params := map[string]interface{}{ "offset": runtime.Int("offset"), "limit": runtime.Int("limit"), } if params["limit"].(int) <= 0 { params["limit"] = 30 } if keyword := strings.TrimSpace(runtime.Str("keyword")); keyword != "" { params["query"] = keyword } return common.NewDryRunAPI(). GET("/open-apis/base/v3/bases/:base_token/tables/:table_id/fields/:field_id/options"). Params(params). Set("base_token", runtime.Str("base-token")). Set("table_id", baseTableID(runtime)). Set("field_id", runtime.Str("field-id")) } func validateFieldJSON(runtime *common.RuntimeContext) (map[string]interface{}, error) { pc := newParseCtx(runtime) return parseJSONObject(pc, runtime.Str("json"), "json") } func validateFormulaLookupGuideAck(runtime *common.RuntimeContext, command string, body map[string]interface{}) error { fieldType := strings.ToLower(strings.TrimSpace(common.GetString(body, "type"))) if (fieldType == "formula" || fieldType == "lookup") && !runtime.Bool("i-have-read-guide") { guidePath := "skills/lark-base/references/formula-field-guide.md" if fieldType == "lookup" { guidePath = "skills/lark-base/references/lookup-field-guide.md" } return common.FlagErrorf("--i-have-read-guide is required for %s when --json.type is %q; read %s first, then retry with --i-have-read-guide", command, fieldType, guidePath) } return nil } func validateFieldCreate(runtime *common.RuntimeContext) error { body, err := validateFieldJSON(runtime) if err != nil { return err } return validateFormulaLookupGuideAck(runtime, "+field-create", body) } func validateFieldUpdate(runtime *common.RuntimeContext) error { body, err := validateFieldJSON(runtime) if err != nil { return err } return validateFormulaLookupGuideAck(runtime, "+field-update", body) } func executeFieldList(runtime *common.RuntimeContext) error { offset := runtime.Int("offset") if offset < 0 { offset = 0 } limit := common.ParseIntBounded(runtime, "limit", 1, 200) fields, total, err := listAllFields(runtime, runtime.Str("base-token"), baseTableID(runtime), offset, limit) if err != nil { return err } if total == 0 { total = len(fields) } runtime.Out(map[string]interface{}{"fields": fields, "total": total}, nil) return nil } func executeFieldGet(runtime *common.RuntimeContext) error { baseToken := runtime.Str("base-token") tableIDValue := baseTableID(runtime) fieldRef := runtime.Str("field-id") data, err := baseV3Call(runtime, "GET", baseV3Path("bases", baseToken, "tables", tableIDValue, "fields", fieldRef), nil, nil) if err != nil { return err } runtime.Out(map[string]interface{}{"field": data}, nil) return nil } func executeFieldCreate(runtime *common.RuntimeContext) error { pc := newParseCtx(runtime) body, err := parseJSONObject(pc, runtime.Str("json"), "json") if err != nil { return err } data, err := baseV3Call(runtime, "POST", baseV3Path("bases", runtime.Str("base-token"), "tables", baseTableID(runtime), "fields"), nil, body) if err != nil { return err } runtime.Out(map[string]interface{}{"field": data, "created": true}, nil) return nil } func executeFieldUpdate(runtime *common.RuntimeContext) error { pc := newParseCtx(runtime) baseToken := runtime.Str("base-token") tableIDValue := baseTableID(runtime) body, err := parseJSONObject(pc, runtime.Str("json"), "json") if err != nil { return err } fieldRef := runtime.Str("field-id") data, err := baseV3Call(runtime, "PUT", baseV3Path("bases", baseToken, "tables", tableIDValue, "fields", fieldRef), nil, body) if err != nil { return err } runtime.Out(map[string]interface{}{"field": data, "updated": true}, nil) return nil } func executeFieldDelete(runtime *common.RuntimeContext) error { baseToken := runtime.Str("base-token") tableIDValue := baseTableID(runtime) fieldRef := runtime.Str("field-id") _, err := baseV3Call(runtime, "DELETE", baseV3Path("bases", baseToken, "tables", tableIDValue, "fields", fieldRef), nil, nil) if err != nil { return err } runtime.Out(map[string]interface{}{"deleted": true, "field_id": fieldRef, "field_name": fieldRef}, nil) return nil } func executeFieldSearchOptions(runtime *common.RuntimeContext) error { baseToken := runtime.Str("base-token") tableIDValue := baseTableID(runtime) fieldRef := runtime.Str("field-id") params := map[string]interface{}{ "offset": runtime.Int("offset"), "limit": runtime.Int("limit"), } if params["limit"].(int) <= 0 { params["limit"] = 30 } if keyword := strings.TrimSpace(runtime.Str("keyword")); keyword != "" { params["query"] = keyword } data, err := baseV3Call(runtime, "GET", baseV3Path("bases", baseToken, "tables", tableIDValue, "fields", fieldRef, "options"), params, nil) if err != nil { return err } options, _ := data["options"].([]interface{}) total := toInt(data["total"]) if total == 0 { total = len(options) } runtime.Out(map[string]interface{}{ "field_id": fieldRef, "field_name": fieldRef, "keyword": strings.TrimSpace(runtime.Str("keyword")), "options": options, "total": total, }, nil) return nil }