Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

amplify-prompts

Package Overview
Dependencies
Maintainers
1
Versions
194
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

amplify-prompts - npm Package Compare versions

Comparing version 1.3.0-ext2.0 to 1.3.0-ext20.0

11

CHANGELOG.md

@@ -6,3 +6,3 @@ # Change Log

# [1.3.0-ext2.0](https://github.com/aws-amplify/amplify-cli/compare/amplify-prompts@1.1.2...amplify-prompts@1.3.0-ext2.0) (2021-10-18)
# [1.3.0-ext20.0](https://github.com/aws-amplify/amplify-cli/compare/amplify-prompts@1.2.0...amplify-prompts@1.3.0-ext20.0) (2021-11-10)

@@ -12,14 +12,9 @@

* Flag to allow schema changes that require table replacement ([#8144](https://github.com/aws-amplify/amplify-cli/issues/8144)) ([2d4e65a](https://github.com/aws-amplify/amplify-cli/commit/2d4e65acfd034d33c6fa8ac1f5f8582e7e3bc399))
* update pick styling, hint text, and ctrl+z listener ([#8167](https://github.com/aws-amplify/amplify-cli/issues/8167)) ([620a36a](https://github.com/aws-amplify/amplify-cli/commit/620a36a8d4596cfd686820a5556431077977db5a))
* add byValue and byValues helper functions to select pick options by value ([#8253](https://github.com/aws-amplify/amplify-cli/issues/8253)) ([2fa32e8](https://github.com/aws-amplify/amplify-cli/commit/2fa32e8c368eda408b515a04195744fb25a29a3d))
* flag to allow destructive schema changes ([#8273](https://github.com/aws-amplify/amplify-cli/issues/8273)) ([18de856](https://github.com/aws-amplify/amplify-cli/commit/18de856fb61bf2df8f73375e4e55a58c6159a232))
### Reverts
* Revert "feat: Flag to allow schema changes that require table replacement (#8144)" (#8268) ([422dd04](https://github.com/aws-amplify/amplify-cli/commit/422dd04425c72aa7276e086d38ce4d5f4681f9f3)), closes [#8144](https://github.com/aws-amplify/amplify-cli/issues/8144) [#8268](https://github.com/aws-amplify/amplify-cli/issues/8268)
# [1.2.0](https://github.com/aws-amplify/amplify-cli/compare/amplify-prompts@1.1.2...amplify-prompts@1.2.0) (2021-09-27)

@@ -26,0 +21,0 @@

@@ -83,2 +83,4 @@ "use strict";

printResult(await prompter_1.prompter.pick('Pick your favorite colors', choices2, { returnSize: 'many', initial: [1, 2] }));
printer_1.printer.info('Choices can also be selected by value using the provided helper function "byValue" (or "byValues" for multi-select)');
printResult(await prompter_1.prompter.pick('Pick your favorite color', choices2, { initial: prompter_1.byValue(4) }));
printer_1.printer.info('Individual choices can be disabled or have hint text next to them');

@@ -85,0 +87,0 @@ choices2[1].hint = 'definitely the best';

import { Validator } from './validators';
export declare const prompter: Prompter;
export declare const byValues: <T>(selection: T[], equals?: EqualsFunction<T>) => MultiFilterFunction<T>;
export declare const byValue: <T>(selection: T, equals?: EqualsFunction<T>) => SingleFilterFunction<T>;
declare type EqualsFunction<T> = (a: T, b: T) => boolean;
declare type Prompter = {

@@ -7,3 +10,3 @@ confirmContinue: (message?: string) => Promise<boolean>;

input: <RS extends ReturnSize = 'one', T = string>(message: string, ...options: MaybeOptionalInputOptions<RS, T>) => Promise<PromptReturn<RS, T>>;
pick: <RS extends ReturnSize = 'one', T = string>(message: string, choices: Choices<T>, ...options: MaybeOptionalPickOptions<RS>) => Promise<PromptReturn<RS, T>>;
pick: <RS extends ReturnSize = 'one', T = string>(message: string, choices: Choices<T>, ...options: MaybeOptionalPickOptions<RS, T>) => Promise<PromptReturn<RS, T>>;
};

@@ -13,5 +16,7 @@ declare type MaybeAvailableHiddenInputOption<RS extends ReturnSize> = RS extends 'many' ? {} : {

};
declare type InitialSelectionOption<RS extends ReturnSize> = {
initial?: RS extends 'one' ? number : number[];
declare type InitialSelectionOption<RS extends ReturnSize, T> = {
initial?: RS extends 'one' ? number | SingleFilterFunction<T> : number[] | MultiFilterFunction<T>;
};
declare type SingleFilterFunction<T> = (arr: T[]) => number | undefined;
declare type MultiFilterFunction<T> = (arr: T[]) => number[];
declare type InitialValueOption<T> = {

@@ -41,7 +46,7 @@ initial?: T;

declare type MaybeOptionalInputOptions<RS extends ReturnSize, T> = RS extends 'many' ? [InputOptions<RS, T>] : T extends string ? [InputOptions<RS, T>?] : [InputOptions<RS, T>];
declare type MaybeOptionalPickOptions<RS extends ReturnSize> = RS extends 'many' ? [PickOptions<RS>] : [PickOptions<RS>?];
declare type MaybeOptionalPickOptions<RS extends ReturnSize, T> = RS extends 'many' ? [PickOptions<RS, T>] : [PickOptions<RS, T>?];
declare type PromptReturn<RS extends ReturnSize, T> = RS extends 'many' ? T[] : T;
declare type PickOptions<RS extends ReturnSize> = ReturnSizeOption<RS> & InitialSelectionOption<RS>;
declare type PickOptions<RS extends ReturnSize, T> = ReturnSizeOption<RS> & InitialSelectionOption<RS, T>;
declare type InputOptions<RS extends ReturnSize, T> = ReturnSizeOption<RS> & ValidateValueOption & InitialValueOption<T> & MaybeOptionalTransformOption<T> & MaybeAvailableHiddenInputOption<RS>;
export {};
//# sourceMappingURL=prompter.d.ts.map

@@ -25,3 +25,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.prompter = void 0;
exports.byValue = exports.byValues = exports.prompter = void 0;
const enquirer_1 = require("enquirer");

@@ -98,2 +98,3 @@ const actions = __importStar(require("enquirer/lib/combos"));

: choices;
const initialIndexes = initialOptsToIndexes(genericChoices.map(choice => choice.value), opts === null || opts === void 0 ? void 0 : opts.initial);
const choiceValueMap = new Map();

@@ -110,10 +111,10 @@ const enquirerChoices = genericChoices.map(choice => {

else if (flags_1.isYes) {
if ((opts === null || opts === void 0 ? void 0 : opts.initial) === undefined || (Array.isArray(opts === null || opts === void 0 ? void 0 : opts.initial) && (opts === null || opts === void 0 ? void 0 : opts.initial.length) === 0)) {
if (initialIndexes === undefined || (Array.isArray(initialIndexes) && initialIndexes.length === 0)) {
throw new Error(`Cannot prompt for [${message}] when '--yes' flag is set`);
}
if (typeof (opts === null || opts === void 0 ? void 0 : opts.initial) === 'number') {
result = genericChoices[opts === null || opts === void 0 ? void 0 : opts.initial].name;
if (typeof initialIndexes === 'number') {
result = genericChoices[initialIndexes].name;
}
else {
result = opts === null || opts === void 0 ? void 0 : opts.initial.map(idx => genericChoices[idx].name);
result = initialIndexes.map(idx => genericChoices[idx].name);
}

@@ -131,3 +132,3 @@ }

hint: '(Use arrow keys or type to filter)',
initial: opts === null || opts === void 0 ? void 0 : opts.initial,
initial: initialIndexes,
multiple: (opts === null || opts === void 0 ? void 0 : opts.returnSize) === 'many',

@@ -151,2 +152,9 @@ choices: enquirerChoices,

exports.prompter = new AmplifyPrompter();
const byValues = (selection, equals = defaultEquals) => (choices) => selection.map(sel => choices.findIndex(choice => equals(choice, sel))).filter(idx => idx >= 0);
exports.byValues = byValues;
const byValue = (selection, equals = defaultEquals) => (choices) => {
const idx = choices.findIndex(choice => equals(choice, selection));
return idx < 0 ? undefined : idx;
};
exports.byValue = byValue;
const validateEachWith = (validator) => async (input) => {

@@ -163,2 +171,9 @@ if (!validator) {

};
const initialOptsToIndexes = (values, initial) => {
if (initial === undefined || typeof initial === 'number' || Array.isArray(initial)) {
return initial;
}
return initial(values);
};
const defaultEquals = (a, b) => a === b;
//# sourceMappingURL=prompter.js.map

@@ -6,2 +6,3 @@ export declare type Validator = (value: string) => true | string | Promise<true | string>;

export declare const minLength: (minLen: number, message?: string | undefined) => Validator;
export declare const exact: (expected: string, message?: string | undefined) => Validator;
export declare const and: (validators: [Validator, Validator, ...Validator[]], message?: string | undefined) => Validator;

@@ -8,0 +9,0 @@ export declare const or: (validators: [Validator, Validator, ...Validator[]], message?: string | undefined) => Validator;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.not = exports.or = exports.and = exports.minLength = exports.maxLength = exports.integer = exports.alphanumeric = void 0;
exports.not = exports.or = exports.and = exports.exact = exports.minLength = exports.maxLength = exports.integer = exports.alphanumeric = void 0;
const alphanumeric = (message = 'Input must be alphanumeric') => (input) => /^[a-zA-Z0-9]+$/.test(input) ? true : message;

@@ -12,2 +12,4 @@ exports.alphanumeric = alphanumeric;

exports.minLength = minLength;
const exact = (expected, message) => (input) => input === expected ? true : message !== null && message !== void 0 ? message : 'Input does not match expected value';
exports.exact = exact;
const and = (validators, message) => async (input) => {

@@ -14,0 +16,0 @@ for (const validator of validators) {

{
"name": "amplify-prompts",
"version": "1.3.0-ext2.0",
"version": "1.3.0-ext20.0",
"description": "Utility functions for Amplify CLI terminal I/O",

@@ -51,3 +51,3 @@ "main": "lib/index.js",

},
"gitHead": "a8f1746356ac50d6bd230f566f39ff433b64fec4"
"gitHead": "6a930893e4d90ccf369bff1f4e460ab96b825d6a"
}

@@ -1,2 +0,2 @@

import { prompter } from '../prompter';
import { byValue, byValues, prompter } from '../prompter';
import { prompt } from 'enquirer';

@@ -80,5 +80,6 @@ import * as flags from '../flags';

prompt_mock.mockResolvedValueOnce({ result: ['10', '20'] });
expect(
await prompter.input<'many'>('test message', { returnSize: 'many', transform: input => `${input}suffix` }),
).toEqual(['10suffix', '20suffix']);
expect(await prompter.input<'many'>('test message', { returnSize: 'many', transform: input => `${input}suffix` })).toEqual([
'10suffix',
'20suffix',
]);
});

@@ -108,2 +109,15 @@ });

it('computes selection index using selection function', async () => {
prompt_mock.mockResolvedValueOnce({ result: 'opt2' });
await prompter.pick('test message', ['opt1', 'opt2', 'opt3'], { initial: byValue('opt2') });
expect((prompt_mock.mock.calls[0][0] as any).initial).toBe(1);
});
it('returns initial selection using selection function when yes flag is set', async () => {
flags_mock.isYes = true;
const result = await prompter.pick('test message', ['opt1', 'opt2', 'opt3'], { initial: byValue('opt2') });
expect(result).toBe('opt2');
expect(prompt_mock.mock.calls.length).toBe(0);
});
it('throws if no choices provided', async () => {

@@ -128,6 +142,36 @@ expect(() => prompter.pick('test message', [])).rejects.toThrowErrorMatchingInlineSnapshot(

prompt_mock.mockResolvedValueOnce({ result: mockResult });
expect(
await prompter.pick<'many'>('test message', ['val1', 'val2', 'val3'], { returnSize: 'many' }),
).toEqual(mockResult);
expect(await prompter.pick<'many'>('test message', ['val1', 'val2', 'val3'], { returnSize: 'many' })).toEqual(mockResult);
});
});
describe('byValue', () => {
it('defaults to === when no equals function specified', () => {
expect(byValue('fox')(['the', 'quick', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog'])).toBe(2);
});
it('returns the index of the first match if multiple present', () => {
expect(byValue('the')(['the', 'quick', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog'])).toBe(0);
});
it('returns undefined when no match found', () => {
expect(byValue('dne')(['the', 'quick', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog'])).toBeUndefined();
});
it('uses the equals function if specified', () => {
expect(byValue('four', (a, b) => a.length === b.length)(['the', 'quick', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog'])).toBe(4);
});
});
describe('byValues', () => {
it('defaults to === when no equals function specified', () => {
expect(byValues(['fox', 'the'])(['the', 'quick', 'fox', 'jumped', 'over', 'lazy', 'dog']).sort()).toEqual([0, 2]);
});
it('returns [] when no matches found', () => {
expect(byValues(['dne'])(['the', 'quick', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog'])).toEqual([]);
});
it('uses the equals function if specified', () => {
expect(byValues(['a', 'aa'], (a, b) => a.length === b.length)(['bbbb', 'bb', 'bbb', 'b']).sort()).toEqual([1, 3]);
});
});
import { printer } from '../printer';
import { prompter } from '../prompter';
import { byValue, prompter } from '../prompter';
import { alphanumeric, and, integer, minLength } from '../validators';

@@ -120,2 +120,5 @@

printer.info('Choices can also be selected by value using the provided helper function "byValue" (or "byValues" for multi-select)');
printResult(await prompter.pick<'one', number>('Pick your favorite color', choices2, { initial: byValue(4) }));
printer.info('Individual choices can be disabled or have hint text next to them');

@@ -122,0 +125,0 @@ (choices2[1] as any).hint = 'definitely the best';

@@ -108,2 +108,5 @@ import { prompt } from 'enquirer';

* @returns The item(s) selected. If PickType = 'one' this is a single value. If PickType = 'many', this is an array
*
* Note: due to this TS issue https://github.com/microsoft/TypeScript/issues/30611 type T cannot be an enum.
* If using an enum as the value type for a selection use T = string and assert the return type as the enum type.
*/

@@ -113,3 +116,3 @@ pick = async <RS extends ReturnSize = 'one', T = string>(

choices: Choices<T>,
...options: MaybeOptionalPickOptions<RS>
...options: MaybeOptionalPickOptions<RS, T>
): Promise<PromptReturn<RS, T>> => {

@@ -129,2 +132,7 @@ // some choices must be provided

const initialIndexes = initialOptsToIndexes(
genericChoices.map(choice => choice.value),
opts?.initial,
);
// enquirer requires all choice values be strings, so set up a mapping of string => T

@@ -145,9 +153,9 @@ // and format choices to conform to enquirer's interface

} else if (isYes) {
if (opts?.initial === undefined || (Array.isArray(opts?.initial) && opts?.initial.length === 0)) {
if (initialIndexes === undefined || (Array.isArray(initialIndexes) && initialIndexes.length === 0)) {
throw new Error(`Cannot prompt for [${message}] when '--yes' flag is set`);
}
if (typeof opts?.initial === 'number') {
result = genericChoices[opts?.initial].name;
if (typeof initialIndexes === 'number') {
result = genericChoices[initialIndexes].name;
} else {
result = opts?.initial.map(idx => genericChoices[idx].name);
result = initialIndexes.map(idx => genericChoices[idx].name);
}

@@ -172,3 +180,3 @@ } else {

hint: '(Use arrow keys or type to filter)',
initial: opts?.initial,
initial: initialIndexes,
// there is a typo in the .d.ts file for this field -- muliple -> multiple

@@ -199,2 +207,26 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment

/**
* Helper function to generate a function that will return the indices of a selection set from a list
* @param selection The list of values to select from a list
* @param equals An optional function to determine if two elements are equal. If not specified, === is used
* Note that choices are assumed to be unique by the equals function definition
*/
export const byValues =
<T>(selection: T[], equals: EqualsFunction<T> = defaultEquals): MultiFilterFunction<T> =>
(choices: T[]) =>
selection.map(sel => choices.findIndex(choice => equals(choice, sel))).filter(idx => idx >= 0);
/**
* Helper function to generate a function that will return an index of a single selection from a list
* @param selection The single selection to find in the list
* @param equals An optional function to determine if two elements are equal. If not specified, === is used
* Note that choices are assumed to be unique by the equals function definition
*/
export const byValue =
<T>(selection: T, equals: EqualsFunction<T> = defaultEquals): SingleFilterFunction<T> =>
(choices: T[]) => {
const idx = choices.findIndex(choice => equals(choice, selection));
return idx < 0 ? undefined : idx;
};
const validateEachWith = (validator?: Validator) => async (input: string[]) => {

@@ -212,2 +244,16 @@ if (!validator) {

const initialOptsToIndexes = <RS extends ReturnSize, T>(
values: T[],
initial: InitialSelectionOption<RS, T>['initial'],
): number | number[] | undefined => {
if (initial === undefined || typeof initial === 'number' || Array.isArray(initial)) {
return initial;
}
return initial(values);
};
type EqualsFunction<T> = (a: T, b: T) => boolean;
const defaultEquals = <T>(a: T, b: T) => a === b;
type Prompter = {

@@ -225,3 +271,3 @@ confirmContinue: (message?: string) => Promise<boolean>;

// options is typed using spread because it's the only way to make it required if RS is 'many' but optional if RS is 'one'
...options: MaybeOptionalPickOptions<RS>
...options: MaybeOptionalPickOptions<RS, T>
) => Promise<PromptReturn<RS, T>>;

@@ -239,6 +285,12 @@ };

type InitialSelectionOption<RS extends ReturnSize> = {
initial?: RS extends 'one' ? number : number[];
// The initial selection for a pick prompt can be specified either by index or a selection function that generates indexes.
// See byValues and byValue above
type InitialSelectionOption<RS extends ReturnSize, T> = {
initial?: RS extends 'one' ? number | SingleFilterFunction<T> : number[] | MultiFilterFunction<T>;
};
type SingleFilterFunction<T> = (arr: T[]) => number | undefined;
type MultiFilterFunction<T> = (arr: T[]) => number[];
type InitialValueOption<T> = {

@@ -285,3 +337,3 @@ initial?: T;

type MaybeOptionalPickOptions<RS extends ReturnSize> = RS extends 'many' ? [PickOptions<RS>] : [PickOptions<RS>?];
type MaybeOptionalPickOptions<RS extends ReturnSize, T> = RS extends 'many' ? [PickOptions<RS, T>] : [PickOptions<RS, T>?];

@@ -291,3 +343,3 @@ type PromptReturn<RS extends ReturnSize, T> = RS extends 'many' ? T[] : T;

// the following types are the method input types
type PickOptions<RS extends ReturnSize> = ReturnSizeOption<RS> & InitialSelectionOption<RS>;
type PickOptions<RS extends ReturnSize, T> = ReturnSizeOption<RS> & InitialSelectionOption<RS, T>;

@@ -294,0 +346,0 @@ type InputOptions<RS extends ReturnSize, T> = ReturnSizeOption<RS> &

@@ -15,14 +15,27 @@ export type Validator = (value: string) => true | string | Promise<true | string>;

export const alphanumeric = (message: string = 'Input must be alphanumeric'): Validator => (input: string) =>
/^[a-zA-Z0-9]+$/.test(input) ? true : message;
export const alphanumeric =
(message: string = 'Input must be alphanumeric'): Validator =>
(input: string) =>
/^[a-zA-Z0-9]+$/.test(input) ? true : message;
export const integer = (message: string = 'Input must be a number'): Validator => (input: string) =>
/^[0-9]+$/.test(input) ? true : message;
export const integer =
(message: string = 'Input must be a number'): Validator =>
(input: string) =>
/^[0-9]+$/.test(input) ? true : message;
export const maxLength = (maxLen: number, message?: string): Validator => (input: string) =>
input.length > maxLen ? message || `Input must be less than ${maxLen} characters long` : true;
export const maxLength =
(maxLen: number, message?: string): Validator =>
(input: string) =>
input.length > maxLen ? message || `Input must be less than ${maxLen} characters long` : true;
export const minLength = (minLen: number, message?: string): Validator => (input: string) =>
input.length < minLen ? message || `Input must be more than ${minLen} characters long` : true;
export const minLength =
(minLen: number, message?: string): Validator =>
(input: string) =>
input.length < minLen ? message || `Input must be more than ${minLen} characters long` : true;
export const exact =
(expected: string, message?: string): Validator =>
(input: string) =>
input === expected ? true : message ?? 'Input does not match expected value';
/**

@@ -32,11 +45,13 @@ * Logically "and"s several validators

*/
export const and = (validators: [Validator, Validator, ...Validator[]], message?: string): Validator => async (input: string) => {
for (const validator of validators) {
const result = await validator(input);
if (typeof result === 'string') {
return message ?? result;
export const and =
(validators: [Validator, Validator, ...Validator[]], message?: string): Validator =>
async (input: string) => {
for (const validator of validators) {
const result = await validator(input);
if (typeof result === 'string') {
return message ?? result;
}
}
}
return true;
};
return true;
};

@@ -47,12 +62,14 @@ /**

*/
export const or = (validators: [Validator, Validator, ...Validator[]], message?: string): Validator => async (input: string) => {
let result: string | true = true;
for (const validator of validators) {
result = await validator(input);
if (result === true) {
return true;
export const or =
(validators: [Validator, Validator, ...Validator[]], message?: string): Validator =>
async (input: string) => {
let result: string | true = true;
for (const validator of validators) {
result = await validator(input);
if (result === true) {
return true;
}
}
}
return message ?? result;
};
return message ?? result;
};

@@ -63,3 +80,5 @@ /**

*/
export const not = (validator: Validator, message: string): Validator => async (input: string) =>
typeof (await validator(input)) === 'string' ? true : message;
export const not =
(validator: Validator, message: string): Validator =>
async (input: string) =>
typeof (await validator(input)) === 'string' ? true : message;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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