Skip to content
Prev Previous commit
Next Next commit
chore: extract the verify function outside of the main function
  • Loading branch information
atlj committed Oct 13, 2024
commit 98a048b3f99d23c62de63d4b7719ae37a2d8178b
118 changes: 61 additions & 57 deletions packages/create-react-native-library/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ const TYPE_CHOICES: {
},
];

type Question = Omit<PromptObject<keyof Answers>, 'validate' | 'name'> & {
validate?: (value: string) => boolean | string;
name: keyof Answers;
};

const args: Record<ArgName, yargs.Options> = {
'slug': {
description: 'Name of the npm package',
Expand Down Expand Up @@ -356,10 +361,7 @@ async function create(_argv: yargs.Arguments<any>) {

const basename = path.basename(folder);

const questions: (Omit<PromptObject<keyof Answers>, 'validate' | 'name'> & {
validate?: (value: string) => boolean | string;
name: keyof Answers;
})[] = [
const questions: Question[] = [
{
type: 'text',
name: 'slug',
Expand Down Expand Up @@ -468,58 +470,7 @@ async function create(_argv: yargs.Arguments<any>) {
});
}

const validate = (answers: Answers) => {
for (const [key, value] of Object.entries(answers)) {
if (value == null) {
continue;
}

const question = questions.find((q) => q.name === key);

if (question == null) {
continue;
}

let valid = question.validate ? question.validate(String(value)) : true;

// We also need to guard against invalid choices
// If we don't already have a validation message to provide a better error
if (typeof valid !== 'string' && 'choices' in question) {
const choices =
typeof question.choices === 'function'
? question.choices(
undefined,
// @ts-expect-error: it complains about optional values, but it should be fine
answers,
question
)
: question.choices;

if (choices && !choices.some((choice) => choice.value === value)) {
valid = `Supported values are - ${choices.map((c) =>
kleur.green(c.value)
)}`;
}
}

if (valid !== true) {
let message = `Invalid value ${kleur.red(
String(value)
)} passed for ${kleur.blue(key)}`;

if (typeof valid === 'string') {
message += `: ${valid}`;
}

console.log(message);

process.exit(1);
}
}
};

// Validate arguments passed to the CLI
validate(argv);
assertOptions(questions, argv);

const singleChoiceAnswers: Partial<Answers> = {};

Expand Down Expand Up @@ -575,7 +526,7 @@ async function create(_argv: yargs.Arguments<any>) {
...singleChoiceAnswers,
} as Answers;

validate(answers);
assertOptions(questions, answers);

const {
slug,
Expand Down Expand Up @@ -983,3 +934,56 @@ yargs
'strip-dashed': true,
})
.strict().argv;

/**
* Makes sure the answers are in expected form and ends the process with error if they are not
*/
export function assertOptions(questions: Question[], answers: Answers) {
for (const [key, value] of Object.entries(answers)) {
if (value == null) {
continue;
}

const question = questions.find((q) => q.name === key);

if (question == null) {
continue;
}

let valid = question.validate ? question.validate(String(value)) : true;

// We also need to guard against invalid choices
// If we don't already have a validation message to provide a better error
if (typeof valid !== 'string' && 'choices' in question) {
const choices =
typeof question.choices === 'function'
? question.choices(
undefined,
// @ts-expect-error: it complains about optional values, but it should be fine
answers,
question
)
: question.choices;

if (choices && !choices.some((choice) => choice.value === value)) {
valid = `Supported values are - ${choices.map((c) =>
kleur.green(c.value)
)}`;
}
}

if (valid !== true) {
let message = `Invalid value ${kleur.red(
String(value)
)} passed for ${kleur.blue(key)}`;

if (typeof valid === 'string') {
message += `: ${valid}`;
}

console.log(message);

process.exit(1);
}
}
}