Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Convert prompts to TypeScript (final part) #1293

Merged
merged 17 commits into from
Dec 11, 2024
2 changes: 1 addition & 1 deletion lib/prompts/accountNamePrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type AccountNamePromptResponse = {
};

export function getCliAccountNamePromptConfig(
defaultName: string
defaultName?: string
): PromptConfig<AccountNamePromptResponse> {
return {
name: 'name',
Expand Down
45 changes: 22 additions & 23 deletions lib/prompts/accountsPrompt.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,41 @@
// @ts-nocheck
const {
import {
getConfigDefaultAccount,
getConfigAccounts,
} = require('@hubspot/local-dev-lib/config');
const {
getAccountIdentifier,
} = require('@hubspot/local-dev-lib/config/getAccountIdentifier');
const { promptUser } = require('./promptUtils');
const { i18n } = require('../lang');
const { uiAccountDescription } = require('../ui');
} from '@hubspot/local-dev-lib/config';
import { getAccountIdentifier } from '@hubspot/local-dev-lib/config/getAccountIdentifier';
import { promptUser } from './promptUtils';
import { i18n } from '../lang';
import { uiAccountDescription } from '../ui';
import { CLIAccount } from '@hubspot/local-dev-lib/types/Accounts';
import { PromptChoices } from '../../types/prompts';

const mapAccountChoices = portals =>
portals.map(p => ({
name: uiAccountDescription(getAccountIdentifier(p), false),
value: p.name || getAccountIdentifier(p),
}));
function mapAccountChoices(
portals: CLIAccount[] | null | undefined
): PromptChoices {
return (
portals?.map(p => ({
name: uiAccountDescription(getAccountIdentifier(p), false),
value: String(p.name || getAccountIdentifier(p)),
})) || []
);
}

const i18nKey = 'commands.account.subcommands.use';

const selectAccountFromConfig = async (prompt = '') => {
export async function selectAccountFromConfig(prompt = ''): Promise<string> {
const accountsList = getConfigAccounts();
const defaultAccount = getConfigDefaultAccount();

const { default: selectedDefault } = await promptUser([
const { default: selectedDefault } = await promptUser<{ default: string }>([
{
type: 'list',
look: false,
name: 'default',
pageSize: 20,
message: prompt || i18n(`${i18nKey}.promptMessage`),
choices: mapAccountChoices(accountsList),
default: defaultAccount,
default: defaultAccount ?? undefined,
},
]);

return selectedDefault;
};

module.exports = {
selectAccountFromConfig,
};
}
39 changes: 20 additions & 19 deletions lib/prompts/cmsFieldPrompt.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
// @ts-nocheck
const path = require('path');
const fs = require('fs');
const { promptUser } = require('./promptUtils');
const { i18n } = require('../lang');
const escapeRegExp = require('@hubspot/local-dev-lib/escapeRegExp');
import path from 'path';
import fs from 'fs';
import { promptUser } from './promptUtils';
import { i18n } from '../lang';
import { escapeRegExp } from '@hubspot/local-dev-lib/escapeRegExp';

const i18nKey = 'lib.prompts.uploadPrompt';
const FIELDS_FILES = ['fields.json', 'fields.js', 'fields.cjs', 'fields.mjs'];

const fieldsJsPrompt = async (filePath, projectDir, skipFiles = []) => {
export async function fieldsJsPrompt(
filePath: string,
projectDir: string,
skipFiles: string[] = []
): Promise<[string, string[]]> {
const dirName = path.dirname(filePath);

// Get a list of all field files in the directory, resolve their absolute path, and remove the ones that we already skipped.
Expand All @@ -18,34 +22,31 @@ const fieldsJsPrompt = async (filePath, projectDir, skipFiles = []) => {
.filter(file => !skipFiles.includes(file));

if (!fileChoices.length) return [filePath, []];
if (fileChoices.length == 1) return [fileChoices[0], []];
if (fileChoices.length === 1) return [fileChoices[0], []];

// We get the directory above the project one so that relative paths are printed with the root of the project dir attached.
projectDir = projectDir.substring(0, projectDir.lastIndexOf('/'));
const projectDirRegex = new RegExp(`^${escapeRegExp(projectDir)}`);
const fileDir = path.dirname(fileChoices[0]).replace(projectDirRegex, '');

const selection = [];
fileChoices.forEach(fileChoice => {
selection.push({
name: fileChoice.replace(projectDirRegex, ''),
value: fileChoice,
});
});
const promptVal = await promptUser([
const selection = fileChoices.map(fileChoice => ({
name: fileChoice.replace(projectDirRegex, ''),
value: fileChoice,
}));

const promptVal = await promptUser<{ filePathChoice: string }>([
{
message: i18n(`${i18nKey}.fieldsPrompt`, { dir: fileDir }),
type: 'list',
name: 'filePathChoice',
choices: selection,
},
]);

const choice = promptVal.filePathChoice;

// Add the ones that were not picked to skip files array.
const notPicked = fileChoices.filter(item => item !== choice);
skipFiles.push(...notPicked);
return [choice, skipFiles];
};

module.exports = { fieldsJsPrompt };
}
119 changes: 73 additions & 46 deletions lib/prompts/createApiSamplePrompt.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,90 @@
// @ts-nocheck
const { promptUser } = require('./promptUtils');
const { i18n } = require('../lang');
import { promptUser } from './promptUtils';
import { i18n } from '../lang';
import { PromptOperand, PromptConfig } from '../../types/prompts';

const i18nKey = 'lib.prompts.createApiSamplePrompt';

const getSampleTypesPrompt = choices => ({
type: 'rawlist',
name: 'sampleType',
message: i18n(`${i18nKey}.selectApiSampleApp`),
choices: choices.map(choice => ({
name: `${choice.name} - ${choice.description}`,
value: choice.id,
})),
validate: input => {
return new Promise(function(resolve, reject) {
if (input.length > 0) {
resolve(true);
}
reject(i18n(`${i18nKey}.errors.apiSampleAppRequired`));
});
},
});
type SampleChoice = {
name: string;
description: string;
id: string;
languages: string[];
};

type SampleConfig = {
samples: SampleChoice[];
};

type CreateApiSamplePromptResponse = {
sampleType?: string;
sampleLanguage?: string;
};

function getSampleTypesPrompt(
choices: SampleChoice[]
): PromptConfig<CreateApiSamplePromptResponse> {
return {
type: 'rawlist',
name: 'sampleType',
message: i18n(`${i18nKey}.selectApiSampleApp`),
choices: choices.map(choice => ({
name: `${choice.name} - ${choice.description}`,
value: choice.id,
})),
validate: function(input?: string) {
return new Promise<PromptOperand>(function(resolve, reject) {
if (input && input.length > 0) {
resolve(true);
} else {
reject(i18n(`${i18nKey}.errors.apiSampleAppRequired`));
}
});
},
};
}

const getLanguagesPrompt = choices => ({
type: 'rawlist',
name: 'sampleLanguage',
message: i18n(`${i18nKey}.selectLanguage`),
choices: choices.map(choice => ({
name: choice,
value: choice,
})),
validate: input => {
return new Promise(function(resolve, reject) {
if (input.length > 0) {
resolve(true);
}
reject(i18n(`${i18nKey}.errors.languageRequired`));
});
},
});
function getLanguagesPrompt(
choices: string[]
): PromptConfig<CreateApiSamplePromptResponse> {
return {
type: 'rawlist',
name: 'sampleLanguage',
message: i18n(`${i18nKey}.selectLanguage`),
choices: choices.map(choice => ({
name: choice,
value: choice,
})),
validate: function(input: string | undefined) {
return new Promise<PromptOperand>(function(resolve, reject) {
if (input && input.length > 0) {
resolve(true);
}
reject(i18n(`${i18nKey}.errors.languageRequired`));
});
},
};
}

const createApiSamplePrompt = async samplesConfig => {
export async function createApiSamplePrompt(
samplesConfig: SampleConfig
): Promise<CreateApiSamplePromptResponse> {
try {
const { samples } = samplesConfig;
const sampleTypeAnswer = await promptUser(getSampleTypesPrompt(samples));
const sampleTypeAnswer = await promptUser<CreateApiSamplePromptResponse>(
getSampleTypesPrompt(samples)
);
const chosenSample = samples.find(
sample => sample.id === sampleTypeAnswer.sampleType
);
const { languages } = chosenSample;
const languagesAnswer = await promptUser(getLanguagesPrompt(languages));
const { languages } = chosenSample!;
const languagesAnswer = await promptUser<CreateApiSamplePromptResponse>(
getLanguagesPrompt(languages)
);
return {
...sampleTypeAnswer,
...languagesAnswer,
};
} catch (e) {
return {};
}
};

module.exports = {
createApiSamplePrompt,
};
}
Loading
Loading