From 8b25260998f8fe468a774e8a3be2e5b8e0d416f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Wed, 18 Dec 2024 13:24:18 +0100 Subject: [PATCH] Fix support for extension creation in dev-console --- .../models/extensions/extension-instance.ts | 4 +- .../app/src/cli/services/dev/extension.ts | 48 ++++++++++++------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/packages/app/src/cli/models/extensions/extension-instance.ts b/packages/app/src/cli/models/extensions/extension-instance.ts index 72b7915ac3..dcdfa4d66f 100644 --- a/packages/app/src/cli/models/extensions/extension-instance.ts +++ b/packages/app/src/cli/models/extensions/extension-instance.ts @@ -25,7 +25,7 @@ import {DeveloperPlatformClient} from '../../utilities/developer-platform-client import {AppConfigurationWithoutPath, CurrentAppConfiguration} from '../app/app.js' import {ok} from '@shopify/cli-kit/node/result' import {constantize, slugify} from '@shopify/cli-kit/common/string' -import {hashString, randomUUID} from '@shopify/cli-kit/node/crypto' +import {hashString, nonRandomUUID, randomUUID} from '@shopify/cli-kit/node/crypto' import {partnersFqdn} from '@shopify/cli-kit/node/context/fqdn' import {joinPath, basename} from '@shopify/cli-kit/node/path' import {fileExists, touchFile, moveFile, writeFile, glob} from '@shopify/cli-kit/node/fs' @@ -149,8 +149,8 @@ export class ExtensionInstance { - const payloadStoreOptions = { + const payloadOptions = { ...options, websocketURL: getWebSocketUrl(options.url), } - const bundlePath = options.appWatcher.buildOutputPath - const payloadStoreRawPayload = await getExtensionsPayloadStoreRawPayload(payloadStoreOptions, bundlePath) - const payloadStore = new ExtensionsPayloadStore(payloadStoreRawPayload, payloadStoreOptions) - outputDebug(`Setting up the UI extensions HTTP server...`, options.stdout) - const httpServer = setupHTTPServer({devOptions: options, payloadStore}) + // NOTE: Always use `payloadOptions`, never `options` directly. This way we can mutate `payloadOptions` without + // affecting the original `options` object and we only need to care about `payloadOptions` in this function. - outputDebug(`Setting up the UI extensions Websocket server...`, options.stdout) - const websocketConnection = setupWebsocketConnection({...options, httpServer, payloadStore}) - outputDebug(`Setting up the UI extensions bundler and file watching...`, options.stdout) + const bundlePath = payloadOptions.appWatcher.buildOutputPath + const payloadStoreRawPayload = await getExtensionsPayloadStoreRawPayload(payloadOptions, bundlePath) + const payloadStore = new ExtensionsPayloadStore(payloadStoreRawPayload, payloadOptions) + + outputDebug(`Setting up the UI extensions HTTP server...`, payloadOptions.stdout) + const httpServer = setupHTTPServer({devOptions: payloadOptions, payloadStore}) + + outputDebug(`Setting up the UI extensions Websocket server...`, payloadOptions.stdout) + const websocketConnection = setupWebsocketConnection({...payloadOptions, httpServer, payloadStore}) + outputDebug(`Setting up the UI extensions bundler and file watching...`, payloadOptions.stdout) const eventHandler = async ({extensionEvents}: AppEvent) => { for (const event of extensionEvents) { @@ -130,18 +135,29 @@ export async function devUIExtensions(options: ExtensionDevOptions): Promise ext.devUUID !== event.extension.devUUID, - ) + payloadOptions.extensions = payloadOptions.extensions.filter((ext) => ext.devUUID !== event.extension.devUUID) + // eslint-disable-next-line no-await-in-loop await payloadStore.deleteExtension(event.extension) break @@ -149,9 +165,9 @@ export async function devUIExtensions(options: ExtensionDevOptions): Promise { + payloadOptions.signal.addEventListener('abort', () => { outputDebug('Closing the UI extensions dev server...') websocketConnection.close() httpServer.close()