diff --git a/commands/logs.ts b/commands/logs.ts index 3570a1416..c6e86375e 100644 --- a/commands/logs.ts +++ b/commands/logs.ts @@ -61,13 +61,7 @@ const endpointLog = async (accountId, functionPath, options) => { } }; - await tailLogs({ - accountId, - compact, - tailCall, - fetchLatest, - name: functionPath, - }); + await tailLogs(accountId, functionPath, fetchLatest, tailCall, compact); } else if (latest) { try { const { data } = await getLatestFunctionLog(accountId, functionPath); diff --git a/commands/sandbox/create.ts b/commands/sandbox/create.ts index 33dbb1314..d05ef2b77 100644 --- a/commands/sandbox/create.ts +++ b/commands/sandbox/create.ts @@ -28,7 +28,7 @@ const { HUBSPOT_ACCOUNT_TYPES, HUBSPOT_ACCOUNT_TYPE_STRINGS, } = require('@hubspot/local-dev-lib/constants/config'); -const { buildNewAccount } = require('../../lib/buildAccount'); +const { buildSandbox } = require('../../lib/buildAccount'); const { hubspotAccountNamePrompt, } = require('../../lib/prompts/accountNamePrompt'); @@ -130,13 +130,13 @@ exports.handler = async options => { } try { - const { result } = await buildNewAccount({ - name: sandboxName, - accountType: sandboxType, + const result = await buildSandbox( + sandboxName, accountConfig, + sandboxType, env, - force, - }); + force + ); const sandboxAccountConfig = getAccountConfig(result.sandbox.sandboxHubId); // For v1 sandboxes, keep sync here. Once we migrate to v2, this will be handled by BE automatically diff --git a/lang/en.lyaml b/lang/en.lyaml index 0b4f5c7e4..8634c9de2 100644 --- a/lang/en.lyaml +++ b/lang/en.lyaml @@ -1499,7 +1499,7 @@ en: missingScopeError: "Couldn't execute the {{ request }} because the access key for {{ accountName }} is missing required scopes. To update scopes, run {{ authCommand }}. Then deactivate the existing key and generate a new one that includes the missing scopes." serverless: verifyAccessKeyAndUserAccess: - fetchScopeDataError: "Error verifying access of scopeGroup {{ scopeGroup }}: {{ error }}" + fetchScopeDataError: "Error verifying access of scopeGroup {{ scopeGroup }}:" portalMissingScope: "Your account does not have access to this action. Talk to an account admin to request it." userMissingScope: "You don't have access to this action. Ask an account admin to change your permissions in Users & Teams settings." genericMissingScope: "Your access key does not allow this action. Please generate a new access key by running `hs auth personalaccesskey`." diff --git a/lib/__tests__/serverlessLogs.test.ts b/lib/__tests__/serverlessLogs.test.ts index 1cb92dd66..195787f82 100644 --- a/lib/__tests__/serverlessLogs.test.ts +++ b/lib/__tests__/serverlessLogs.test.ts @@ -12,16 +12,10 @@ const ACCOUNT_ID = 123; describe('lib/serverlessLogs', () => { describe('tailLogs()', () => { let stdinMock; - let spinnies; beforeEach(() => { jest.spyOn(process, 'exit').mockImplementation(() => {}); stdinMock = mockStdIn.stdin(); - spinnies = { - succeed: jest.fn(), - fail: jest.fn(), - stopAll: jest.fn(), - }; }); afterEach(() => { @@ -33,14 +27,16 @@ describe('lib/serverlessLogs', () => { const compact = false; const fetchLatest = jest.fn(() => { return Promise.resolve({ - id: '1234', - executionTime: 510, - log: 'Log message', - error: null, - status: 'SUCCESS', - createdAt: 1620232011451, - memory: '70/128 MB', - duration: '53.40 ms', + data: { + id: '1234', + executionTime: 510, + log: 'Log message', + error: null, + status: 'SUCCESS', + createdAt: 1620232011451, + memory: '70/128 MB', + duration: '53.40 ms', + }, }); }); const tailCall = jest.fn(() => { @@ -54,13 +50,7 @@ describe('lib/serverlessLogs', () => { }); }); - await tailLogs({ - accountId: ACCOUNT_ID, - compact, - spinnies, - fetchLatest, - tailCall, - }); + await tailLogs(ACCOUNT_ID, 'name', fetchLatest, tailCall, compact); jest.runOnlyPendingTimers(); expect(fetchLatest).toHaveBeenCalled(); @@ -116,13 +106,7 @@ describe('lib/serverlessLogs', () => { Promise.resolve({ data: latestLogResponse }) ); - await tailLogs({ - accountId: ACCOUNT_ID, - compact, - spinnies, - fetchLatest, - tailCall, - }); + await tailLogs(ACCOUNT_ID, 'name', fetchLatest, tailCall, compact); jest.runOnlyPendingTimers(); expect(outputLogs).toHaveBeenCalledWith( latestLogResponse, @@ -148,13 +132,7 @@ describe('lib/serverlessLogs', () => { ) ); - await tailLogs({ - accountId: ACCOUNT_ID, - compact, - spinnies, - fetchLatest, - tailCall, - }); + await tailLogs(ACCOUNT_ID, 'name', fetchLatest, tailCall, compact); jest.runOnlyPendingTimers(); expect(tailCall).toHaveBeenCalledTimes(2); }); diff --git a/lib/buildAccount.ts b/lib/buildAccount.ts index e6e236678..91f421bea 100644 --- a/lib/buildAccount.ts +++ b/lib/buildAccount.ts @@ -1,47 +1,39 @@ -// @ts-nocheck -const { +import { getAccessToken, updateConfigWithAccessToken, -} = require('@hubspot/local-dev-lib/personalAccessKey'); -const { - personalAccessKeyPrompt, -} = require('./prompts/personalAccessKeyPrompt'); -const { +} from '@hubspot/local-dev-lib/personalAccessKey'; +import { accountNameExistsInConfig, updateAccountConfig, writeConfig, getAccountId, -} = require('@hubspot/local-dev-lib/config'); -const { - getAccountIdentifier, -} = require('@hubspot/local-dev-lib/config/getAccountIdentifier'); -const { logger } = require('@hubspot/local-dev-lib/logger'); -const { i18n } = require('./lang'); -const { cliAccountNamePrompt } = require('./prompts/accountNamePrompt'); -const SpinniesManager = require('./ui/SpinniesManager'); -const { debugError, logError } = require('./errorHandlers/index'); -const { - createDeveloperTestAccount, -} = require('@hubspot/local-dev-lib/api/developerTestAccounts'); -const { - HUBSPOT_ACCOUNT_TYPES, -} = require('@hubspot/local-dev-lib/constants/config'); -const { createSandbox } = require('@hubspot/local-dev-lib/api/sandboxHubs'); -const { - SANDBOX_API_TYPE_MAP, - handleSandboxCreateError, -} = require('./sandboxes'); -const { - handleDeveloperTestAccountCreateError, -} = require('./developerTestAccounts'); - -async function saveAccountToConfig({ - env, - personalAccessKey, - accountName, - accountId, - force = false, -}) { +} from '@hubspot/local-dev-lib/config'; +import { getAccountIdentifier } from '@hubspot/local-dev-lib/config/getAccountIdentifier'; +import { logger } from '@hubspot/local-dev-lib/logger'; +import { createDeveloperTestAccount } from '@hubspot/local-dev-lib/api/developerTestAccounts'; +import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config'; +import { createSandbox } from '@hubspot/local-dev-lib/api/sandboxHubs'; +import { Environment } from '@hubspot/local-dev-lib/types/Config'; + +import { personalAccessKeyPrompt } from './prompts/personalAccessKeyPrompt'; +import { i18n } from './lang'; +import { cliAccountNamePrompt } from './prompts/accountNamePrompt'; +import SpinniesManager from './ui/SpinniesManager'; +import { debugError, logError } from './errorHandlers/index'; + +import { SANDBOX_API_TYPE_MAP, handleSandboxCreateError } from './sandboxes'; +import { handleDeveloperTestAccountCreateError } from './developerTestAccounts'; +import { CLIAccount } from '@hubspot/local-dev-lib/types/Accounts'; +import { DeveloperTestAccount } from '@hubspot/local-dev-lib/types/developerTestAccounts'; +import { SandboxResponse } from '@hubspot/local-dev-lib/types/Sandbox'; + +export async function saveAccountToConfig( + accountId: number | undefined, + accountName: string, + env: Environment, + personalAccessKey?: string, + force = false +): Promise { if (!personalAccessKey) { const configData = await personalAccessKeyPrompt({ env, @@ -57,8 +49,8 @@ async function saveAccountToConfig({ env ); - let validName = updatedConfig.name; - if (!updatedConfig.name) { + let validName = updatedConfig?.name || ''; + if (!updatedConfig?.name) { const nameForConfig = accountName.toLowerCase().split(' ').join('-'); validName = nameForConfig; const invalidAccountName = accountNameExistsInConfig(nameForConfig); @@ -83,8 +75,8 @@ async function saveAccountToConfig({ updateAccountConfig({ ...updatedConfig, - environment: updatedConfig.env, - tokenInfo: updatedConfig.auth.tokenInfo, + env: updatedConfig?.env, + tokenInfo: updatedConfig?.auth?.tokenInfo, name: validName, }); writeConfig(); @@ -93,105 +85,145 @@ async function saveAccountToConfig({ return validName; } -async function buildNewAccount({ - name, - accountType, - accountConfig, - env, - portalLimit, // Used only for developer test accounts - force = false, -}) { +export async function buildDeveloperTestAccount( + name: string, + accountConfig: CLIAccount, + env: Environment, + portalLimit: number +): Promise { + const i18nKey = 'lib.developerTestAccount.create.loading'; + + const id = getAccountIdentifier(accountConfig); + const accountId = getAccountId(id); + + if (!accountId) { + throw new Error(i18n(`${i18nKey}.fail`)); + } + SpinniesManager.init({ succeedColor: 'white', }); + + logger.log(''); + SpinniesManager.add('buildDeveloperTestAccount', { + text: i18n(`${i18nKey}.add`, { + accountName: name, + }), + }); + + let developerTestAccount: DeveloperTestAccount; + + try { + const { data } = await createDeveloperTestAccount(accountId, name); + + developerTestAccount = data; + + SpinniesManager.succeed('buildDeveloperTestAccount', { + text: i18n(`${i18nKey}.succeed`, { + accountName: name, + accountId: developerTestAccount.id, + }), + }); + } catch (e) { + debugError(e); + + SpinniesManager.fail('buildDeveloperTestAccount', { + text: i18n(`${i18nKey}.fail`, { + accountName: name, + }), + }); + + handleDeveloperTestAccountCreateError(e, accountId, env, portalLimit); + } + + try { + await saveAccountToConfig(accountId, name, env); + } catch (err) { + logError(err); + throw err; + } + + return developerTestAccount; +} + +type SandboxType = + | typeof HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX + | typeof HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX; + +type SandboxAccount = SandboxResponse & { + name: string; +}; + +export async function buildSandbox( + name: string, + accountConfig: CLIAccount, + sandboxType: SandboxType, + env: Environment, + force = false +): Promise { + let i18nKey: string; + if (sandboxType === HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX) { + i18nKey = 'lib.sandbox.create.loading.standard'; + } else { + i18nKey = 'lib.sandbox.create.loading.developer'; + } + const id = getAccountIdentifier(accountConfig); const accountId = getAccountId(id); - const isSandbox = - accountType === HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX || - accountType === HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX; - const isDeveloperTestAccount = - accountType === HUBSPOT_ACCOUNT_TYPES.DEVELOPER_TEST; - - let result; - let spinniesI18nKey; - if (isSandbox) { - if (accountType === HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX) { - spinniesI18nKey = 'lib.sandbox.create.loading.standard'; - } - if (accountType === HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX) { - spinniesI18nKey = 'lib.sandbox.create.loading.developer'; - } - } else if (isDeveloperTestAccount) { - spinniesI18nKey = 'lib.developerTestAccount.create.loading'; + + if (!accountId) { + throw new Error(i18n(`${i18nKey}.fail`)); } + SpinniesManager.init({ + succeedColor: 'white', + }); + logger.log(''); - SpinniesManager.add('buildNewAccount', { - text: i18n(`${spinniesI18nKey}.add`, { + SpinniesManager.add('buildSandbox', { + text: i18n(`${i18nKey}.add`, { accountName: name, }), }); - let resultAccountId; + let sandbox: SandboxAccount; + try { - if (isSandbox) { - const sandboxApiType = SANDBOX_API_TYPE_MAP[accountType]; // API expects sandbox type as 1 or 2. - - const { data } = await createSandbox(accountId, name, sandboxApiType); - result = { name, ...data }; - resultAccountId = result.sandbox.sandboxHubId; - } else if (isDeveloperTestAccount) { - const { data } = await createDeveloperTestAccount(accountId, name); - result = data; - resultAccountId = result.id; - } + const sandboxApiType = SANDBOX_API_TYPE_MAP[sandboxType]; + + const { data } = await createSandbox(accountId, name, sandboxApiType); + sandbox = { name, ...data }; - SpinniesManager.succeed('buildNewAccount', { - text: i18n(`${spinniesI18nKey}.succeed`, { + SpinniesManager.succeed('buildSandbox', { + text: i18n(`${i18nKey}.succeed`, { accountName: name, - accountId: resultAccountId, + accountId: sandbox.sandbox.sandboxHubId, }), }); - } catch (err) { - debugError(err); + } catch (e) { + debugError(e); - SpinniesManager.fail('buildNewAccount', { - text: i18n(`${spinniesI18nKey}.fail`, { + SpinniesManager.fail('buildSandbox', { + text: i18n(`${i18nKey}.fail`, { accountName: name, }), }); - if (isSandbox) { - handleSandboxCreateError(err, env, name, accountId); - } - if (isDeveloperTestAccount) { - handleDeveloperTestAccountCreateError(err, env, accountId, portalLimit); - } + handleSandboxCreateError(e, env, name, accountId); } - let configAccountName; - try { - // Response contains PAK, save to config here - configAccountName = await saveAccountToConfig({ + await saveAccountToConfig( + accountId, + name, env, - personalAccessKey: result.personalAccessKey, - accountName: name, - accountId: resultAccountId, - force, - }); + sandbox.personalAccessKey, + force + ); } catch (err) { logError(err); throw err; } - return { - configAccountName, - result, - }; + return sandbox; } - -module.exports = { - buildNewAccount, - saveAccountToConfig, -}; diff --git a/lib/localDev.ts b/lib/localDev.ts index 20d5b02b9..886e185ca 100644 --- a/lib/localDev.ts +++ b/lib/localDev.ts @@ -49,7 +49,11 @@ const { logError, ApiErrorContext } = require('./errorHandlers/index'); const { PERSONAL_ACCESS_KEY_AUTH_METHOD, } = require('@hubspot/local-dev-lib/constants/auth'); -const { buildNewAccount, saveAccountToConfig } = require('./buildAccount'); +const { + buildSandbox, + buildDeveloperTestAccount, + saveAccountToConfig, +} = require('./buildAccount'); const { hubspotAccountNamePrompt } = require('./prompts/accountNamePrompt'); const i18nKey = 'lib.localDev'; @@ -208,12 +212,12 @@ const createSandboxForLocalDev = async (accountId, accountConfig, env) => { accountId ); - const { result } = await buildNewAccount({ + const result = await buildSandbox( name, - accountType: HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX, accountConfig, - env, - }); + HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX, + env + ); const targetAccountId = result.sandbox.sandboxHubId; @@ -286,13 +290,12 @@ const createDeveloperTestAccountForLocalDev = async ( accountId ); - const { result } = await buildNewAccount({ + const result = await buildDeveloperTestAccount( name, - accountType: HUBSPOT_ACCOUNT_TYPES.DEVELOPER_TEST, accountConfig, env, - portalLimit: maxTestPortals, - }); + maxTestPortals + ); return result.id; } catch (err) { @@ -319,11 +322,11 @@ const useExistingDevTestAccount = async (env, account) => { logger.log(''); process.exit(EXIT_CODES.SUCCESS); } - const devTestAcctConfigName = await saveAccountToConfig({ - env, - accountName: account.accountName, - accountId: account.id, - }); + const devTestAcctConfigName = await saveAccountToConfig( + account.id, + account.accountName, + env + ); logger.success( i18n(`lib.developerTestAccount.create.success.configFileUpdated`, { accountName: devTestAcctConfigName, diff --git a/lib/prompts/personalAccessKeyPrompt.ts b/lib/prompts/personalAccessKeyPrompt.ts index dd15dc6ef..51c43436a 100644 --- a/lib/prompts/personalAccessKeyPrompt.ts +++ b/lib/prompts/personalAccessKeyPrompt.ts @@ -49,7 +49,7 @@ export async function personalAccessKeyPrompt({ account, }: { env: string; - account?: string; + account?: number; }): Promise { const websiteOrigin = getHubSpotWebsiteOrigin(env); let url = `${websiteOrigin}/l/personal-access-key`; diff --git a/lib/sandboxes.ts b/lib/sandboxes.ts index feb561dd8..b4a25698a 100644 --- a/lib/sandboxes.ts +++ b/lib/sandboxes.ts @@ -186,7 +186,7 @@ export function handleSandboxCreateError( env: Environment, name: string, accountId: number -) { +): never { if (isMissingScopeError(err)) { logger.error( i18n(`${i18nKey}.create.failure.scopes.message`, { diff --git a/lib/serverlessLogs.ts b/lib/serverlessLogs.ts index c716d7ece..476d4f4de 100644 --- a/lib/serverlessLogs.ts +++ b/lib/serverlessLogs.ts @@ -1,37 +1,41 @@ -// @ts-nocheck -const https = require('https'); -const SpinniesManager = require('./ui/SpinniesManager'); -const { handleExit, handleKeypress } = require('./process'); -const chalk = require('chalk'); -const { logger } = require('@hubspot/local-dev-lib/logger'); -const { outputLogs } = require('./ui/serverlessFunctionLogs'); -const { logError, ApiErrorContext } = require('./errorHandlers/index'); - -const { EXIT_CODES } = require('./enums/exitCodes'); -const { +import https from 'https'; +import chalk from 'chalk'; +import { logger } from '@hubspot/local-dev-lib/logger'; +import { isHubSpotHttpError, isMissingScopeError, -} = require('@hubspot/local-dev-lib/errors/index'); -const { +} from '@hubspot/local-dev-lib/errors/index'; +import { SCOPE_GROUPS, PERSONAL_ACCESS_KEY_AUTH_METHOD, -} = require('@hubspot/local-dev-lib/constants/auth'); -const { getAccountConfig } = require('@hubspot/local-dev-lib/config'); -const { fetchScopeData } = require('@hubspot/local-dev-lib/api/localDevAuth'); -const { i18n } = require('./lang'); +} from '@hubspot/local-dev-lib/constants/auth'; +import { getAccountConfig } from '@hubspot/local-dev-lib/config'; +import { fetchScopeData } from '@hubspot/local-dev-lib/api/localDevAuth'; + +import { outputLogs } from './ui/serverlessFunctionLogs'; +import { logError, ApiErrorContext } from './errorHandlers/index'; +import SpinniesManager from './ui/SpinniesManager'; +import { handleExit, handleKeypress } from './process'; +import { EXIT_CODES } from './enums/exitCodes'; +import { i18n } from './lang'; +import { HubSpotPromise } from '@hubspot/local-dev-lib/types/Http'; +import { + FunctionLog, + GetFunctionLogsResponse, +} from '@hubspot/local-dev-lib/types/Functions'; const TAIL_DELAY = 5000; -const base64EncodeString = valueToEncode => { +function base64EncodeString(valueToEncode: string): string { if (typeof valueToEncode !== 'string') { return valueToEncode; } const stringBuffer = Buffer.from(valueToEncode); return encodeURIComponent(stringBuffer.toString('base64')); -}; +} -const handleUserInput = () => { +function handleUserInput(): void { const onTerminate = async () => { SpinniesManager.remove('tailLogs'); SpinniesManager.remove('stopMessage'); @@ -44,10 +48,18 @@ const handleUserInput = () => { onTerminate(); } }); -}; +} -async function verifyAccessKeyAndUserAccess(accountId, scopeGroup) { +async function verifyAccessKeyAndUserAccess( + accountId: number, + scopeGroup: string +): Promise { const accountConfig = getAccountConfig(accountId); + + if (!accountConfig) { + return; + } + // TODO[JOE]: Update this i18n key const i18nKey = 'lib.serverless'; const { authType } = accountConfig; @@ -57,14 +69,15 @@ async function verifyAccessKeyAndUserAccess(accountId, scopeGroup) { let scopesData; try { - scopesData = await fetchScopeData(accountId, scopeGroup); + const resp = await fetchScopeData(accountId, scopeGroup); + scopesData = resp.data; } catch (e) { logger.debug( i18n(`${i18nKey}.verifyAccessKeyAndUserAccess.fetchScopeDataError`, { scopeGroup, - error: e, }) ); + logger.debug(e); return; } const { portalScopesInGroup, userScopesInGroup } = scopesData; @@ -87,14 +100,14 @@ async function verifyAccessKeyAndUserAccess(accountId, scopeGroup) { } } -const tailLogs = async ({ - accountId, - compact, - fetchLatest, - tailCall, - name, -}) => { - let initialAfter; +export async function tailLogs( + accountId: number, + name: string, + fetchLatest: () => HubSpotPromise, + tailCall: (after?: string) => HubSpotPromise, + compact = false +): Promise { + let initialAfter = ''; try { const { data: latestLog } = await fetchLatest(); @@ -113,9 +126,9 @@ const tailLogs = async ({ } } - const tail = async after => { - let latestLog; - let nextAfter; + async function tail(after?: string): Promise { + let latestLog: GetFunctionLogsResponse; + let nextAfter: string; try { const { data } = await tailCall(after); latestLog = data; @@ -141,7 +154,7 @@ const tailLogs = async ({ setTimeout(async () => { await tail(nextAfter); }, TAIL_DELAY); - }; + } SpinniesManager.init(); @@ -156,14 +169,14 @@ const tailLogs = async ({ handleUserInput(); await tail(initialAfter); -}; +} -const outputBuildLog = async buildLogUrl => { +export async function outputBuildLog(buildLogUrl: string): Promise { if (!buildLogUrl) { logger.debug( 'Unable to display build output. No build log URL was provided.' ); - return; + return ''; } return new Promise(resolve => { @@ -191,9 +204,4 @@ const outputBuildLog = async buildLogUrl => { resolve(''); } }); -}; - -module.exports = { - outputBuildLog, - tailLogs, -}; +} diff --git a/lib/ui/serverlessFunctionLogs.ts b/lib/ui/serverlessFunctionLogs.ts index 66108eab3..f75a56a16 100644 --- a/lib/ui/serverlessFunctionLogs.ts +++ b/lib/ui/serverlessFunctionLogs.ts @@ -2,11 +2,15 @@ import moment from 'moment'; import chalk from 'chalk'; import { logger, Styles } from '@hubspot/local-dev-lib/logger'; import { i18n } from '../lang'; +import { + FunctionLog, + GetFunctionLogsResponse, +} from '@hubspot/local-dev-lib/types/Functions'; const i18nKey = 'lib.ui.serverlessFunctionLogs'; const SEPARATOR = ' - '; -const LOG_STATUS_COLORS = { +const LOG_STATUS_COLORS: { [key: string]: (status: string) => string } = { SUCCESS: Styles.success, ERROR: Styles.error, UNHANDLED_ERROR: Styles.error, @@ -15,22 +19,6 @@ const LOG_STATUS_COLORS = { type LogStatus = keyof typeof LOG_STATUS_COLORS; -type Log = { - status: LogStatus; - createdAt: string; - executionTime: number; - log?: string; - error?: { - type: string; - message: string; - stackTrace?: string[]; - }; -}; - -type LogsResponse = { - results?: Log[]; -}; - type Options = { compact?: boolean; insertions?: { @@ -38,22 +26,22 @@ type Options = { }; }; -function errorHandler(log: Log, options: Options): string { +function errorHandler(log: FunctionLog, options: Options): string { return `${formatLogHeader(log, options)}${formatError(log, options)}`; } const logHandler: { - [key in LogStatus]: (log: Log, options: Options) => string; + [key in LogStatus]: (log: FunctionLog, options: Options) => string; } = { ERROR: errorHandler, UNHANDLED_ERROR: errorHandler, HANDLED_ERROR: errorHandler, - SUCCESS: (log: Log, options: Options): string => { + SUCCESS: (log: FunctionLog, options: Options): string => { return `${formatLogHeader(log, options)}${formatSuccess(log, options)}`; }, }; -function formatSuccess(log: Log, options: Options): string { +function formatSuccess(log: FunctionLog, options: Options): string { if (!log.log || options.compact) { return ''; } @@ -61,7 +49,7 @@ function formatSuccess(log: Log, options: Options): string { return `\n${log.log}`; } -function formatError(log: Log, options: Options): string { +function formatError(log: FunctionLog, options: Options): string { if (!log.error || options.compact) { return ''; } @@ -69,7 +57,7 @@ function formatError(log: Log, options: Options): string { return `${log.error.type}: ${log.error.message}\n${formatStackTrace(log)}`; } -function formatLogHeader(log: Log, options: Options): string { +function formatLogHeader(log: FunctionLog, options: Options): string { const color = LOG_STATUS_COLORS[log.status]; const headerInsertion = options && options.insertions && options.insertions.header; @@ -79,7 +67,7 @@ function formatLogHeader(log: Log, options: Options): string { }${SEPARATOR}${formatExecutionTime(log)}`; } -function formatStackTrace(log: Log): string { +function formatStackTrace(log: FunctionLog): string { const stackTrace = log.error?.stackTrace || []; return stackTrace .map(trace => { @@ -88,15 +76,15 @@ function formatStackTrace(log: Log): string { .join(''); } -function formatTimestamp(log: Log): string { +function formatTimestamp(log: FunctionLog): string { return `${chalk.whiteBright(moment(log.createdAt).toISOString())}`; } -function formatExecutionTime(log: Log): string { +function formatExecutionTime(log: FunctionLog): string { return `${chalk.whiteBright('Execution Time:')} ${log.executionTime}ms`; } -function processLog(log: Log, options: Options): string | void { +function processLog(log: FunctionLog, options: Options): string | void { try { return logHandler[log.status](log, options); } catch (e) { @@ -109,8 +97,8 @@ function processLog(log: Log, options: Options): string | void { } function isLogsResponse( - logsResp: LogsResponse | Log -): logsResp is LogsResponse { + logsResp: GetFunctionLogsResponse | FunctionLog +): logsResp is GetFunctionLogsResponse { return ( logsResp && 'results' in logsResp && @@ -120,7 +108,7 @@ function isLogsResponse( } function processLogs( - logsResp: LogsResponse | Log, + logsResp: GetFunctionLogsResponse | FunctionLog, options: Options ): string | void { const isLogsResp = isLogsResponse(logsResp); @@ -134,13 +122,12 @@ function processLogs( }) .join('\n'); } - return processLog(logsResp as Log, options); + return processLog(logsResp, options); } -function outputLogs(logsResp: LogsResponse | Log, options: Options): void { +export function outputLogs( + logsResp: GetFunctionLogsResponse | FunctionLog, + options: Options +): void { logger.log(processLogs(logsResp, options)); } - -module.exports = { - outputLogs, -}; diff --git a/package.json b/package.json index 06cc0c486..84432f9cd 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.1.1", + "@hubspot/local-dev-lib": "3.1.2", "@hubspot/serverless-dev-runtime": "7.0.1", "@hubspot/theme-preview-dev-server": "0.0.10", "@hubspot/ui-extensions-dev-server": "0.8.40", diff --git a/yarn.lock b/yarn.lock index 065849c51..564d14de1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1446,10 +1446,10 @@ semver "^6.3.0" unixify "^1.0.0" -"@hubspot/local-dev-lib@3.1.1": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@hubspot/local-dev-lib/-/local-dev-lib-3.1.1.tgz#b67646d7a7b399cebc5d74f62c389c13554e950c" - integrity sha512-/SIKBuC3ORkKMXityS6tCz2sNU7OY96slJtLM0CxRlKDCiwEGb08Lf0Ruf1PMBJnAu8iHbw/6SprefFEHEQOpw== +"@hubspot/local-dev-lib@3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@hubspot/local-dev-lib/-/local-dev-lib-3.1.2.tgz#9af9f8ca5cf9aba912cb9c5f9acf51e760604465" + integrity sha512-vn9pyKs/2NW86GWhTlp9VyDcpKUUUEWQgHwQpq57Luz9IWwCFAmFaTzSggmttTnqJRAmqwMIN8DHUKeMEJqquA== dependencies: address "^2.0.1" axios "^1.3.5"