From 9757c6d8c2f4c340f578de5cd6dd4bb5ebf6300a Mon Sep 17 00:00:00 2001 From: Branden Rodgers Date: Fri, 9 May 2025 11:15:42 -0400 Subject: [PATCH 1/3] port cms lighthousr-score to TS --- commands/cms/lighthouseScore.ts | 201 +++++++++++++++++++++----------- 1 file changed, 131 insertions(+), 70 deletions(-) diff --git a/commands/cms/lighthouseScore.ts b/commands/cms/lighthouseScore.ts index 32b1753f4..efb186b58 100644 --- a/commands/cms/lighthouseScore.ts +++ b/commands/cms/lighthouseScore.ts @@ -1,23 +1,29 @@ -// @ts-nocheck -const SpinniesManager = require('../../lib/ui/SpinniesManager'); -const { - addAccountOptions, - addConfigOptions, - addUseEnvironmentOptions, -} = require('../../lib/commonOpts'); -const { logger } = require('@hubspot/local-dev-lib/logger'); -const { getTableContents, getTableHeader } = require('../../lib/ui/table'); -const { promptUser } = require('../../lib/prompts/promptUtils'); -const { i18n } = require('../../lib/lang'); -const { fetchThemes } = require('@hubspot/local-dev-lib/api/designManager'); -const { +import { Argv, ArgumentsCamelCase } from 'yargs'; +import SpinniesManager from '../../lib/ui/SpinniesManager'; +import { logger } from '@hubspot/local-dev-lib/logger'; +import { getTableContents, getTableHeader } from '../../lib/ui/table'; +import { promptUser } from '../../lib/prompts/promptUtils'; +import { i18n } from '../../lib/lang'; +import { fetchThemes } from '@hubspot/local-dev-lib/api/designManager'; +import { requestLighthouseScore, getLighthouseScoreStatus, getLighthouseScore, -} = require('@hubspot/local-dev-lib/api/lighthouseScore'); -const { HUBSPOT_FOLDER, MARKETPLACE_FOLDER } = require('../../lib/constants'); -const { uiLink } = require('../../lib/ui'); -const { EXIT_CODES } = require('../../lib/enums/exitCodes'); +} from '@hubspot/local-dev-lib/api/lighthouseScore'; +import { + RequestLighthouseScoreResponse, + GetLighthouseScoreResponse, +} from '@hubspot/local-dev-lib/types/Lighthouse'; +import { HUBSPOT_FOLDER, MARKETPLACE_FOLDER } from '../../lib/constants'; +import { uiLink } from '../../lib/ui'; +import { EXIT_CODES } from '../../lib/enums/exitCodes'; +import { + AccountArgs, + CommonArgs, + EnvironmentArgs, + YargsCommandModule, +} from '../../types/Yargs'; +import { makeYargsBuilder } from '../../lib/yargsUtils'; const DEFAULT_TABLE_HEADER = [ 'Accessibility', @@ -27,50 +33,67 @@ const DEFAULT_TABLE_HEADER = [ 'SEO', ]; -exports.command = 'lighthouse-score [--theme]'; -exports.describe = false; +const EMPTY_SCORE: GetLighthouseScoreResponse['scores'][0] = { + accessibilityScore: 0, + bestPracticesScore: 0, + performanceScore: 0, + pwaScore: 0, + seoScore: 0, + runWarnings: [], + auditDetails: null, + emulatedFormFactor: '', + templatePath: null, + link: null, +}; + +const command = 'lighthouse-score [--theme]'; +const describe = undefined; + +type LighthouseScoreArgs = CommonArgs & + AccountArgs & + EnvironmentArgs & { theme?: string; target: string; verbose: boolean }; + +async function selectTheme(accountId: number): Promise { + let themes: string[] = []; + try { + const { data: result } = await fetchThemes(accountId, { + limit: 500, + sorting: 'MOST_USED', + }); + if (result && result.objects) { + themes = result.objects + .map(({ theme }) => theme.path) + .filter( + themePath => + !themePath.startsWith(HUBSPOT_FOLDER) && + !themePath.startsWith(MARKETPLACE_FOLDER) + ); + } + } catch (err) { + logger.error( + i18n( + `commands.cms.subcommands.lighthouseScore.errors.failedToFetchThemes` + ) + ); + process.exit(EXIT_CODES.ERROR); + } -const selectTheme = async accountId => { const { theme: selectedTheme } = await promptUser([ { type: 'list', - look: false, name: 'theme', message: i18n( `commands.cms.subcommands.lighthouseScore.info.promptMessage` ), - choices: async () => { - try { - const { data: result } = await fetchThemes(accountId, { - limit: 500, - sorting: 'MOST_USED', - }); - if (result && result.objects) { - return result.objects - .map(({ theme }) => theme.path) - .filter( - themePath => - !themePath.startsWith(HUBSPOT_FOLDER) && - !themePath.startsWith(MARKETPLACE_FOLDER) - ); - } - } catch (err) { - logger.error( - i18n( - `commands.cms.subcommands.lighthouseScore.errors.failedToFetchThemes` - ) - ); - process.exit(EXIT_CODES.ERROR); - } - }, + choices: themes, }, ]); return selectedTheme; -}; +} -exports.handler = async options => { - const { target, verbose, theme, derivedAccountId } = options; +async function handler(args: ArgumentsCamelCase) { + const { target, verbose, theme, derivedAccountId } = args; const includeDesktopScore = target === 'desktop' || !verbose; const includeMobileScore = target === 'mobile' || !verbose; @@ -82,7 +105,7 @@ exports.handler = async options => { const { data: result } = await fetchThemes(derivedAccountId, { name: encodeURIComponent(themeToCheck), }); - isValidTheme = result && result.total; + isValidTheme = result && !!result.total; } catch (err) { isValidTheme = false; } @@ -100,7 +123,8 @@ exports.handler = async options => { } // Kick off the scoring - let requestResult; + let requestResult: RequestLighthouseScoreResponse | undefined; + try { const { data } = await requestLighthouseScore(derivedAccountId, { themePath: themeToCheck, @@ -165,9 +189,9 @@ exports.handler = async options => { } // Fetch the scoring results - let desktopScoreResult = {}; - let mobileScoreResult = {}; - let verboseViewAverageScoreResult = {}; + let desktopScoreResult: GetLighthouseScoreResponse | undefined; + let mobileScoreResult: GetLighthouseScoreResponse | undefined; + let verboseViewAverageScoreResult: GetLighthouseScoreResponse | undefined; try { const params = { isAverage: !verbose }; @@ -191,8 +215,8 @@ exports.handler = async options => { const { data } = await getLighthouseScore(derivedAccountId, { ...params, isAverage: true, - desktopId: includeDesktopScore ? requestResult.desktopId : null, - mobileId: includeMobileScore ? requestResult.mobileId : null, + desktopId: includeDesktopScore ? requestResult.desktopId : undefined, + mobileId: includeMobileScore ? requestResult.mobileId : undefined, }); verboseViewAverageScoreResult = data; } @@ -206,13 +230,25 @@ exports.handler = async options => { } if (verbose) { + const scoreResult = + target === 'desktop' ? desktopScoreResult : mobileScoreResult; + + if (!verboseViewAverageScoreResult || !scoreResult) { + logger.error( + i18n( + `commands.cms.subcommands.lighthouseScore.errors.failedToGetLighthouseScore` + ) + ); + process.exit(EXIT_CODES.ERROR); + } + logger.log(`${themeToCheck} ${target} scores`); const tableHeader = getTableHeader(DEFAULT_TABLE_HEADER); const scores = verboseViewAverageScoreResult.scores ? verboseViewAverageScoreResult.scores[0] - : {}; + : EMPTY_SCORE; const averageTableData = [ scores.accessibilityScore, @@ -238,9 +274,6 @@ exports.handler = async options => { ...DEFAULT_TABLE_HEADER, ]); - const scoreResult = - target === 'desktop' ? desktopScoreResult : mobileScoreResult; - const templateTableData = scoreResult.scores.map(score => { return [ score.templatePath, @@ -263,7 +296,9 @@ exports.handler = async options => { ); scoreResult.scores.forEach(score => { - logger.log(' ', uiLink(score.templatePath, score.link)); + if (score.templatePath && score.link) { + logger.log(' ', uiLink(score.templatePath, score.link)); + } }); if (scoreResult.failedTemplatePaths.length) { @@ -288,8 +323,11 @@ exports.handler = async options => { logger.log(`Theme: ${themeToCheck}`); const tableHeader = getTableHeader(['Target', ...DEFAULT_TABLE_HEADER]); - const getTableData = (target, scoreResult) => { - const scores = scoreResult.scores ? scoreResult.scores[0] : {}; + const getTableData = ( + target: string, + scoreResult?: GetLighthouseScoreResponse + ): [string, number, number, number, number, number] => { + const scores = scoreResult?.scores ? scoreResult.scores[0] : EMPTY_SCORE; return [ target, scores.accessibilityScore, @@ -324,10 +362,10 @@ exports.handler = async options => { )}.` ); - process.exit(); -}; + process.exit(EXIT_CODES.SUCCESS); +} -exports.builder = yargs => { +function cmslighthouseScoreBuilder(yargs: Argv): Argv { yargs.option('theme', { describe: i18n( `commands.cms.subcommands.lighthouseScore.options.theme.describe` @@ -356,9 +394,32 @@ exports.builder = yargs => { ], ]); - addConfigOptions(yargs); - addAccountOptions(yargs); - addUseEnvironmentOptions(yargs); - - return yargs; + return yargs as Argv; +} + +const builder = makeYargsBuilder( + cmslighthouseScoreBuilder, + command, + describe, + { + useGlobalOptions: true, + useConfigOptions: true, + useAccountOptions: true, + useEnvironmentOptions: true, + } +); + +const cmslighthouseScoreCommand: YargsCommandModule< + unknown, + LighthouseScoreArgs +> = { + command, + describe, + handler, + builder, }; + +export default cmslighthouseScoreCommand; + +// TODO remove this after cms.ts is ported to TypeScript +module.exports = cmslighthouseScoreCommand; From 5897914d3dc08904bf66b929d09d8a92548e5bc8 Mon Sep 17 00:00:00 2001 From: Branden Rodgers Date: Fri, 9 May 2025 11:54:42 -0400 Subject: [PATCH 2/3] use function --- commands/cms/lighthouseScore.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/commands/cms/lighthouseScore.ts b/commands/cms/lighthouseScore.ts index efb186b58..b95815985 100644 --- a/commands/cms/lighthouseScore.ts +++ b/commands/cms/lighthouseScore.ts @@ -154,11 +154,11 @@ async function handler(args: ArgumentsCamelCase) { ), }); - const checkScoreStatus = async () => { + async function checkScoreStatus(): Promise { let desktopScoreStatus = 'COMPLETED'; if (includeDesktopScore) { const { data } = await getLighthouseScoreStatus(derivedAccountId, { - themeId: requestResult.desktopId, + themeId: requestResult!.desktopId, }); desktopScoreStatus = data; } @@ -166,7 +166,7 @@ async function handler(args: ArgumentsCamelCase) { let mobileScoreStatus = 'COMPLETED'; if (includeDesktopScore) { const { data } = await getLighthouseScoreStatus(derivedAccountId, { - themeId: requestResult.mobileId, + themeId: requestResult!.mobileId, }); mobileScoreStatus = data; } @@ -178,7 +178,7 @@ async function handler(args: ArgumentsCamelCase) { await new Promise(resolve => setTimeout(resolve, 2000)); await checkScoreStatus(); } - }; + } await checkScoreStatus(); From 378dd8d3d9b9f026a33c299bb0d3cc71727e030c Mon Sep 17 00:00:00 2001 From: Branden Rodgers Date: Fri, 9 May 2025 16:19:54 -0400 Subject: [PATCH 3/3] bump ldl version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9b8f41c0d..4fddf058c 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "license": "Apache-2.0", "repository": "https://github.com/HubSpot/hubspot-cli", "dependencies": { - "@hubspot/local-dev-lib": "3.5.5", + "@hubspot/local-dev-lib": "3.5.6", "@hubspot/project-parsing-lib": "0.1.7", "@hubspot/serverless-dev-runtime": "7.0.2", "@hubspot/theme-preview-dev-server": "0.0.10",