generated from bennycode/ts-node-starter
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathWizardy.ts
74 lines (64 loc) · 2.03 KB
/
Wizardy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import {EventEmitter} from 'events';
import {Prompt} from './Prompt';
export enum TOPIC {
'END' = 'Wizardy.TOPIC.END',
'START' = 'Wizardy.TOPIC.START',
}
export interface Wizardy<T = any> {
on(event: TOPIC.START, listener: () => void): this;
on(event: TOPIC.END, listener: (answers: Record<string, T>) => void): this;
}
export class Wizardy<T = any> extends EventEmitter {
private static readonly STARTING_INDEX = -1;
static TOPIC = TOPIC;
answers: Record<string, T> = {};
inConversation: boolean = false;
private index: number = Wizardy.STARTING_INDEX;
private questions: Prompt<T>[] = [];
constructor(public id?: string) {
super();
}
addQuestion(question: Prompt<T>): void {
this.questions.push(question);
if (this.index === -1) {
this.emit(Wizardy.TOPIC.START);
this.index = 0;
}
}
addQuestions(questions: Prompt<T>[]): void {
questions.forEach(question => this.addQuestion(question));
}
answer(answer: string): string {
const question = Object.assign({}, this.questions[this.index]);
try {
const {answerKey, response} = question;
const value = question.answerValue(answer, this.answers);
this.answers[answerKey] = value;
this.questions.shift();
if (this.questions.length === 0) {
this.inConversation = false;
this.emit(Wizardy.TOPIC.END, this.answers);
}
return typeof response === 'string' ? response : response();
} catch (error) {
return error instanceof Error ? error.message : 'Unknown error without an error message.';
}
}
ask(): string {
if (this.questions.length === 0) {
throw Error('Please add some questions.');
}
this.inConversation = true;
const question = this.questions[this.index]!.question;
return typeof question === 'string' ? question : question();
}
get step(): number {
return Object.keys(this.answers).length;
}
reset(): void {
this.answers = {};
this.index = Wizardy.STARTING_INDEX;
this.inConversation = false;
this.questions = [];
}
}