pax_global_header00006660000000000000000000000064125011163120014502gustar00rootroot0000000000000052 comment=780ead051299aa28be2584199ab6fa503a32d354 promzard-0.3.0/000077500000000000000000000000001250111631200133405ustar00rootroot00000000000000promzard-0.3.0/.gitignore000066400000000000000000000000361250111631200153270ustar00rootroot00000000000000example/npm-init/package.json promzard-0.3.0/LICENSE000066400000000000000000000013541250111631200143500ustar00rootroot00000000000000The ISC License Copyright (c) Isaac Z. Schlueter Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. promzard-0.3.0/README.md000066400000000000000000000105721250111631200146240ustar00rootroot00000000000000# promzard A prompting wizard for building files from specialized PromZard modules. Used by `npm init`. A reimplementation of @SubStack's [prompter](https://github.com/substack/node-prompter), which does not use AST traversal. From another point of view, it's a reimplementation of [@Marak](https://github.com/marak)'s [wizard](https://github.com/Marak/wizard) which doesn't use schemas. The goal is a nice drop-in enhancement for `npm init`. ## Usage ```javascript var promzard = require('promzard') promzard(inputFile, optionalContextAdditions, function (er, data) { // .. you know what you doing .. }) ``` In the `inputFile` you can have something like this: ```javascript var fs = require('fs') module.exports = { "greeting": prompt("Who shall you greet?", "world", function (who) { return "Hello, " + who }), "filename": __filename, "directory": function (cb) { fs.readdir(__dirname, cb) } } ``` When run, promzard will display the prompts and resolve the async functions in order, and then either give you an error, or the resolved data, ready to be dropped into a JSON file or some other place. ### promzard(inputFile, ctx, callback) The inputFile is just a node module. You can require() things, set module.exports, etc. Whatever that module exports is the result, and it is walked over to call any functions as described below. The only caveat is that you must give PromZard the full absolute path to the module (you can get this via Node's `require.resolve`.) Also, the `prompt` function is injected into the context object, so watch out. Whatever you put in that `ctx` will of course also be available in the module. You can get quite fancy with this, passing in existing configs and so on. ### Class: promzard.PromZard(file, ctx) Just like the `promzard` function, but the EventEmitter that makes it all happen. Emits either a `data` event with the data, or a `error` event if it blows up. If `error` is emitted, then `data` never will be. ### prompt(...) In the promzard input module, you can call the `prompt` function. This prompts the user to input some data. The arguments are interpreted based on type: 1. `string` The first string encountered is the prompt. The second is the default value. 2. `function` A transformer function which receives the data and returns something else. More than meets the eye. 3. `object` The `prompt` member is the prompt, the `default` member is the default value, and the `transform` is the transformer. Whatever the final value is, that's what will be put on the resulting object. ### Functions If there are any functions on the promzard input module's exports, then promzard will call each of them with a callback. This way, your module can do asynchronous actions if necessary to validate or ascertain whatever needs verification. The functions are called in the context of the ctx object, and are given a single argument, which is a callback that should be called with either an error, or the result to assign to that spot. In the async function, you can also call prompt() and return the result of the prompt in the callback. For example, this works fine in a promzard module: ``` exports.asyncPrompt = function (cb) { fs.stat(someFile, function (er, st) { // if there's an error, no prompt, just error // otherwise prompt and use the actual file size as the default cb(er, prompt('file size', st.size)) }) } ``` You can also return other async functions in the async function callback. Though that's a bit silly, it could be a handy way to reuse functionality in some cases. ### Sync vs Async The `prompt()` function is not synchronous, though it appears that way. It just returns a token that is swapped out when the data object is walked over asynchronously later, and returns a token. For that reason, prompt() calls whose results don't end up on the data object are never shown to the user. For example, this will only prompt once: ``` exports.promptThreeTimes = prompt('prompt me once', 'shame on you') exports.promptThreeTimes = prompt('prompt me twice', 'um....') exports.promptThreeTimes = prompt('you cant prompt me again') ``` ### Isn't this exactly the sort of 'looks sync' that you said was bad about other libraries? Yeah, sorta. I wouldn't use promzard for anything more complicated than a wizard that spits out prompts to set up a config file or something. Maybe there are other use cases I haven't considered. promzard-0.3.0/example/000077500000000000000000000000001250111631200147735ustar00rootroot00000000000000promzard-0.3.0/example/buffer.js000066400000000000000000000005171250111631200166050ustar00rootroot00000000000000var pz = require('../promzard') var path = require('path') var file = path.resolve(__dirname, 'substack-input.js') var buf = require('fs').readFileSync(file) var ctx = { basename: path.basename(path.dirname(file)) } pz.fromBuffer(buf, ctx, function (er, res) { if (er) throw er console.error(JSON.stringify(res, null, 2)) }) promzard-0.3.0/example/index.js000066400000000000000000000004321250111631200164370ustar00rootroot00000000000000var pz = require('../promzard') var path = require('path') var file = path.resolve(__dirname, 'substack-input.js') var ctx = { basename: path.basename(path.dirname(file)) } pz(file, ctx, function (er, res) { if (er) throw er console.error(JSON.stringify(res, null, 2)) }) promzard-0.3.0/example/npm-init/000077500000000000000000000000001250111631200165265ustar00rootroot00000000000000promzard-0.3.0/example/npm-init/README.md000066400000000000000000000002341250111631200200040ustar00rootroot00000000000000# npm-init An initter you init wit, innit? ## More stuff here Blerp derp herp lerg borgle pop munch efemerate baz foo a gandt synergy jorka chatt slurm. promzard-0.3.0/example/npm-init/init-input.js000066400000000000000000000136521250111631200211730ustar00rootroot00000000000000var fs = require('fs') var path = require('path'); module.exports = { "name" : prompt('name', typeof name === 'undefined' ? basename.replace(/^node-|[.-]js$/g, ''): name), "version" : prompt('version', typeof version !== "undefined" ? version : '0.0.0'), "description" : (function () { if (typeof description !== 'undefined' && description) { return description } var value; try { var src = fs.readFileSync('README.md', 'utf8'); value = src.split('\n').filter(function (line) { return /\s+/.test(line) && line.trim() !== basename.replace(/^node-/, '') && !line.trim().match(/^#/) ; })[0] .trim() .replace(/^./, function (c) { return c.toLowerCase() }) .replace(/\.$/, '') ; } catch (e) { try { // Wouldn't it be nice if that file mattered? var d = fs.readFileSync('.git/description', 'utf8') } catch (e) {} if (d.trim() && !value) value = d } return prompt('description', value); })(), "main" : (function () { var f try { f = fs.readdirSync(dirname).filter(function (f) { return f.match(/\.js$/) }) if (f.indexOf('index.js') !== -1) f = 'index.js' else if (f.indexOf('main.js') !== -1) f = 'main.js' else if (f.indexOf(basename + '.js') !== -1) f = basename + '.js' else f = f[0] } catch (e) {} return prompt('entry point', f || 'index.js') })(), "bin" : function (cb) { fs.readdir(dirname + '/bin', function (er, d) { // no bins if (er) return cb() // just take the first js file we find there, or nada return cb(null, d.filter(function (f) { return f.match(/\.js$/) })[0]) }) }, "directories" : function (cb) { fs.readdir('.', function (er, dirs) { if (er) return cb(er) var res = {} dirs.forEach(function (d) { switch (d) { case 'example': case 'examples': return res.example = d case 'test': case 'tests': return res.test = d case 'doc': case 'docs': return res.doc = d case 'man': return res.man = d } }) if (Object.keys(res).length === 0) res = undefined return cb(null, res) }) }, "dependencies" : typeof dependencies !== 'undefined' ? dependencies : function (cb) { fs.readdir('node_modules', function (er, dir) { if (er) return cb() var deps = {} var n = dir.length dir.forEach(function (d) { if (d.match(/^\./)) return next() if (d.match(/^(expresso|mocha|tap|coffee-script|coco|streamline)$/)) return next() fs.readFile('node_modules/' + d + '/package.json', function (er, p) { if (er) return next() try { p = JSON.parse(p) } catch (e) { return next() } if (!p.version) return next() deps[d] = '~' + p.version return next() }) }) function next () { if (--n === 0) return cb(null, deps) } }) }, "devDependencies" : typeof devDependencies !== 'undefined' ? devDependencies : function (cb) { // same as dependencies but for dev deps fs.readdir('node_modules', function (er, dir) { if (er) return cb() var deps = {} var n = dir.length dir.forEach(function (d) { if (d.match(/^\./)) return next() if (!d.match(/^(expresso|mocha|tap|coffee-script|coco|streamline)$/)) return next() fs.readFile('node_modules/' + d + '/package.json', function (er, p) { if (er) return next() try { p = JSON.parse(p) } catch (e) { return next() } if (!p.version) return next() deps[d] = '~' + p.version return next() }) }) function next () { if (--n === 0) return cb(null, deps) } }) }, "scripts" : (function () { // check to see what framework is in use, if any try { var d = fs.readdirSync('node_modules') } catch (e) { d = [] } var s = typeof scripts === 'undefined' ? {} : scripts if (d.indexOf('coffee-script') !== -1) s.prepublish = prompt('build command', s.prepublish || 'coffee src/*.coffee -o lib') var notest = 'echo "Error: no test specified" && exit 1' function tx (test) { return test || notest } if (!s.test || s.test === notest) { if (d.indexOf('tap') !== -1) s.test = prompt('test command', 'tap test/*.js', tx) else if (d.indexOf('expresso') !== -1) s.test = prompt('test command', 'expresso test', tx) else if (d.indexOf('mocha') !== -1) s.test = prompt('test command', 'mocha', tx) else s.test = prompt('test command', tx) } return s })(), "repository" : (function () { try { var gconf = fs.readFileSync('.git/config') } catch (e) { gconf = null } if (gconf) { gconf = gconf.split(/\r?\n/) var i = gconf.indexOf('[remote "origin"]') if (i !== -1) { var u = gconf[i + 1] if (!u.match(/^\s*url =/)) u = gconf[i + 2] if (!u.match(/^\s*url =/)) u = null else u = u.replace(/^\s*url = /, '') } if (u && u.match(/^git@github.com:/)) u = u.replace(/^git@github.com:/, 'git://github.com/') } return prompt('git repository', u) })(), "keywords" : prompt(function (s) { if (!s) return undefined if (Array.isArray(s)) s = s.join(' ') if (typeof s !== 'string') return s return s.split(/[\s,]+/) }), "author" : config['init.author.name'] ? { "name" : config['init.author.name'], "email" : config['init.author.email'], "url" : config['init.author.url'] } : undefined, "license" : prompt('license', 'BSD') } promzard-0.3.0/example/npm-init/init.js000066400000000000000000000020101250111631200200200ustar00rootroot00000000000000var PZ = require('../../promzard').PromZard var path = require('path') var input = path.resolve(__dirname, 'init-input.js') var fs = require('fs') var package = path.resolve(__dirname, 'package.json') var pkg fs.readFile(package, 'utf8', function (er, d) { if (er) ctx = {} try { ctx = JSON.parse(d); pkg = JSON.parse(d) } catch (e) { ctx = {} } ctx.dirname = path.dirname(package) ctx.basename = path.basename(ctx.dirname) if (!ctx.version) ctx.version = undefined // this should be replaced with the npm conf object ctx.config = {} console.error('ctx=', ctx) var pz = new PZ(input, ctx) pz.on('data', function (data) { console.error('pz data', data) if (!pkg) pkg = {} Object.keys(data).forEach(function (k) { if (data[k] !== undefined && data[k] !== null) pkg[k] = data[k] }) console.error('package data %s', JSON.stringify(data, null, 2)) fs.writeFile(package, JSON.stringify(pkg, null, 2), function (er) { if (er) throw er console.log('ok') }) }) }) promzard-0.3.0/example/substack-input.js000066400000000000000000000034131250111631200203060ustar00rootroot00000000000000module.exports = { "name" : basename.replace(/^node-/, ''), "version" : "0.0.0", "description" : (function (cb) { var fs = require('fs'); var value; try { var src = fs.readFileSync('README.markdown', 'utf8'); value = src.split('\n').filter(function (line) { return /\s+/.test(line) && line.trim() !== basename.replace(/^node-/, '') ; })[0] .trim() .replace(/^./, function (c) { return c.toLowerCase() }) .replace(/\.$/, '') ; } catch (e) {} return prompt('description', value); })(), "main" : prompt('entry point', 'index.js'), "bin" : function (cb) { var path = require('path'); var fs = require('fs'); var exists = fs.exists || path.exists; exists('bin/cmd.js', function (ex) { var bin if (ex) { var bin = {} bin[basename.replace(/^node-/, '')] = 'bin/cmd.js' } cb(null, bin); }); }, "directories" : { "example" : "example", "test" : "test" }, "dependencies" : {}, "devDependencies" : { "tap" : "~0.2.5" }, "scripts" : { "test" : "tap test/*.js" }, "repository" : { "type" : "git", "url" : "git://github.com/substack/" + basename + ".git" }, "homepage" : "https://github.com/substack/" + basename, "keywords" : prompt(function (s) { return s.split(/\s+/) }), "author" : { "name" : "James Halliday", "email" : "mail@substack.net", "url" : "http://substack.net" }, "license" : "MIT", "engine" : { "node" : ">=0.6" } } promzard-0.3.0/package.json000066400000000000000000000006241250111631200156300ustar00rootroot00000000000000{ "author": "Isaac Z. Schlueter (http://blog.izs.me/)", "name": "promzard", "description": "prompting wizardly", "version": "0.3.0", "repository": { "url": "git://github.com/isaacs/promzard" }, "dependencies": { "read": "1" }, "devDependencies": { "tap": "~0.2.5" }, "main": "promzard.js", "scripts": { "test": "tap test/*.js" }, "license": "ISC" } promzard-0.3.0/promzard.js000066400000000000000000000136511250111631200155420ustar00rootroot00000000000000module.exports = promzard promzard.PromZard = PromZard var fs = require('fs') var vm = require('vm') var util = require('util') var files = {} var crypto = require('crypto') var EventEmitter = require('events').EventEmitter var read = require('read') var Module = require('module').Module var path = require('path') function promzard (file, ctx, cb) { if (typeof ctx === 'function') cb = ctx, ctx = null; if (!ctx) ctx = {}; var pz = new PromZard(file, ctx) pz.on('error', cb) pz.on('data', function (data) { cb(null, data) }) } promzard.fromBuffer = function (buf, ctx, cb) { var filename = 0 do { filename = '\0' + Math.random(); } while (files[filename]) files[filename] = buf var ret = promzard(filename, ctx, cb) delete files[filename] return ret } function PromZard (file, ctx) { if (!(this instanceof PromZard)) return new PromZard(file, ctx) EventEmitter.call(this) this.file = file this.ctx = ctx this.unique = crypto.randomBytes(8).toString('hex') this.load() } PromZard.prototype = Object.create( EventEmitter.prototype, { constructor: { value: PromZard, readable: true, configurable: true, writable: true, enumerable: false } } ) PromZard.prototype.load = function () { if (files[this.file]) return this.loaded() fs.readFile(this.file, 'utf8', function (er, d) { if (er && this.backupFile) { this.file = this.backupFile delete this.backupFile return this.load() } if (er) return this.emit('error', this.error = er) files[this.file] = d this.loaded() }.bind(this)) } PromZard.prototype.loaded = function () { this.ctx.prompt = this.makePrompt() this.ctx.__filename = this.file this.ctx.__dirname = path.dirname(this.file) this.ctx.__basename = path.basename(this.file) var mod = this.ctx.module = this.makeModule() this.ctx.require = function (path) { return mod.require(path) } this.ctx.require.resolve = function(path) { return Module._resolveFilename(path, mod); } this.ctx.exports = mod.exports this.script = this.wrap(files[this.file]) var fn = vm.runInThisContext(this.script, this.file) var args = Object.keys(this.ctx).map(function (k) { return this.ctx[k] }.bind(this)) try { var res = fn.apply(this.ctx, args) } catch (er) { this.emit('error', er) } if (res && typeof res === 'object' && exports === mod.exports && Object.keys(exports).length === 1) { this.result = res } else { this.result = mod.exports } this.walk() } PromZard.prototype.makeModule = function () { var mod = new Module(this.file, module) mod.loaded = true mod.filename = this.file mod.id = this.file mod.paths = Module._nodeModulePaths(path.dirname(this.file)) return mod } PromZard.prototype.wrap = function (body) { var s = '(function( %s ) { %s\n })' var args = Object.keys(this.ctx).join(', ') return util.format(s, args, body) } PromZard.prototype.makePrompt = function () { this.prompts = [] return prompt.bind(this) function prompt () { var p, d, t for (var i = 0; i < arguments.length; i++) { var a = arguments[i] if (typeof a === 'string' && p) d = a else if (typeof a === 'string') p = a else if (typeof a === 'function') t = a else if (a && typeof a === 'object') { p = a.prompt || p d = a.default || d t = a.transform || t } } try { return this.unique + '-' + this.prompts.length } finally { this.prompts.push([p, d, t]) } } } PromZard.prototype.walk = function (o, cb) { o = o || this.result cb = cb || function (er, res) { if (er) return this.emit('error', this.error = er) this.result = res return this.emit('data', res) } cb = cb.bind(this) var keys = Object.keys(o) var i = 0 var len = keys.length L.call(this) function L () { if (this.error) return while (i < len) { var k = keys[i] var v = o[k] i++ if (v && typeof v === 'object') { return this.walk(v, function (er, res) { if (er) return cb(er) o[k] = res L.call(this) }.bind(this)) } else if (v && typeof v === 'string' && v.indexOf(this.unique) === 0) { var n = +v.substr(this.unique.length + 1) var prompt = this.prompts[n] if (isNaN(n) || !prompt) continue // default to the key if (undefined === prompt[0]) prompt[0] = k // default to the ctx value, if there is one if (undefined === prompt[1]) prompt[1] = this.ctx[k] return this.prompt(prompt, function (er, res) { if (er) { if (!er.notValid) { return this.emit('error', this.error = er); } console.log(er.message) i -- return L.call(this) } o[k] = res L.call(this) }.bind(this)) } else if (typeof v === 'function') { try { return v.call(this.ctx, function (er, res) { if (er) return this.emit('error', this.error = er) o[k] = res // back up so that we process this one again. // this is because it might return a prompt() call in the cb. i -- L.call(this) }.bind(this)) } catch (er) { this.emit('error', er) } } } // made it to the end of the loop, maybe if (i >= len) return cb(null, o) } } PromZard.prototype.prompt = function (pdt, cb) { var prompt = pdt[0] var def = pdt[1] var tx = pdt[2] if (tx) { cb = function (cb) { return function (er, data) { try { var res = tx(data) if (!er && res instanceof Error && !!res.notValid) { return cb(res, null) } return cb(er, res) } catch (er) { this.emit('error', er) } }}(cb).bind(this) } read({ prompt: prompt + ':' , default: def }, cb) } promzard-0.3.0/test/000077500000000000000000000000001250111631200143175ustar00rootroot00000000000000promzard-0.3.0/test/basic.js000066400000000000000000000040721250111631200157410ustar00rootroot00000000000000var tap = require('tap') var pz = require('../promzard.js') var spawn = require('child_process').spawn tap.test('run the example', function (t) { var example = require.resolve('../example/index.js') var node = process.execPath var expect = { "name": "example", "version": "0.0.0", "description": "testing description", "main": "test-entry.js", "directories": { "example": "example", "test": "test" }, "dependencies": {}, "devDependencies": { "tap": "~0.2.5" }, "scripts": { "test": "tap test/*.js" }, "repository": { "type": "git", "url": "git://github.com/substack/example.git" }, "homepage": "https://github.com/substack/example", "keywords": [ "fugazi", "function", "waiting", "room" ], "author": { "name": "James Halliday", "email": "mail@substack.net", "url": "http://substack.net" }, "license": "MIT", "engine": { "node": ">=0.6" } } console.error('%s %s', node, example) var c = spawn(node, [example], { customFds: [-1,-1,-1] }) var output = '' c.stdout.on('data', function (d) { output += d respond() }) var actual = '' c.stderr.on('data', function (d) { actual += d }) function respond () { console.error('respond', output) if (output.match(/description: $/)) { c.stdin.write('testing description\n') return } if (output.match(/entry point: \(index\.js\) $/)) { c.stdin.write('test-entry.js\n') return } if (output.match(/keywords: $/)) { c.stdin.write('fugazi function waiting room\n') // "read" module is weird on node >= 0.10 when not a TTY // requires explicit ending for reasons. // could dig in, but really just wanna make tests pass, whatever. c.stdin.end() return } } c.on('exit', function () { console.error('exit event') }) c.on('close', function () { console.error('actual', actual) actual = JSON.parse(actual) t.deepEqual(actual, expect) t.end() }) }) promzard-0.3.0/test/buffer.js000066400000000000000000000036261250111631200161350ustar00rootroot00000000000000var tap = require('tap') var pz = require('../promzard.js') var spawn = require('child_process').spawn tap.test('run the example using a buffer', function (t) { var example = require.resolve('../example/buffer.js') var node = process.execPath var expect = { "name": "example", "version": "0.0.0", "description": "testing description", "main": "test-entry.js", "directories": { "example": "example", "test": "test" }, "dependencies": {}, "devDependencies": { "tap": "~0.2.5" }, "scripts": { "test": "tap test/*.js" }, "repository": { "type": "git", "url": "git://github.com/substack/example.git" }, "homepage": "https://github.com/substack/example", "keywords": [ "fugazi", "function", "waiting", "room" ], "author": { "name": "James Halliday", "email": "mail@substack.net", "url": "http://substack.net" }, "license": "MIT", "engine": { "node": ">=0.6" } } var c = spawn(node, [example], { customFds: [-1,-1,-1] }) var output = '' c.stdout.on('data', function (d) { output += d respond() }) var actual = '' c.stderr.on('data', function (d) { actual += d }) function respond () { if (output.match(/description: $/)) { c.stdin.write('testing description\n') return } if (output.match(/entry point: \(index\.js\) $/)) { c.stdin.write('test-entry.js\n') return } if (output.match(/keywords: $/)) { c.stdin.write('fugazi function waiting room\n') // "read" module is weird on node >= 0.10 when not a TTY // requires explicit ending for reasons. // could dig in, but really just wanna make tests pass, whatever. c.stdin.end() return } } c.on('close', function () { actual = JSON.parse(actual) t.deepEqual(actual, expect) t.end() }) }) promzard-0.3.0/test/exports.input000066400000000000000000000002161250111631200171030ustar00rootroot00000000000000exports.a = 1 + 2 exports.b = prompt('To be or not to be?', '!2b') exports.c = {} exports.c.x = prompt() exports.c.y = tmpdir + "/y/file.txt" promzard-0.3.0/test/exports.js000066400000000000000000000016431250111631200163650ustar00rootroot00000000000000var test = require('tap').test; var promzard = require('../'); if (process.argv[2] === 'child') { return child() } test('exports', function (t) { t.plan(1); var spawn = require('child_process').spawn var child = spawn(process.execPath, [__filename, 'child']) var output = '' child.stderr.on('data', function (c) { output += c }) setTimeout(function () { child.stdin.write('\n'); }, 100) setTimeout(function () { child.stdin.end('55\n'); }, 200) child.on('close', function () { console.error('output=%j', output) output = JSON.parse(output) t.same({ a : 3, b : '!2b', c : { x : 55, y : '/tmp/y/file.txt', } }, output); t.end() }) }); function child () { var ctx = { tmpdir : '/tmp' } var file = __dirname + '/exports.input'; promzard(file, ctx, function (err, output) { console.error(JSON.stringify(output)) }); } promzard-0.3.0/test/fn.input000066400000000000000000000006741250111631200160120ustar00rootroot00000000000000var fs = require('fs') module.exports = { "a": 1 + 2, "b": prompt('To be or not to be?', '!2b', function (s) { return s.toUpperCase() + '...' }), "c": { "x": prompt(function (x) { return x * 100 }), "y": tmpdir + "/y/file.txt" }, a_function: function (cb) { fs.readFile(__filename, 'utf8', cb) }, asyncPrompt: function (cb) { return cb(null, prompt('a prompt at any other time would smell as sweet')) } } promzard-0.3.0/test/fn.js000066400000000000000000000022031250111631200152550ustar00rootroot00000000000000var test = require('tap').test; var promzard = require('../'); var fs = require('fs') var file = __dirname + '/fn.input'; var expect = { a : 3, b : '!2B...', c : { x : 5500, y : '/tmp/y/file.txt', } } expect.a_function = fs.readFileSync(file, 'utf8') expect.asyncPrompt = 'async prompt' if (process.argv[2] === 'child') { return child() } test('prompt callback param', function (t) { t.plan(1); var spawn = require('child_process').spawn var child = spawn(process.execPath, [__filename, 'child']) var output = '' child.stderr.on('data', function (c) { output += c }) child.on('close', function () { console.error('output=%j', output) output = JSON.parse(output) t.same(output, expect); t.end() }) setTimeout(function () { child.stdin.write('\n') }, 100) setTimeout(function () { child.stdin.write('55\n') }, 150) setTimeout(function () { child.stdin.end('async prompt\n') }, 200) }) function child () { var ctx = { tmpdir : '/tmp' } var file = __dirname + '/fn.input'; promzard(file, ctx, function (err, output) { console.error(JSON.stringify(output)) }) } promzard-0.3.0/test/simple.input000066400000000000000000000002201250111631200166630ustar00rootroot00000000000000module.exports = { "a": 1 + 2, "b": prompt('To be or not to be?', '!2b'), "c": { "x": prompt(), "y": tmpdir + "/y/file.txt" } } promzard-0.3.0/test/simple.js000066400000000000000000000012351250111631200161470ustar00rootroot00000000000000var test = require('tap').test; var promzard = require('../'); test('simple', function (t) { t.plan(1); var ctx = { tmpdir : '/tmp' } var file = __dirname + '/simple.input'; promzard(file, ctx, function (err, output) { t.same( { a : 3, b : '!2b', c : { x : 55, y : '/tmp/y/file.txt', } }, output ); }); setTimeout(function () { process.stdin.emit('data', '\n'); }, 100); setTimeout(function () { process.stdin.emit('data', '55\n'); }, 200); }); promzard-0.3.0/test/validate.input000066400000000000000000000002621250111631200171710ustar00rootroot00000000000000module.exports = { "name": prompt("name", function (data) { if (data === 'cool') return data var er = new Error('not cool') er.notValid = true return er }) } promzard-0.3.0/test/validate.js000066400000000000000000000007251250111631200164520ustar00rootroot00000000000000 var promzard = require('../') var test = require('tap').test test('validate', function (t) { t.plan(2) var ctx = { tmpdir : '/tmp' } var file = __dirname + '/validate.input' promzard(file, ctx, function (er, found) { t.ok(!er) var wanted = { name: 'cool' } t.same(found, wanted) }) setTimeout(function () { process.stdin.emit('data', 'not cool\n') }, 100) setTimeout(function () { process.stdin.emit('data', 'cool\n') }, 200) })