From 9bebf7c33844a6931f1d8f20e26efe2d08cc40fc Mon Sep 17 00:00:00 2001 From: Alfonso Noriega Date: Tue, 10 Mar 2026 11:24:17 +0100 Subject: [PATCH] Clean up module outputFile calculation and move it to the specifications --- .../src/cli/models/extensions/extension-instance.ts | 12 ++---------- .../app/src/cli/models/extensions/specification.ts | 1 + .../specifications/checkout_post_purchase.ts | 5 +++++ .../specifications/checkout_ui_extension.ts | 4 ++++ .../cli/models/extensions/specifications/function.ts | 2 ++ .../extensions/specifications/pos_ui_extension.ts | 8 +++++++- .../specifications/product_subscription.ts | 7 +++++++ .../extensions/specifications/tax_calculation.ts | 5 +++++ .../models/extensions/specifications/ui_extension.ts | 3 +++ .../extensions/specifications/web_pixel_extension.ts | 4 ++++ .../cli/services/dev/extension/server/middlewares.ts | 4 ++-- 11 files changed, 42 insertions(+), 13 deletions(-) diff --git a/packages/app/src/cli/models/extensions/extension-instance.ts b/packages/app/src/cli/models/extensions/extension-instance.ts index 1732badeae3..f076bc017ed 100644 --- a/packages/app/src/cli/models/extensions/extension-instance.ts +++ b/packages/app/src/cli/models/extensions/extension-instance.ts @@ -137,14 +137,7 @@ export class ExtensionInstance) => string getBundleExtensionStdinContent?: (config: TConfiguration) => {main: string; assets?: Asset[]} deployConfig?: ( config: TConfiguration, diff --git a/packages/app/src/cli/models/extensions/specifications/checkout_post_purchase.ts b/packages/app/src/cli/models/extensions/specifications/checkout_post_purchase.ts index 616adf80b73..69c5af596b7 100644 --- a/packages/app/src/cli/models/extensions/specifications/checkout_post_purchase.ts +++ b/packages/app/src/cli/models/extensions/specifications/checkout_post_purchase.ts @@ -1,9 +1,12 @@ +import {ExtensionInstance} from '../extension-instance.js' import {BaseSchema, MetafieldSchema} from '../schemas.js' import {createExtensionSpecification} from '../specification.js' +import {joinPath} from '@shopify/cli-kit/node/path' import {zod} from '@shopify/cli-kit/node/schema' const dependency = '@shopify/post-purchase-ui-extensions' +type CheckoutPostPurchaseConfigType = zod.infer const CheckoutPostPurchaseSchema = BaseSchema.extend({ metafields: zod.array(MetafieldSchema).optional(), }) @@ -15,6 +18,8 @@ const checkoutPostPurchaseSpec = createExtensionSpecification({ schema: CheckoutPostPurchaseSchema, appModuleFeatures: (_) => ['ui_preview', 'cart_url', 'esbuild', 'single_js_entry_path'], buildConfig: {mode: 'ui'}, + getOutputFileName: (extension: ExtensionInstance) => + joinPath('dist', `${extension.handle}.js`), deployConfig: async (config, _) => { return {metafields: config.metafields ?? []} }, diff --git a/packages/app/src/cli/models/extensions/specifications/checkout_ui_extension.ts b/packages/app/src/cli/models/extensions/specifications/checkout_ui_extension.ts index f08dfd97c40..c2ae52d46c9 100644 --- a/packages/app/src/cli/models/extensions/specifications/checkout_ui_extension.ts +++ b/packages/app/src/cli/models/extensions/specifications/checkout_ui_extension.ts @@ -1,10 +1,13 @@ import {createExtensionSpecification} from '../specification.js' import {BaseSchema, MetafieldSchema} from '../schemas.js' import {loadLocalesConfig} from '../../../utilities/extensions/locales-configuration.js' +import {ExtensionInstance} from '../extension-instance.js' import {zod} from '@shopify/cli-kit/node/schema' +import {joinPath} from '@shopify/cli-kit/node/path' const dependency = '@shopify/checkout-ui-extensions' +type CheckoutConfigType = zod.infer const CheckoutSchema = BaseSchema.extend({ name: zod.string(), extension_points: zod.array(zod.string()).optional(), @@ -22,6 +25,7 @@ const checkoutSpec = createExtensionSpecification({ schema: CheckoutSchema, appModuleFeatures: (_) => ['ui_preview', 'cart_url', 'esbuild', 'single_js_entry_path', 'generates_source_maps'], buildConfig: {mode: 'ui'}, + getOutputFileName: (extension: ExtensionInstance) => joinPath('dist', `${extension.handle}.js`), deployConfig: async (config, directory) => { return { extension_points: config.extension_points, diff --git a/packages/app/src/cli/models/extensions/specifications/function.ts b/packages/app/src/cli/models/extensions/specifications/function.ts index ce6d2ec5a5d..acf46299cf8 100644 --- a/packages/app/src/cli/models/extensions/specifications/function.ts +++ b/packages/app/src/cli/models/extensions/specifications/function.ts @@ -1,6 +1,7 @@ import {createExtensionSpecification} from '../specification.js' import {BaseSchema} from '../schemas.js' import {loadLocalesConfig} from '../../../utilities/extensions/locales-configuration.js' +import {ExtensionInstance} from '../extension-instance.js' import {zod} from '@shopify/cli-kit/node/schema' import {joinPath} from '@shopify/cli-kit/node/path' import {fileExists, readFile} from '@shopify/cli-kit/node/fs' @@ -88,6 +89,7 @@ const functionSpec = createExtensionSpecification({ schema: FunctionExtensionSchema, appModuleFeatures: (_) => ['function'], buildConfig: {mode: 'function'}, + getOutputFileName: (_extension: ExtensionInstance) => joinPath('dist', 'index.wasm'), deployConfig: async (config, directory, apiKey) => { let inputQuery: string | undefined const moduleId = randomUUID() diff --git a/packages/app/src/cli/models/extensions/specifications/pos_ui_extension.ts b/packages/app/src/cli/models/extensions/specifications/pos_ui_extension.ts index 33962306a24..df4d08f6d7d 100644 --- a/packages/app/src/cli/models/extensions/specifications/pos_ui_extension.ts +++ b/packages/app/src/cli/models/extensions/specifications/pos_ui_extension.ts @@ -1,17 +1,23 @@ import {getDependencyVersion} from '../../app/app.js' import {createExtensionSpecification} from '../specification.js' import {BaseSchema} from '../schemas.js' +import {ExtensionInstance} from '../extension-instance.js' import {BugError} from '@shopify/cli-kit/node/error' import {zod} from '@shopify/cli-kit/node/schema' +import {joinPath} from '@shopify/cli-kit/node/path' const dependency = '@shopify/retail-ui-extensions' +type PosUIConfigType = zod.infer +const PosUISchema = BaseSchema.extend({name: zod.string()}) + const posUISpec = createExtensionSpecification({ identifier: 'pos_ui_extension', dependency, - schema: BaseSchema.extend({name: zod.string()}), + schema: PosUISchema, appModuleFeatures: (_) => ['ui_preview', 'esbuild', 'single_js_entry_path'], buildConfig: {mode: 'ui'}, + getOutputFileName: (extension: ExtensionInstance) => joinPath('dist', `${extension.handle}.js`), deployConfig: async (config, directory) => { const result = await getDependencyVersion(dependency, directory) if (result === 'not_found') throw new BugError(`Dependency ${dependency} not found`) diff --git a/packages/app/src/cli/models/extensions/specifications/product_subscription.ts b/packages/app/src/cli/models/extensions/specifications/product_subscription.ts index ba807e409f6..cc6dc378637 100644 --- a/packages/app/src/cli/models/extensions/specifications/product_subscription.ts +++ b/packages/app/src/cli/models/extensions/specifications/product_subscription.ts @@ -1,10 +1,15 @@ import {getDependencyVersion} from '../../app/app.js' import {createExtensionSpecification} from '../specification.js' import {BaseSchema} from '../schemas.js' +import {ExtensionInstance} from '../extension-instance.js' import {BugError} from '@shopify/cli-kit/node/error' +import {zod} from '@shopify/cli-kit/node/schema' +import {joinPath} from '@shopify/cli-kit/node/path' const dependency = '@shopify/admin-ui-extensions' +type ProductSubscriptionConfigType = zod.infer + const productSubscriptionSpec = createExtensionSpecification({ identifier: 'product_subscription', additionalIdentifiers: ['subscription_management'], @@ -13,6 +18,8 @@ const productSubscriptionSpec = createExtensionSpecification({ schema: BaseSchema, appModuleFeatures: (_) => ['ui_preview', 'esbuild', 'single_js_entry_path'], buildConfig: {mode: 'ui'}, + getOutputFileName: (extension: ExtensionInstance) => + joinPath('dist', `${extension.handle}.js`), deployConfig: async (_, directory) => { const result = await getDependencyVersion(dependency, directory) if (result === 'not_found') throw new BugError(`Dependency ${dependency} not found`) diff --git a/packages/app/src/cli/models/extensions/specifications/tax_calculation.ts b/packages/app/src/cli/models/extensions/specifications/tax_calculation.ts index 1e97e577bb6..f9a18bfdca2 100644 --- a/packages/app/src/cli/models/extensions/specifications/tax_calculation.ts +++ b/packages/app/src/cli/models/extensions/specifications/tax_calculation.ts @@ -1,11 +1,14 @@ import {createExtensionSpecification} from '../specification.js' import {BaseSchema, MetafieldSchema} from '../schemas.js' +import {ExtensionInstance} from '../extension-instance.js' import {zod} from '@shopify/cli-kit/node/schema' +import {joinPath} from '@shopify/cli-kit/node/path' const CartLinePropertySchema = zod.object({ key: zod.string(), }) +type TaxCalculationsConfigType = zod.infer const TaxCalculationsSchema = BaseSchema.extend({ production_api_base_url: zod.string(), benchmark_api_base_url: zod.string().optional(), @@ -29,6 +32,8 @@ const spec = createExtensionSpecification({ schema: TaxCalculationsSchema, appModuleFeatures: (_) => [], buildConfig: {mode: 'tax_calculation'}, + getOutputFileName: (extension: ExtensionInstance) => + joinPath('dist', `${extension.handle}.js`), deployConfig: async (config, _) => { return { production_api_base_url: config.production_api_base_url, diff --git a/packages/app/src/cli/models/extensions/specifications/ui_extension.ts b/packages/app/src/cli/models/extensions/specifications/ui_extension.ts index f3e04cbeab9..0cb6c0202d7 100644 --- a/packages/app/src/cli/models/extensions/specifications/ui_extension.ts +++ b/packages/app/src/cli/models/extensions/specifications/ui_extension.ts @@ -36,6 +36,7 @@ export interface BuildManifest { const missingExtensionPointsMessage = 'No extension targets defined, add a `targeting` field to your configuration' +type UIExtensionConfigType = zod.infer export const UIExtensionSchema = BaseSchema.extend({ name: zod.string(), type: zod.literal('ui_extension'), @@ -102,6 +103,8 @@ const uiExtensionSpec = createExtensionSpecification({ dependency, schema: UIExtensionSchema, buildConfig: {mode: 'ui'}, + getOutputFileName: (extension: ExtensionInstance) => + joinPath('dist', `${extension.handle}.js`), appModuleFeatures: (config) => { const basic: ExtensionFeature[] = ['ui_preview', 'esbuild', 'generates_source_maps'] const needsCart = diff --git a/packages/app/src/cli/models/extensions/specifications/web_pixel_extension.ts b/packages/app/src/cli/models/extensions/specifications/web_pixel_extension.ts index 298a18d876b..06eddd6b9cc 100644 --- a/packages/app/src/cli/models/extensions/specifications/web_pixel_extension.ts +++ b/packages/app/src/cli/models/extensions/specifications/web_pixel_extension.ts @@ -1,8 +1,10 @@ import {createExtensionSpecification} from '../specification.js' import {BaseSchema} from '../schemas.js' +import {ExtensionInstance} from '../extension-instance.js' import {zod} from '@shopify/cli-kit/node/schema' import {AbortError} from '@shopify/cli-kit/node/error' import {fileSize} from '@shopify/cli-kit/node/fs' +import {joinPath} from '@shopify/cli-kit/node/path' const kilobytes = 1024 const BUNDLE_SIZE_LIMIT_KB = 128 @@ -10,6 +12,7 @@ const BUNDLE_SIZE_LIMIT = BUNDLE_SIZE_LIMIT_KB * kilobytes const dependency = '@shopify/web-pixels-extension' +type WebPixelConfigType = zod.infer const WebPixelSchema = BaseSchema.extend({ runtime_context: zod.string(), version: zod.string().optional(), @@ -32,6 +35,7 @@ const webPixelSpec = createExtensionSpecification({ schema: WebPixelSchema, appModuleFeatures: (_) => ['esbuild', 'single_js_entry_path'], buildConfig: {mode: 'ui'}, + getOutputFileName: (extension: ExtensionInstance) => joinPath('dist', `${extension.handle}.js`), deployConfig: async (config, _) => { return { runtime_context: config.runtime_context, diff --git a/packages/app/src/cli/services/dev/extension/server/middlewares.ts b/packages/app/src/cli/services/dev/extension/server/middlewares.ts index 7bf8116bc11..9cec5a369c4 100644 --- a/packages/app/src/cli/services/dev/extension/server/middlewares.ts +++ b/packages/app/src/cli/services/dev/extension/server/middlewares.ts @@ -5,7 +5,7 @@ import {getHTML} from '../templates.js' import {getWebSocketUrl} from '../../extension.js' import {fileExists, isDirectory, readFile, findPathUp} from '@shopify/cli-kit/node/fs' import {IncomingMessage, ServerResponse, sendRedirect, send} from 'h3' -import {joinPath, extname, moduleDirectory} from '@shopify/cli-kit/node/path' +import {joinPath, dirname, extname, moduleDirectory} from '@shopify/cli-kit/node/path' import {outputDebug} from '@shopify/cli-kit/node/output' export function corsMiddleware(_request: IncomingMessage, response: ServerResponse, next: (err?: Error) => unknown) { @@ -90,7 +90,7 @@ export function getExtensionAssetMiddleware({devOptions, getExtensions}: GetExte const bundlePath = devOptions.appWatcher.buildOutputPath const extensionOutputPath = extension.getOutputPathForDirectory(bundlePath) - const buildDirectory = extensionOutputPath.replace(extension.outputFileName, '') + const buildDirectory = dirname(extensionOutputPath) return fileServerMiddleware(request, response, next, { filePath: joinPath(buildDirectory, assetPath),