diff --git a/commands/project/__tests__/logs.test.ts b/commands/project/__tests__/logs.test.ts index 47ac06335..663405e1e 100644 --- a/commands/project/__tests__/logs.test.ts +++ b/commands/project/__tests__/logs.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck const yargs = require('yargs'); const { addUseEnvironmentOptions } = require('../../../lib/commonOpts'); -const ProjectLogsManager = require('../../../lib/ProjectLogsManager'); +const ProjectLogsManager = require('../../../lib/projects/ProjectLogsManager'); const { projectLogsPrompt, } = require('../../../lib/prompts/projectsLogsPrompt'); @@ -16,7 +16,7 @@ jest.mock('@hubspot/local-dev-lib/logger'); jest.mock('../../../lib/commonOpts'); jest.mock('../../../lib/usageTracking'); jest.mock('../../../lib/validation'); -jest.mock('../../../lib/ProjectLogsManager'); +jest.mock('../../../lib/projects/ProjectLogsManager'); jest.mock('../../../lib/prompts/projectsLogsPrompt'); jest.mock('../../../lib/ui/table'); jest.mock('../../../lib/errorHandlers'); diff --git a/commands/project/logs.ts b/commands/project/logs.ts index e92634adf..ed95041cf 100644 --- a/commands/project/logs.ts +++ b/commands/project/logs.ts @@ -15,7 +15,7 @@ const { uiBetaTag, uiLine, uiLink } = require('../../lib/ui'); const { projectLogsPrompt } = require('../../lib/prompts/projectsLogsPrompt'); const { i18n } = require('../../lib/lang'); const { EXIT_CODES } = require('../../lib/enums/exitCodes'); -const ProjectLogsManager = require('../../lib/ProjectLogsManager'); +const ProjectLogsManager = require('../../lib/projects/ProjectLogsManager'); const i18nKey = 'commands.project.subcommands.logs'; diff --git a/lang/en.lyaml b/lang/en.lyaml index ee6bbdbcf..1042ad0fd 100644 --- a/lang/en.lyaml +++ b/lang/en.lyaml @@ -653,6 +653,8 @@ en: noFunctionsInProject: "There aren't any functions in this project\n\t- Run `{{#orange}}hs project logs --help{{/orange}}` to learn more about logs\n\t- {{link}} to learn more about serverless functions" noFunctionWithName: "No function with name \"{{ name }}\"" functionNotDeployed: "The function with name \"{{ name }}\" is not deployed" + projectLogsManagerNotInitialized: "Function called on ProjectLogsManager before initialization" + generic: "Error fetching logs" logs: showingLogs: "Showing logs for:" hubspotLogsDirectLink: "View function logs in HubSpot" diff --git a/lib/__tests__/ProjectLogsManager.test.ts b/lib/__tests__/ProjectLogsManager.test.ts index c2fcd6da4..bd601d625 100644 --- a/lib/__tests__/ProjectLogsManager.test.ts +++ b/lib/__tests__/ProjectLogsManager.test.ts @@ -1,5 +1,5 @@ // @ts-nocheck -const ProjectLogsManager = require('../ProjectLogsManager'); +const ProjectLogsManager = require('../projects/ProjectLogsManager'); const { getProjectConfig, ensureProjectExists } = require('../projects'); const { fetchProjectComponentsMetadata, @@ -8,7 +8,7 @@ const { jest.mock('../projects'); jest.mock('@hubspot/local-dev-lib/api/projects'); -describe('lib/ProjectLogsManager', () => { +describe('lib/projects/ProjectLogsManager', () => { const accountId = 12345678; const appId = 999999; const projectName = 'super cool test project'; @@ -180,7 +180,7 @@ describe('lib/ProjectLogsManager', () => { name: 'APP_FUNCTION', }, deployOutput: { - endpoint: { path: 'yooooooo', method: ['GET'] }, + endpoint: { path: 'yooooooo', methods: ['GET'] }, }, }; ProjectLogsManager.functions = [functionToChoose]; @@ -188,7 +188,6 @@ describe('lib/ProjectLogsManager', () => { expect(ProjectLogsManager.functionName).toEqual('function1'); expect(ProjectLogsManager.endpointName).toEqual('yooooooo'); expect(ProjectLogsManager.selectedFunction).toEqual(functionToChoose); - expect(ProjectLogsManager.method).toEqual(['GET']); expect(ProjectLogsManager.isPublicFunction).toEqual(true); }); diff --git a/lib/ProjectLogsManager.ts b/lib/projects/ProjectLogsManager.ts similarity index 63% rename from lib/ProjectLogsManager.ts rename to lib/projects/ProjectLogsManager.ts index b8afc34f2..251fb53e4 100644 --- a/lib/ProjectLogsManager.ts +++ b/lib/projects/ProjectLogsManager.ts @@ -1,23 +1,40 @@ -// @ts-nocheck -const { getProjectConfig, ensureProjectExists } = require('./projects'); -const { - fetchProjectComponentsMetadata, -} = require('@hubspot/local-dev-lib/api/projects'); -const { i18n } = require('./lang'); -const { uiLink } = require('./ui'); +import { getProjectConfig, ensureProjectExists } from './index'; +import { fetchProjectComponentsMetadata } from '@hubspot/local-dev-lib/api/projects'; +import { AppFunctionComponentMetadata } from '@hubspot/local-dev-lib/types/ComponentStructure'; +import { logger } from '@hubspot/local-dev-lib/logger'; +import { i18n } from '../lang'; +import { uiLink } from '../ui'; const i18nKey = 'commands.project.subcommands.logs'; class ProjectLogsManager { - reset() { - Object.keys(this).forEach(key => { - if (Object.hasOwn(this, key)) { - this[key] = undefined; - } - }); + projectName: string | undefined; + projectId: number | undefined; + accountId: number | undefined; + functions: AppFunctionComponentMetadata[]; + selectedFunction: AppFunctionComponentMetadata | undefined; + functionName: string | undefined; + appId: number | undefined; + isPublicFunction: boolean | undefined; + endpointName: string | undefined; + + reset(): void { + this.projectName = undefined; + this.projectId = undefined; + this.accountId = undefined; + this.functions = []; + this.selectedFunction = undefined; + this.functionName = undefined; + this.appId = undefined; + this.isPublicFunction = undefined; + this.endpointName = undefined; + } + + constructor() { + this.functions = []; } - async init(accountId) { + async init(accountId: number): Promise { const { projectConfig } = await getProjectConfig(); if (!projectConfig || !projectConfig.name) { @@ -50,11 +67,16 @@ class ProjectLogsManager { await this.fetchFunctionDetails(); } - async fetchFunctionDetails() { + async fetchFunctionDetails(): Promise { if (!this.projectId) { throw new Error(i18n(`${i18nKey}.errors.noProjectConfig`)); } + if (!this.accountId) { + logger.debug(i18n(`${i18nKey}.errors.projectLogsManagerNotInitialized`)); + throw new Error(i18n(`${i18nKey}.errors.generic`)); + } + const { data: { topLevelComponentMetadata }, } = await fetchProjectComponentsMetadata(this.accountId, this.projectId); @@ -64,15 +86,12 @@ class ProjectLogsManager { return type && type.name === 'PRIVATE_APP'; }); - if (!this.functions) { - this.functions = []; - } - apps.forEach(app => { this.functions.push( - ...app.featureComponents.filter( + // If component type is APP_FUNCTION, we can safely cast as AppFunctionComponentMetadata + ...(app.featureComponents.filter( component => component.type.name === 'APP_FUNCTION' - ) + ) as AppFunctionComponentMetadata[]) ); }); @@ -89,26 +108,20 @@ class ProjectLogsManager { } getFunctionNames() { - if (!this.functions) { - return []; - } return this.functions.map( serverlessFunction => serverlessFunction.componentName ); } - setFunction(functionName) { - if (!this.functions) { + setFunction(functionName: string) { + if (!(this.functions.length > 0)) { throw new Error( i18n(`${i18nKey}.errors.noFunctionsInProject`, { link: uiLink( i18n(`${i18nKey}.errors.noFunctionsLinkText`), 'https://developers.hubspot.com/docs/platform/serverless-functions' ), - }), - { - projectName: this.projectName, - } + }) ); } @@ -133,7 +146,6 @@ class ProjectLogsManager { if (this.selectedFunction.deployOutput.endpoint) { this.endpointName = this.selectedFunction.deployOutput.endpoint.path; - this.method = this.selectedFunction.deployOutput.endpoint.method; this.isPublicFunction = true; } else { this.isPublicFunction = false; @@ -141,4 +153,4 @@ class ProjectLogsManager { } } -module.exports = new ProjectLogsManager(); +export default new ProjectLogsManager();