swiss-node
v3.2.1
Published
Swiss Army Knife for node
Downloads
30
Readme
swiss-node
Swiss Army Knife for node
A collection of helper functions and useful little things for node.js
Uses swiss-ak
ask
A collection of functions to ask the user for input.
- ask
text
ask.text(question: string | Breadcrumb, initial: string, validate: (value: string) => ask.ValidationResponse, lc: LineCounter): Promise<string>
Get a text input from the user.
const name = await ask.text('What is your name?'); // 'Jack'
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:--------------------------------------------|
| 0 | question
| Yes | string \| Breadcrumb
|
| 1 | initial
| No | string
|
| 2 | validate
| No | (value: string) => ask.ValidationResponse
|
| 3 | lc
| No | LineCounter
|
| Return Type |
|-------------------|
| Promise<string>
|
autotext
ask.autotext(question: string | Breadcrumb, choices: ask.PromptChoice<T>[], initial: T | string, validate: (item: T, index: number, typedValue: string) => ask.ValidationResponse, lc: LineCounter): Promise<T>
Get a text input from the user, with auto-completion.
const name = await ask.autotext('What is your name?', ['Jack', 'Jane', 'Joe']); // 'Jack'
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:-------------------------------------------------------------------------|
| 0 | question
| Yes | string \| Breadcrumb
|
| 1 | choices
| Yes | ask.PromptChoice<T>[]
|
| 2 | initial
| No | T \| string
|
| 3 | validate
| No | (item: T, index: number, typedValue: string) => ask.ValidationResponse
|
| 4 | lc
| No | LineCounter
|
| Return Type |
|--------------|
| Promise<T>
|
number
ask.number(question: string | Breadcrumb, initial: number, validate: (value: number) => ask.ValidationResponse, lc: LineCounter): Promise<number>
Get a number input from the user.
const age = await ask.number('How old are you?'); // 30
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:--------------------------------------------|
| 0 | question
| Yes | string \| Breadcrumb
|
| 1 | initial
| No | number
|
| 2 | validate
| No | (value: number) => ask.ValidationResponse
|
| 3 | lc
| No | LineCounter
|
| Return Type |
|-------------------|
| Promise<number>
|
boolean
ask.boolean(question: string | Breadcrumb, initial: boolean, validate: (value: boolean) => ask.ValidationResponse, lc: LineCounter): Promise<boolean>
Get a boolean input from the user (yes or no)
const isCool = await ask.boolean('Is this cool?'); // true
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:---------------------------------------------|:--------|
| 0 | question
| Yes | string \| Breadcrumb
| |
| 1 | initial
| No | boolean
| true
|
| 2 | validate
| No | (value: boolean) => ask.ValidationResponse
| |
| 3 | lc
| No | LineCounter
| |
| Return Type |
|--------------------|
| Promise<boolean>
|
booleanYN
ask.booleanYN(question: string | Breadcrumb, validate: (value: boolean) => ask.ValidationResponse, lc: LineCounter): Promise<boolean>
Get a boolean input from the user (yes or no)
Alternative interface to ask.boolean
const isCool = await ask.booleanYN('Is this cool?'); // true
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:---------------------------------------------|
| 0 | question
| Yes | string \| Breadcrumb
|
| 1 | validate
| No | (value: boolean) => ask.ValidationResponse
|
| 2 | lc
| No | LineCounter
|
| Return Type |
|--------------------|
| Promise<boolean>
|
select
ask.select(question: string | Breadcrumb, choices: ask.PromptChoice<T>[], initial: ask.PromptChoice<T> | number, validate: (item: T, index: number) => ask.ValidationResponse, lc: LineCounter): Promise<T>
Get the user to select an option from a list.
const colour = await ask.select('Whats your favourite colour?', ['red', 'green', 'blue']); // 'red'
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:-----------------------------------------------------|
| 0 | question
| Yes | string \| Breadcrumb
|
| 1 | choices
| Yes | ask.PromptChoice<T>[]
|
| 2 | initial
| No | ask.PromptChoice<T> \| number
|
| 3 | validate
| No | (item: T, index: number) => ask.ValidationResponse
|
| 4 | lc
| No | LineCounter
|
| Return Type |
|--------------|
| Promise<T>
|
multiselect
ask.multiselect(question: string | Breadcrumb, choices: ask.PromptChoice<T>[], initial: ask.PromptChoice<T> | ask.PromptChoice<T>[] | number | number[], validate: (items: T[], indexes: number[]) => ask.ValidationResponse, lc: LineCounter): Promise<T[]>
Get the user to select multiple opts from a list.
const colours = await ask.multiselect('Whats your favourite colours?', ['red', 'green', 'blue']); // ['red', 'green']
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:---------------------------------------------------------------------|
| 0 | question
| Yes | string \| Breadcrumb
|
| 1 | choices
| Yes | ask.PromptChoice<T>[]
|
| 2 | initial
| No | ask.PromptChoice<T> \| ask.PromptChoice<T>[] \| number \| number[]
|
| 3 | validate
| No | (items: T[], indexes: number[]) => ask.ValidationResponse
|
| 4 | lc
| No | LineCounter
|
| Return Type |
|----------------|
| Promise<T[]>
|
date
ask.date(questionText: string | Breadcrumb, initial: Date, validate: (date: Date) => ask.ValidationResponse, lc: LineCounter): Promise<Date>
Get a date input from the user.
const date = await ask.date('Whats the date?');
// [Date: 2023-01-01T12:00:00.000Z] (user inputted date, always at 12 midday)
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:-----------------------------------------|
| 0 | questionText
| No | string \| Breadcrumb
|
| 1 | initial
| No | Date
|
| 2 | validate
| No | (date: Date) => ask.ValidationResponse
|
| 3 | lc
| No | LineCounter
|
| Return Type |
|-----------------|
| Promise<Date>
|
time
ask.time(questionText: string | Breadcrumb, initial: Date, validate: (date: Date) => ask.ValidationResponse, lc: LineCounter): Promise<Date>
Get a time input from the user.
const time = await ask.time('Whats the time?');
// [Date: 2023-01-01T12:00:00.000Z] (user inputted time, with todays date)
const time2 = await ask.time('Whats the time?', new Date('1999-12-31'));
// [Date: 1999-12-31T12:00:00.000Z] (user inputted time, with same date as initial)
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:-----------------------------------------|
| 0 | questionText
| No | string \| Breadcrumb
|
| 1 | initial
| No | Date
|
| 2 | validate
| No | (date: Date) => ask.ValidationResponse
|
| 3 | lc
| No | LineCounter
|
| Return Type |
|-----------------|
| Promise<Date>
|
datetime
ask.datetime(questionText: string | Breadcrumb, initial: Date, validate: (date: Date) => ask.ValidationResponse, lc: LineCounter): Promise<Date>
Get a date and time input from the user.
const when = await ask.datetime('Whats the date/time?');
// [Date: 2023-03-05T20:30:00.000Z] (user inputted time & date)
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:-----------------------------------------|
| 0 | questionText
| No | string \| Breadcrumb
|
| 1 | initial
| No | Date
|
| 2 | validate
| No | (date: Date) => ask.ValidationResponse
|
| 3 | lc
| No | LineCounter
|
| Return Type |
|-----------------|
| Promise<Date>
|
dateRange
ask.dateRange(questionText: string | Breadcrumb, initialStart: Date, initialEnd: Date, validate: (dates: [Date, Date]) => ask.ValidationResponse, lc: LineCounter): Promise<[Date, Date]>
Get a date range input from the user.
const range = await ask.dateRange('When is the festival?');
// [
// [Date: 2023-03-01T12:00:00.000Z],
// [Date: 2023-03-31T12:00:00.000Z]
// ]
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:--------------------------------------------------|
| 0 | questionText
| No | string \| Breadcrumb
|
| 1 | initialStart
| No | Date
|
| 2 | initialEnd
| No | Date
|
| 3 | validate
| No | (dates: [Date, Date]) => ask.ValidationResponse
|
| 4 | lc
| No | LineCounter
|
| Return Type |
|-------------------------|
| Promise<[Date, Date]>
|
fileExplorer
fileExplorer
ask.fileExplorer(questionText: string | Breadcrumb, selectType: 'd' | 'f', startPath: string, validate: (path: string) => ask.ValidationResponse, lc: LineCounter): Promise<string>
Get a file or folder path from the user.
const file = await ask.fileExplorer('What file?', 'f');
// '/Users/user/Documents/some_file.txt'
const dir = await ask.fileExplorer('What file?', 'd', '/Users/jackcannon/Documents');
// '/Users/jackcannon/Documents/some_folder'
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-------------------------------------------|:----------------|
| 0 | questionText
| Yes | string \| Breadcrumb
| |
| 1 | selectType
| No | 'd' \| 'f'
| 'f'
|
| 2 | startPath
| No | string
| process.cwd()
|
| 3 | validate
| No | (path: string) => ask.ValidationResponse
| |
| 4 | lc
| No | LineCounter
| |
| Return Type |
|-------------------|
| Promise<string>
|
multiFileExplorer
ask.multiFileExplorer(questionText: string | Breadcrumb, selectType: 'd' | 'f', startPath: string, validate: (paths: string[]) => ask.ValidationResponse, lc: LineCounter): Promise<string[]>
Get multiple file or folder paths from the user.
const files = await ask.multiFileExplorer('What files?', 'f');
// [
// '/Users/user/Documents/some_file_1.txt',
// '/Users/user/Documents/some_file_2.txt',
// '/Users/user/Documents/some_file_3.txt'
// ]
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:----------------------------------------------|:----------------|
| 0 | questionText
| Yes | string \| Breadcrumb
| |
| 1 | selectType
| No | 'd' \| 'f'
| 'f'
|
| 2 | startPath
| No | string
| process.cwd()
|
| 3 | validate
| No | (paths: string[]) => ask.ValidationResponse
| |
| 4 | lc
| No | LineCounter
| |
| Return Type |
|---------------------|
| Promise<string[]>
|
saveFileExplorer
ask.saveFileExplorer(questionText: string | Breadcrumb, startPath: string, suggestedFileName: string, validate: (dir: string, filename?: string) => ask.ValidationResponse): Promise<string>
Get a file path from the user, with the intention of saving a file to that path.
const HOME_DIR = '/Users/user/Documents';
const savePath = await ask.saveFileExplorer('Save file', HOME_DIR, 'data.json');
// '/Users/user/Documents/data.json'
| # | Parameter Name | Required | Type | Default |
|:---:|:--------------------|:---------|:-------------------------------------------------------------|:----------------|
| 0 | questionText
| Yes | string \| Breadcrumb
| |
| 1 | startPath
| No | string
| process.cwd()
|
| 2 | suggestedFileName
| No | string
| ''
|
| 3 | validate
| No | (dir: string, filename?: string) => ask.ValidationResponse
| |
| Return Type |
|-------------------|
| Promise<string>
|
table
A collection of functions for asking questions with tables.
table.select
ask.table.select(question: string | Breadcrumb, items: T[], settings: AskTableDisplaySettings<T>, initial: T | number, validate: (item: T) => ask.ValidationResponse, lc: LineCounter): Promise<T>
Get a single selection from a table.
const items = [
{ name: 'John', age: 25 },
{ name: 'Jane', age: 26 },
{ name: 'Derek', age: 27 }
];
const headers = [['Name', 'Age']];
const itemToRow = ({ name, age }) => [name, age];
const answer = await ask.table.select('Who?', items, undefined, itemToRow, headers);
// ┏━━━┳━━━━━━━┳━━━━━┓
// ┃ ┃ Name ┃ Age ┃
// ┡━━━╇━━━━━━━╇━━━━━┩
// │ │ John │ 25 │
// ├───┼───────┼─────┤
// │ ❯ │ Jane │ 26 │
// ├───┼───────┼─────┤
// │ │ Derek │ 27 │
// └───┴───────┴─────┘
// Returns: { name: 'Jane', age: 26 }
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:--------------------------------------|:--------|
| 0 | question
| Yes | string \| Breadcrumb
| |
| 1 | items
| Yes | T[]
| |
| 2 | settings
| No | AskTableDisplaySettings<T>
| {}
|
| 3 | initial
| No | T \| number
| |
| 4 | validate
| No | (item: T) => ask.ValidationResponse
| |
| 5 | lc
| No | LineCounter
| |
| Return Type |
|--------------|
| Promise<T>
|
table.multiselect
ask.table.multiselect(question: string | Breadcrumb, items: T[], settings: AskTableDisplaySettings<T>, initial: T[] | number[], validate: (items: T[]) => ask.ValidationResponse, lc: LineCounter): Promise<T[]>
Get multiple selections from a table.
const items = [
{ name: 'John', age: 25 },
{ name: 'Jane', age: 26 },
{ name: 'Derek', age: 27 }
];
const headers = [['Name', 'Age']];
const itemToRow = ({ name, age }) => [name, age];
const answer = await ask.table.multiselect('Who?', items, undefined, itemToRow, headers);
┏━━━┳━━━━━━━┳━━━━━┓
┃ ┃ Name ┃ Age ┃
┡━━━╇━━━━━━━╇━━━━━┩
│ ◉ │ John │ 25 │
├───┼───────┼─────┤
│ ◯ │ Jane │ 26 │
├───┼───────┼─────┤
│ ◉ │ Derek │ 27 │
└───┴───────┴─────┘
// [
// { name: 'John', age: 25 },
// { name: 'Derek', age: 27 }
// ]
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-----------------------------------------|:--------|
| 0 | question
| Yes | string \| Breadcrumb
| |
| 1 | items
| Yes | T[]
| |
| 2 | settings
| No | AskTableDisplaySettings<T>
| {}
|
| 3 | initial
| No | T[] \| number[]
| |
| 4 | validate
| No | (items: T[]) => ask.ValidationResponse
| |
| 5 | lc
| No | LineCounter
| |
| Return Type |
|----------------|
| Promise<T[]>
|
AskTableDisplaySettings
AskTableDisplaySettings<T>;
Settings for how the table should display the items
All settings are optional.
| Name | Type | Description |
| --------- | ------------------------------- | ---------------------------------------------------------------- |
| rows
| any[][] \| (item: T) => any[]
| Rows to display or function that takes an item and returns a row |
| headers
| any[][] \| RemapOf<T, string>
| Header to display, or object with title for each item property |
| options
| table.TableOptions
| Options object for table (some options are overridden) |
trim
ask.trim(question: string | Breadcrumb, totalFrames: number, frameRate: number, initial: Partial<Handles<number>>, validate: (handles: Handles<number>) => ask.ValidationResponse, lc: LineCounter): Promise<Handles<number>>
Get a start and end frame from the user
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-------------------------------------------------------|:--------|
| 0 | question
| Yes | string \| Breadcrumb
| |
| 1 | totalFrames
| Yes | number
| |
| 2 | frameRate
| No | number
| 60
|
| 3 | initial
| No | Partial<Handles<number>>
| |
| 4 | validate
| No | (handles: Handles<number>) => ask.ValidationResponse
| |
| 5 | lc
| No | LineCounter
| |
| Return Type |
|----------------------------|
| Promise<Handles<number>>
|
Extra
These are ask functions that don't prompt the user, but can help manage or organise how you use prompts
customise
ask.customise(options: Partial<ask.AskOptions>): void
Customise the behaviour/appearance of the ask
prompts.
See ask.AskOptions
for the options available.
ask.customise({ general: { themeColour: 'magenta' } }); // change the theme colour to magenta
ask.customise({ general: { lc } }); // set a line counter for that all prompts will add to when complete
ask.customise({ formatters: { formatPrompt: 'fullBox' } }); // change the format of the prompt
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:--------------------------|
| 0 | options
| Yes | Partial<ask.AskOptions>
|
| Return Type |
|-------------|
| void
|
loading
ask.loading(question: string | Breadcrumb, isComplete: boolean, isError: boolean, lc: LineCounter): { stop: () => void; }
Display an animated loading indicator that imitates the display of a prompt
Intended to be indicate a question is coming, but something is loading first. For general 'loading' indicators, use out.loading
.
const loader = ask.loading('What is your name?');
// ...
loader.stop();
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-----------------------|:--------|
| 0 | question
| Yes | string \| Breadcrumb
| |
| 1 | isComplete
| No | boolean
| false
|
| 2 | isError
| No | boolean
| false
|
| 3 | lc
| No | LineCounter
| |
| Return Type |
|-------------------------|
| { stop: () => void; }
|
countdown
ask.countdown(totalSeconds: number, template: (s: second) => string, isComplete: boolean, isError: boolean): Promise<void>
Animated countdown for a given number of seconds
await ask.countdown(5);
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:------------------------|
| 0 | totalSeconds
| Yes | number
|
| 1 | template
| No | (s: second) => string
|
| 2 | isComplete
| No | boolean
|
| 3 | isError
| No | boolean
|
| Return Type |
|-----------------|
| Promise<void>
|
pause
ask.pause(text: string | Breadcrumb): Promise<void>
Pause the program until the user presses enter
await ask.pause();
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-----------------------|:-------------------------------|
| 0 | text
| No | string \| Breadcrumb
| 'Press enter to continue...'
|
| Return Type |
|-----------------|
| Promise<void>
|
imitate
ask.imitate(question: string | Breadcrumb, result: any, isComplete: boolean, isError: boolean, errorMessage: string, lc: LineCounter): void
Imitate the display of a prompt
imitate('What is your name?', 'Jack', true);
ask.imitate('What is your name?', 'Jack', true);
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-----------------------|:--------|
| 0 | question
| Yes | string \| Breadcrumb
| |
| 1 | result
| No | any
| |
| 2 | isComplete
| No | boolean
| true
|
| 3 | isError
| No | boolean
| false
|
| 4 | errorMessage
| No | string
| |
| 5 | lc
| No | LineCounter
| |
| Return Type |
|-------------|
| void
|
prefill
ask.prefill(question: string | Breadcrumb, value: T | undefined, askFn: (question: string | Breadcrumb, lc: LineCounter) => Promise<T> | T, lc: LineCounter): Promise<T>
Auto-fills an ask prompt with the provided value, if defined.
Continues to display the 'prompt', but already 'submitted'
Good for keeping skipping parts of forms, but providing context and keeping display consistent
let data = {};
const name1 = ask.prefill(data.name, 'What is your name?', ask.text); // User input
data = {name: 'Jack'}
const name2 = ask.prefill(data.name, 'What is your name?', ask.text); // Jack
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:-----------------------------------------------------------------------|
| 0 | question
| Yes | string \| Breadcrumb
|
| 1 | value
| Yes | T \| undefined
|
| 2 | askFn
| Yes | (question: string \| Breadcrumb, lc: LineCounter) => Promise<T> \| T
|
| 3 | lc
| No | LineCounter
|
| Return Type |
|--------------|
| Promise<T>
|
wizard
ask.wizard(startObj: Partial<T>): ask.Wizard<T>
Create a wizard object that can be used to build up a complex object
interface Example {
foo: string;
bar: number;
baz: string;
}
const base: Partial<Example> = {
baz: 'baz'
};
const wiz = ask.wizard<Example>(base);
await wiz.add('foo', ask.text('What is foo?')); // User input: foo
await wiz.add('bar', ask.number('What is bar?')); // User input: 123
const result = wiz.get(); // { baz: 'baz', foo: 'foo', bar: 123 }
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-------------|:--------|
| 0 | startObj
| No | Partial<T>
| {}
|
| Return Type |
|-----------------|
| ask.Wizard<T>
|
menu
ask.menu(question: string | Breadcrumb, items: MenuItem<T>[], initial: MenuItem<T> | T | number, validate: (value: T, index: number) => ask.ValidationResponse, lc: LineCounter): Promise<T>
Wrapper for ask.select
that styles the output as a menu, with icons and colours
const menuItems: ask.MenuItem<string>[] = [
{ value: 'done', title: colr.dim(`[ Finished ]`), icon: '✔', colour: colr.dark.green.bold },
{ value: 'create', title: `${colr.bold('Create')} a new thing`, icon: '+', colour: colr.black.greenBg },
{ value: 'duplicate', title: `${colr.bold('Duplicate')} a thing`, icon: '⌥', colour: colr.black.cyanBg },
{ value: 'edit', title: `${colr.bold('Edit')} a thing`, icon: '↻', colour: colr.black.yellowBg },
{ value: 'delete', title: `${colr.bold('Remove')} thing(s)`, icon: '×', colour: colr.black.redBg },
{ value: 'delete-all', title: colr.bold(`Remove all`), icon: '✖', colour: colr.black.darkBg.redBg }
];
const result = await ask.menu('Pick a menu item', menuItems, 'edit'); // 'duplicate' (or other value)
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:------------------------------------------------------|
| 0 | question
| Yes | string \| Breadcrumb
|
| 1 | items
| Yes | MenuItem<T>[]
|
| 2 | initial
| No | MenuItem<T> \| T \| number
|
| 3 | validate
| No | (value: T, index: number) => ask.ValidationResponse
|
| 4 | lc
| No | LineCounter
|
| Return Type |
|--------------|
| Promise<T>
|
section
ask.section(question: string | Breadcrumb, sectionHeader: (lc: LineCounter) => void | Promise<any>, ...questionFns: [...T][]): Promise<TupleFromQuestionFuncs<T>>
Allows information to be displayed before a question, and follow up questions to be asked, while only leaving the 'footprint' of a single question afterwards.
const ans1 = await ask.text('Question 1:');
const ans2 = await ask.section('Question 2:',
(lc: LineCounter) => {
lc.log('Some information');
},
(qst) => ask.text(qst),
() => ask.text('Question 2b:')
);
During the section, it looks like this:
Question 1: answer1
┄┄┄┄┄◦┄┄┄┄┄┄┄◦┄┄┄┄┄┄┄◦┄┄┄┄┄┄┄◦┄┄┄┄┄┄
Some information
┄┄┄┄┄◦┄┄┄┄┄┄┄◦┄┄┄┄┄┄┄◦┄┄┄┄┄┄┄◦┄┄┄┄┄┄
Question 2: answer2
Question 2b: answer2b
After the last question in the section has been submitted, it looks like this:
Question 1: answer1
Question 2a: [ answer2, answer2b ]
| # | Parameter Name | Required | Type |
|:----:|:----------------|:---------|:--------------------------------------------|
| 0 | question
| Yes | string \| Breadcrumb
|
| 1 | sectionHeader
| No | (lc: LineCounter) => void \| Promise<any>
|
| 2… | questionFns
| No | [...T][]
|
| Return Type |
|--------------------------------------|
| Promise<TupleFromQuestionFuncs<T>>
|
separator
ask.separator(version: 'down' | 'none' | 'up', spacing: number, offset: number, width: number, lc: LineCounter): void
Prints a separator line to the console.
ask.separator('down');
// ┄┄┄┄┄▿┄┄┄┄┄┄┄▿┄┄┄┄┄┄┄▿┄┄┄┄┄┄┄▿┄┄┄┄┄┄┄▿┄┄┄┄┄┄┄▿┄┄┄┄┄┄
ask.separator('none', 15);
// ┄┄┄┄┄┄┄┄┄┄◦┄┄┄┄┄┄┄┄┄┄┄┄┄┄◦┄┄┄┄┄┄┄┄┄┄┄┄┄┄◦┄┄┄┄┄┄┄┄┄┄┄
ask.separator('up', 5, 2);
// ┄┄┄┄┄┄┄┄▵┄┄┄┄▵┄┄┄┄▵┄┄┄┄▵┄┄┄┄▵┄┄┄┄▵┄┄┄┄▵┄┄┄┄▵┄┄┄┄┄┄┄┄
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:---------------------------|:-----------------------------------|
| 0 | version
| No | 'down' \| 'none' \| 'up'
| 'down'
|
| 1 | spacing
| No | number
| 8
|
| 2 | offset
| No | number
| 0
|
| 3 | width
| No | number
| out.utils.getTerminalWidth() - 2
|
| 4 | lc
| No | LineCounter
| |
| Return Type |
|-------------|
| void
|
utils
itemsToPromptObjects
ask.utils.itemsToPromptObjects(items: T[], titles: string[], titleFn: TitleFn<T>): { title: string; value: T; }[]
Take an array of items and convert them to an array of prompt objects
ask.utils.itemsToPromptObjects(['lorem', 'ipsum', 'dolor'])
// [
// { title: 'lorem', value: 'lorem' },
// { title: 'ipsum', value: 'ipsum' },
// { title: 'dolor', value: 'dolor' }
// ]
ask.utils.itemsToPromptObjects(['lorem', 'ipsum', 'dolor'], ['Lorem', 'Ipsum', 'Dolor'])
// [
// { title: 'Lorem', value: 'lorem' },
// { title: 'Ipsum', value: 'ipsum' },
// { title: 'Dolor', value: 'dolor' }
// ]
ask.utils.itemsToPromptObjects(['lorem', 'ipsum', 'dolor'], undefined, (s) => s.toUpperCase())
// [
// { title: 'LOREM', value: 'lorem' },
// { title: 'IPSUM', value: 'ipsum' },
// { title: 'DOLOR', value: 'dolor' }
// ]
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-------------|:--------|
| 0 | items
| Yes | T[]
| |
| 1 | titles
| No | string[]
| []
|
| 2 | titleFn
| No | TitleFn<T>
| |
| Return Type |
|----------------------------------|
| { title: string; value: T; }[]
|
AskOptions
ask.AskOptions;
Options to customise the behaviour/appearance of the ask
prompts.
Use with ask.customise
to set these options.
general
Options
ask.AskOptions.general;
General options for customising ask prompts
| Name | Type | Description |
|--------------------------------|---------------------|--------------------------------------------------------------------|
| themeColour | string
(Colour) | Set the main theme colour |
| lc | LineCounter
| A line counter that all ask prompts will add to when complete |
| boxType | 'thin' \| 'thick'
| What type of box drawing lines to use |
| beeps | boolean
| Whether to make an audio beeps when appropriate |
| maxItemsOnScreen | number
| How many select/multiselect items to have on screen at most |
| scrollMargin | number
| How much space to leaving when 'scrolling' lists of items |
| fileExplorerColumnWidth | number
| How wide to make each panel of the fileExplorer interface |
| fileExplorerMaxItems | number
| How many items to show in each panel of the fileExplorer interface |
| tableSelectMaxHeightPercentage | number
| Percent of terminal height to use at max for table selects |
| timelineSpeed | number
| How many frames to move on a timeline at a time |
| timelineFastSpeed | number
| How many frames to move on a timeline at a time (fast mode) |
text
Options
ask.AskOptions.text;
English natural-language elements that you may wish to localise
| Name | Type | Description |
|------------------------------------|----------------------------|-------------------------------------------------------------|
| boolTrueKeys | string
| What buttons to use to indicate true
for boolean prompts |
| boolFalseKeys | string
| What buttons to use to indicate false
for boolean prompts |
| boolYes | string
| 'Yes' |
| boolNo | string
| 'No' |
| boolYesNoSeparator | string
| '/' |
| boolYN | string
| '(Y/n)' |
| selectAll | string
| '[Select All]' |
| done | string
| 'done' |
| items | (num: number) => string
| '[X items]' |
| countdown | (secs: number) => string
| 'Starting in Xs...' |
| file | string
| 'File' |
| directory | string
| 'Directory' |
| loading | string
| 'Loading...' |
| selected | (num: number) => string
| 'X selected' |
| specialNewFolderEnterNothingCancel | string
| 'Enter nothing to cancel' |
| specialNewFolderAddingFolderTo | string
| 'Adding folder to ' |
| specialNewFolderQuestion | (hl: any) => string
| 'What do you want to name the new folder?' |
| specialSaveFileSavingFileTo | string
| 'Saving file to ' |
| specialSaveFileQuestion | (hl: any) => string
| 'What do you want to name the file?' |
formatters
Options
ask.AskOptions.formatters;
Functions for formatting how the prompts should display
formatPrompt
ask.AskOptions.formatters.formatPrompt;
How to format the prompts
Presets: oneLine
, halfBox
, halfBoxClosed
, fullBox
, fullBoxClosed
Type:
(
question: string | Breadcrumb,
value: string,
items: string | undefined,
errorMessage: string | undefined,
theme: AskOptionsForState,
isComplete: boolean,
isExit: boolean
) => string;
formatItems
ask.AskOptions.formatters.formatItems;
How to format lists of items
Presets: block
, blockAlt
, simple
, simpleAlt
Type:
<T extends unknown>(
allItems: PromptChoiceFull<T>[],
scrolledItems: ScrolledItems<PromptChoiceFull<T>>,
selected: number[] | undefined,
type: 'single' | 'multi',
theme: AskOptionsForState,
isExit: boolean
) => string;
colours
Options
ask.AskOptions.colours;
Colours for all the different elements
All colours can be a single WrapFn
value, or a set of WrapFn
values, one for each state (normal, error, done)
When single value, it is used for all states. When only a few states are set, the others will remain unchanged.
| Name | Description | |--------------------------|-------------------------------------------------------------------------------------------------| | decoration | General decoration and cosmetics | | questionText | The text of the question of the prompt | | specialIcon | Special icon for the 'state' | | openingIcon | The initial/opening icon | | promptIcon | The icon that indicates where you are typing | | result | General result | | resultText | String results | | resultNumber | Number results | | resultBoolean | Boolean results | | resultArray | Array results | | resultDate | Date results | | loadingIcon | Icon for ask.loading | | errorMsg | The error message (if there is one) | | item | A normal item in a list | | itemIcon | Icon for a normal item in a list | | itemHover | A hovered item in a list | | itemHoverIcon | Icon for a hovered item in a list | | itemBlockHover | A hovered item in a list (block mode) | | itemBlockHoverIcon | Icon for a hovered item in a list (block mode) | | itemSelected | A selected item in a list | | itemSelectedIcon | Icon for a selected item in a list | | itemUnselected | An unselected item in a list | | itemUnselectedIcon | Icon for an unselected item in a list | | scrollbarTrack | The track for the scrollbar | | scrollbarBar | The bar for the scrollbar | | selectAllText | 'Select All' item in a multi-select | | boolYNText | The '(Y/n)' bit for the booleanYN prompt | | countdown | ask.countdown | | pause | ask.pause | | specialHover | The focus of what the user is controlling (for dates, fileExplorer, etc) | | specialSelected | Something that has been selected (for dates, fileExplorer, etc) | | specialHighlight | More important that normal (e.g. date within a range) (for dates, fileExplorer, etc) | | specialNormal | Normal items (for dates, fileExplorer, etc) | | specialFaded | Not important (for dates, fileExplorer, etc) | | specialHint | Hints/tips/advice (for dates, fileExplorer, etc) | | specialInactiveHover | The focus of what the user is controlling (Inactive) (for dates, fileExplorer, etc) | | specialInactiveSelected | Something that has been selected (Inactive) (for dates, fileExplorer, etc) | | specialInactiveHighlight | More important that normal (e.g. date within a range) (Inactive) (for dates, fileExplorer, etc) | | specialInactiveNormal | Normal items (Inactive) (for dates, fileExplorer, etc) | | specialInactiveFaded | Not important (Inactive) (for dates, fileExplorer, etc) | | specialInactiveHint | Hints/tips/advice (Inactive) (for dates, fileExplorer, etc) | | specialInfo | Action bar at bottom (for dates, fileExplorer, etc) | | specialErrorMsg | Error messages (for dates, fileExplorer, etc) | | specialErrorIcon | Icon for errors (for dates, fileExplorer, etc) | | tableSelectHover | Hover for table selects only (shouldn't be 'block'/bg styles) | | timelineTrack | The (inactive) track of a timeline | | timelineTrackActive | The active track of a timeline | | timelineHandle | The (inactive) control handle on a timeline | | timelineHandleActive | The active control handle on a timeline |
symbols
Options
ask.AskOptions.symbols;
Variety of symbols and 'icons' for different aspects of the display
All symbols can be a single string
value, or a set of string
values, one for each state (normal, error, done)
When single value, it is used for all states. When only a few states are set, the others will remain unchanged.
| Name | Description | |--------------------------|---------------------------------------------------------------------------| | specialIcon | Special icon for the 'state' | | openingIcon | The initial/opening icon | | promptIcon | The icon that indicates where you are typing | | errorMsgPrefix | Icon shown before error messages | | itemIcon | Icon for a normal item in a list | | itemHoverIcon | Icon for a hovered item in a list | | itemSelectedIcon | Icon for a selected item in a list | | itemUnselectedIcon | Icon for an unselected item in a list | | scrollUpIcon | Used to indicate you can scroll up | | scrollDownIcon | Used to indicate you can scroll down | | scrollbarTrack | The track part of the scrollbar | | scrollbarTrackTrimTop | The trimmed top of the track (half height) | | scrollbarTrackTrimBottom | The trimmed bottom of the track (half height) | | scrollbarBar | The bar part of the scrollbar | | scrollbarBarTrimTop | The trimmed top of the bar (half height) | | scrollbarBarTrimBottom | The trimmed bottom of the bar (half height) | | separatorLine | Line added by ask.separator | | separatorNodeDown | Node is ask.separator line that indicates 'down' | | separatorNodeNone | Node is ask.separator line that breaks up the pattern | | separatorNodeUp | Node is ask.separator line that indicates 'up' | | specialErrorIcon | Icon for errors (for dates, fileExplorer, etc) | | folderOpenableIcon | Shown at end of line for folders to show they can be opened (right-wards) | | fileOpenableIcon | File version of folderOpenableIcon. Typically empty | | timelineTrack | The track of a timeline | | timelineHandle | The control handle on a timeline | | timelineBar | The 'bar' (active portion) of a timeline |
PromptChoice
ask.PromptChoice<T>;
A choice for a prompt
Equivalent to T | { title?: string; value?: T; selected?: boolean; }
ValidationResponse
ask.ValidationResponse;
Response type for ask validation functions.
| Response | Type | Result | Error Message |
|----------------------|-----------|---------------|---------------|
| new Error('error')
| Error | ❌ - Rejected | 'error'
|
| 'error'
| string | ❌ - Rejected | 'error'
|
| false
| boolean | ❌ - Rejected | None |
| true
| boolean | ✅ - Accepted | N/A |
| null
| null | ✅ - Accepted | N/A |
| undefined
| undefined | ✅ - Accepted | N/A |
Equivalent to Error | string | boolean | void
out
A collection of functions to print to the console
- out
getWidth
out.getWidth(text: string): number
A rough approximation of the width of the given text (as it would appear in the terminal)
Removes all ansi escape codes, and attempts to count emojis as 2 characters wide
Note: Many special characters may not be counted correctly. Emoji support is also not perfect.
out.getWidth('FOO BAR'); // 7
out.getWidth('↓←→↑'); // 4
out.getWidth(colr.red('this is red')); // 11
| # | Parameter Name | Required | Type |
|:---:|:---------------|:---------|:---------|
| 0 | text
| Yes | string
|
| Return Type |
|-------------|
| number
|
pad
out.pad(line: string, start: number, end: number, replaceChar: string): string
Pad before and after the given text with the given character.
pad('foo', 3, 1, '-'); // '---foo-'
pad('bar', 10, 5, '_'); // '__________bar_____'
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:---------|:--------|
| 0 | line
| Yes | string
| |
| 1 | start
| Yes | number
| |
| 2 | end
| Yes | number
| |
| 3 | replaceChar
| No | string
| ' '
|
| Return Type |
|-------------|
| string
|
center
out.center(item: any, width: number, replaceChar: string, forceWidth: boolean): string
Align the given text to the center within the given width of characters/columns
Giving a width of 0 will use the terminal width
out.center('foo', 10); // ' foo '
out.center('something long', 10); // 'something long'
out.center('lines\n1\n2', 5);
// 'lines' + '\n' +
// ' 1 ' + '\n' +
// ' 2 '
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:----------|:-------------------------------|
| 0 | item
| Yes | any
| |
| 1 | width
| No | number
| out.utils.getTerminalWidth()
|
| 2 | replaceChar
| No | string
| ' '
|
| 3 | forceWidth
| No | boolean
| true
|
| Return Type |
|-------------|
| string
|
left
out.left(item: any, width: number, replaceChar: string, forceWidth: boolean): string
Align the given text to the left within the given width of characters/columns
Giving a width of 0 will use the terminal width
out.left('foo', 10); // 'foo '
out.left('something long', 10); // 'something long'
out.left('lines\n1\n2', 5);
// 'lines' + '\n' +
// '1 ' + '\n' +
// '2 '
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:----------|:-------------------------------|
| 0 | item
| Yes | any
| |
| 1 | width
| No | number
| out.utils.getTerminalWidth()
|
| 2 | replaceChar
| No | string
| ' '
|
| 3 | forceWidth
| No | boolean
| true
|
| Return Type |
|-------------|
| string
|
right
out.right(item: any, width: number, replaceChar: string, forceWidth: boolean): string
Align the given text to the right within the given width of characters/columns
Giving a width of 0 will use the terminal width
out.right('foo', 10); // ' foo'
out.right('something long', 10); // 'something long'
out.right('lines\n1\n2', 5);
// 'lines' + '\n' +
// ' 1' + '\n' +
// ' 2'
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:----------|:-------------------------------|
| 0 | item
| Yes | any
| |
| 1 | width
| No | number
| out.utils.getTerminalWidth()
|
| 2 | replaceChar
| No | string
| ' '
|
| 3 | forceWidth
| No | boolean
| true
|
| Return Type |
|-------------|
| string
|
justify
out.justify(item: any, width: number, replaceChar: string, forceWidth: boolean): string
Evenly space the text horizontally across the given width.
Giving a width of 0 will use the terminal width
const lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit';
out.justify(out.wrap(lorem, 20), 20);
// 'Lorem ipsum dolor' + '\n' +
// 'sit amet,' + '\n' +
// 'consectetur ' + '\n' +
// 'adipiscing elit'
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:----------|:-------------------------------|
| 0 | item
| Yes | any
| |
| 1 | width
| No | number
| out.utils.getTerminalWidth()
|
| 2 | replaceChar
| No | string
| ' '
|
| 3 | forceWidth
| No | boolean
| true
|
| Return Type |
|-------------|
| string
|
leftLines
out.leftLines(lines: string[], width: number): string[]
Align each line of the given text to the left within the given width of characters/columns
out.leftLines(['This is line 1', 'This is a longer line 2', 'Line 3']);
// [
// 'This is line 1 ',
// 'This is a longer line 2',
// 'Line 3 '
// ]
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-----------|:-----------------------|
| 0 | lines
| Yes | string[]
| |
| 1 | width
| No | number
| getLongestLen(lines)
|
| Return Type |
|-------------|
| string[]
|
centerLines
out.centerLines(lines: string[], width: number): string[]
Align each line of the given text to the center within the given width of characters/columns
out.rightLines(['This is line 1', 'This is a longer line 2', 'Line 3']);
// [
// ' This is line 1',
// 'This is a longer line 2',
// ' Line 3'
// ]
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-----------|:-----------------------|
| 0 | lines
| Yes | string[]
| |
| 1 | width
| No | number
| getLongestLen(lines)
|
| Return Type |
|-------------|
| string[]
|
rightLines
out.rightLines(lines: string[], width: number): string[]
Align each line of the given text to the right within the given width of characters/columns
out.centerLines(['This is line 1', 'This is a longer line 2', 'Line 3']);
// [
// ' This is line 1 ',
// 'This is a longer line 2',
// ' Line 3 '
// ]
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-----------|:-----------------------|
| 0 | lines
| Yes | string[]
| |
| 1 | width
| No | number
| getLongestLen(lines)
|
| Return Type |
|-------------|
| string[]
|
justifyLines
out.justifyLines(lines: string[], width: number): string[]
Justify align each line of the given text within the given width of characters/columns
out.justifyLines(['This is line 1', 'This is a longer line 2', 'Line 3']);
// [
// 'This is line 1',
// 'This is a longer line 2',
// 'Line 3'
// ]
| # | Parameter Name | Required | Type | Default |
|:---:|:---------------|:---------|:-----------|:-----------------------|
| 0 | lines
| Yes | string[]
| |
| 1 | width
| No | number
| getLongestLen(lines)
|