mirror of
https://github.com/larksuite/cli.git
synced 2026-07-07 00:55:53 +08:00
* fix(api): add stdin and single-quote support for --params/--data on Windows (#64) Windows PowerShell 5.x mangles JSON double-quotes when passing arguments to native executables, causing --params and --data to fail with "invalid JSON format". This commit adds two mitigations at the framework level: - stdin piping: `echo '{"k":"v"}' | lark-cli --params -` bypasses shell argument parsing entirely and works on all platforms/shells. - single-quote stripping: cmd.exe passes literal single quotes which are now transparently removed before JSON parsing. Implementation: - New `cmdutil.ResolveInput(raw, stdin)` handles `-` (stdin), strip surrounding `'...'`, and plain passthrough. - `ParseJSONMap` and `ParseOptionalBody` now accept an `io.Reader` and delegate to `ResolveInput` before JSON unmarshalling. - `cmd/api` and `cmd/service` pass `IOStreams.In` and guard against simultaneous stdin usage by --params and --data. - Empty stdin is rejected with a clear error message. Closes #64 Change-Id: If21e735d0aed5c6a2d6674c1e6c898186fca3aba * test: add stdin e2e regression coverage Change-Id: I4e00bf1c6b6f3259f503e3414cae10fa4b34ba75
47 lines
1.2 KiB
Go
47 lines
1.2 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package cmdutil
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
)
|
|
|
|
// ResolveInput resolves special input conventions for a raw flag value:
|
|
// - "-" → read all bytes from stdin
|
|
// - "'...'" → strip surrounding single quotes (Windows cmd.exe compatibility)
|
|
// - other → return as-is
|
|
//
|
|
// This allows callers to bypass shell quoting issues (especially on Windows
|
|
// PowerShell) by piping JSON via stdin instead of command-line arguments.
|
|
func ResolveInput(raw string, stdin io.Reader) (string, error) {
|
|
if raw == "" {
|
|
return "", nil
|
|
}
|
|
|
|
// stdin
|
|
if raw == "-" {
|
|
if stdin == nil {
|
|
return "", fmt.Errorf("stdin is not available")
|
|
}
|
|
data, err := io.ReadAll(stdin)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to read stdin: %w", err)
|
|
}
|
|
s := strings.TrimSpace(string(data))
|
|
if s == "" {
|
|
return "", fmt.Errorf("stdin is empty (did you forget to pipe input?)")
|
|
}
|
|
return s, nil
|
|
}
|
|
|
|
// strip surrounding single quotes (Windows cmd.exe passes them literally)
|
|
if len(raw) >= 2 && raw[0] == '\'' && raw[len(raw)-1] == '\'' {
|
|
raw = raw[1 : len(raw)-1]
|
|
}
|
|
|
|
return raw, nil
|
|
}
|