Skip to content

feat(cmdutil): support @file for params and data#724

Open
liangshuo-1 wants to merge 3 commits intomainfrom
feat/cmdutil-at-file-input
Open

feat(cmdutil): support @file for params and data#724
liangshuo-1 wants to merge 3 commits intomainfrom
feat/cmdutil-at-file-input

Conversation

@liangshuo-1
Copy link
Copy Markdown
Collaborator

@liangshuo-1 liangshuo-1 commented Apr 29, 2026

Summary

Adds @file input support for generic API/service --params and --data JSON flags so users can avoid shell quoting issues, especially on Windows PowerShell. This PR keeps file reads behind the FileIO abstraction and supersedes #715.

Changes

  • Support @path file input and @@ escaping in cmdutil.ResolveInput.
  • Wire api/service request builders to pass Factory.ResolveFileIO(ctx) for --params/--data parsing.
  • Share input-file read/error wrapping with shortcut flag input resolution while preserving shortcut empty-file behavior.
  • Update help text and tests for @file parsing, path validation, nil FileIO, empty JSON files, and shortcut empty-file reads.

Test Plan

  • Unit tests pass: make unit-test
  • Manual local verification confirms the lark xxx command works as expected (not run; behavior is covered by request-builder and cmdutil/shortcut unit tests)
  • go vet ./...
  • gofmt -l .
  • go mod tidy (no changes)
  • go run github.com/golangci/golangci-lint/v2/cmd/[email protected] run --new-from-rev=origin/main

Related Issues

Summary by CodeRabbit

  • New Features
    • --params and --data flags now support @<filepath> syntax to read input from files, with automatic whitespace trimming.
    • Added @@ escape sequence to specify literal @ characters in command-line input.

liangshuo-1 and others added 3 commits April 29, 2026 18:03
Inline JSON values for --params/--data are mangled by Windows
PowerShell 5's CommandLineToArgvW. Stdin (-) was the only escape
hatch but supports just one flag at a time.

Extend ResolveInput to accept @<path> (read JSON from a file) and
@@... (escape for a literal @-prefixed value), mirroring the
shortcuts framework's resolveInputFlags semantics. With this, both
--params and --data can be sourced from files in the same call,
sidestepping shell quoting on every platform.

- internal/cmdutil/resolve.go: add @path / @@ handling, trim file
  content like stdin does, error on empty path or empty file
- internal/cmdutil/resolve_test.go: cover file read, whitespace
  trim, missing file, empty path, empty content, @@ escape, plus
  ParseJSONMap / ParseOptionalBody integration through @file
- cmd/api/api.go, cmd/service/service.go: update --params/--data
  help text to mention @file

Change-Id: I366aa0f5783fbec6f05403f7f542505098a98c82
The first cut of @file support called os.ReadFile directly inside
ResolveInput, bypassing the codebase's fileio.FileIO abstraction
(SafeInputPath validation, pluggable provider). That diverged from
how every other file-reading path works: BuildFormdata for --file
uploads and the shortcuts framework's resolveInputFlags both go
through fileio.FileIO.Open with explicit fileio.ErrPathValidation
handling.

Re-route @file through the same path:

- ResolveInput, ParseJSONMap, ParseOptionalBody now take a
  fileio.FileIO; @path uses fileIO.Open which goes through
  SafeInputPath (control-char rejection, abs-path rejection,
  symlink-escape check) — same security posture as --file
- cmd/api and cmd/service callsites pass
  Factory.ResolveFileIO(ctx); the upload path now reuses the
  resolved fileIO instead of resolving twice
- Path-validation errors surface as
  `--params: invalid file path "...": ...` distinct from
  `--params: cannot read file "...": ...` for genuine I/O errors
- Nil fileIO with an @path returns a clear
  "file input (@path) is not available" error
- Tests use localfileio.LocalFileIO with TestChdir(t, dir),
  matching the existing fileupload_test.go pattern; absolute-path
  rejection and nil-fileIO are covered

This makes the feature behave identically under any FileIO
provider (including server mode) instead of being silently bound
to the local filesystem.

Change-Id: I878c4e8fb03f43f1f19afad75ec3af9cdab7a7f9
Change-Id: I92a6eb6ea8fd02054bf8f4925cd81807449d5e51
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

📝 Walkthrough

Walkthrough

The pull request adds @file input support for --params and --data flags by threading a fileIO dependency through the request parsing pipeline. The implementation introduces @path syntax to read JSON and body data from files, alongside a @@ escape prefix for literal @ values, while maintaining compatibility with existing stdin (-) and inline input methods.

Changes

Cohort / File(s) Summary
Command handlers
cmd/api/api.go, cmd/service/service.go
Updated help text to document @file input support; both now resolve fileIO once and thread it through ParseJSONMap and ParseOptionalBody for consistent file-backed input handling across normal and multipart form-upload paths.
Core input resolution
internal/cmdutil/resolve.go
Added @<path> and @@ input syntax support; implements ReadInputFile helper for centralized file reading with path validation and error wrapping; ResolveInput signature updated to accept fileIO parameter and handle file path resolution with trimming and validation.
JSON/body parsing
internal/cmdutil/json.go
Updated ParseOptionalBody and ParseJSONMap signatures to accept fileIO parameter and pass it through to ResolveInput, enabling file-backed JSON input for both functions.
Unit tests for parsing
internal/cmdutil/json_test.go, internal/cmdutil/resolve_test.go
Test invocations updated with new fileIO parameter; resolve_test.go introduces comprehensive @file test suite covering success cases, whitespace trimming, missing files, path validation, empty file rejection, and @@ escape handling.
Shortcut/runner utilities
shortcuts/common/runner.go, shortcuts/common/runner_input_test.go
resolveInputFlags now uses cmdutil.ReadInputFile instead of direct file I/O; error handling simplified to surface all failures uniformly; test suite adds TestResolveInputFlags_EmptyFile and uses cmdutil.TestChdir for cleaner temporary directory management.

Sequence Diagram

sequenceDiagram
    participant User as User/CLI
    participant Cmd as Command Handler<br/>(api.go/service.go)
    participant Resolve as ResolveInput<br/>(resolve.go)
    participant FileIO as FileIO Instance
    participant JSON as JSON Parser<br/>(json.go)
    participant File as File System

    User->>Cmd: Pass --params `@params.json`
    Cmd->>Cmd: Resolve fileIO from factory
    Cmd->>JSON: Call ParseJSONMap(input, fileIO)
    JSON->>Resolve: Call ResolveInput(input, fileIO)
    Resolve->>Resolve: Check if input starts with @
    alt `@file` path detected
        Resolve->>FileIO: Open file at path
        FileIO->>File: Read file contents
        File-->>FileIO: Return bytes
        FileIO-->>Resolve: Return trimmed string
    else @@escape or other
        Resolve->>Resolve: Return as-is or process
    end
    Resolve-->>JSON: Return resolved string
    JSON->>JSON: Parse JSON string
    JSON-->>Cmd: Return parsed JSON object
    Cmd->>Cmd: Use in request
    Cmd-->>User: Send API request
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

size/L

Suggested reviewers

  • kongenpei
  • MaxHuang22
  • liuxinyanglxy

Poem

🐰 A file-hopping hop and a @ so grand,

No shell-quoting woes in any land!

From PowerShell pains to paths so clean,

Our @file support saves the scene! ✨

Windows and bash, all friends at last,

Shell troubles fading to the past! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly and concisely summarizes the main feature addition: @file support for params and data flags, matching the primary objective.
Linked Issues check ✅ Passed All code changes directly implement the @file feature requirements from issue #705: ResolveInput handles @ and @@ escaping, FileIO abstraction is used throughout, help text is updated, and comprehensive tests cover the new functionality.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing @file support for --params/--data: internal utilities are extended with FileIO parameter, request builders thread it through, and tests are updated accordingly. No unrelated modifications detected.
Description check ✅ Passed The PR description covers all required sections with clear information about motivation, changes, test execution, and linked issue.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cmdutil-at-file-input

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the size/L Large or sensitive change across domains or core paths label Apr 29, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 29, 2026

Codecov Report

❌ Patch coverage is 91.83673% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.16%. Comparing base (4181925) to head (51a0ddc).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
internal/cmdutil/resolve.go 93.10% 1 Missing and 1 partial ⚠️
cmd/api/api.go 85.71% 1 Missing ⚠️
cmd/service/service.go 85.71% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #724      +/-   ##
==========================================
+ Coverage   64.14%   64.16%   +0.01%     
==========================================
  Files         504      504              
  Lines       44285    44337      +52     
==========================================
+ Hits        28406    28448      +42     
- Misses      13411    13416       +5     
- Partials     2468     2473       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/cmdutil/resolve.go (1)

32-73: ⚠️ Potential issue | 🟠 Major

Strip single quotes before interpreting special tokens.

Because Line 70 runs after the -/@ branches, inputs like '@params.json', '@@literal', and '-' are treated as plain strings instead of file/stdin/escaped inputs. That breaks the shell-quoting compatibility this feature is supposed to add.

Proposed fix
 func ResolveInput(raw string, stdin io.Reader, fileIO fileio.FileIO) (string, error) {
 	if raw == "" {
 		return "", nil
 	}
+
+	// strip surrounding single quotes first (Windows shell compatibility)
+	if len(raw) >= 2 && raw[0] == '\'' && raw[len(raw)-1] == '\'' {
+		raw = raw[1 : len(raw)-1]
+	}
 
 	// stdin
 	if raw == "-" {
 		if stdin == nil {
 			return "", fmt.Errorf("stdin is not available")
@@
-	// 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
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmdutil/resolve.go` around lines 32 - 73, The code currently strips
surrounding single quotes after handling stdin ("-"), escaped "@@" and file
"@path" branches, so inputs like "'@file'", "'@@literal'" or "'-'" are not
recognized; move the single-quote stripping logic (the check that trims raw =
raw[1:len(raw)-1] when raw starts and ends with '\'') to occur before the
stdin/escape/file handling (i.e., immediately after obtaining the raw
parameter), so that the subsequent checks using raw, stdin and
ReadInputFile(fileIO, path) correctly interpret quoted special tokens; ensure
you still preserve the existing behavior for unquoted inputs and keep the
escape/file/stdin branches unchanged otherwise.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@internal/cmdutil/resolve.go`:
- Around line 32-73: The code currently strips surrounding single quotes after
handling stdin ("-"), escaped "@@" and file "@path" branches, so inputs like
"'@file'", "'@@literal'" or "'-'" are not recognized; move the single-quote
stripping logic (the check that trims raw = raw[1:len(raw)-1] when raw starts
and ends with '\'') to occur before the stdin/escape/file handling (i.e.,
immediately after obtaining the raw parameter), so that the subsequent checks
using raw, stdin and ReadInputFile(fileIO, path) correctly interpret quoted
special tokens; ensure you still preserve the existing behavior for unquoted
inputs and keep the escape/file/stdin branches unchanged otherwise.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c798c0d7-fa93-4364-ba27-4afcbfe9c01a

📥 Commits

Reviewing files that changed from the base of the PR and between d7ee5b5 and 51a0ddc.

📒 Files selected for processing (8)
  • cmd/api/api.go
  • cmd/service/service.go
  • internal/cmdutil/json.go
  • internal/cmdutil/json_test.go
  • internal/cmdutil/resolve.go
  • internal/cmdutil/resolve_test.go
  • shortcuts/common/runner.go
  • shortcuts/common/runner_input_test.go

@github-actions
Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@51a0ddce805475bb4a6e5e755087f6c058c3f532

🧩 Skill update

npx skills add larksuite/cli#feat/cmdutil-at-file-input -y -g

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--params / --data fail on Windows PowerShell 5 due to JSON quote mangling + feature request: @file support

1 participant