feat: cli 支持记录分享 no-meego (#466)

Change-Id: Ie78da99096cc1fc8a4671d8178176f4c587466ba
This commit is contained in:
yballul-bytedance
2026-04-22 10:31:37 +08:00
committed by GitHub
parent 018eeb6414
commit f3699298aa
7 changed files with 168 additions and 1 deletions

View File

@@ -132,7 +132,7 @@ func TestShortcutsCatalog(t *testing.T) {
"+table-list", "+table-get", "+table-create", "+table-update", "+table-delete",
"+field-list", "+field-get", "+field-create", "+field-update", "+field-delete", "+field-search-options",
"+view-list", "+view-get", "+view-create", "+view-delete", "+view-get-filter", "+view-set-filter", "+view-get-visible-fields", "+view-set-visible-fields", "+view-get-group", "+view-set-group", "+view-get-sort", "+view-set-sort", "+view-get-timebar", "+view-set-timebar", "+view-get-card", "+view-set-card", "+view-rename",
"+record-list", "+record-search", "+record-get", "+record-upsert", "+record-batch-create", "+record-batch-update", "+record-upload-attachment", "+record-delete",
"+record-list", "+record-search", "+record-get", "+record-upsert", "+record-batch-create", "+record-batch-update", "+record-share-link-create", "+record-upload-attachment", "+record-delete",
"+record-history-list",
"+base-get", "+base-copy", "+base-create",
"+role-create", "+role-delete", "+role-update", "+role-list", "+role-get", "+advperm-enable", "+advperm-disable",

View File

@@ -112,6 +112,56 @@ func dryRunRecordHistoryList(_ context.Context, runtime *common.RuntimeContext)
Set("base_token", runtime.Str("base-token"))
}
func dryRunRecordShareBatch(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
recordIDs := deduplicateRecordIDs(runtime)
return common.NewDryRunAPI().
POST("/open-apis/base/v3/bases/:base_token/tables/:table_id/records/share_links/batch").
Body(map[string]interface{}{"record_ids": recordIDs}).
Set("base_token", runtime.Str("base-token")).
Set("table_id", baseTableID(runtime))
}
const maxShareBatchSize = 100
func validateRecordShareBatch(runtime *common.RuntimeContext) error {
recordIDs := deduplicateRecordIDs(runtime)
if len(recordIDs) == 0 {
return common.FlagErrorf("--record-ids is required and must not be empty")
}
if len(recordIDs) > maxShareBatchSize {
return common.FlagErrorf("--record-ids exceeds maximum limit of %d (got %d)", maxShareBatchSize, len(recordIDs))
}
return nil
}
func deduplicateRecordIDs(runtime *common.RuntimeContext) []string {
raw := runtime.StrSlice("record-ids")
seen := make(map[string]bool, len(raw))
result := make([]string, 0, len(raw))
for _, id := range raw {
if id != "" && !seen[id] {
seen[id] = true
result = append(result, id)
}
}
return result
}
func executeRecordShareBatch(runtime *common.RuntimeContext) error {
recordIDs := deduplicateRecordIDs(runtime)
body := map[string]interface{}{
"record_ids": recordIDs,
}
data, err := baseV3Call(runtime, "POST",
baseV3Path("bases", runtime.Str("base-token"), "tables", baseTableID(runtime), "records", "share_links", "batch"),
nil, body)
if err != nil {
return err
}
runtime.Out(data, nil)
return nil
}
func validateRecordJSON(runtime *common.RuntimeContext) error {
pc := newParseCtx(runtime)
_, err := parseJSONObject(pc, runtime.Str("json"), "json")

View File

@@ -0,0 +1,35 @@
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package base
import (
"context"
"github.com/larksuite/cli/shortcuts/common"
)
var BaseRecordShareLinkCreate = common.Shortcut{
Service: "base",
Command: "+record-share-link-create",
Description: "Generate share links for one or more records (max 100 per request)",
Risk: "read",
Scopes: []string{"base:record:read"},
AuthTypes: authTypes(),
Flags: []common.Flag{
baseTokenFlag(true),
tableRefFlag(true),
{Name: "record-ids", Type: "string_slice", Desc: "record IDs to generate share links for (comma-separated or repeatable, max 100)", Required: true},
},
Tips: []string{
`Single record: --base-token xxx --table-id tblxxx --record-ids recxxx`,
`Multiple records: --base-token xxx --table-id tblxxx --record-ids rec001,rec002,rec003`,
},
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
return validateRecordShareBatch(runtime)
},
DryRun: dryRunRecordShareBatch,
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
return executeRecordShareBatch(runtime)
},
}

View File

@@ -42,6 +42,7 @@ func Shortcuts() []common.Shortcut {
BaseRecordUpsert,
BaseRecordBatchCreate,
BaseRecordBatchUpdate,
BaseRecordShareLinkCreate,
BaseRecordUploadAttachment,
BaseRecordDelete,
BaseRecordHistoryList,

View File

@@ -181,6 +181,12 @@ func (ctx *RuntimeContext) StrArray(name string) []string {
return v
}
// StrSlice returns a string-slice flag value (supports CSV splitting and repeated flags).
func (ctx *RuntimeContext) StrSlice(name string) []string {
v, _ := ctx.Cmd.Flags().GetStringSlice(name)
return v
}
// ── API helpers ──
// CallAPI uses an internal HTTP wrapper with limited control over request/response.
@@ -857,6 +863,8 @@ func registerShortcutFlagsWithContext(ctx context.Context, cmd *cobra.Command, f
cmd.Flags().Int(fl.Name, d, desc)
case "string_array":
cmd.Flags().StringArray(fl.Name, nil, desc)
case "string_slice":
cmd.Flags().StringSlice(fl.Name, nil, desc)
default:
cmd.Flags().String(fl.Name, fl.Default, desc)
}

View File

@@ -0,0 +1,72 @@
# base +record-share-link-create
> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。
为一条或多条记录生成分享链接(单次调用最多传入 100 条,内部调用批量接口)。
## 推荐命令
```bash
# 单条记录
lark-cli base +record-share-link-create \
--base-token xxx \
--table-id tbl_xxx \
--record-ids rec_xxx
# 多条记录(使用 "," 分隔)
lark-cli base +record-share-link-create \
--base-token xxx \
--table-id tbl_xxx \
--record-ids rec001,rec002,rec003
```
## 参数
| 参数 | 必填 | 说明 |
|------|------|------|
| `--base-token <token>` | 是 | Base Token |
| `--table-id <id>` | 是 | 表 ID |
| `--record-ids <ids...>` | 是 | 记录 ID 列表,逗号分隔或重复使用该标志,最多 100 条 |
## API 入参详情
**HTTP 方法和路径:**
```http
POST /open-apis/base/v3/bases/:base_token/tables/:table_id/records/share_links/batch
```
**请求体:**
```json
{
"record_ids": ["rec001", "rec002", "rec003"]
}
```
> CLI 会自动对 `--record-ids` 去重后再调用接口。
## 返回重点
- 成功时直接返回接口 `data` 字段内容,包含 `record_share_links` 映射key 为 record_idvalue 为分享链接)。结构如下:
```json
{
"record_share_links": {
"rec001": "https://example.feishu.cn/record/TW2wrdbkoeoYXYcwvyIczJ2ZnFb"
}
}
```
- 若部分记录 ID 无权限/不存在,则 `record_share_links` 中只会包含有效记录对应的分享链接
- 若全部记录 ID 都无权限/不存在,则会返回错误信息 `records do not exist or no read permission`
## 坑点
- ⚠️ 单次最多 100 条记录,超出会被 CLI 校验拦截。
- ⚠️ 重复的 record_id 会在调用前自动去重。
- ⚠️ `--record-ids` 为空时会被校验拦截。
## 参考
- [lark-base-record.md](lark-base-record.md) — record 索引页

View File

@@ -17,6 +17,7 @@ record 相关命令索引。
| [lark-base-record-upload-attachment.md](lark-base-record-upload-attachment.md) | `+record-upload-attachment` | 上传本地文件到附件字段并更新记录 |
| [`../../lark-doc/references/lark-doc-media-download.md`](../../lark-doc/references/lark-doc-media-download.md) | `lark-cli docs +media-download` | 下载 Base 附件到本地(附件的 `file_token` 来自 `+record-get` 的附件字段) |
| [lark-base-record-delete.md](lark-base-record-delete.md) | `+record-delete` | 删除记录 |
| [lark-base-record-share-link-create.md](lark-base-record-share-link-create.md) | `+record-share-link-create` | 生成记录分享链接(支持单条或批量,最多 100 条)|
## 说明