Prompting
What is a prompt
❯ tps react-component Nav
? Would you like to include unit tests? (true)
Prompting is a useful feature that allows you to obtain data from the user. By displaying a message on the command line, we can request a response from the user. Additionally, prompts can be answered by providing a flag via the command line or through the node module package, which is particularly helpful when users already know their desired input. The options for prompts can vary in various formats.
In our system, we utilize the inquirer library for prompting. This enables you to use any property available in inquirer when creating prompts. For more information on the available properties in inquirer, you can refer to the documentation here.
How to make a Prompt
To add prompts to your template, simply add a prompts
property to your
settings file, which should be an array consisting of the prompts you wish to
present to the user. Each prompt will be represented as an object, with varying
properties depending on the type of prompt.
{
"prompts": [
/* prompts ... */
]
}
Don't remember what the setting file is? Refresh your memory in the settings files guide
Now lets go over some of the basics. To get a full list of properties check out the Prompts API documentation
Name
Let's start with the name
field. This field is essential for enabling
prompting functionality. All of your prompt answers will be conveniently stored
under the tps.answers
object property.
{
"prompts": [
{
"name": "<some-name>"
// ...
}
]
}
The name you provide to the prompt will be used in order to access the users answer.
{{= tps.answers["<name-of-prompt>"]}}
Example
{
"prompts": [
{
"name": "age"
// ...
}
]
}
you can access the users answer with:
{{= tps.answers.age }}
Message
The second property is message
. This property will tell inquirer what to ask
the user when they are rendering a new instance.
{
"prompts": [
{
"message": "<some-message>"
// ...
}
]
}
Example
{
"prompts": [
{
"name": "unit",
"message": "Would you like to include unit tests?"
}
]
}
When the user renders a new instance they will see the message added in your prompt
❯ tps react-component Nav
? Would you like to include unit tests?
Type
The next property is type
. This property will tell inquirer what type of
prompting you would like to use. You can see more about this property in the
inquirer question docs.
{
"prompts": [
{
"type": "confirm | input | checkbox | list | rawlist | password"
// ...
}
]
}
Example
{
"prompts": [
{
"name": "over18",
"type": "confirm",
"message": "Are you over the age of 18?"
}
]
}
Produces
❯ tps react-component Nav
? Are you over the age of 18?
Tps Type
The next field is tpsType
. This field tells tps how it should process the
users answer. There are two options package
or data
.
If you don't specify a tpsType
field. Tps will use package
by default.
package
{
"prompts": [
{
"tpsType": "package"
// ...
}
]
}
When you have package
as the tpsType
, tps will try to use the users value to
render a package that is in your template. Different values passed in will have
different behaviors.
boolean
In the case where a prompt's answer is a boolean and its value is true
, Tps
will utilize the name of the prompt to search for a package with the same
name. If such a package is found, tps will include it during the rendering
process of the new instance. When the value is false
, tps will disregard the
prompt and do nothing.
Prompts of type confirm
will return their answers as booleans.
Example
Say were rendering a new express-app
instance and we have a prompt like so
{
"prompts": [
{
"name": "unit",
"tpsType": "package",
"type": "confirm",
"message": "Do you want to include unit tests?"
}
]
}
since this is declared as a package type, this needs a corresponding package in the template
| - .tps/
| - express-app/
| settings.json
| - default/
| - server.js
| - unit/ <-- matches name of prompt
| - server.test.js
When the user is rendering a new template, the prompt will be displayed and they can answer.
❯ tps express-app newApp
? Would you like to include unit tests?
Depending on what the user answers depends on what will happen:
- User answers yes
- User answers no
If user answers yes
, then the unit
package will be included in the rendering
process so a server.test.js
will be added
| - newApp/
| - server.js
| - server.test.js
If user answers no
, then the unit
package will not be include in the
rendering process so no server.test.js
.
| - newApp/
| - server.js
string
When a prompt's answer is a string, word or name, tps will take that answer and attempt to find a package that corresponds to it. If one is found then tps will include it in the rendering process.
Prompts of type list
and input
will return their answers as strings.
Example
Say were rendering a new express-app
instance and we have a prompt like so
{
"prompts": [
{
"name": "framework",
"tpsType": "package",
"message": "What type of frontend framework would you like to use?",
"type": "list", // <--- makes prompt accept strings
"choices": ["react", "angular"]
}
]
}
since this is declared as a package type, the choices to the question must match a package in our template.
| - .tps/
| - express-app/
| settings.json
| - default/
| - server.js
| - react/
| - react.js
| - angular/
| - angular.js
When the user is rendering a new instance, the prompt will be displayed and the user can answer.
❯ tps express-app newApp
? What type of framework would you like to use?
> react
angular
With the choice the user selects, tps will then include a package that matches the answer
- User answers react
- User answers angular
If user answers react
, then the react
package will be included in the
rendering process so a react.js
will be added
| - newApp/
| - server.js
| - react.js
If user answers angular
, then the angular
package will be included in the
rendering process so a angular.js
will be added
| - newApp/
| - server.js
| - angular.js
list
If a prompt's answer consists of a list of strings, tps will consider each individual answer and locate the corresponding packages associated with them. These packages will then be included during the rendering process.
Prompts of type checkbox
will return their answer as list of strings.
Example
Say were rendering a new express-app
instance and we have a prompt like so
{
"prompts": [
{
"name": "extras",
"message": "Would you like to include any other features?",
"tpsType": "package",
"type": "checkbox", // <--- makes prompt accept list of strings
"choices": ["metrics", "unit", "e2e", "api"]
}
]
}
since this is declared as a package type, the choices to the question must match a package in our template.
| - .tps/
| - express-app/
| settings.json
| - default/
| - server.js
| - metrics/
| - metrics.js
| - unit/
| - server.test.js
| - e2e/
| - website.test.js
| - api/
| - api.js
When the user renders a new template. tps will ask for an list of inputs. Whatever the user answers, tps will take all of the values and try to find a packages that matches the answers.
If the user answers metrics
and unit
then both packages will be included in
the rendering process
| - newApp/
| - metrics.js
| - server.test.js
| - server.js
data
{
"prompts": [
{
"tpsType": "data"
// ...
}
]
}
When the tpsType
is set to data
, tps will leave the data untouched. This
data type is designed to allow you to retrieve additional information from the
user, which you can then process according to your specific needs. One common
use case for this is to conditionally render specific code within the file based
on the user's response to a certain question. Any inquirer type can be
used.
Example
Say were rendering a new express-app
instance and we have a prompt like so
{
"prompts": [
{
"name": "security",
"message": "Would you like to include common express security packages?",
"tpsType": "data",
"type": "confirm" // <--- makes prompt accept boolean
}
]
}
When the user is rendering a new instance, the prompt will be displayed and the user can answer. Whatever the user answers will now be available for use in your dynamic files.
const express = require("express");
{{{? tps.answers.security }}}
const helmet = require("helmet");
{{{?}}}
const app = express();
{{{? tps.answers.security }}}
app.use(helmet());
{{{?}}}
/* node code ... */
null
Aliases
The aliases
option allows you to give aliases to your prompts. These aliases
can be used when answer prompts either through the command line, node, or a
configuration file which we will cover more in detail in
how to answer prompts.
{
"prompts": [
{
"name": "some-name",
/* ... */
"aliases": ["<alias-name>"]
}
]
}
On the command line, single letter aliases should be answered with a single dash
-
and other names should be answered with two dashes --
{
"prompts": [
{
"name": "name",
"type": "input",
/* ... */
"aliases": ["n", "realName"]
}
]
}
Now I can answer this prompt with one of the following
tps some-template test --name lino
# or
tps some-template test -n lino
# or
tps some-template test --realName lino
Example
If we were rendering a new instance using the express-app
template and had
this settings file
{
"prompts": [
{
"name": "framework",
"choices": ["react", "vue", "angular"],
/* ... */
"aliases": ["f"]
}
]
}
Now we can answer the prompt question with the alias
- Command line
- Node
tps express-app app -f react
const Templates = require('tps');
const tps = new Templates('express-app');
tps.setAnswers({ f: 'react' });
Hidden
The hidden
option makes the prompt a hidden prompt. Hidden prompts do not get
prompted by default. This is useful when you want to add more customizable logic
in your template but dont want to overwhelm users with a tons of prompt
questions.
{
"prompts": [
{
"hidden": true
// ...
}
]
}
Example
Lets say we had a template named hidden-prompt-test
that had these two
prompts, one being a hidden prompt and the not.
{
"prompts": [
{
"name": "prompt1",
"message": "Would you like to include prompt1",
"tpsType": "data",
"type": "confirm"
},
{
"name": "prompt2",
"message": "Would you like to include prompt2",
"tpsType": "data",
"type": "confirm",
"hidden": true
}
]
}
when users generate a new instance by default, hidden prompts wont be prompted
so only prompt1
will be prompted to the user.
tps hidden-prompt-test test
? Would you like to include prompt1 (n/Y)
Hidden prompts can still be answered and prompted.
Prompting all hidden prompts
Use can use the hidden option to prompt all hidden prompts.
- CLI
- .tpsrc
tps hidden-prompt-test test --hidden
{
"hidden-prompt-test": {
"opts": {
"hidden": true
}
}
}
Example
Lets say we had a template named hidden-prompt-test
that had these two
prompts, one being a hidden prompt and the not.
{
"prompts": [
{
"name": "prompt1",
"message": "Would you like to include prompt1",
"tpsType": "data",
"type": "confirm"
},
{
"name": "prompt2",
"message": "Would you like to include prompt2",
"tpsType": "data",
"type": "confirm",
"hidden": true
}
]
}
If we wanted to get prompted hidden prompts, we can use the hidden option and all hidden prompts will now be prompted to you
tps hidden-prompt-test test --hidden
? Would you like to include prompt1 (n/Y)
? Would you like to include prompt2 (n/Y)
Answering hidden prompts
You can also answer hidden prompt just like any normal prompt which we will cover in the next section
- CLI
- .tpsrc
tps hidden-prompt-test test --hiddenPrompt
{
"hidden-prompt-test": {
"opts": {
"hiddenPrompt": true
}
}
}
Example
Lets say we had a template named hidden-prompt-test
that had these two
prompts, one being a hidden prompt and the not.
{
"prompts": [
{
"name": "prompt1",
"message": "Would you like to include prompt1",
"tpsType": "data",
"type": "confirm"
},
{
"name": "prompt2",
"message": "Would you like to include prompt2",
"tpsType": "data",
"type": "confirm",
"hidden": true
}
]
}
If we wanted to answer prompt2
without being prompted we can pass in the
prompt2
flag.
tps hidden-prompt-test test --prompt2
? Would you like to include prompt1 (n/Y)
How to answer prompts
Interactive
The primary method of answering prompts is through interactive prompts. When you generate a new instance of a template, tps will prompt the user to provide answers until all the prompts are completed. This interactive mode is also the default way to respond to prompts.
Flags
Tps also supports answering prompt questions through command line flags. This feature enables users to obtain their desired results directly without having to go through all the prompts interactively. The flag's name will correspond to the prompt's name specified in your settings file.
tps some-template app --some-flag <some-value>
Example
If we were rendering a new instance using the express-app
template and had
this settings file
{
"prompts": [
{
"name": "unit",
"message": "Would you like to include unit tests?",
"tpsType": "package",
"type": "confirm"
}
]
}
The user can answer this prompts questions by adding a unit
command line flag
tps express-app app --unit
Now lets go over how to answer different types of prompts
boolean
When dealing with boolean values, such as those from a confirm prompt, you have
the option to answer the prompt using a flag with the same name as the prompt.
To answer with true
, simply use:
--unit
On the other hand, if you want to provide a false
value, add no-
before the
flag name:
--no-unit
Example
If we were rendering a new instance using the express-app
template and had
this settings file
{
"prompts": [
{
"name": "unit",
"message": "Would you like to include unit tests?",
"tpsType": "package",
"type": "confirm"
}
]
}
The user can answer this prompts questions by adding a unit
command line flag
tps express-app app --unit
string
When dealing with string values, such as those from a input or list prompts, add the value right after your flag
--cssType less
# or if you need a number
--age 23
# if your value has spaces then you need to do this
--message "hey there everyone"
Example
If we were rendering a new instance using the express-app
template and had
this settings file
{
"prompts": [
{
"name": "framework",
"message": "What frontend package would you like to include",
"tpsType": "package",
"type": "list",
"choices": ["react", "angular", "vue"]
}
]
}
The user can answer this prompts questions by adding a framework
command line
flag and adding the value after the flag named
tps express-app app --framework react
list
If the value type is an list then you end up with something like this.
--ages 23 45 65
# or strings
--numbers ten nine five
Example
If we were rendering a new instance using the express-app
template and had
this settings file
{
"prompts": [
{
"name": "extras",
"message": "Would you like to include any other features?",
"tpsType": "package",
"type": "checkbox", // <--- makes prompt accept list of strings
"choices": ["metrics", "unit", "e2e", "api"]
}
]
}
The user can answer this prompts questions by adding a extras
flag and putting
the values after the flag name
tps express-app app --extras metrics unit e2e
Using list types can be difficult when using multiple flags etc. yargs is used for its command line parser. You can refer how to pass in list of arguments here
When using lists on the command line it is recommended to add the flag after all required fields:
- Bad
- Good
when using lists on the command line before all required params, you have to add
a extra --
after the list flag so yargs can parse the require params correctly
tps express-app --extras metrics api unit -- app
Move the list param to the end of the command in order to prevent this extra adition
tps express-app app --extras metrics api unit
# Addition flags
tps express-app app --extras metrics api unit --some-other-flag
Configuration File
Templates also supports answering prompts in our configuration file aka (tpsrc file). When adding an answer to your config file, templates will use this answer when generating a new instance and will no longer be prompt you the prompted you answered.
You can read more about how to use our configuration file in our configuration guide
{
"<template-name>": {
"answers": {
"<prompt-name>": "<prompt-answer>"
}
}
}
Example
If I had a template named hello-world
and a prompt named age
:
{
"prompts": [
{
"name": "age"
// ...
}
]
}
Then I can set the answer to the prompt in our .tpsrc
file with:
{
"hello-world": {
"answers": {
"age": 23
}
}
}
Now you will no longer be prompted the age
prompt and templates will use the
answer 23 for ever instance you render.
node
To answer prompts in javascript using the module. Use the setAnswers
function.
const Templates = require('tps');
const tps = new Templates('react-component');
/**
* Just like the command line passing in data supports strings, numbers, and arrays
* @example string
* const data = '23';
* @example number
* const data = 23;
* @example boolean
* const data = true;
* @example array
* const data = [23, 45, 65];
*/
const age = 23;
tps.setAnswers({ age });
Examples
View can view more detailed examples in our prompt api docs