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 d2f4c16ac5..a1c4b670b3 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 @@ -223,7 +223,7 @@ export class AppEventWatcher extends EventEmitter { return useConcurrentOutputContext({outputPrefix: ext.handle, stripAnsi: false}, async () => { try { if (this.esbuildManager.contexts[ext.handle]) { - await this.esbuildManager.contexts[ext.handle]?.rebuild() + await this.esbuildManager.rebuildContext(ext) } else { await this.buildExtension(ext) } diff --git a/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.ts b/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.ts index fec1fab652..2dc89991fb 100644 --- a/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.ts +++ b/packages/app/src/cli/services/dev/app-events/app-watcher-esbuild.ts @@ -3,6 +3,8 @@ import {ExtensionInstance} from '../../../models/extensions/extension-instance.j import {getESBuildOptions} from '../../extensions/bundle.js' import {BuildContext, context as esContext} from 'esbuild' import {AbortSignal} from '@shopify/cli-kit/node/abort' +import {copyFile} from '@shopify/cli-kit/node/fs' +import {dirname} from '@shopify/cli-kit/node/path' export interface DevAppWatcherOptions { dotEnvVariables: {[key: string]: string} @@ -65,6 +67,22 @@ export class ESBuildContextManager { await Promise.all(promises) } + async rebuildContext(extension: ExtensionInstance) { + const context = this.contexts[extension.handle] + if (!context) return + await context.rebuild() + + // The default output path for a extension is now inside `.shopify/bundle//dist`, + // all extensions output need to be under the same directory so that it can all be zipped together. + + // But historically the output was inside each extension's directory. + // To avoid breaking flows that depend on this, we copy the output to the old location. + // This also makes it easier to access sourcemaps or other built artifacts. + const outputPath = dirname(extension.getOutputPathForDirectory(this.outputPath)) + const copyPath = dirname(extension.outputPath) + await copyFile(outputPath, copyPath) + } + async updateContexts(appEvent: AppEvent) { this.dotEnvVariables = appEvent.app.dotenv?.variables ?? {} const createdEsBuild = appEvent.extensionEvents