From 7ea76a83f700be82b7b4683bf6ddc1c65c832fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Wed, 6 Nov 2024 15:41:14 +0100 Subject: [PATCH 1/7] Change colors --- .../dev/app-events/app-event-watcher.ts | 25 +++++++++++-------- .../services/dev/extension/localization.ts | 3 +-- .../cli/services/dev/processes/dev-session.ts | 15 +++++++---- .../app-management-client.ts | 8 +++--- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts b/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts index 295aeea11c..cd266f8e21 100644 --- a/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts +++ b/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts @@ -9,6 +9,7 @@ import {outputDebug} from '@shopify/cli-kit/node/output' import {AbortSignal} from '@shopify/cli-kit/node/abort' import {joinPath} from '@shopify/cli-kit/node/path' import {fileExists, mkdir, rmdir} from '@shopify/cli-kit/node/fs' +import {useConcurrentOutputContext} from '@shopify/cli-kit/node/ui/components' import EventEmitter from 'events' /** @@ -200,18 +201,20 @@ export class AppEventWatcher extends EventEmitter { */ private async buildExtensions(extensions: ExtensionInstance[]): Promise { const promises = extensions.map(async (ext) => { - try { - if (this.esbuildManager.contexts[ext.handle]) { - const result = await this.esbuildManager.contexts[ext.handle]?.rebuild() - if (result?.errors?.length) throw new Error(result?.errors.map((err) => err.text).join('\n')) - } else { - await this.buildExtension(ext) + return useConcurrentOutputContext({outputPrefix: ext.handle, stripAnsi: false}, async () => { + try { + if (this.esbuildManager.contexts[ext.handle]) { + const result = await this.esbuildManager.contexts[ext.handle]?.rebuild() + if (result?.errors?.length) throw new Error(result?.errors.map((err) => err.text).join('\n')) + } else { + await this.buildExtension(ext) + } + return {status: 'ok', handle: ext.handle} as const + // eslint-disable-next-line no-catch-all/no-catch-all, @typescript-eslint/no-explicit-any + } catch (error: any) { + return {status: 'error', error: error.message, handle: ext.handle} as const } - return {status: 'ok', handle: ext.handle} as const - // eslint-disable-next-line no-catch-all/no-catch-all, @typescript-eslint/no-explicit-any - } catch (error: any) { - return {status: 'error', error: error.message, handle: ext.handle} as const - } + }) }) // ESBuild errors are already logged by the ESBuild bundler return Promise.all(promises) diff --git a/packages/app/src/cli/services/dev/extension/localization.ts b/packages/app/src/cli/services/dev/extension/localization.ts index bb0110f71f..8683a6bb46 100644 --- a/packages/app/src/cli/services/dev/extension/localization.ts +++ b/packages/app/src/cli/services/dev/extension/localization.ts @@ -4,7 +4,7 @@ import {ExtensionInstance} from '../../../models/extensions/extension-instance.j import {joinPath} from '@shopify/cli-kit/node/path' import {readFile, glob} from '@shopify/cli-kit/node/fs' import {ExtendableError} from '@shopify/cli-kit/node/error' -import {outputInfo, outputWarn} from '@shopify/cli-kit/node/output' +import {outputWarn} from '@shopify/cli-kit/node/output' type Locale = string @@ -57,7 +57,6 @@ export async function getLocalization( }), ) localization.lastUpdated = Date.now() - outputInfo(`Parsed locales for extension ${extension.handle} at ${extension.directory}`, options.stdout) // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-catch-all/no-catch-all } catch (error: any) { status = 'error' diff --git a/packages/app/src/cli/services/dev/processes/dev-session.ts b/packages/app/src/cli/services/dev/processes/dev-session.ts index 8090957152..8c2b3ef8df 100644 --- a/packages/app/src/cli/services/dev/processes/dev-session.ts +++ b/packages/app/src/cli/services/dev/processes/dev-session.ts @@ -47,7 +47,7 @@ export async function setupDevSessionProcess({ }: Omit): Promise { return { type: 'dev-session', - prefix: 'extensions', + prefix: 'dev-session', function: pushUpdatesForDevSession, options: { app, @@ -106,8 +106,9 @@ export const pushUpdatesForDevSession: DevProcessFunction = a if (result) { processOptions.stdout.write(`✅ Session updated [Network: ${endNetworkTime}ms -- Total: ${endTime}ms]`) } else { - processOptions.stdout.write( + outputDebug( `❌ Session update aborted (new change detected) [Network: ${endNetworkTime}ms -- Total: ${endTime}ms]`, + processOptions.stdout, ) } }, refreshToken) @@ -115,7 +116,7 @@ export const pushUpdatesForDevSession: DevProcessFunction = a .onStart(async () => { await performActionWithRetryAfterRecovery(async () => { await bundleExtensionsAndUpload(processOptions, false) - await printWarning('[BETA] Dev session ready, watching for changes in your app', processOptions.stdout) + await printSuccess('[BETA] Dev session ready, watching for changes in your app', processOptions.stdout) }, refreshToken) }) @@ -188,7 +189,7 @@ async function bundleExtensionsAndUpload(options: DevSessionProcessOptions, upda // Re-throw the error so the recovery procedure can be executed throw new Error('Unauthorized') } else { - options.stderr.write(`❌ ${updating ? 'Update' : 'Create'} Dev Session Error`) + await printError(`${updating ? 'Update' : 'Create'} Dev session error`, options.stderr) await printError(`${error.message}`, options.stderr) } } @@ -203,8 +204,12 @@ async function printError(message: string, stdout: Writable) { await printLogMessage(outputContent`${outputToken.errorText(message)}`.value, stdout) } +async function printSuccess(message: string, stdout: Writable) { + await printLogMessage(outputContent`${outputToken.green(message)}`.value, stdout) +} + async function printLogMessage(message: string, stdout: Writable) { - await useConcurrentOutputContext({outputPrefix: 'extensions', stripAnsi: false}, () => { + await useConcurrentOutputContext({outputPrefix: 'dev-session', stripAnsi: false}, () => { stdout.write(message) }) } diff --git a/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts b/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts index 6d4ef78e88..83358c3d64 100644 --- a/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts +++ b/packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts @@ -112,7 +112,7 @@ import { } from '@shopify/cli-kit/node/api/business-platform' import {CLI_KIT_VERSION} from '@shopify/cli-kit/common/version' import {versionSatisfies} from '@shopify/cli-kit/node/node-package-manager' -import {outputWarn} from '@shopify/cli-kit/node/output' +import {outputDebug} from '@shopify/cli-kit/node/output' import {developerDashboardFqdn} from '@shopify/cli-kit/node/context/fqdn' const TEMPLATE_JSON_URL = 'https://raw.githubusercontent.com/Shopify/extensions-templates/main/templates.json' @@ -734,7 +734,7 @@ export class AppManagementClient implements DeveloperPlatformClient { } async sendSampleWebhook(_input: SendSampleWebhookVariables): Promise { - outputWarn('⚠️ sendSampleWebhook is not implemented') + outputDebug('⚠️ sendSampleWebhook is not implemented') return { sendSampleWebhook: { samplePayload: '', @@ -746,7 +746,7 @@ export class AppManagementClient implements DeveloperPlatformClient { } async apiVersions(): Promise { - outputWarn('⚠️ apiVersions is not implemented') + outputDebug('⚠️ apiVersions is not implemented') return {publicApiVersions: ['unstable']} } @@ -763,7 +763,7 @@ export class AppManagementClient implements DeveloperPlatformClient { } async updateURLs(_input: UpdateURLsVariables): Promise { - outputWarn('⚠️ updateURLs is not implemented') + outputDebug('⚠️ updateURLs is not implemented') return {appUpdate: {userErrors: []}} } From 92b778ec95f7dc64080c9c4f035238ce4c438e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Thu, 7 Nov 2024 17:47:27 +0100 Subject: [PATCH 2/7] Improve logs --- .../app-events/app-event-watcher-handler.ts | 1 + .../dev/app-events/app-event-watcher.ts | 6 +- .../cli/services/dev/processes/dev-session.ts | 102 +++++++++++------- 3 files changed, 70 insertions(+), 39 deletions(-) diff --git a/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts b/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts index dc0c606c39..862fd8742f 100644 --- a/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts +++ b/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts @@ -137,6 +137,7 @@ export async function reloadApp(app: AppLinkedInterface, options: OutputContextO remoteFlags: app.remoteFlags, }) outputDebug(`App reloaded [${endHRTimeInMs(start)}ms]`, options.stdout) + // options.stdout.write(`App reloaded [${endHRTimeInMs(start)}ms]`) return newApp as AppLinkedInterface // eslint-disable-next-line no-catch-all/no-catch-all, @typescript-eslint/no-explicit-any } catch (error: any) { diff --git a/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts b/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts index cd266f8e21..c2361bec81 100644 --- a/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts +++ b/packages/app/src/cli/services/dev/app-events/app-event-watcher.ts @@ -56,9 +56,9 @@ Examples: * - Created: The extension was created */ export enum EventType { - Updated, - Deleted, - Created, + Updated = 'changed', + Deleted = 'deleted', + Created = 'created', } export interface ExtensionEvent { diff --git a/packages/app/src/cli/services/dev/processes/dev-session.ts b/packages/app/src/cli/services/dev/processes/dev-session.ts index 8c2b3ef8df..91fac1e06c 100644 --- a/packages/app/src/cli/services/dev/processes/dev-session.ts +++ b/packages/app/src/cli/services/dev/processes/dev-session.ts @@ -2,7 +2,7 @@ import {BaseProcess, DevProcessFunction} from './types.js' import {DeveloperPlatformClient} from '../../../utilities/developer-platform-client.js' import {AppLinkedInterface} from '../../../models/app/app.js' import {getExtensionUploadURL} from '../../deploy/upload.js' -import {AppEventWatcher, EventType} from '../app-events/app-event-watcher.js' +import {AppEvent, AppEventWatcher} from '../app-events/app-event-watcher.js' import {reloadApp} from '../app-events/app-event-watcher-handler.js' import {readFileSync, writeFile} from '@shopify/cli-kit/node/fs' import {dirname, joinPath} from '@shopify/cli-kit/node/path' @@ -37,8 +37,17 @@ export interface DevSessionProcess extends BaseProcess { type: 'dev-session' } +interface DevSessionResult { + status: 'updated' | 'created' | 'aborted' | 'error' + error?: string +} + let bundleControllers: AbortController[] = [] +// Current status of the dev session +// Since the watcher can emit events before the dev session is ready, we need to keep track of the status +let devSessionStatus: 'idle' | 'initializing' | 'ready' = 'idle' + export async function setupDevSessionProcess({ app, apiKey, @@ -73,9 +82,9 @@ export const pushUpdatesForDevSession: DevProcessFunction = a const appWatcher = new AppEventWatcher(app, options.url, {stderr, stdout, signal}) - const processOptions = {...options, stderr, stdout, signal, bundlePath: appWatcher.buildOutputPath} + const processOptions = {...options, stderr, stdout, signal, bundlePath: appWatcher.buildOutputPath, app} - await printWarning('[BETA] Starting Dev Session', processOptions.stdout) + processOptions.stdout.write('Preparing dev session') appWatcher .onEvent(async (event) => { @@ -84,39 +93,27 @@ export const pushUpdatesForDevSession: DevProcessFunction = a // Remove aborted controllers from array: bundleControllers = bundleControllers.filter((controller) => !controller.signal.aborted) - event.extensionEvents.map((eve) => { - switch (eve.type) { - case EventType.Created: - processOptions.stdout.write(`✅ Extension created ->> ${eve.extension.handle}`) - break - case EventType.Deleted: - processOptions.stdout.write(`❌ Extension deleted ->> ${eve.extension.handle}`) - break - case EventType.Updated: - processOptions.stdout.write(`🔄 Extension Updated ->> ${eve.extension.handle}`) - break - } + // For each extension event, print a message to the terminal + // eslint-disable-next-line @typescript-eslint/no-misused-promises + event.extensionEvents.forEach(async (eve) => { + const outputPrefix = eve.extension.isAppConfigExtension ? 'app-config' : eve.extension.handle + const message = `${eve.extension.isAppConfigExtension ? 'App config' : 'Extension'} ${eve.type}` + await useConcurrentOutputContext({outputPrefix, stripAnsi: false}, () => processOptions.stdout.write(message)) }) const networkStartTime = startHRTime() await performActionWithRetryAfterRecovery(async () => { - const result = await bundleExtensionsAndUpload({...processOptions, app: event.app}, true) + const result = await bundleExtensionsAndUpload({...processOptions, app: event.app}) + await handleDevSessionResult(result, processOptions, event) const endTime = endHRTimeInMs(event.startTime) const endNetworkTime = endHRTimeInMs(networkStartTime) - if (result) { - processOptions.stdout.write(`✅ Session updated [Network: ${endNetworkTime}ms -- Total: ${endTime}ms]`) - } else { - outputDebug( - `❌ Session update aborted (new change detected) [Network: ${endNetworkTime}ms -- Total: ${endTime}ms]`, - processOptions.stdout, - ) - } + outputDebug(`✅ Event handled [Network: ${endNetworkTime}ms -- Total: ${endTime}ms]`, processOptions.stdout) }, refreshToken) }) .onStart(async () => { await performActionWithRetryAfterRecovery(async () => { - await bundleExtensionsAndUpload(processOptions, false) - await printSuccess('[BETA] Dev session ready, watching for changes in your app', processOptions.stdout) + const result = await bundleExtensionsAndUpload(processOptions) + await handleDevSessionResult(result, processOptions) }, refreshToken) }) @@ -124,6 +121,32 @@ export const pushUpdatesForDevSession: DevProcessFunction = a await appWatcher.start() } +async function handleDevSessionResult( + result: DevSessionResult, + processOptions: DevSessionProcessOptions, + event?: AppEvent, +) { + if (result.status === 'updated') { + await printSuccess(`✅ Session updated`, processOptions.stdout) + const scopeChanges = event?.extensionEvents.find((eve) => eve.extension.handle === 'app-access') + if (scopeChanges) { + await printWarning(`🔄 Action required`, processOptions.stdout) + const message = outputContent`${outputToken.yellow(`└ Scopes updated`)}. ${outputToken.link( + 'Open app to accept scopes.', + 'https://shopify.dev/docs/apps/build/app-scopes/scopes-overview', + )}` + await printWarning(message.value, processOptions.stdout) + } + } else if (result.status === 'created') { + await printSuccess(`✅ Dev session created, watching for changes in your app `, processOptions.stdout) + } else if (result.status === 'aborted') { + outputDebug('❌ Session update aborted (new change detected)', processOptions.stdout) + } else { + await printError(`❌ Error`, processOptions.stderr) + await printError(`└ ${result.error}`, processOptions.stderr) + } +} + /** * Bundle all extensions and upload them to the developer platform * Generate a new manifest in the bundle folder, zip it and upload it to GCS. @@ -132,13 +155,18 @@ export const pushUpdatesForDevSession: DevProcessFunction = a * @param options - The options for the process * @param updating - Whether the dev session is being updated or created */ -async function bundleExtensionsAndUpload(options: DevSessionProcessOptions, updating: boolean) { +async function bundleExtensionsAndUpload(options: DevSessionProcessOptions): Promise { + // If the dev session is still initializing, ignore this event + if (devSessionStatus === 'initializing') return {status: 'aborted'} + // If the dev session is idle, set the status to initializing + if (devSessionStatus === 'idle') devSessionStatus = 'initializing' + // Every new bundle process gets its own controller. This way we can cancel any previous one if a new change // is detected even when multiple events are triggered very quickly (which causes weird edge cases) const currentBundleController = new AbortController() bundleControllers.push(currentBundleController) - if (currentBundleController.signal.aborted) return false + if (currentBundleController.signal.aborted) return {status: 'aborted'} outputDebug('Bundling and uploading extensions', options.stdout) const bundleZipPath = joinPath(dirname(options.bundlePath), `bundle.zip`) @@ -148,14 +176,14 @@ async function bundleExtensionsAndUpload(options: DevSessionProcessOptions, upda await writeFile(manifestPath, JSON.stringify(appManifest, null, 2)) // Create zip file with everything - if (currentBundleController.signal.aborted) return false + if (currentBundleController.signal.aborted) return {status: 'aborted'} await zip({ inputDirectory: options.bundlePath, outputZipPath: bundleZipPath, }) // Get a signed URL to upload the zip file - if (currentBundleController.signal.aborted) return false + if (currentBundleController.signal.aborted) return {status: 'aborted'} const signedURL = await getExtensionUploadURL(options.developerPlatformClient, { apiKey: options.appId, organizationId: options.organizationId, @@ -163,7 +191,7 @@ async function bundleExtensionsAndUpload(options: DevSessionProcessOptions, upda }) // Upload the zip file - if (currentBundleController.signal.aborted) return false + if (currentBundleController.signal.aborted) return {status: 'aborted'} const form = formData() const buffer = readFileSync(bundleZipPath) form.append('my_upload', buffer) @@ -176,12 +204,16 @@ async function bundleExtensionsAndUpload(options: DevSessionProcessOptions, upda const payload = {shopFqdn: options.storeFqdn, appId: options.appId, assetsUrl: signedURL} // Create or update the dev session - if (currentBundleController.signal.aborted) return false + if (currentBundleController.signal.aborted) return {status: 'aborted'} try { - if (updating) { + if (devSessionStatus === 'ready') { await options.developerPlatformClient.devSessionUpdate(payload) + return {status: 'updated'} } else { await options.developerPlatformClient.devSessionCreate(payload) + // eslint-disable-next-line require-atomic-updates + devSessionStatus = 'ready' + return {status: 'created'} } // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { @@ -189,11 +221,9 @@ async function bundleExtensionsAndUpload(options: DevSessionProcessOptions, upda // Re-throw the error so the recovery procedure can be executed throw new Error('Unauthorized') } else { - await printError(`${updating ? 'Update' : 'Create'} Dev session error`, options.stderr) - await printError(`${error.message}`, options.stderr) + return {status: 'error', error: error.message} } } - return true } async function printWarning(message: string, stdout: Writable) { From da7a6e84ab8d8cf5957ddca3b5f0c90fcfd9b136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Fri, 8 Nov 2024 16:30:19 +0100 Subject: [PATCH 3/7] Use alternative palette for consistent-dev --- .../app/src/cli/services/dev/processes/dev-session.ts | 4 ++-- .../app/src/cli/services/dev/ui/components/Dev.tsx | 1 + .../private/node/ui/components/ConcurrentOutput.tsx | 10 +++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/app/src/cli/services/dev/processes/dev-session.ts b/packages/app/src/cli/services/dev/processes/dev-session.ts index 91fac1e06c..2b15752361 100644 --- a/packages/app/src/cli/services/dev/processes/dev-session.ts +++ b/packages/app/src/cli/services/dev/processes/dev-session.ts @@ -127,7 +127,7 @@ async function handleDevSessionResult( event?: AppEvent, ) { if (result.status === 'updated') { - await printSuccess(`✅ Session updated`, processOptions.stdout) + await printSuccess(`✅ Updated`, processOptions.stdout) const scopeChanges = event?.extensionEvents.find((eve) => eve.extension.handle === 'app-access') if (scopeChanges) { await printWarning(`🔄 Action required`, processOptions.stdout) @@ -138,7 +138,7 @@ async function handleDevSessionResult( await printWarning(message.value, processOptions.stdout) } } else if (result.status === 'created') { - await printSuccess(`✅ Dev session created, watching for changes in your app `, processOptions.stdout) + await printSuccess(`✅ Ready, watching for changes in your app `, processOptions.stdout) } else if (result.status === 'aborted') { outputDebug('❌ Session update aborted (new change detected)', processOptions.stdout) } else { diff --git a/packages/app/src/cli/services/dev/ui/components/Dev.tsx b/packages/app/src/cli/services/dev/ui/components/Dev.tsx index 3cfb7e102d..32c38675d2 100644 --- a/packages/app/src/cli/services/dev/ui/components/Dev.tsx +++ b/packages/app/src/cli/services/dev/ui/components/Dev.tsx @@ -214,6 +214,7 @@ const Dev: FunctionComponent = ({ prefixColumnSize={calculatePrefixColumnSize(errorHandledProcesses, app.extensions)} abortSignal={abortController.signal} keepRunningAfterProcessesResolve={true} + useAlternativeColorPalette={app.developerPlatformClient.supportsDevSessions} /> {/* eslint-disable-next-line no-negated-condition */} {!isAborted ? ( diff --git a/packages/cli-kit/src/private/node/ui/components/ConcurrentOutput.tsx b/packages/cli-kit/src/private/node/ui/components/ConcurrentOutput.tsx index e098cd5b25..a28ec3c36a 100644 --- a/packages/cli-kit/src/private/node/ui/components/ConcurrentOutput.tsx +++ b/packages/cli-kit/src/private/node/ui/components/ConcurrentOutput.tsx @@ -14,6 +14,7 @@ export interface ConcurrentOutputProps { abortSignal: AbortSignal showTimestamps?: boolean keepRunningAfterProcessesResolve?: boolean + useAlternativeColorPalette?: boolean } interface Chunk { @@ -88,10 +89,17 @@ const ConcurrentOutput: FunctionComponent = ({ abortSignal, showTimestamps = true, keepRunningAfterProcessesResolve = false, + useAlternativeColorPalette = false, }) => { const [processOutput, setProcessOutput] = useState([]) const {exit: unmountInk} = useApp() - const concurrentColors: TextProps['color'][] = useMemo(() => ['yellow', 'cyan', 'magenta', 'green', 'blue'], []) + const concurrentColors: TextProps['color'][] = useMemo( + () => + useAlternativeColorPalette + ? ['#b994c3', '#e69e19', '#d17a73', 'cyan', 'magenta', 'blue'] + : ['yellow', 'cyan', 'magenta', 'green', 'blue'], + [useAlternativeColorPalette], + ) const calculatedPrefixColumnSize = useMemo(() => { const maxColumnSize = 25 From 32e44d7c076e1b09921d4febb6cdfb5a3492187c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Fri, 8 Nov 2024 16:53:00 +0100 Subject: [PATCH 4/7] Remove commented code --- .../src/cli/services/dev/app-events/app-event-watcher-handler.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts b/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts index 862fd8742f..dc0c606c39 100644 --- a/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts +++ b/packages/app/src/cli/services/dev/app-events/app-event-watcher-handler.ts @@ -137,7 +137,6 @@ export async function reloadApp(app: AppLinkedInterface, options: OutputContextO remoteFlags: app.remoteFlags, }) outputDebug(`App reloaded [${endHRTimeInMs(start)}ms]`, options.stdout) - // options.stdout.write(`App reloaded [${endHRTimeInMs(start)}ms]`) return newApp as AppLinkedInterface // eslint-disable-next-line no-catch-all/no-catch-all, @typescript-eslint/no-explicit-any } catch (error: any) { From 149a5460fbc3288236aae6d9c54a7c37b3657f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Mon, 11 Nov 2024 11:01:36 +0100 Subject: [PATCH 5/7] Fix a test --- packages/app/src/cli/services/dev/extension/localization.ts | 3 ++- .../src/cli/services/dev/processes/setup-dev-processes.test.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/app/src/cli/services/dev/extension/localization.ts b/packages/app/src/cli/services/dev/extension/localization.ts index 8683a6bb46..8eaff9a189 100644 --- a/packages/app/src/cli/services/dev/extension/localization.ts +++ b/packages/app/src/cli/services/dev/extension/localization.ts @@ -4,7 +4,7 @@ import {ExtensionInstance} from '../../../models/extensions/extension-instance.j import {joinPath} from '@shopify/cli-kit/node/path' import {readFile, glob} from '@shopify/cli-kit/node/fs' import {ExtendableError} from '@shopify/cli-kit/node/error' -import {outputWarn} from '@shopify/cli-kit/node/output' +import {outputDebug, outputWarn} from '@shopify/cli-kit/node/output' type Locale = string @@ -57,6 +57,7 @@ export async function getLocalization( }), ) localization.lastUpdated = Date.now() + outputDebug(`Parsed locales for extension ${extension.handle} at ${extension.directory}`) // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-catch-all/no-catch-all } catch (error: any) { status = 'error' diff --git a/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts b/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts index fddc8aa26d..0714c74740 100644 --- a/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts +++ b/packages/app/src/cli/services/dev/processes/setup-dev-processes.test.ts @@ -324,7 +324,7 @@ describe('setup-dev-processes', () => { expect(res.processes[2]).toMatchObject({ type: 'dev-session', - prefix: 'extensions', + prefix: 'dev-session', function: pushUpdatesForDevSession, options: { app: localApp, From dd35e0cee71903cb81a28f4032844adc9036ba9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Mon, 11 Nov 2024 11:22:53 +0100 Subject: [PATCH 6/7] Print locale changes to debug --- .../src/cli/services/dev/extension/localization.test.ts | 8 ++++---- .../app/src/cli/services/dev/extension/localization.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/app/src/cli/services/dev/extension/localization.test.ts b/packages/app/src/cli/services/dev/extension/localization.test.ts index 12873b8a34..01e03430eb 100644 --- a/packages/app/src/cli/services/dev/extension/localization.test.ts +++ b/packages/app/src/cli/services/dev/extension/localization.test.ts @@ -5,7 +5,7 @@ import * as output from '@shopify/cli-kit/node/output' import {describe, expect, vi, test} from 'vitest' import {mkdir, writeFile, inTemporaryDirectory} from '@shopify/cli-kit/node/fs' import {joinPath} from '@shopify/cli-kit/node/path' -import {outputInfo} from '@shopify/cli-kit/node/output' +import {outputDebug} from '@shopify/cli-kit/node/output' async function testGetLocalization(tmpDir: string, currentLocalization?: Localization) { const mockOptions = {} as unknown as ExtensionDevOptions @@ -142,7 +142,7 @@ describe('when there are locale files', () => { }) test('outputs message when there are no JSON errors', async () => { await inTemporaryDirectory(async (tmpDir) => { - vi.spyOn(output, 'outputInfo') + vi.spyOn(output, 'outputDebug') await mkdir(joinPath(tmpDir, 'locales')) await writeFile(joinPath(tmpDir, 'locales', 'en.json'), '{"greeting": "Hi!"}') @@ -150,8 +150,8 @@ describe('when there are locale files', () => { await testGetLocalization(tmpDir) - expect(outputInfo).toHaveBeenCalledWith(expect.stringContaining('mock-name'), undefined) - expect(outputInfo).toHaveBeenCalledWith(expect.stringContaining(tmpDir), undefined) + expect(outputDebug).toHaveBeenLastCalledWith(expect.stringContaining('mock-name'), undefined) + expect(outputDebug).toHaveBeenLastCalledWith(expect.stringContaining(tmpDir), undefined) }) }) diff --git a/packages/app/src/cli/services/dev/extension/localization.ts b/packages/app/src/cli/services/dev/extension/localization.ts index 8eaff9a189..ad0f1887e7 100644 --- a/packages/app/src/cli/services/dev/extension/localization.ts +++ b/packages/app/src/cli/services/dev/extension/localization.ts @@ -57,7 +57,7 @@ export async function getLocalization( }), ) localization.lastUpdated = Date.now() - outputDebug(`Parsed locales for extension ${extension.handle} at ${extension.directory}`) + outputDebug(`Parsed locales for extension ${extension.handle} at ${extension.directory}`, options.stdout) // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-catch-all/no-catch-all } catch (error: any) { status = 'error' From 1005d0d4f11fce7c5cd061464aba39fc39ebbab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Mon, 11 Nov 2024 11:29:07 +0100 Subject: [PATCH 7/7] Use helper function --- packages/app/src/cli/services/dev/processes/dev-session.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/app/src/cli/services/dev/processes/dev-session.ts b/packages/app/src/cli/services/dev/processes/dev-session.ts index 2b15752361..b0cd0682a3 100644 --- a/packages/app/src/cli/services/dev/processes/dev-session.ts +++ b/packages/app/src/cli/services/dev/processes/dev-session.ts @@ -84,7 +84,7 @@ export const pushUpdatesForDevSession: DevProcessFunction = a const processOptions = {...options, stderr, stdout, signal, bundlePath: appWatcher.buildOutputPath, app} - processOptions.stdout.write('Preparing dev session') + await printLogMessage('Preparing dev session', processOptions.stdout) appWatcher .onEvent(async (event) => { @@ -238,6 +238,7 @@ async function printSuccess(message: string, stdout: Writable) { await printLogMessage(outputContent`${outputToken.green(message)}`.value, stdout) } +// Helper function to print to terminal using output context with stripAnsi disabled. async function printLogMessage(message: string, stdout: Writable) { await useConcurrentOutputContext({outputPrefix: 'dev-session', stripAnsi: false}, () => { stdout.write(message)