wiki

package
v1.0.32 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 15, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
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.

View Source
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.

View Source
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.

View Source
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.

View Source
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.

View Source
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

func Shortcuts

func Shortcuts() []common.Shortcut

Shortcuts returns all wiki shortcuts.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL