diff --git a/packages/app/src/cli/services/build/extension.test.ts b/packages/app/src/cli/services/build/extension.test.ts index adf92867b84..7f4be985566 100644 --- a/packages/app/src/cli/services/build/extension.test.ts +++ b/packages/app/src/cli/services/build/extension.test.ts @@ -7,7 +7,8 @@ import {beforeEach, describe, expect, test, vi} from 'vitest' import {exec} from '@shopify/cli-kit/node/system' import lockfile from 'proper-lockfile' import {AbortError} from '@shopify/cli-kit/node/error' -import {fileExistsSync} from '@shopify/cli-kit/node/fs' +import {fileExistsSync, touchFile, writeFile} from '@shopify/cli-kit/node/fs' +import {joinPath} from '@shopify/cli-kit/node/path' vi.mock('@shopify/cli-kit/node/system') vi.mock('../function/build.js') @@ -416,4 +417,26 @@ describe('buildFunctionExtension', () => { expect(releaseLock).toHaveBeenCalled() expect(runWasmOpt).toHaveBeenCalled() }) + + test('does not rebundle when build.path stays in the default output directory', async () => { + // Given + extension.configuration.build!.path = 'dist/custom.wasm' + vi.mocked(fileExistsSync).mockReturnValue(true) + + // When + await expect( + buildFunctionExtension(extension, { + stdout, + stderr, + signal, + app, + environment: 'production', + }), + ).resolves.toBeUndefined() + + // Then + expect(fileExistsSync).toHaveBeenCalledWith(joinPath(extension.directory, 'dist/custom.wasm')) + expect(touchFile).not.toHaveBeenCalled() + expect(writeFile).not.toHaveBeenCalled() + }) }) diff --git a/packages/app/src/cli/services/build/extension.ts b/packages/app/src/cli/services/build/extension.ts index 9e056d5ecee..d14164e17b2 100644 --- a/packages/app/src/cli/services/build/extension.ts +++ b/packages/app/src/cli/services/build/extension.ts @@ -159,7 +159,11 @@ export async function buildFunctionExtension( await runTrampoline(extension.outputPath) } - if (fileExistsSync(extension.outputPath) && bundlePath !== extension.outputPath) { + if ( + fileExistsSync(extension.outputPath) && + bundlePath !== extension.outputPath && + dirname(bundlePath) !== dirname(extension.outputPath) + ) { await bundleFunctionExtension(extension.outputPath, bundlePath) } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/app/src/cli/services/function/runner.test.ts b/packages/app/src/cli/services/function/runner.test.ts index 2e78d04d545..6f32757e3af 100644 --- a/packages/app/src/cli/services/function/runner.test.ts +++ b/packages/app/src/cli/services/function/runner.test.ts @@ -3,6 +3,7 @@ import {functionRunnerBinary, downloadBinary} from './binaries.js' import {testFunctionExtension} from '../../models/app/app.test-data.js' import {describe, test, vi, expect} from 'vitest' import {exec} from '@shopify/cli-kit/node/system' +import {joinPath} from '@shopify/cli-kit/node/path' import {Readable, Writable} from 'stream' vi.mock('@shopify/cli-kit/node/system') @@ -71,4 +72,21 @@ describe('runFunction', () => { }, ) }) + + test('uses build.path when configured', async () => { + // Given + vi.mocked(exec).mockResolvedValue() + const functionExtension = await testFunctionExtension() + functionExtension.configuration.build!.path = 'dist/custom.wasm' + + // When + await runFunction({functionExtension}) + + // Then + expect(exec).toHaveBeenCalledWith( + functionRunnerBinary().path, + ['-f', joinPath(functionExtension.directory, 'dist/custom.wasm')], + expect.objectContaining({cwd: functionExtension.directory}), + ) + }) }) diff --git a/packages/app/src/cli/services/function/runner.ts b/packages/app/src/cli/services/function/runner.ts index e81fe684461..29336bc6069 100644 --- a/packages/app/src/cli/services/function/runner.ts +++ b/packages/app/src/cli/services/function/runner.ts @@ -3,6 +3,7 @@ import {validateShopifyFunctionPackageVersion} from './build.js' import {ExtensionInstance} from '../../models/extensions/extension-instance.js' import {FunctionConfigType} from '../../models/extensions/specifications/function.js' import {exec} from '@shopify/cli-kit/node/system' +import {joinPath} from '@shopify/cli-kit/node/path' import {Readable, Writable} from 'stream' interface FunctionRunnerOptions { @@ -26,6 +27,13 @@ async function getFunctionRunnerBinary(ext: ExtensionInstance) { + if (ext.configuration.build?.path) { + return joinPath(ext.directory, ext.configuration.build.path) + } + return ext.outputPath +} + export async function runFunction(options: FunctionRunnerOptions) { const ext = options.functionExtension @@ -47,7 +55,9 @@ export async function runFunction(options: FunctionRunnerOptions) { args.push('--query-path', options.queryPath) } - return exec(functionRunner.path, ['-f', options.functionExtension.outputPath, ...args], { + const functionPath = getFunctionPath(ext) + + return exec(functionRunner.path, ['-f', functionPath, ...args], { cwd: options.functionExtension.directory, stdin: options.stdin, stdout: options.stdout ?? 'inherit',