From 36238dbbfbfb2231bad8e4c9f9d40740f36d0eda Mon Sep 17 00:00:00 2001 From: Ryan Manuel Date: Tue, 10 Jun 2025 14:48:36 -0500 Subject: [PATCH 1/5] share error utils with cloud --- .../driver/src/cy/commands/prompt/index.ts | 22 ++++++++++--------- .../cy/commands/prompt/prompt-driver-types.ts | 4 ++++ packages/driver/src/cypress/error_utils.ts | 14 ++++++++++-- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/packages/driver/src/cy/commands/prompt/index.ts b/packages/driver/src/cy/commands/prompt/index.ts index b64245a4751b..14a7e5eaeabd 100644 --- a/packages/driver/src/cy/commands/prompt/index.ts +++ b/packages/driver/src/cy/commands/prompt/index.ts @@ -1,6 +1,7 @@ import { init, loadRemote } from '@module-federation/runtime' import type { CypressInternal, CyPromptDriverDefaultShape } from './prompt-driver-types' import type Emitter from 'component-emitter' +import errorUtils from '../../../cypress/error_utils' interface CyPromptDriver { default: CyPromptDriverDefaultShape } @@ -60,13 +61,18 @@ const initializeCloudCyPrompt = async (Cypress: Cypress.Cypress, cy: Cypress.Cyp Cypress: Cypress as CypressInternal, cy, eventManager: window.getEventManager ? window.getEventManager() : undefined, + errorUtils: { + extendErrorMessages: errorUtils.extendErrorMessages, + throwErrByPath: errorUtils.throwErrByPath, + }, }) } catch (error) { return error } } -export default (Commands, Cypress, cy) => { +export default (Commands: Cypress.Cypress['Commands'], Cypress: Cypress.Cypress, cy: Cypress.Cypress['cy']) => { + // @ts-expect-error - these types are not yet implemented until the prompt command is rolled out if (Cypress.config('experimentalPromptCommand')) { let initializeCloudCyPromptPromise: Promise | Error> | undefined @@ -74,27 +80,23 @@ export default (Commands, Cypress, cy) => { initializeCloudCyPromptPromise = initializeCloudCyPrompt(Cypress, cy) } - const prompt = async (message: string, options: object = {}) => { + const prompt = (message: string, options: object = {}): Cypress.Chainable => { if (!initializeCloudCyPromptPromise) { // TODO: (cy.prompt) We will look into supporting other browsers (and testing them) // as this is rolled out throw new Error('`cy.prompt()` is not supported in this browser.') } - try { - const bundleResult = await initializeCloudCyPromptPromise - + // TODO: figure out how to handle timeout more generally + return cy.wrap(initializeCloudCyPromptPromise, { log: false, timeout: 45000 }).then((bundleResult: ReturnType | Error) => { if (bundleResult instanceof Error) { throw bundleResult } const cyPrompt = bundleResult - return await cyPrompt(message, options) - } catch (error) { - // TODO: handle this better - throw new Error(`CyPromptDriver not found: ${error}`) - } + return cyPrompt(message, options) + }) } // For testing purposes, we can reset the prompt command initialization diff --git a/packages/driver/src/cy/commands/prompt/prompt-driver-types.ts b/packages/driver/src/cy/commands/prompt/prompt-driver-types.ts index 2b57f796ce6b..42316c817928 100644 --- a/packages/driver/src/cy/commands/prompt/prompt-driver-types.ts +++ b/packages/driver/src/cy/commands/prompt/prompt-driver-types.ts @@ -46,6 +46,10 @@ export interface CyPromptOptions { // Note that the eventManager is present in same origin AUTs, but not cross origin // so we need to check for it's presence before using it eventManager?: CyPromptEventManager + errorUtils: { + extendErrorMessages: (errorMessages: any) => void + throwErrByPath: (err: any, path: string) => void + } } export interface CyPromptDriverDefaultShape { diff --git a/packages/driver/src/cypress/error_utils.ts b/packages/driver/src/cypress/error_utils.ts index aef91fdc5014..f71959142525 100644 --- a/packages/driver/src/cypress/error_utils.ts +++ b/packages/driver/src/cypress/error_utils.ts @@ -22,6 +22,8 @@ const ERR_PREPARED_FOR_SERIALIZATION = Symbol('ERR_PREPARED_FOR_SERIALIZATION') const crossOriginScriptRe = /^script error/i +let allErrorMessages = $errorMessages + if (!Error.captureStackTrace) { Error.captureStackTrace = (err, fn) => { const stack = (new Error()).stack @@ -396,7 +398,7 @@ const docsUrlByParents = (msgPath) => { return // reached root } - const obj = _.get($errorMessages, msgPath) + const obj = _.get(allErrorMessages, msgPath) if (obj.hasOwnProperty('docsUrl')) { return obj.docsUrl @@ -406,7 +408,7 @@ const docsUrlByParents = (msgPath) => { } const errByPath = (msgPath, args?) => { - let msgValue = _.get($errorMessages, msgPath) + let msgValue = _.get(allErrorMessages, msgPath) if (!msgValue) { return internalErr({ message: `Error message path '${msgPath}' does not exist` }) @@ -655,6 +657,13 @@ const getUnsupportedPlugin = (runnable) => { return null } +const extendErrorMessages = (errorMessages: any) => { + allErrorMessages = { + ...allErrorMessages, + ...errorMessages, + } +} + export default { stackWithReplacedProps, appendErrMsg, @@ -679,4 +688,5 @@ export default { throwErrByPath, warnByPath, wrapErr, + extendErrorMessages, } From 093b280d43e350c5df04286d3455711c54f6b2f1 Mon Sep 17 00:00:00 2001 From: Ryan Manuel Date: Wed, 11 Jun 2025 08:28:34 -0500 Subject: [PATCH 2/5] additional rework --- .../cy-prompt/CyPromptLifecycleManager.ts | 45 +++++++++++++++---- .../lib/cloud/cy-prompt/CyPromptManager.ts | 12 +++-- packages/server/lib/modes/run.ts | 2 + packages/server/lib/project-base.ts | 3 +- .../src/cy-prompt/cy-prompt-server-types.ts | 15 ++++++- 5 files changed, 62 insertions(+), 15 deletions(-) diff --git a/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts b/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts index 22ae9a6afab8..1000a6a62cd7 100644 --- a/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts +++ b/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts @@ -12,6 +12,7 @@ import { readFile } from 'fs-extra' import { ensureCyPromptBundle } from './ensure_cy_prompt_bundle' import chokidar from 'chokidar' import { getCloudMetadata } from '../get_cloud_metadata' +import { CyPromptAuthenticatedUserShape } from '@packages/types' const debug = Debug('cypress:server:cy-prompt-lifecycle-manager') @@ -30,22 +31,33 @@ export class CyPromptLifecycleManager { * @param ctx Data context to register this instance with */ initializeCyPromptManager ({ - projectId, cloudDataSource, ctx, + record, + key, }: { - projectId?: string cloudDataSource: CloudDataSource ctx: DataContext + record?: boolean + key?: string }): void { // Register this instance in the data context ctx.update((data) => { data.cyPromptLifecycleManager = this }) + const getProjectOptions = async () => { + return { + user: await ctx.actions.auth.authApi.getUser(), + projectSlug: (await ctx.project.getConfig()).projectId || undefined, + record, + key, + } + } + const cyPromptManagerPromise = this.createCyPromptManager({ - projectId, cloudDataSource, + getProjectOptions, }).catch(async (error) => { debug('Error during cy prompt manager setup: %o', error) @@ -78,8 +90,8 @@ export class CyPromptLifecycleManager { this.cyPromptManagerPromise = cyPromptManagerPromise this.setupWatcher({ - projectId, cloudDataSource, + getProjectOptions, }) } @@ -94,17 +106,25 @@ export class CyPromptLifecycleManager { } private async createCyPromptManager ({ - projectId, cloudDataSource, + getProjectOptions, }: { projectId?: string cloudDataSource: CloudDataSource + getProjectOptions: () => Promise<{ + user?: CyPromptAuthenticatedUserShape + projectSlug?: string + record?: boolean + key?: string + }> }): Promise { let cyPromptHash: string let cyPromptPath: string + const currentProjectOptions = await getProjectOptions() + const projectId = currentProjectOptions.projectSlug const cyPromptSession = await postCyPromptSession({ - projectId, + projectId: currentProjectOptions.projectSlug, }) if (!process.env.CYPRESS_LOCAL_CY_PROMPT_PATH) { @@ -135,20 +155,19 @@ export class CyPromptLifecycleManager { const script = await readFile(serverFilePath, 'utf8') const cyPromptManager = new CyPromptManager() - const { cloudUrl, cloudHeaders } = await getCloudMetadata(cloudDataSource) + const { cloudUrl } = await getCloudMetadata(cloudDataSource) await cyPromptManager.setup({ script, cyPromptPath, cyPromptHash, - projectSlug: projectId, cloudApi: { cloudUrl, - cloudHeaders, CloudRequest, isRetryableError, asyncRetry, }, + getProjectOptions, }) debug('cy prompt is ready') @@ -178,9 +197,16 @@ export class CyPromptLifecycleManager { private setupWatcher ({ projectId, cloudDataSource, + getProjectOptions, }: { projectId?: string cloudDataSource: CloudDataSource + getProjectOptions: () => Promise<{ + user?: CyPromptAuthenticatedUserShape + projectSlug?: string + record?: boolean + key?: string + }> }) { // Don't setup a watcher if the cy prompt bundle is NOT local if (!process.env.CYPRESS_LOCAL_CY_PROMPT_PATH) { @@ -201,6 +227,7 @@ export class CyPromptLifecycleManager { this.cyPromptManagerPromise = this.createCyPromptManager({ projectId, cloudDataSource, + getProjectOptions, }).catch((error) => { debug('Error during reload of cy prompt manager: %o', error) diff --git a/packages/server/lib/cloud/cy-prompt/CyPromptManager.ts b/packages/server/lib/cloud/cy-prompt/CyPromptManager.ts index aa9bb17b0cf8..3aedaf852c1d 100644 --- a/packages/server/lib/cloud/cy-prompt/CyPromptManager.ts +++ b/packages/server/lib/cloud/cy-prompt/CyPromptManager.ts @@ -1,4 +1,4 @@ -import type { CyPromptManagerShape, CyPromptStatus, CyPromptServerDefaultShape, CyPromptServerShape, CyPromptCloudApi, CyPromptCDPClient } from '@packages/types' +import type { CyPromptManagerShape, CyPromptStatus, CyPromptServerDefaultShape, CyPromptServerShape, CyPromptCloudApi, CyPromptCDPClient, CyPromptAuthenticatedUserShape } from '@packages/types' import type { Router } from 'express' import Debug from 'debug' import { requireScript } from '../require_script' @@ -12,6 +12,12 @@ interface SetupOptions { cyPromptHash?: string projectSlug?: string cloudApi: CyPromptCloudApi + getProjectOptions: () => Promise<{ + user?: CyPromptAuthenticatedUserShape + projectSlug?: string + record?: boolean + key?: string + }> } const debug = Debug('cypress:server:cy-prompt') @@ -20,14 +26,14 @@ export class CyPromptManager implements CyPromptManagerShape { status: CyPromptStatus = 'NOT_INITIALIZED' private _cyPromptServer: CyPromptServerShape | undefined - async setup ({ script, cyPromptPath, cyPromptHash, projectSlug, cloudApi }: SetupOptions): Promise { + async setup ({ script, cyPromptPath, cyPromptHash, getProjectOptions, cloudApi }: SetupOptions): Promise { const { createCyPromptServer } = requireScript(script).default this._cyPromptServer = await createCyPromptServer({ cyPromptHash, cyPromptPath, - projectSlug, cloudApi, + getProjectOptions, }) this.status = 'INITIALIZED' diff --git a/packages/server/lib/modes/run.ts b/packages/server/lib/modes/run.ts index 1e668ddb0fd2..390226216a9e 100644 --- a/packages/server/lib/modes/run.ts +++ b/packages/server/lib/modes/run.ts @@ -160,6 +160,8 @@ const openProjectCreate = (projectRoot, socketId, args) => { onWarning, spec: args.spec, onError: args.onError, + record: args.record, + key: args.key, } return openProject.create(projectRoot, args, options) diff --git a/packages/server/lib/project-base.ts b/packages/server/lib/project-base.ts index 1ecb8a6d824a..76f2ae6832df 100644 --- a/packages/server/lib/project-base.ts +++ b/packages/server/lib/project-base.ts @@ -166,9 +166,10 @@ export class ProjectBase extends EE { const cyPromptLifecycleManager = new CyPromptLifecycleManager() cyPromptLifecycleManager.initializeCyPromptManager({ - projectId: cfg.projectId, cloudDataSource: this.ctx.cloud, ctx: this.ctx, + record: this.options.record, + key: this.options.key, }) } diff --git a/packages/types/src/cy-prompt/cy-prompt-server-types.ts b/packages/types/src/cy-prompt/cy-prompt-server-types.ts index b212f1910664..2d882ec5361d 100644 --- a/packages/types/src/cy-prompt/cy-prompt-server-types.ts +++ b/packages/types/src/cy-prompt/cy-prompt-server-types.ts @@ -22,7 +22,6 @@ interface RetryOptions { export interface CyPromptCloudApi { cloudUrl: string - cloudHeaders: Record CloudRequest: AxiosInstance isRetryableError: (err: unknown) => boolean asyncRetry: AsyncRetry @@ -33,10 +32,22 @@ type AsyncRetry = ( options: RetryOptions ) => (...args: TArgs) => Promise +export interface CyPromptAuthenticatedUserShape { + id?: string //Cloud user id + name?: string + email?: string + authToken?: string +} + export interface CyPromptServerOptions { cyPromptHash?: string + getProjectOptions: () => Promise<{ + user?: CyPromptAuthenticatedUserShape + projectSlug?: string + record?: boolean + key?: string + }> cyPromptPath: string - projectSlug?: string cloudApi: CyPromptCloudApi } From 3b44e8d5fc5b800fc143a3675c52f3f81fcfec87 Mon Sep 17 00:00:00 2001 From: estrada9166 Date: Wed, 11 Jun 2025 16:19:36 -0500 Subject: [PATCH 3/5] Fix command, add isOpenMode --- packages/driver/src/cy/commands/prompt/index.ts | 2 +- packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/driver/src/cy/commands/prompt/index.ts b/packages/driver/src/cy/commands/prompt/index.ts index e763ab38ee8f..a4a45692f0a7 100644 --- a/packages/driver/src/cy/commands/prompt/index.ts +++ b/packages/driver/src/cy/commands/prompt/index.ts @@ -98,7 +98,7 @@ export default (Commands: Cypress.Cypress['Commands'], Cypress: Cypress.Cypress, initializeCloudCyPromptPromise = initializeCloudCyPrompt(Cypress, cy) } - const prompt = async (message: string, options: object = {}) => { + const prompt = (message: string, options: object = {}) => { if (Cypress.testingType === 'component') { $errUtils.throwErrByPath('prompt.promptTestingTypeError') diff --git a/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts b/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts index a3702005750f..b2a78ae48e99 100644 --- a/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts +++ b/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts @@ -55,6 +55,7 @@ export class CyPromptLifecycleManager { projectSlug: (await ctx.project.getConfig()).projectId || undefined, record, key, + isOpenMode: ctx.isOpenMode, } } From 687dd46f0ad4b62a3eff63cb938aae9bb01f13c8 Mon Sep 17 00:00:00 2001 From: estrada9166 Date: Fri, 13 Jun 2025 14:18:47 -0500 Subject: [PATCH 4/5] Add / fix test --- .../cypress/e2e/cypress/error_utils.cy.ts | 21 ++++++++++ .../CyPromptLifecycleManager_spec.ts | 41 +++++++++++++------ packages/server/test/unit/project_spec.js | 11 ++++- 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/packages/driver/cypress/e2e/cypress/error_utils.cy.ts b/packages/driver/cypress/e2e/cypress/error_utils.cy.ts index 609ea324eb5b..7eb2ab0a0ce1 100644 --- a/packages/driver/cypress/e2e/cypress/error_utils.cy.ts +++ b/packages/driver/cypress/e2e/cypress/error_utils.cy.ts @@ -624,6 +624,27 @@ describe('driver/src/cypress/error_utils', () => { }) }) + context('.extendErrorMessages', () => { + it('extends error messages', () => { + $errUtils.extendErrorMessages({ + testErrors: { + test: 'test error message', + }, + }) + + const fn = () => { + $errUtils.throwErrByPath('testErrors.test') + } + + expect(fn).to.throw().and.satisfy((err) => { + expect(err.message).to.equal('test error message') + expect(err.name).to.eq('CypressError') + + return true + }) + }) + }) + context('.getUnsupportedPlugin', () => { it('returns unsupported plugin if the error msg is the expected one', () => { const unsupportedPlugin = $errUtils.getUnsupportedPlugin({ diff --git a/packages/server/test/unit/cloud/cy-prompt/CyPromptLifecycleManager_spec.ts b/packages/server/test/unit/cloud/cy-prompt/CyPromptLifecycleManager_spec.ts index 47fe38b6d30a..091d9fd0081b 100644 --- a/packages/server/test/unit/cloud/cy-prompt/CyPromptLifecycleManager_spec.ts +++ b/packages/server/test/unit/cloud/cy-prompt/CyPromptLifecycleManager_spec.ts @@ -75,6 +75,20 @@ describe('CyPromptLifecycleManager', () => { emitter: { cyPromptStatusChange: cyPromptStatusChangeEmitterStub, }, + actions: { + auth: { + authApi: { + getUser: sinon.stub().resolves({ + authToken: 'test-token', + }), + }, + }, + }, + project: { + getConfig: sinon.stub().resolves({ + projectId: 'test-project-id', + }), + }, } as unknown as DataContext mockCloudDataSource = { @@ -96,9 +110,10 @@ describe('CyPromptLifecycleManager', () => { describe('initializeCyPromptManager', () => { it('initializes the cy-prompt manager and registers it in the data context', async () => { cyPromptLifecycleManager.initializeCyPromptManager({ - projectId: 'test-project-id', cloudDataSource: mockCloudDataSource, ctx: mockCtx, + record: false, + key: '123e4567-e89b-12d3-a456-426614174000', }) const cyPromptReadyPromise = new Promise((resolve) => { @@ -120,14 +135,13 @@ describe('CyPromptLifecycleManager', () => { script: 'console.log("cy-prompt script")', cyPromptPath: path.join(os.tmpdir(), 'cypress', 'cy-prompt', 'abc'), cyPromptHash: 'abc', - projectSlug: 'test-project-id', cloudApi: { cloudUrl: 'https://cloud.cypress.io', - cloudHeaders: { 'Authorization': 'Bearer test-token' }, CloudRequest, isRetryableError, asyncRetry, }, + getProjectOptions: sinon.match.func, }) expect(postCyPromptSessionStub).to.be.calledWith({ @@ -141,9 +155,10 @@ describe('CyPromptLifecycleManager', () => { it('only calls ensureCyPromptBundle once per cy prompt hash', async () => { cyPromptLifecycleManager.initializeCyPromptManager({ - projectId: 'test-project-id', cloudDataSource: mockCloudDataSource, ctx: mockCtx, + record: false, + key: '123e4567-e89b-12d3-a456-426614174000', }) const cyPromptReadyPromise1 = new Promise((resolve) => { @@ -155,9 +170,10 @@ describe('CyPromptLifecycleManager', () => { const cyPromptManager1 = await cyPromptReadyPromise1 cyPromptLifecycleManager.initializeCyPromptManager({ - projectId: 'test-project-id', cloudDataSource: mockCloudDataSource, ctx: mockCtx, + record: false, + key: '123e4567-e89b-12d3-a456-426614174000', }) const cyPromptReadyPromise2 = new Promise((resolve) => { @@ -182,14 +198,13 @@ describe('CyPromptLifecycleManager', () => { script: 'console.log("cy-prompt script")', cyPromptPath: path.join(os.tmpdir(), 'cypress', 'cy-prompt', 'abc'), cyPromptHash: 'abc', - projectSlug: 'test-project-id', cloudApi: { cloudUrl: 'https://cloud.cypress.io', - cloudHeaders: { 'Authorization': 'Bearer test-token' }, CloudRequest, isRetryableError, asyncRetry, }, + getProjectOptions: sinon.match.func, }) expect(postCyPromptSessionStub).to.be.calledWith({ @@ -205,9 +220,10 @@ describe('CyPromptLifecycleManager', () => { process.env.CYPRESS_LOCAL_CY_PROMPT_PATH = '/path/to/cy-prompt' cyPromptLifecycleManager.initializeCyPromptManager({ - projectId: 'test-project-id', cloudDataSource: mockCloudDataSource, ctx: mockCtx, + record: false, + key: '123e4567-e89b-12d3-a456-426614174000', }) const cyPromptReadyPromise = new Promise((resolve) => { @@ -225,14 +241,13 @@ describe('CyPromptLifecycleManager', () => { script: 'console.log("cy-prompt script")', cyPromptPath: '/path/to/cy-prompt', cyPromptHash: 'local', - projectSlug: 'test-project-id', cloudApi: { cloudUrl: 'https://cloud.cypress.io', - cloudHeaders: { 'Authorization': 'Bearer test-token' }, CloudRequest, isRetryableError, asyncRetry, }, + getProjectOptions: sinon.match.func, }) expect(postCyPromptSessionStub).to.be.calledWith({ @@ -378,9 +393,10 @@ describe('CyPromptLifecycleManager', () => { ]) cyPromptLifecycleManager.initializeCyPromptManager({ - projectId: 'test-project-id', cloudDataSource: mockCloudDataSource, ctx: mockCtx, + record: false, + key: '123e4567-e89b-12d3-a456-426614174000', }) await listenersCalledPromise @@ -414,9 +430,10 @@ describe('CyPromptLifecycleManager', () => { ]) cyPromptLifecycleManager.initializeCyPromptManager({ - projectId: 'test-project-id', cloudDataSource: mockCloudDataSource, ctx: mockCtx, + record: false, + key: '123e4567-e89b-12d3-a456-426614174000', }) await listenersCalledPromise diff --git a/packages/server/test/unit/project_spec.js b/packages/server/test/unit/project_spec.js index 1c953bc13529..3886aee2b72c 100644 --- a/packages/server/test/unit/project_spec.js +++ b/packages/server/test/unit/project_spec.js @@ -462,20 +462,26 @@ This option will not have an effect in Some-other-name. Tests that rely on web s it('initializes cy prompt lifecycle manager if experimentalPromptCommand is enabled', function () { this.config.projectId = 'abc123' this.config.experimentalPromptCommand = true + this.project.options.record = true + this.project.options.key = '123e4567-e89b-12d3-a456-426614174000' initializeCyPromptManagerStub = sinon.stub(CyPromptLifecycleManager.prototype, 'initializeCyPromptManager') return this.project.open() .then(() => { expect(initializeCyPromptManagerStub).to.be.calledWith({ - projectId: 'abc123', cloudDataSource: ctx.cloud, ctx, + record: true, + key: '123e4567-e89b-12d3-a456-426614174000', }) }) }) it('initializes cy prompt lifecycle manager if process.env.CYPRESS_ENABLE_CY_PROMPT is enabled', function () { + this.project.options.record = false + this.project.options.key = undefined + process.env.CYPRESS_ENABLE_CY_PROMPT = 'true' initializeCyPromptManagerStub = sinon.stub(CyPromptLifecycleManager.prototype, 'initializeCyPromptManager') @@ -483,9 +489,10 @@ This option will not have an effect in Some-other-name. Tests that rely on web s return this.project.open() .then(() => { expect(initializeCyPromptManagerStub).to.be.calledWith({ - projectId: 'abc123', cloudDataSource: ctx.cloud, ctx, + record: false, + key: undefined, }) }) }) From bc8c85b07f5604e6a2d21c470958b3eee52dd6d3 Mon Sep 17 00:00:00 2001 From: estrada9166 Date: Fri, 13 Jun 2025 14:43:23 -0500 Subject: [PATCH 5/5] fix ts --- packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts b/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts index b2a78ae48e99..2809e815d7f0 100644 --- a/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts +++ b/packages/server/lib/cloud/cy-prompt/CyPromptLifecycleManager.ts @@ -12,7 +12,7 @@ import { readFile } from 'fs-extra' import { ensureCyPromptBundle } from './ensure_cy_prompt_bundle' import chokidar from 'chokidar' import { getCloudMetadata } from '../get_cloud_metadata' -import { CyPromptAuthenticatedUserShape } from '@packages/types' +import type { CyPromptAuthenticatedUserShape } from '@packages/types' const debug = Debug('cypress:server:cy-prompt-lifecycle-manager')