diff --git a/README.md b/README.md index 06ac419..4d21518 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,75 @@ launchr login \ --keyring-passphrase-file=/path/to/your/secret ``` +To add a new key-value pair with an interactive shell: +```shell +launchr keyring:set your-key +``` + +It's possible to parse a user value and store it as a struct in a keyring. Supported formats are [string, yaml, json]: +```shell +launchr keyring:set your-key value +``` + +It's possible to parse a user value and store it as a struct in a keyring. Possible formats are [string, yaml, json]: +```shell +launchr keyring:set key --format yaml -- "- name: test-1 +- name: test-2" +launchr keyring:set key --format yaml -- "$(cat file.yaml)" +launchr keyring:set key --format json -- '[ + { + "name": "test-1" + }, + { + "name": "test-2" + } +]' +launchr keyring:set key --format json -- "$(cat file.json)" +``` + +You can dynamically build JSON\YAML wit structures and pass them directly to the command: `jq` +```shell +# Define your variables +TOKEN1="abc123def456" +NAME1="production-api-key" +CREATED1="2025-01-15T10:30:00Z" + +TOKEN2="xyz789uvw012" +NAME2="development-token" +CREATED2="2025-01-15T11:45:00Z" +EXPIRES2="2025-07-15T11:45:00Z" + +launchr keyring:set api-tokens-json --format json -- "$(jq -n \ + --arg t1 "$TOKEN1" --arg n1 "$NAME1" --arg c1 "$CREATED1" \ + --arg t2 "$TOKEN2" --arg n2 "$NAME2" --arg c2 "$CREATED2" --arg e2 "$EXPIRES2" \ + '[ + { + tokenhash: $t1, + name: $n1, + created: $c1, + expires: null + }, + { + tokenhash: $t2, + name: $n2, + created: $c2, + expires: $e2 + } + ]')" +``` +`yq` using same variables: +```shell +launchr keyring:set api-tokens-yaml --format yaml -- "$(yq -n \ + '.[0].tokenhash = env(TOKEN1) | + .[0].name = env(NAME1) | + .[0].created = env(CREATED1) | + .[0].expires = null | + .[1].tokenhash = env(TOKEN2) | + .[1].name = env(NAME2) | + .[1].created = env(CREATED2) | + .[1].expires = env(EXPIRES2)')" +``` + Flags `--keyring-passphrase` and `--keyring-passphrase-file` are available for all launchr commands, for example: ```shell launchr compose --keyring-passphrase=YOURPASSHRPASE diff --git a/action.set.yaml b/action.set.yaml index ab0a81c..f0bd6ef 100644 --- a/action.set.yaml +++ b/action.set.yaml @@ -13,3 +13,9 @@ action: title: Value description: Value default: "" + options: + - name: format + title: Value Format + description: Format to parse the input value + enum: ["string", "yaml", "json"] + default: string diff --git a/plugin.go b/plugin.go index c3f40a7..95534f3 100644 --- a/plugin.go +++ b/plugin.go @@ -175,7 +175,17 @@ func (p *Plugin) DiscoverActions(_ context.Context) ([]*action.Action, error) { key := KeyValueItem{ Key: input.Arg("key").(string), } - key.Value, _ = input.Arg("value").(string) + + userValue := input.Arg("value").(string) + format := input.Opt("format").(string) + var err error + + // @TODO cover with tests + key.Value, err = parseFromString(format, userValue) + if err != nil { + return fmt.Errorf("failed to parse %s: %w", format, err) + } + return saveKey(p.k, key) })) diff --git a/yaml.go b/yaml.go index 94bb458..c31bd0d 100644 --- a/yaml.go +++ b/yaml.go @@ -1,6 +1,7 @@ package keyring import ( + "encoding/json" "errors" "os" "strings" @@ -235,3 +236,22 @@ func (s *dataStoreYaml) Save() error { func (s *dataStoreYaml) Destroy() error { return s.file.Remove() } + +func parseFromString(format, value string) (interface{}, error) { + if format == "string" || value == "" { + return value, nil + } + + var parsed interface{} + var err error + switch format { + case "json": + err = json.Unmarshal([]byte(value), &parsed) + case "yaml": + err = yaml.Unmarshal([]byte(value), &parsed) + default: + panic("unsupported format: " + format) + } + + return parsed, err +}