Socket
Socket
Sign inDemoInstall

question-store

Package Overview
Dependencies
Maintainers
1
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

question-store - npm Package Compare versions

Comparing version 0.8.0 to 0.8.1

298

index.js

@@ -6,3 +6,3 @@ 'use strict';

var util = require('util');
var debug = require('debug')('question-store');
var debug = require('debug')('questions');
var Store = require('data-store');

@@ -14,2 +14,10 @@ var Options = require('option-cache');

/**
* Answer stores, for persisting answers across sessions
*/
var globals;
var store;
var hints;
/**
* Answer cache, for caching answers during a session,

@@ -35,8 +43,4 @@ * and potentially across instances

}
this.options = this.options || {};
Options.call(this);
Options.call(this, options);
use(this);
if (options) this.option(options);
this.initQuestions(this.options);

@@ -56,14 +60,36 @@ }

Questions.prototype.initQuestions = function(opts) {
debug('initializing question-store');
this.inquirer = opts.inquirer || utils.inquirer();
this.project = opts.project || utils.project(process.cwd());
this.answers = sessionAnswers;
this.data = opts.data || {};
this.answers = sessionAnswers;
this.cache = {};
this.queue = [];
this.createStores(opts);
};
// persist answers that the user has marked as a "global default"
utils.sync(this, 'global', function() {
return new Store('global-answers');
/**
* Create stores for persisting data across sessions.
*
* - `globals`: Persist non-project-specific answers when `question.options.global` is true
* - `store`: Persist project-specific answers
* - `hints`: Persist project-specific hints. This is used to populate the `question.default` value.
*
* @param {Object} `options`
* @return {Object}
* @api public
*/
Questions.prototype.createStores = function(options) {
var self = this;
// persist answers to questions with `{ global: true }`
utils.sync(this, 'globals', function() {
debug('creating globals store');
if (typeof globals === 'undefined') {
globals = new Store('globals', { cwd: utils.resolveDir('~/') });
debug('created globals store');
}
return globals;
});

@@ -73,3 +99,9 @@

utils.sync(this, 'store', function() {
return opts.store || new Store(this.project);
debug('creating project store');
if (typeof store === 'undefined') {
store = options.store || new Store(this.project);
debug('created project store');
}
return store;
});

@@ -79,3 +111,9 @@

utils.sync(this, 'hints', function() {
return new Store(this.project + '/hints');
debug('creating hints store');
if (typeof hints === 'undefined') {
hints = self.store.create('hints');
debug('created hints store');
}
return hints;
});

@@ -85,8 +123,13 @@ };

/**
* Cache a question to be asked at a later point. Creates an instance
* of [Question](#question), so any `Question` options or settings
* may be used.
* Calls [addQuestion](#addQuestion), with the only difference being that `.set`
* returns the `questions` instance and `.addQuestion` returns the question object.
* So use `.set` if you want to chain questions, or `.addQuestion` if you need
* the created question object.
*
* ```js
* questions.set('drink', 'What is your favorite beverage?');
* questions
* .set('drink', 'What is your favorite beverage?')
* .set('color', 'What is your favorite color?')
* .set('season', 'What is your favorite season?');
*
* // or

@@ -97,2 +140,3 @@ * questions.set('drink', {

* });
*
* // or

@@ -105,4 +149,5 @@ * questions.set({

* ```
* @param {Object|String} `value` Question object, message (string), or options object.
* @param {String} `locale` Optionally pass the locale to use, otherwise the default locale is used.
* @param {Object|String} `name` Question name, message (string), or question/options object.
* @param {Object|String} `value` Question message (string), or question/options object.
* @param {Object|String} `options` Question/options object.
* @api public

@@ -112,2 +157,34 @@ */

Questions.prototype.set = function(name, val, options) {
this.addQuestion.apply(this, arguments);
return this;
};
/**
* Add a question to be asked at a later point. Creates an instance of
* [Question](#question), so any `Question` options or settings may be used.
* Also, the default `type` is `input` if not defined by the user.
*
* ```js
* questions.addQuestion('drink', 'What is your favorite beverage?');
*
* // or
* questions.addQuestion('drink', {
* type: 'input',
* message: 'What is your favorite beverage?'
* });
*
* // or
* questions.addQuestion({
* name: 'drink'
* type: 'input',
* message: 'What is your favorite beverage?'
* });
* ```
* @param {Object|String} `name` Question name, message (string), or question/options object.
* @param {Object|String} `value` Question message (string), or question/options object.
* @param {Object|String} `options` Question/options object.
* @api public
*/
Questions.prototype.addQuestion = function(name, val, options) {
if (utils.isObject(name) && !utils.isQuestion(name)) {

@@ -118,2 +195,4 @@ return this.visit('set', name);

var question = new Question(name, val, options);
debug('questions#set "%s"', name);
this.emit('set', question.name, question);

@@ -124,2 +203,30 @@ this.cache[question.name] = question;

this.run(question);
return question;
};
/**
* Create a "choices" question from an array of values.
*
* ```js
* questions.choices('foo', ['a', 'b', 'c']);
*
* // or
* questions.choices('foo', {
* message: 'Favorite letter?',
* choices: ['a', 'b', 'c']
* });
* ```
* @param {String|Array} `queue` Name or array of question names.
* @param {Object|Function} `options` Question options or callback function
* @param {Function} `callback` callback function
* @api public
*/
Questions.prototype.choices = function(name, msg, items, options) {
var choices = utils.toChoices();
var question = choices.apply(null, arguments);
if (!question.hasOwnProperty('save')) {
question.save = false;
}
this.set(question.name, question);
return this;

@@ -129,2 +236,110 @@ };

/**
* Create a "list" question from an array of values.
*
* ```js
* questions.list('foo', ['a', 'b', 'c']);
*
* // or
* questions.list('foo', {
* message: 'Favorite letter?',
* choices: ['a', 'b', 'c']
* });
* ```
* @param {String|Array} `queue` Name or array of question names.
* @param {Object|Function} `options` Question options or callback function
* @param {Function} `callback` callback function
* @api public
*/
Questions.prototype.list = function(name, msg, list, options) {
var choices = utils.toChoices({type: 'list'});
var question = choices.apply(null, arguments);
if (options) {
question.options = options;
}
this.set(question.name, question);
return this;
};
/**
* Create a "rawlist" question from an array of values.
*
* ```js
* questions.rawlist('foo', ['a', 'b', 'c']);
*
* // or
* questions.rawlist('foo', {
* message: 'Favorite letter?',
* choices: ['a', 'b', 'c']
* });
* ```
* @param {String|Array} `queue` Name or array of question names.
* @param {Object|Function} `options` Question options or callback function
* @param {Function} `callback` callback function
* @api public
*/
Questions.prototype.rawlist = function(name, msg, list, options) {
var choices = utils.toChoices({type: 'rawlist'});
var question = choices.apply(null, arguments);
if (options) {
question.options = options;
}
this.set(question.name, question);
return this;
};
/**
* Create an "expand" question from an array of values.
*
* ```js
* questions.expand('foo', ['a', 'b', 'c']);
*
* // or
* questions.expand('foo', {
* message: 'Favorite letter?',
* choices: ['a', 'b', 'c']
* });
* ```
* @param {String|Array} `queue` Name or array of question names.
* @param {Object|Function} `options` Question options or callback function
* @param {Function} `callback` callback function
* @api public
*/
Questions.prototype.expand = function(name, msg, list, options) {
var choices = utils.toChoices({type: 'expand'});
var question = choices.apply(null, arguments);
if (options) {
question.options = options;
}
this.set(question.name, question);
return this;
};
/**
* Create a "choices" question from an array of values.
*
* ```js
* questions.choices('foo', ['a', 'b', 'c']);
*
* // or
* questions.choices('foo', {
* message: 'Favorite letter?',
* choices: ['a', 'b', 'c']
* });
* ```
* @param {String|Array} `queue` Name or array of question names.
* @param {Object|Function} `options` Question options or callback function
* @param {Function} `callback` callback function
* @api public
*/
Questions.prototype.confirm = function() {
var question = this.addQuestion.apply(this, arguments);
question.type = 'confirm';
return this;
};
/**
* Get question `name`, or group `name` if question is not found.

@@ -262,2 +477,4 @@ * You can also do a direct lookup using `quesions.cache['foo']`.

async.reduce(questions, this.answers, function(answers, key, next) {
debug('asking question "%s"', key);
try {

@@ -268,7 +485,9 @@ var opts = utils.merge({}, self.options, config);

var question = self.get(key);
var val = question.answer(answers, data, self.store, self.hints);
var options = question.opts(opts);
var val = question.answer(answers, data, self);
debug('using answer %j', val);
if (utils.isAnswer(val) && options.enabled('global')) {
val = this.global.get(key);
if (!utils.isAnswer(val) && options.enabled('global')) {
val = this.globals.get(key);
debug('no answer found, using global: "%s"', val);
}

@@ -282,4 +501,6 @@

options = question.opts(opts, question.options);
debug('using options %j', options);
if (options.enabled('skip')) {
debug('skipping question "%s", using answer "%j"', key, val);
question.next(val, self, answers, next);

@@ -293,3 +514,4 @@ return;

if (!isForced && utils.isAnswer(val)) {
utils.set(answers, question.name, val);
debug('question "%s", using answer "%j"', key, val);
utils.set(answers, key, val);
question.next(val, self, answers, next);

@@ -300,4 +522,9 @@ return;

self.inquirer.prompt([question], function(answer) {
debug('answered "%s" with "%j"', key, answer);
try {
var val = answer[question.name];
var val = answer[key];
if (question.type === 'checkbox') {
val = utils.flatten(val);
}

@@ -311,8 +538,10 @@ if (!utils.isAnswer(val)) {

if (!options.disabled('save')) {
self.store.set(question.name, val);
debug('saving answer in project store: %j', val);
self.store.set(key, val);
}
// persist to 'global-defaults' store if 'global' is enabled
// persist to 'global-globals' store if 'global' is enabled
if (options.enabled('global')) {
self.global.set(question.name, val);
debug('saving answer in global store: %j', val);
self.globals.set(key, val);
}

@@ -322,3 +551,4 @@

if (!options.disabled('hint')) {
self.hints.set(question.name, val);
debug('saving answer in hints store: %j', val);
self.hints.set(key, val);
}

@@ -330,3 +560,3 @@

// set answer on 'answers' cache
utils.set(answers, question.name, val);
utils.set(answers, key, val);
question.next(val, self, answers, next);

@@ -343,3 +573,7 @@ } catch (err) {

}
}, cb);
}, function(err, answers) {
if (err) return cb(err);
self.emit('answers', answers);
cb(null, answers);
});
};

@@ -379,2 +613,4 @@

Questions.prototype.normalize = function(name) {
debug('normalizing %j', name);
// get `name` from question object

@@ -381,0 +617,0 @@ if (utils.isQuestion(name)) {

@@ -10,2 +10,4 @@ /*!

var util = require('util');
var debug = require('debug')('questions:question');
var utils = require('./utils');

@@ -70,3 +72,2 @@

question.next = function(answer, questions, answers, next) {
if (answer === true) {

@@ -81,4 +82,30 @@ questions.ask(question.options.next, next);

Question.prototype.next = function(answer, questions, answers, cb) {
cb(null, answers);
/**
* Optionally define the next question to ask by setting a custom `next`
* function on the question object.
*
* ```js
* questions.choice('deps', 'Where?')
* questions.set('install', 'Want to install?', {
* type: 'confirm',
* next: function(answer, questions, answers, cb) {
* if (answer === true) {
* questions.ask('config.other', cb);
* } else {
* cb(null, answers);
* }
* }
* });
* ```
*
* @param {Object} `answer`
* @param {Object} `questions`
* @param {Object} `answers`
* @param {Function} `next`
* @return {Function}
* @api public
*/
Question.prototype.next = function(answer, questions, answers, next) {
next(null, answers);
};

@@ -131,16 +158,40 @@

Question.prototype.answer = function(answers, data, store, hints) {
Question.prototype.answer = function(answers, data, app) {
debug('looking for answer for: "%s"', this.name);
var answer = utils.get(data, this.name);
debug('answer:data %j', util.inspect(answer));
if (typeof answer === 'undefined') {
answer = answers[this.name];
debug('answer:answers %j', util.inspect(answer));
}
if (typeof answer === 'undefined') {
answer = store.get(this.name);
answer = utils.get(answers, this.name);
debug('answer:answers.get %j', util.inspect(answer));
}
if (typeof answer === 'undefined') {
answer = app.store.get(this.name);
debug('answer:store.get %j', util.inspect(answer));
}
if (typeof answer === 'undefined' && this.options.global === true) {
answer = app.globals.get(this.name);
debug('answer:globals.get %j', util.inspect(answer));
}
if (this.type === 'checkbox') {
debug('returning answer: %j', answer);
return answer;
}
if (typeof answer !== 'undefined') {
this.default = answer;
debug('default:answer %j', util.inspect(this.default));
}
if (typeof this.default === 'undefined') {
this.default = hints.get(this.name);
this.default = app.hints.get(this.name);
debug('default:hint %j', util.inspect(this.default));
}
debug('returning answer: %j', answer);
return answer;

@@ -147,0 +198,0 @@ };

@@ -11,5 +11,7 @@ 'use strict';

require = utils;
require('arr-flatten', 'flatten');
require('arr-union', 'union');
require('async');
require('define-property', 'define');
require('resolve-dir');
require('get-value', 'get');

@@ -24,2 +26,3 @@ require('has-value', 'has');

require('set-value', 'set');
require('to-choices');
require = fn;

@@ -26,0 +29,0 @@

8

package.json
{
"name": "question-store",
"description": "Ask questions, persist the answers. Basic support for i18n and storing answers based on current working directory.",
"version": "0.8.0",
"version": "0.8.1",
"homepage": "https://github.com/jonschlinkert/question-store",

@@ -24,5 +24,6 @@ "author": "Jon Schlinkert (https://github.com/jonschlinkert)",

"dependencies": {
"arr-flatten": "^1.0.1",
"arr-union": "^3.1.0",
"async": "^1.5.2",
"data-store": "^0.15.1",
"data-store": "^0.15.3",
"debug": "^2.2.0",

@@ -40,3 +41,5 @@ "define-property": "^0.2.5",

"project-name": "^0.2.4",
"resolve-dir": "^0.1.0",
"set-value": "^0.3.3",
"to-choices": "^0.2.0",
"use": "^1.1.2"

@@ -54,3 +57,2 @@ },

"question-match": "^0.1.1",
"resolve-dir": "^0.1.0",
"through2": "^2.0.1"

@@ -57,0 +59,0 @@ },

@@ -39,3 +39,3 @@ # question-store [![NPM version](https://img.shields.io/npm/v/question-store.svg)](https://www.npmjs.com/package/question-store) [![Build Status](https://img.shields.io/travis/jonschlinkert/question-store.svg)](https://travis-ci.org/jonschlinkert/question-store)

### [Questions](index.js#L29)
### [Questions](index.js#L37)

@@ -54,15 +54,33 @@ Create an instance of `Questions` with the given `options`.

### [.set](index.js#L102)
### [.createStores](index.js#L79)
Cache a question to be asked at a later point. Creates an instance of [Question](#question), so any `Question` options or settings may be used.
Create stores for persisting data across sessions.
* `globals`: Persist non-project-specific answers when `question.options.global` is true
* `store`: Persist project-specific answers
* `hints`: Persist project-specific hints. This is used to populate the `question.default` value.
**Params**
* `value` **{Object|String}**: Question object, message (string), or options object.
* `locale` **{String}**: Optionally pass the locale to use, otherwise the default locale is used.
* `options` **{Object}**
* `returns` **{Object}**
### [.set](index.js#L147)
Calls [addQuestion](#addQuestion), with the only difference being that `.set` returns the `questions` instance and `.addQuestion` returns the question object. So use `.set` if you want to chain questions, or `.addQuestion` if you need the created question object.
**Params**
* `name` **{Object|String}**: Question name, message (string), or question/options object.
* `value` **{Object|String}**: Question message (string), or question/options object.
* `options` **{Object|String}**: Question/options object.
**Example**
```js
questions.set('drink', 'What is your favorite beverage?');
questions
.set('drink', 'What is your favorite beverage?')
.set('color', 'What is your favorite color?')
.set('season', 'What is your favorite season?');
// or

@@ -73,2 +91,3 @@ questions.set('drink', {

});
// or

@@ -82,4 +101,135 @@ questions.set({

### [.get](index.js#L129)
### [.addQuestion](index.js#L179)
Add a question to be asked at a later point. Creates an instance of [Question](#question), so any `Question` options or settings may be used. Also, the default `type` is `input` if not defined by the user.
**Params**
* `name` **{Object|String}**: Question name, message (string), or question/options object.
* `value` **{Object|String}**: Question message (string), or question/options object.
* `options` **{Object|String}**: Question/options object.
**Example**
```js
questions.addQuestion('drink', 'What is your favorite beverage?');
// or
questions.addQuestion('drink', {
type: 'input',
message: 'What is your favorite beverage?'
});
// or
questions.addQuestion({
name: 'drink'
type: 'input',
message: 'What is your favorite beverage?'
});
```
### [.choices](index.js#L213)
Create a "choices" question from an array of values.
**Params**
* `queue` **{String|Array}**: Name or array of question names.
* `options` **{Object|Function}**: Question options or callback function
* `callback` **{Function}**: callback function
**Example**
```js
questions.choices('foo', ['a', 'b', 'c']);
// or
questions.choices('foo', {
message: 'Favorite letter?',
choices: ['a', 'b', 'c']
});
```
### [.list](index.js#L241)
Create a "list" question from an array of values.
**Params**
* `queue` **{String|Array}**: Name or array of question names.
* `options` **{Object|Function}**: Question options or callback function
* `callback` **{Function}**: callback function
**Example**
```js
questions.list('foo', ['a', 'b', 'c']);
// or
questions.list('foo', {
message: 'Favorite letter?',
choices: ['a', 'b', 'c']
});
```
### [.rawlist](index.js#L269)
Create a "rawlist" question from an array of values.
**Params**
* `queue` **{String|Array}**: Name or array of question names.
* `options` **{Object|Function}**: Question options or callback function
* `callback` **{Function}**: callback function
**Example**
```js
questions.rawlist('foo', ['a', 'b', 'c']);
// or
questions.rawlist('foo', {
message: 'Favorite letter?',
choices: ['a', 'b', 'c']
});
```
### [.expand](index.js#L297)
Create an "expand" question from an array of values.
**Params**
* `queue` **{String|Array}**: Name or array of question names.
* `options` **{Object|Function}**: Question options or callback function
* `callback` **{Function}**: callback function
**Example**
```js
questions.expand('foo', ['a', 'b', 'c']);
// or
questions.expand('foo', {
message: 'Favorite letter?',
choices: ['a', 'b', 'c']
});
```
### [.confirm](index.js#L325)
Create a "choices" question from an array of values.
**Params**
* `queue` **{String|Array}**: Name or array of question names.
* `options` **{Object|Function}**: Question options or callback function
* `callback` **{Function}**: callback function
**Example**
**GFM_5**
### [.get](index.js#L344)
Get question `name`, or group `name` if question is not found. You can also do a direct lookup using `quesions.cache['foo']`.

@@ -99,3 +249,3 @@

### [.has](index.js#L145)
### [.has](index.js#L360)

@@ -113,3 +263,3 @@ Returns true if `questions.cache` or `questions.groups` has question `name`.

### [.del](index.js#L170)
### [.del](index.js#L385)

@@ -133,3 +283,3 @@ Delete the given question or any questions that have the given namespace using dot-notation.

### [.clearAnswers](index.js#L188)
### [.clearAnswers](index.js#L403)

@@ -144,3 +294,3 @@ Clear all cached answers.

### [.clearQuestions](index.js#L203)
### [.clearQuestions](index.js#L418)

@@ -155,3 +305,3 @@ Clear all questions from the cache.

### [.clear](index.js#L218)
### [.clear](index.js#L433)

@@ -166,3 +316,3 @@ Clear all cached questions and answers.

### [.ask](index.js#L237)
### [.ask](index.js#L452)

@@ -185,3 +335,3 @@ Ask one or more questions, with the given `options` and callback.

### [.normalize](index.js#L356)
### [.normalize](index.js#L590)

@@ -195,3 +345,3 @@ Normalize the given value to return an array of question keys.

### [Question](lib/question.js#L23)
### [Question](lib/question.js#L25)

@@ -211,4 +361,32 @@ Create new `Question` store `name`, with the given `options`.

### [.answer](lib/question.js#L128)
### [.next](lib/question.js#L106)
Optionally define the next question to ask by setting a custom `next` function on the question object.
**Params**
* `answer` **{Object}**
* `questions` **{Object}**
* `answers` **{Object}**
* `next` **{Function}**
* `returns` **{Function}**
**Example**
```js
questions.choice('deps', 'Where?')
questions.set('install', 'Want to install?', {
type: 'confirm',
next: function(answer, questions, answers, cb) {
if (answer === true) {
questions.ask('config.other', cb);
} else {
cb(null, answers);
}
}
});
```
### [.answer](lib/question.js#L155)
Resolve the answer for the question from the given data sources, then set the question's `default` value with any stored hints or answers if not already defined.

@@ -230,3 +408,3 @@

### [.force](lib/question.js#L155)
### [.force](lib/question.js#L206)

@@ -233,0 +411,0 @@ Force the question to be asked.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc