bf9395e022
CI / results (push) Blocked by required conditions
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / e2e-live (push) Waiting to run
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / deadcode (push) Waiting to run
108 lines
3.6 KiB
Go
108 lines
3.6 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package sheets
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/larksuite/cli/shortcuts/common"
|
|
)
|
|
|
|
// ─── flag definitions, sourced from sheet-skill-spec ───────────────────
|
|
//
|
|
// data/flag-defs.json is the canonical, full definition of every CLI flag
|
|
// (name, type, default, desc, enum, input, hidden, required, kind),
|
|
// generated by sheet-skill-spec's sync script. The sync script also emits
|
|
// flag_defs_gen.go — the compiled `flagDefs` map — so command startup pays
|
|
// no JSON unmarshal (the parse cost used to land on every CLI invocation,
|
|
// sheets or not). We build each shortcut's []common.Flag from flagDefs at
|
|
// assembly time, so flag metadata never has to be hand-written in Go.
|
|
//
|
|
// Flags with kind == "system" (--dry-run, --yes, ...) are NOT materialized
|
|
// here: the framework auto-injects them based on Risk / DryRun / HasFormat.
|
|
// Do not hand-edit flag_defs_gen.go or data/flag-defs.json; regenerate via
|
|
// the sync script. flag_defs_gen_test.go guards the two against drift.
|
|
|
|
type flagDef struct {
|
|
Name string `json:"name"`
|
|
Kind string `json:"kind"` // "public" | "own" | "system"
|
|
Type string `json:"type"` // string | bool | int | int64 | float64 | string_array | string_slice
|
|
Required string `json:"required"` // "required" | "optional" | "xor"
|
|
Desc string `json:"desc"`
|
|
Default string `json:"default"`
|
|
Hidden bool `json:"hidden"`
|
|
Enum []string `json:"enum"`
|
|
Input []string `json:"input"`
|
|
}
|
|
|
|
type commandDef struct {
|
|
Risk string `json:"risk"`
|
|
Flags []flagDef `json:"flags"`
|
|
}
|
|
|
|
// loadFlagDefs returns the compiled flag definitions (flag_defs_gen.go).
|
|
// The error return is always nil; it is retained so existing call sites that
|
|
// handled a parse error keep compiling. There is no longer a runtime parse.
|
|
func loadFlagDefs() (map[string]commandDef, error) {
|
|
return flagDefs, nil
|
|
}
|
|
|
|
// flagsFor builds the []common.Flag for a shortcut command directly from
|
|
// flag-defs.json. System-kind flags are skipped (the framework injects
|
|
// them). Panics if the command is absent or the JSON is malformed — this
|
|
// is a build-time data contract, so a missing entry is a programming error
|
|
// surfaced loudly at startup rather than a silent empty flag set.
|
|
func flagsFor(command string) []common.Flag {
|
|
defs, err := loadFlagDefs()
|
|
if err != nil {
|
|
panic(fmt.Sprintf("sheets: %v", err))
|
|
}
|
|
spec, ok := defs[command]
|
|
if !ok {
|
|
panic(fmt.Sprintf("sheets: no flag-defs.json entry for %q", command))
|
|
}
|
|
out := make([]common.Flag, 0, len(spec.Flags))
|
|
for _, df := range spec.Flags {
|
|
if df.Kind == "system" {
|
|
continue
|
|
}
|
|
out = append(out, common.Flag{
|
|
Name: df.Name,
|
|
Type: df.Type,
|
|
Default: df.Default,
|
|
Desc: df.Desc,
|
|
Hidden: df.Hidden,
|
|
Required: df.Required == "required",
|
|
Enum: df.Enum,
|
|
Input: df.Input,
|
|
})
|
|
}
|
|
return out
|
|
}
|
|
|
|
// flagAcceptsStdin reports whether the (command, flag) pair declares stdin as
|
|
// an input source in flag-defs.json. Used to decide whether an "invalid JSON"
|
|
// error should also steer the caller toward stdin. It runs on an error path,
|
|
// so it returns false for an unknown command/flag rather than panicking the
|
|
// way flagsFor does.
|
|
func flagAcceptsStdin(command, name string) bool {
|
|
defs, _ := loadFlagDefs()
|
|
spec, ok := defs[command]
|
|
if !ok {
|
|
return false
|
|
}
|
|
for _, df := range spec.Flags {
|
|
if df.Name != name {
|
|
continue
|
|
}
|
|
for _, in := range df.Input {
|
|
if in == common.Stdin {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
return false
|
|
}
|