prompting wizardly
npm install promzardA prompting wizard for building files from specialized PromZard modules.
Used by npm init.
A reimplementation of @SubStack's
prompter, which does not
use AST traversal.
From another point of view, it's a reimplementation of
@Marak's
wizard which doesn't use schemas.
The goal is a nice drop-in enhancement for npm init.
``javascript`
const promzard = require('promzard')
const data = await promzard(inputFile, optionalContextAdditions, options)
In the inputFile you can have something like this:
`javascriptHello, ${who}
const fs = require('fs/promises')
module.exports = {
"greeting": prompt("Who shall you greet?", "world", (who) => ),entry: ${e}
"filename": __filename,
"directory": async () => {
const entries = await fs.readdir(__dirname)
return entries.map(e => )`
}
}
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.
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,prompt
the 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.
#### options.backupFile
Use the backupFile option as a fallback when inputFile fails to be read.
Just like the promzard function, but the class that makes itload
all happen. The method returns a promise which will resolve
to the resolved data or throw with an error.
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 isfunction
the default value.
2. A transformer function which receives the data and returnsobject
something else. More than meets the eye.
3. The prompt member is the prompt, the default member istransform
the default value, and the is the transformer.
Whatever the final value is, that's what will be put on the resulting
object.
If there are any functions on the promzard input module's exports, then
promzard will await each of them. 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.
In the async function, you can also call prompt() and return the result
of the prompt.
For example, this works fine in a promzard module:
`js`
exports.asyncPrompt = async function () {
const st = await fs.stat(someFile)
// if there's an error, no prompt, just error
// otherwise prompt and use the actual file size as the default
return 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.
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')
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.