interactiveKeySet function

Future<void> interactiveKeySet({
  1. required String? name,
  2. required SecureKeyCache keys,
  3. required void onSecretStored(
    1. String name,
    2. String value
    )?,
  4. required Future<TuiPromptAnswer?> prompt(
    1. TuiPromptSpec
    ),
  5. required void onResult(
    1. String message
    ),
  6. required void onSaved(
    1. String name,
    2. String value
    ),
})

Testable core of the TUI key-set flow: prompts for name (when name is null) and a masked value through prompt, validates, saves to keys, and reports the outcome through onResult. The freshly saved key is handed to onSaved for immediate provider pickup.

Implementation

Future<void> interactiveKeySet({
  required String? name,
  required SecureKeyCache keys,
  required void Function(String name, String value)? onSecretStored,
  required Future<TuiPromptAnswer?> Function(TuiPromptSpec) prompt,
  required void Function(String message) onResult,
  required void Function(String name, String value) onSaved,
}) async {
  final keyNamePattern = RegExp(r'^[A-Za-z0-9_]+$');
  final keyName = await promptTextTui(
    prompt,
    name,
    header: 'Key',
    question: 'Key name (UPPER_SNAKE or [A-Za-z0-9_]+):',
  );
  if (keyName == null) return;
  if (!keyNamePattern.hasMatch(keyName)) {
    onResult('invalid key name: $keyName');
    return;
  }
  final value = await promptTextTui(
    prompt,
    null,
    header: 'Key',
    question: 'Value for $keyName:',
    secret: true,
  );
  if (value == null || value.isEmpty) {
    onResult('cancelled');
    return;
  }
  if (!await keys.save(keyName, value)) {
    onResult('could not save $keyName');
    return;
  }
  onSecretStored?.call(keyName, value);
  onResult('saved $keyName to ${keys.label}');
  onSaved(keyName, value);
}