Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var WikiDeleteSpace = common.Shortcut{ Service: "wiki", Command: "+delete-space", Description: "Delete a wiki space, polling the async delete task when needed", Risk: "high-risk-write", Scopes: []string{"wiki:space:write_only", "wiki:space:read"}, AuthTypes: []string{"user", "bot"}, Flags: []common.Flag{ {Name: "space-id", Desc: "wiki space ID to delete", Required: true}, }, Tips: []string{ "Deletion is irreversible; double-check --space-id before running.", "This is a high-risk-write command; pass --yes to confirm the deletion.", "If the API returns a long-running task, this command polls for a bounded window and then prints a follow-up drive +task_result command.", }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { return validateWikiDeleteSpaceSpec(readWikiDeleteSpaceSpec(runtime)) }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { return buildWikiDeleteSpaceDryRun(readWikiDeleteSpaceSpec(runtime)) }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { spec := readWikiDeleteSpaceSpec(runtime) fmt.Fprintf(runtime.IO().ErrOut, "Deleting wiki space %s...\n", spec.SpaceID) out, err := runWikiDeleteSpace(ctx, wikiDeleteSpaceAPI{runtime: runtime}, runtime, spec) if err != nil { return err } runtime.Out(out, nil) return nil }, }
WikiDeleteSpace deletes a wiki space. The DELETE endpoint may complete synchronously (empty task_id) or return a task_id that must be polled against /open-apis/wiki/v2/tasks/:task_id with task_type=delete_space.
var WikiMove = common.Shortcut{ Service: "wiki", Command: "+move", Description: "Move a wiki node, or move a Drive document into Wiki", Risk: "write", Scopes: []string{"wiki:node:move", "wiki:node:read", "wiki:space:read"}, AuthTypes: []string{"user", "bot"}, Flags: []common.Flag{ {Name: "node-token", Desc: "wiki node token to move inside Wiki"}, {Name: "source-space-id", Desc: "source wiki space ID for --node-token; if omitted, it is resolved from the node token"}, {Name: "target-space-id", Desc: "target wiki space ID; required for docs-to-wiki, optional for node move when --target-parent-token is set"}, {Name: "target-parent-token", Desc: "target parent wiki node token; if omitted for docs-to-wiki, the document is moved to the target space root"}, {Name: "obj-type", Desc: "Drive document type for docs-to-wiki mode", Enum: wikiMoveObjectTypes}, {Name: "obj-token", Desc: "Drive document token for docs-to-wiki mode"}, {Name: "apply", Type: "bool", Desc: "submit a move request when the caller lacks permission to move the document immediately"}, }, Tips: []string{ "Use --node-token to move an existing wiki node inside or across wiki spaces.", "Use --obj-type and --obj-token to move a Drive document into Wiki.", "If docs-to-wiki returns a long-running task, this command polls for a bounded window and then prints a follow-up drive +task_result command.", }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { spec := readWikiMoveSpec(runtime) if runtime.As().IsBot() && spec.TargetSpaceID == wikiMyLibrarySpaceID { return output.ErrValidation("--target-space-id my_library is a per-user personal library alias and cannot be used with --as bot; resolve it to a real space_id first via `lark-cli wiki spaces get --params '{\"space_id\":\"my_library\"}' --as user`") } return validateWikiMoveSpec(spec) }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { return buildWikiMoveDryRun(readWikiMoveSpec(runtime)) }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { spec := readWikiMoveSpec(runtime) fmt.Fprintf(runtime.IO().ErrOut, "Running wiki move (%s)...\n", spec.Mode()) out, err := runWikiMove(ctx, wikiMoveAPI{runtime: runtime}, runtime, spec) if err != nil { return err } runtime.Out(out, nil) return nil }, }
WikiMove moves an existing wiki node inside Wiki or migrates a Drive document into Wiki with bounded polling for async task completion.
var WikiNodeCopy = common.Shortcut{ Service: "wiki", Command: "+node-copy", Description: "Copy a wiki node to a target space or parent node", Risk: "high-risk-write", Scopes: []string{"wiki:node:copy"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, Flags: []common.Flag{ {Name: "space-id", Desc: "source wiki space ID", Required: true}, {Name: "node-token", Desc: "source node token to copy", Required: true}, {Name: "target-space-id", Desc: "target wiki space ID; required if --target-parent-node-token is not set"}, {Name: "target-parent-node-token", Desc: "target parent node token; required if --target-space-id is not set"}, {Name: "title", Desc: "new title for the copied node; leave empty to keep the original title"}, }, Tips: []string{ "At least one of --target-space-id or --target-parent-node-token must be provided.", "Omit --title to keep the original node title in the copy.", }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if err := validateOptionalResourceName(strings.TrimSpace(runtime.Str("space-id")), "--space-id"); err != nil { return err } if err := validateOptionalResourceName(strings.TrimSpace(runtime.Str("node-token")), "--node-token"); err != nil { return err } targetSpaceID := strings.TrimSpace(runtime.Str("target-space-id")) targetParent := strings.TrimSpace(runtime.Str("target-parent-node-token")) if targetSpaceID == "" && targetParent == "" { return output.ErrValidation("at least one of --target-space-id or --target-parent-node-token is required") } if targetSpaceID != "" && targetParent != "" { return output.ErrValidation("--target-space-id and --target-parent-node-token are mutually exclusive; provide only one") } if err := validateOptionalResourceName(targetSpaceID, "--target-space-id"); err != nil { return err } return validateOptionalResourceName(targetParent, "--target-parent-node-token") }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { spaceID := strings.TrimSpace(runtime.Str("space-id")) nodeToken := strings.TrimSpace(runtime.Str("node-token")) return common.NewDryRunAPI(). POST(fmt.Sprintf("/open-apis/wiki/v2/spaces/%s/nodes/%s/copy", validate.EncodePathSegment(spaceID), validate.EncodePathSegment(nodeToken))). Body(buildNodeCopyBody(runtime)). Set("space_id", spaceID). Set("node_token", nodeToken) }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { spaceID := strings.TrimSpace(runtime.Str("space-id")) nodeToken := strings.TrimSpace(runtime.Str("node-token")) fmt.Fprintf(runtime.IO().ErrOut, "Copying wiki node %s from space %s\n", common.MaskToken(nodeToken), common.MaskToken(spaceID)) data, err := runtime.CallAPI("POST", fmt.Sprintf("/open-apis/wiki/v2/spaces/%s/nodes/%s/copy", validate.EncodePathSegment(spaceID), validate.EncodePathSegment(nodeToken)), nil, buildNodeCopyBody(runtime)) if err != nil { return err } node, err := parseWikiNodeRecord(common.GetMap(data, "node")) if err != nil { return err } fmt.Fprintf(runtime.IO().ErrOut, "Copied to node %s in space %s\n", common.MaskToken(node.NodeToken), common.MaskToken(node.SpaceID)) out := wikiNodeCopyOutput(node) runtime.OutFormat(out, nil, func(w io.Writer) { renderWikiNodeCopyPretty(w, out) }) return nil }, }
WikiNodeCopy copies a wiki node into a target space or under a target parent node.
var WikiNodeCreate = common.Shortcut{ Service: "wiki", Command: "+node-create", Description: "Create a wiki node with automatic space resolution", Risk: "write", Scopes: []string{"wiki:node:create", "wiki:node:read", "wiki:space:read"}, AuthTypes: []string{"user", "bot"}, Flags: []common.Flag{ {Name: "space-id", Desc: "target wiki space ID; use my_library for the personal document library"}, {Name: "parent-node-token", Desc: "parent wiki node token; if set, the new node is created under that parent"}, {Name: "title", Desc: "node title"}, {Name: "node-type", Default: wikiNodeTypeOrigin, Desc: "node type", Enum: []string{wikiNodeTypeOrigin, wikiNodeTypeShortcut}}, {Name: "obj-type", Default: "docx", Desc: "target object type", Enum: wikiObjectTypes}, {Name: "origin-node-token", Desc: "source node token when --node-type=shortcut"}, }, Tips: []string{ "If --space-id and --parent-node-token are both omitted, user identity falls back to my_library.", "Use --node-type shortcut --origin-node-token <token> to create a shortcut node.", }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { return validateWikiNodeCreateSpec(readWikiNodeCreateSpec(runtime), runtime.As()) }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { dry := buildWikiNodeCreateDryRun(readWikiNodeCreateSpec(runtime)) if runtime.IsBot() { dry.Desc("After wiki node creation succeeds in bot mode, the CLI will also try to grant the current CLI user full_access (可管理权限) on the new wiki node.") } return dry }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { spec := readWikiNodeCreateSpec(runtime) fmt.Fprintf(runtime.IO().ErrOut, "Creating wiki node...\n") execution, err := runWikiNodeCreate(ctx, wikiNodeCreateAPI{runtime: runtime}, runtime.As(), spec) if err != nil { return err } fmt.Fprintf(runtime.IO().ErrOut, "Created wiki node in space %s via %s.\n", execution.ResolvedSpace.SpaceID, execution.ResolvedSpace.ResolvedBy) runtime.Out(augmentWikiNodeCreateOutput(runtime, execution), nil) return nil }, }
WikiNodeCreate wraps wiki node creation with shortcut-specific ergonomics: it can infer the target space from the parent node or the caller's personal document library instead of forcing users to pass a numeric space ID first.
var WikiNodeList = common.Shortcut{ Service: "wiki", Command: "+node-list", Description: "List wiki nodes in a space or under a parent node", Risk: "read", Scopes: []string{"wiki:node:retrieve"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, Flags: []common.Flag{ {Name: "space-id", Desc: "wiki space ID; use my_library for the personal document library, or +space-list to discover other space IDs", Required: true}, {Name: "parent-node-token", Desc: "parent node token; if omitted, lists the root-level nodes of the space"}, {Name: "page-size", Type: "int", Default: strconv.Itoa(wikiNodeListDefaultPageSize), Desc: fmt.Sprintf("page size, 1-%d", wikiNodeListMaxPageSize)}, {Name: "page-token", Desc: "page token; implies single-page fetch (no auto-pagination)"}, {Name: "page-all", Type: "bool", Desc: "automatically paginate through all pages (capped by --page-limit)"}, {Name: "page-limit", Type: "int", Default: "10", Desc: "max pages to fetch with --page-all (default 10, 0 = unlimited)"}, }, Tips: []string{ "Default fetches a single page; pass --page-all to walk every page (large knowledge bases can be huge — keep an eye on --page-limit).", "Use --parent-node-token to drill into a sub-directory.", "Run +space-list first to discover your space IDs, including the personal document library.", "--space-id my_library is a per-user alias and is only valid with --as user.", }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { spaceID := strings.TrimSpace(runtime.Str("space-id")) if runtime.As().IsBot() && spaceID == wikiMyLibrarySpaceID { return output.ErrValidation("bot identity does not support --space-id my_library; use an explicit --space-id") } if err := validateOptionalResourceName(spaceID, "--space-id"); err != nil { return err } if err := validateOptionalResourceName(strings.TrimSpace(runtime.Str("parent-node-token")), "--parent-node-token"); err != nil { return err } return validateWikiListPagination(runtime, wikiNodeListMaxPageSize) }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { spaceID := strings.TrimSpace(runtime.Str("space-id")) params := map[string]interface{}{"page_size": runtime.Int("page-size")} if pt := strings.TrimSpace(runtime.Str("parent-node-token")); pt != "" { params["parent_node_token"] = pt } if pt := strings.TrimSpace(runtime.Str("page-token")); pt != "" { params["page_token"] = pt } d := common.NewDryRunAPI() if wikiListShouldAutoPaginate(runtime) { d.Desc("Auto-paginates through all pages (capped by --page-limit when > 0)") } if spaceID == wikiMyLibrarySpaceID { return d. Desc("2-step orchestration: resolve my_library -> list nodes"). GET("/open-apis/wiki/v2/spaces/my_library"). Desc("[1] Resolve my_library space ID"). GET(fmt.Sprintf("/open-apis/wiki/v2/spaces/%s/nodes", "<resolved_space_id>")). Desc("[2] List nodes"). Params(params). Set("space_id", "<resolved_space_id>") } return d. GET(fmt.Sprintf("/open-apis/wiki/v2/spaces/%s/nodes", validate.EncodePathSegment(spaceID))). Params(params). Set("space_id", spaceID) }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { warnIfConflictingPagingFlags(runtime) spaceID := strings.TrimSpace(runtime.Str("space-id")) if spaceID == wikiMyLibrarySpaceID { resolved, err := resolveMyLibrarySpaceID(runtime) if err != nil { return err } fmt.Fprintf(runtime.IO().ErrOut, "Resolved my_library to space %s\n", common.MaskToken(resolved)) spaceID = resolved } nodes, hasMore, nextToken, err := fetchWikiNodes(runtime, spaceID) if err != nil { return err } fmt.Fprintf(runtime.IO().ErrOut, "Found %d node(s)\n", len(nodes)) outData := map[string]interface{}{ "nodes": nodes, "has_more": hasMore, "page_token": nextToken, } runtime.OutFormat(outData, &output.Meta{Count: len(nodes)}, func(w io.Writer) { renderWikiNodesPretty(w, nodes, hasMore, nextToken) }) return nil }, }
WikiNodeList lists child nodes in a wiki space or under a parent node.
var WikiSpaceList = common.Shortcut{ Service: "wiki", Command: "+space-list", Description: "List wiki spaces accessible to the caller", Risk: "read", Scopes: []string{"wiki:space:retrieve"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, Flags: []common.Flag{ {Name: "page-size", Type: "int", Default: strconv.Itoa(wikiSpaceListDefaultPageSize), Desc: fmt.Sprintf("page size, 1-%d", wikiSpaceListMaxPageSize)}, {Name: "page-token", Desc: "page token; implies single-page fetch (no auto-pagination)"}, {Name: "page-all", Type: "bool", Desc: "automatically paginate through all pages (capped by --page-limit)"}, {Name: "page-limit", Type: "int", Default: "10", Desc: "max pages to fetch with --page-all (default 10, 0 = unlimited)"}, }, Tips: []string{ "Default fetches a single page (matches other list shortcuts in this CLI); pass --page-all to pull every page.", "The underlying API never returns the my_library personal library; resolve it via `wiki spaces get --params '{\"space_id\":\"my_library\"}'`.", }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { return validateWikiListPagination(runtime, wikiSpaceListMaxPageSize) }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { params := map[string]interface{}{"page_size": runtime.Int("page-size")} if pt := strings.TrimSpace(runtime.Str("page-token")); pt != "" { params["page_token"] = pt } dry := common.NewDryRunAPI() if wikiListShouldAutoPaginate(runtime) { dry.Desc("Auto-paginates through all pages (capped by --page-limit when > 0)") } return dry.GET(wikiSpaceListAPIPath).Params(params) }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { warnIfConflictingPagingFlags(runtime) spaces, hasMore, nextToken, err := fetchWikiSpaces(runtime) if err != nil { return err } fmt.Fprintf(runtime.IO().ErrOut, "Found %d wiki space(s)\n", len(spaces)) outData := map[string]interface{}{ "spaces": spaces, "has_more": hasMore, "page_token": nextToken, } runtime.OutFormat(outData, &output.Meta{Count: len(spaces)}, func(w io.Writer) { renderWikiSpacesPretty(w, spaces, hasMore, nextToken) }) return nil }, }
WikiSpaceList lists all wiki spaces the caller has access to.
Functions ¶
Types ¶
This section is empty.