diff --git a/packages/app/src/cli/services/build/steps/include-assets/copy-config-key-entry.test.ts b/packages/app/src/cli/services/build/steps/include-assets/copy-config-key-entry.test.ts index 66134f8837..9e6cddf87b 100644 --- a/packages/app/src/cli/services/build/steps/include-assets/copy-config-key-entry.test.ts +++ b/packages/app/src/cli/services/build/steps/include-assets/copy-config-key-entry.test.ts @@ -354,4 +354,57 @@ describe('copyConfigKeyEntry', () => { await expect(fileExists(joinPath(outDir, 'tools.json'))).resolves.toBe(true) }) }) + + describe('value guard', () => { + test('throws when value is an empty string', async () => { + await inTemporaryDirectory(async (tmpDir) => { + const outDir = joinPath(tmpDir, 'out') + await mkdir(outDir) + const context = makeContext({assets: ''}) + const promise = copyConfigKeyEntry({ + key: 'assets', + baseDir: tmpDir, + outputDir: outDir, + context, + appDirectory: tmpDir, + }) + await expect(promise).rejects.toThrow(AbortError) + await expect(promise).rejects.toThrow(`'assets' can't be empty.`) + }) + }) + + test('throws when value is whitespace-only', async () => { + await inTemporaryDirectory(async (tmpDir) => { + const outDir = joinPath(tmpDir, 'out') + await mkdir(outDir) + const context = makeContext({assets: ' '}) + const promise = copyConfigKeyEntry({ + key: 'assets', + baseDir: tmpDir, + outputDir: outDir, + context, + appDirectory: tmpDir, + }) + await expect(promise).rejects.toThrow(AbortError) + await expect(promise).rejects.toThrow(`'assets' can't be empty.`) + }) + }) + + test('throws with the full configKey when the key is nested', async () => { + await inTemporaryDirectory(async (tmpDir) => { + const outDir = joinPath(tmpDir, 'out') + await mkdir(outDir) + const context = makeContext({extension_points: [{assets: ''}]}) + const promise = copyConfigKeyEntry({ + key: 'extension_points[].assets', + baseDir: tmpDir, + outputDir: outDir, + context, + appDirectory: tmpDir, + }) + await expect(promise).rejects.toThrow(AbortError) + await expect(promise).rejects.toThrow(`'extension_points[].assets' can't be empty.`) + }) + }) + }) }) diff --git a/packages/app/src/cli/services/build/steps/include-assets/copy-config-key-entry.ts b/packages/app/src/cli/services/build/steps/include-assets/copy-config-key-entry.ts index c46e20a8e2..c952cd8abf 100644 --- a/packages/app/src/cli/services/build/steps/include-assets/copy-config-key-entry.ts +++ b/packages/app/src/cli/services/build/steps/include-assets/copy-config-key-entry.ts @@ -51,6 +51,12 @@ export async function copyConfigKeyEntry(config: { paths = [] } + for (const sourcePath of paths) { + if (sourcePath.trim() === '') { + throw new AbortError(`'${key}' can't be empty.`) + } + } + if (paths.length === 0) { outputDebug(`No value for configKey '${key}', skipping\n`, stdout) return {filesCopied: 0, pathMap: new Map()}