mirror of
https://github.com/larksuite/cli.git
synced 2026-07-03 14:02:43 +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
52 lines
1.5 KiB
Go
52 lines
1.5 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package cmdutil
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
|
|
"github.com/larksuite/cli/internal/output"
|
|
)
|
|
|
|
// ParseOptionalBody parses --data JSON for methods that accept a request body.
|
|
// Supports stdin (-) and single-quote stripping via ResolveInput.
|
|
// Returns (nil, nil) if the method has no body or data is empty.
|
|
func ParseOptionalBody(httpMethod, data string, stdin io.Reader) (interface{}, error) {
|
|
switch httpMethod {
|
|
case "POST", "PUT", "PATCH", "DELETE":
|
|
default:
|
|
return nil, nil
|
|
}
|
|
resolved, err := ResolveInput(data, stdin)
|
|
if err != nil {
|
|
return nil, output.ErrValidation("--data: %s", err)
|
|
}
|
|
if resolved == "" {
|
|
return nil, nil
|
|
}
|
|
var body interface{}
|
|
if err := json.Unmarshal([]byte(resolved), &body); err != nil {
|
|
return nil, output.ErrValidation("--data invalid JSON format")
|
|
}
|
|
return body, nil
|
|
}
|
|
|
|
// ParseJSONMap parses a JSON string into a map. Returns an empty map if input is empty.
|
|
// Supports stdin (-) and single-quote stripping via ResolveInput.
|
|
func ParseJSONMap(input, label string, stdin io.Reader) (map[string]any, error) {
|
|
resolved, err := ResolveInput(input, stdin)
|
|
if err != nil {
|
|
return nil, output.ErrValidation("%s: %s", label, err)
|
|
}
|
|
if resolved == "" {
|
|
return map[string]any{}, nil
|
|
}
|
|
var result map[string]any
|
|
if err := json.Unmarshal([]byte(resolved), &result); err != nil {
|
|
return nil, output.ErrValidation("%s invalid format, expected JSON object", label)
|
|
}
|
|
return result, nil
|
|
}
|