UNPKG

luhn-generator

Version:

A generator of numbers that passes the validation of Luhn algorithm or Luhn formula, also known as the 'modulus 10' or 'mod 10' algorithm

125 lines (104 loc) 3.06 kB
'use strict'; var _ = require('lodash'); var { defer, empty, from, of } = require('rxjs'); var { concatMap, filter, publish, reduce } = require('rxjs/operators'); var runAsync = require('run-async'); var utils = require('../utils/utils'); var Base = require('./baseUI'); /** * Base interface class other can inherits from */ class PromptUI extends Base { constructor(prompts, opt) { super(opt); this.prompts = prompts; } run(questions) { // Keep global reference to the answers this.answers = {}; // Make sure questions is an array. if (_.isPlainObject(questions)) { questions = [questions]; } // Create an observable, unless we received one as parameter. // Note: As this is a public interface, we cannot do an instanceof check as we won't // be using the exact same object in memory. var obs = _.isArray(questions) ? from(questions) : questions; this.process = obs.pipe( concatMap(this.processQuestion.bind(this)), publish() // Creates a hot Observable. It prevents duplicating prompts. ); this.process.connect(); return this.process .pipe( reduce((answers, answer) => { _.set(this.answers, answer.name, answer.answer); return this.answers; }, {}) ) .toPromise(Promise) .then(this.onCompletion.bind(this)); } /** * Once all prompt are over */ onCompletion() { this.close(); return this.answers; } processQuestion(question) { question = _.clone(question); return defer(() => { var obs = of(question); return obs.pipe( concatMap(this.setDefaultType.bind(this)), concatMap(this.filterIfRunnable.bind(this)), concatMap(() => utils.fetchAsyncQuestionProperty(question, 'message', this.answers) ), concatMap(() => utils.fetchAsyncQuestionProperty(question, 'default', this.answers) ), concatMap(() => utils.fetchAsyncQuestionProperty(question, 'choices', this.answers) ), concatMap(this.fetchAnswer.bind(this)) ); }); } fetchAnswer(question) { var Prompt = this.prompts[question.type]; this.activePrompt = new Prompt(question, this.rl, this.answers); return defer(() => from( this.activePrompt.run().then(answer => ({ name: question.name, answer: answer })) ) ); } setDefaultType(question) { // Default type to input if (!this.prompts[question.type]) { question.type = 'input'; } return defer(() => of(question)); } filterIfRunnable(question) { if (question.when === false) { return empty(); } if (!_.isFunction(question.when)) { return of(question); } var answers = this.answers; return defer(() => from( runAsync(question.when)(answers).then(shouldRun => { if (shouldRun) { return question; } }) ).pipe(filter(val => val != null)) ); } } module.exports = PromptUI;