diff --git a/packages/app/src/cli/models/extensions/extension-instance.test.ts b/packages/app/src/cli/models/extensions/extension-instance.test.ts index 5a808958df9..dbafca2026a 100644 --- a/packages/app/src/cli/models/extensions/extension-instance.test.ts +++ b/packages/app/src/cli/models/extensions/extension-instance.test.ts @@ -72,10 +72,10 @@ describe('keepBuiltSourcemapsLocally', async () => { await extensionInstance.keepBuiltSourcemapsLocally(bundleDirectory) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToMove.js'))).toBe(false) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToMove.js.map'))).toBe(true) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToIgnore.js'))).toBe(false) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToIgnore.js.map'))).toBe(false) + expect(fileExistsSync(joinPath(outputPath, 'uid1', 'scriptToMove.js'))).toBe(false) + expect(fileExistsSync(joinPath(outputPath, 'uid1', 'scriptToMove.js.map'))).toBe(true) + expect(fileExistsSync(joinPath(outputPath, 'otherUID', 'scriptToIgnore.js'))).toBe(false) + expect(fileExistsSync(joinPath(outputPath, 'otherUID', 'scriptToIgnore.js.map'))).toBe(false) }) }) }) @@ -103,10 +103,10 @@ describe('keepBuiltSourcemapsLocally', async () => { await extensionInstance.keepBuiltSourcemapsLocally(bundleInputPath) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToMove.js'))).toBe(false) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToMove.js.map'))).toBe(false) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToIgnore.js'))).toBe(false) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToIgnore.js.map'))).toBe(false) + expect(fileExistsSync(joinPath(outputPath, 'wrongUID', 'scriptToMove.js'))).toBe(false) + expect(fileExistsSync(joinPath(outputPath, 'wrongUID', 'scriptToMove.js.map'))).toBe(false) + expect(fileExistsSync(joinPath(outputPath, 'otherUID', 'scriptToIgnore.js'))).toBe(false) + expect(fileExistsSync(joinPath(outputPath, 'otherUID', 'scriptToIgnore.js.map'))).toBe(false) }) }) }) @@ -133,10 +133,10 @@ describe('keepBuiltSourcemapsLocally', async () => { await extensionInstance.keepBuiltSourcemapsLocally(bundleDirectory) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToMove.js'))).toBe(false) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToMove.js.map'))).toBe(false) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToIgnore.js'))).toBe(false) - expect(fileExistsSync(joinPath(outputPath, 'dist', 'scriptToIgnore.js.map'))).toBe(false) + expect(fileExistsSync(joinPath(outputPath, 'uid1', 'scriptToMove.js'))).toBe(false) + expect(fileExistsSync(joinPath(outputPath, 'uid1', 'scriptToMove.js.map'))).toBe(false) + expect(fileExistsSync(joinPath(outputPath, 'otherUID', 'scriptToIgnore.js'))).toBe(false) + expect(fileExistsSync(joinPath(outputPath, 'otherUID', 'scriptToIgnore.js.map'))).toBe(false) }) }) }) diff --git a/packages/app/src/cli/models/extensions/extension-instance.ts b/packages/app/src/cli/models/extensions/extension-instance.ts index 1732badeae3..295fb5bdf7d 100644 --- a/packages/app/src/cli/models/extensions/extension-instance.ts +++ b/packages/app/src/cli/models/extensions/extension-instance.ts @@ -27,7 +27,7 @@ import {ok} from '@shopify/cli-kit/node/result' import {constantize, slugify} from '@shopify/cli-kit/common/string' import {hashString, nonRandomUUID} from '@shopify/cli-kit/node/crypto' import {partnersFqdn} from '@shopify/cli-kit/node/context/fqdn' -import {joinPath, basename, normalizePath, resolvePath} from '@shopify/cli-kit/node/path' +import {joinPath, basename, normalizePath, resolvePath, relativePath} from '@shopify/cli-kit/node/path' import {fileExists, touchFile, moveFile, writeFile, glob, copyFile, globSync} from '@shopify/cli-kit/node/fs' import {getPathValue} from '@shopify/cli-kit/common/object' import {outputDebug} from '@shopify/cli-kit/node/output' @@ -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..f93fe7cb4eb 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,8 @@ const functionSpec = createExtensionSpecification({ schema: FunctionExtensionSchema, appModuleFeatures: (_) => ['function'], buildConfig: {mode: 'function'}, + getOutputFileName: (extension: ExtensionInstance) => + extension.configuration.build?.path ?? 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),