Files
wehub-resource-sync bf9395e022
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / results (push) Has been cancelled
CI / deadcode (push) Has been cancelled
CI / e2e-live (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:54 +08:00

246 lines
7.9 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package base
import (
"context"
"strings"
"time"
"github.com/larksuite/cli/shortcuts/common"
)
var fieldCreateBatchDelay = time.Second
func dryRunFieldList(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
offset := runtime.Int("offset")
if offset < 0 {
offset = 0
}
limit := getPaginationLimit(runtime)
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)
bodies, _ := parseFieldCreateBodies(pc, runtime.Str("json"))
dr := common.NewDryRunAPI().
Set("base_token", runtime.Str("base-token")).
Set("table_id", baseTableID(runtime))
for _, body := range bodies {
dr.POST("/open-apis/base/v3/bases/:base_token/tables/:table_id/fields").Body(body)
}
return dr
}
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 {
limit := getPaginationLimit(runtime)
params := map[string]interface{}{
"offset": runtime.Int("offset"),
"limit": limit,
}
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 baseFlagErrorf("--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 {
bodies, err := parseFieldCreateBodies(newParseCtx(runtime), runtime.Str("json"))
if err != nil {
return err
}
for _, body := range bodies {
if err := validateFormulaLookupGuideAck(runtime, "+field-create", body); err != nil {
return err
}
}
return nil
}
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 := getPaginationLimit(runtime)
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 {
bodies, err := parseFieldCreateBodies(newParseCtx(runtime), runtime.Str("json"))
if err != nil {
return err
}
fields := make([]interface{}, 0, len(bodies))
for idx, body := range bodies {
if idx > 0 && fieldCreateBatchDelay > 0 {
time.Sleep(fieldCreateBatchDelay)
}
data, err := baseV3Call(runtime, "POST", baseV3Path("bases", runtime.Str("base-token"), "tables", baseTableID(runtime), "fields"), nil, body)
if err != nil {
return err
}
fields = append(fields, data)
}
if len(fields) == 1 {
runtime.Out(map[string]interface{}{"field": fields[0], "created": true}, nil)
return nil
}
runtime.Out(map[string]interface{}{"fields": fields, "created": true, "total": len(fields)}, nil)
return nil
}
func parseFieldCreateBodies(pc *parseCtx, raw string) ([]map[string]interface{}, error) {
bodies, err := parseObjectList(pc, raw, "json")
if err != nil {
return nil, err
}
if len(bodies) == 0 {
return nil, baseFlagErrorf("--json must contain at least one field JSON object")
}
return bodies, 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")
limit := getPaginationLimit(runtime)
params := map[string]interface{}{
"offset": runtime.Int("offset"),
"limit": limit,
}
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
}