You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
3.1 KiB
77 lines
3.1 KiB
import {AnySchemaDataFor} from "./SchemaData";
|
|
import {dump, load} from "js-yaml";
|
|
import {InquireFunction, ShowFunction} from "../prompts/Inquire";
|
|
import {EditorQuestion, ExpandQuestion} from "inquirer";
|
|
|
|
const RETRY = "Retry"
|
|
const ABORT = "Abort"
|
|
|
|
export interface YamlPromptOptions<ObjectT> {
|
|
schema: AnySchemaDataFor<ObjectT>
|
|
currentValue: ObjectT|undefined
|
|
name: string
|
|
}
|
|
|
|
export interface YamlPromptSetOptions<ObjectT> extends YamlPromptOptions<ObjectT> {
|
|
currentValue: ObjectT
|
|
}
|
|
|
|
export interface YamlPromptDependencies {
|
|
inquire: InquireFunction<EditorQuestion, string> & InquireFunction<ExpandQuestion, typeof RETRY|typeof ABORT>
|
|
showError: ShowFunction
|
|
}
|
|
|
|
export type YamlPromptFunction = (<ObjectT>(opts: YamlPromptSetOptions<ObjectT>) => Promise<ObjectT>) & (<ObjectT>(opts: YamlPromptOptions<ObjectT>) => Promise<ObjectT|undefined>)
|
|
|
|
export function yamlPrompt(deps: YamlPromptDependencies): YamlPromptFunction {
|
|
function injectedYamlPrompt<ObjectT>(opts: YamlPromptSetOptions<ObjectT>): Promise<ObjectT>
|
|
function injectedYamlPrompt<ObjectT>(opts: YamlPromptOptions<ObjectT>): Promise<ObjectT|undefined>
|
|
function injectedYamlPrompt<ObjectT>(opts: YamlPromptOptions<ObjectT>): Promise<ObjectT|undefined> {
|
|
return promptForYaml<ObjectT>(opts, deps)
|
|
}
|
|
return injectedYamlPrompt
|
|
}
|
|
|
|
export async function promptForYaml<ObjectT>({schema, currentValue, name}: YamlPromptSetOptions<ObjectT>, {inquire, showError}: YamlPromptDependencies): Promise<ObjectT>
|
|
export async function promptForYaml<ObjectT>({schema, currentValue, name}: YamlPromptOptions<ObjectT>, {inquire, showError}: YamlPromptDependencies): Promise<ObjectT|undefined>
|
|
export async function promptForYaml<ObjectT>({schema, currentValue, name}: YamlPromptOptions<ObjectT>, {inquire, showError}: YamlPromptDependencies): Promise<ObjectT|undefined> {
|
|
const original = dump(currentValue)
|
|
let text = original
|
|
while (true) {
|
|
const modified = await inquire({
|
|
type: "editor",
|
|
message: `View and edit ${name}:`,
|
|
default: text,
|
|
})
|
|
if (original !== modified) {
|
|
try {
|
|
const result = load(modified)
|
|
if (schema.validate(result)) {
|
|
return result
|
|
} else {
|
|
await showError(schema.validate.errors?.map((e) => e.toString()).join("; ") || "Failed validation")
|
|
}
|
|
} catch (e) {
|
|
await showError(e.toString())
|
|
}
|
|
const option = await inquire({
|
|
type: "expand",
|
|
message: "Choose how to proceed:",
|
|
choices: [
|
|
{key: "r", name: "Retry edits with current text", value: RETRY},
|
|
{key: "a", name: "Abort editing and keep original state", value: ABORT}
|
|
],
|
|
})
|
|
switch (option) {
|
|
default:
|
|
case RETRY:
|
|
text = modified
|
|
break
|
|
case ABORT:
|
|
return currentValue
|
|
}
|
|
} else {
|
|
return currentValue
|
|
}
|
|
}
|
|
} |