Implemented roadmap #9: Shell scripts execution with variables. Features: - set <name> <value> - Set shell variable - unset <name> - Remove variable - vars - List all variables - Variable substitution in all commands Variable syntax: - $VAR or ${VAR} - Shell variables - $ENV:VARNAME - Environment variables Variables expand before command execution, enabling: - Dynamic key paths: put $BASE/$ID '{"data":"value"}' - Reusable values: set TOKEN xyz && auth $TOKEN - Script parameterization in batch files Example batch script: set USER alice set KEY_PREFIX users put $KEY_PREFIX/$USER '{"name":"$USER"}' get $KEY_PREFIX/$USER Variables are session-scoped and work in both interactive and batch modes. Environment variables can be injected using $ENV:HOME syntax. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
64 lines
1.4 KiB
Go
64 lines
1.4 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// KVSClient maintains the connection state and configuration
|
|
type KVSClient struct {
|
|
baseURL string
|
|
currentToken string
|
|
currentUser string
|
|
httpClient *http.Client
|
|
profiles map[string]Profile
|
|
activeProfile string
|
|
variables map[string]string // Shell variables for scripting
|
|
}
|
|
|
|
// NewKVSClient creates a new KVS client instance
|
|
func NewKVSClient(baseURL string) *KVSClient {
|
|
return &KVSClient{
|
|
baseURL: baseURL,
|
|
httpClient: &http.Client{
|
|
Timeout: 30 * time.Second,
|
|
},
|
|
profiles: make(map[string]Profile),
|
|
variables: make(map[string]string),
|
|
}
|
|
}
|
|
|
|
// doRequest performs an HTTP request with JSON body and auth headers
|
|
func (c *KVSClient) doRequest(method, path string, body interface{}) ([]byte, int, error) {
|
|
var reqBody io.Reader
|
|
if body != nil {
|
|
jsonData, err := json.Marshal(body)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
reqBody = bytes.NewBuffer(jsonData)
|
|
}
|
|
|
|
req, err := http.NewRequest(method, c.baseURL+path, reqBody)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
if c.currentToken != "" {
|
|
req.Header.Set("Authorization", "Bearer "+c.currentToken)
|
|
}
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
respBody, err := io.ReadAll(resp.Body)
|
|
return respBody, resp.StatusCode, err
|
|
}
|