diff --git a/packages/core/src/cli/commands.ts b/packages/core/src/cli/commands.ts index 195adeb0d..9d73cdb22 100644 --- a/packages/core/src/cli/commands.ts +++ b/packages/core/src/cli/commands.ts @@ -80,7 +80,13 @@ export function runCli(): void { await cliBuild(); } catch (err) { logger.error('Failed to build.'); - logger.error(err); + if (err instanceof AggregateError) { + for (const error of err.errors) { + logger.error(error); + } + } else { + logger.error(err); + } process.exit(1); } }); diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index 155018e9f..cddd2b02e 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -899,22 +899,40 @@ const composeEntryConfig = async ( } if (bundle !== false) { - let isFileEntry = false; + const entryErrorReasons: string[] = []; traverseEntryQuery(entries, (entry) => { const entryAbsPath = path.isAbsolute(entry) ? entry : path.resolve(root, entry); + const isDirLike = path.extname(entryAbsPath) === ''; + const dirError = `Glob pattern ${color.cyan(`"${entry}"`)} is not supported when "bundle" is "true", considering "bundle" to "false" to use bundleless mode, or specify a file entry to bundle. See ${color.green('https://lib.rsbuild.dev/guide/basic/output-structure')} for more details.`; + if (fs.existsSync(entryAbsPath)) { const stats = fs.statSync(entryAbsPath); - isFileEntry = stats.isFile(); + if (!stats.isFile()) { + // Existed dir. + entryErrorReasons.push(dirError); + } else { + // Existed file. + } + } else { + if (isDirLike) { + // Non-existed dir. + entryErrorReasons.push(dirError); + } else { + // Non-existed file. + entryErrorReasons.push( + `Can't resolve the entry ${color.cyan(`"${entry}"`)} at the location ${color.cyan(`${entryAbsPath}`)}. Please ensure that the file exists.`, + ); + } } return entry; }); - if (!isFileEntry) { - throw new Error( - `Glob pattern is not supported when "bundle" is "true", considering ${color.green('set "bundle" to "false"')} to use bundleless mode. See ${color.green('https://lib.rsbuild.dev/guide/basic/output-structure')} for more details.`, + if (entryErrorReasons.length) { + throw new AggregateError( + entryErrorReasons.map((reason) => new Error(reason)), ); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 973e9cbfb..449fa639a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -664,12 +664,12 @@ importers: tests/integration/entry/glob: {} - tests/integration/entry/glob-bundle: {} - tests/integration/entry/multiple: {} tests/integration/entry/single: {} + tests/integration/entry/validate: {} + tests/integration/extension-alias: {} tests/integration/external-helpers/config-override: diff --git a/tests/integration/entry/glob-bundle/rslib.config.ts b/tests/integration/entry/glob-bundle/rslib.config.ts deleted file mode 100644 index f52a536d2..000000000 --- a/tests/integration/entry/glob-bundle/rslib.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig } from '@rslib/core'; -import { generateBundleEsmConfig } from 'test-helper'; - -export default defineConfig({ - lib: [generateBundleEsmConfig({})], - source: { - entry: { - index: ['./src', '!./src/ignored'], - }, - }, -}); diff --git a/tests/integration/entry/index.test.ts b/tests/integration/entry/index.test.ts index 81f78a432..499b3aad9 100644 --- a/tests/integration/entry/index.test.ts +++ b/tests/integration/entry/index.test.ts @@ -124,16 +124,34 @@ test('glob entry bundleless', async () => { `); }); -test('glob entry bundle', async () => { - const fixturePath = join(__dirname, 'glob-bundle'); +test('validate entry and throw errors', async () => { + const fixturePath = join(__dirname, 'validate'); let errMsg = ''; try { - await buildAndGetResults({ fixturePath }); + await buildAndGetResults({ + fixturePath, + configPath: 'bundleWithGlob.config.ts', + }); } catch (e) { - errMsg = (e as Error).message; + errMsg = (e as AggregateError).errors.join('\n\n'); + } + + expect(stripAnsi(errMsg)).toMatchInlineSnapshot(` + "Error: Glob pattern "./src" is not supported when "bundle" is "true", considering "bundle" to "false" to use bundleless mode, or specify a file entry to bundle. See https://lib.rsbuild.dev/guide/basic/output-structure for more details. + + Error: Glob pattern "!./src/ignored" is not supported when "bundle" is "true", considering "bundle" to "false" to use bundleless mode, or specify a file entry to bundle. See https://lib.rsbuild.dev/guide/basic/output-structure for more details." + `); + + try { + await buildAndGetResults({ + fixturePath, + configPath: 'nonExistingFile.config.ts', + }); + } catch (e) { + errMsg = (e as AggregateError).errors.join('\n\n'); } expect(stripAnsi(errMsg)).toMatchInlineSnapshot( - `"Glob pattern is not supported when "bundle" is "true", considering set "bundle" to "false" to use bundleless mode. See https://lib.rsbuild.dev/guide/basic/output-structure for more details."`, + `"Error: Can't resolve the entry "./src/main.ts" at the location /tests/integration/entry/validate/src/main.ts. Please ensure that the file exists."`, ); }); diff --git a/tests/integration/entry/validate/bundleWithGlob.config.ts b/tests/integration/entry/validate/bundleWithGlob.config.ts new file mode 100644 index 000000000..cdcd8c496 --- /dev/null +++ b/tests/integration/entry/validate/bundleWithGlob.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from '@rslib/core'; +import { generateBundleEsmConfig } from 'test-helper'; + +export default defineConfig({ + lib: [ + generateBundleEsmConfig({ + source: { + entry: { + index: ['./src', '!./src/ignored'], + }, + }, + }), + ], +}); diff --git a/tests/integration/entry/validate/nonExistingFile.config.ts b/tests/integration/entry/validate/nonExistingFile.config.ts new file mode 100644 index 000000000..64901da30 --- /dev/null +++ b/tests/integration/entry/validate/nonExistingFile.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from '@rslib/core'; +import { generateBundleEsmConfig } from 'test-helper'; + +export default defineConfig({ + lib: [ + generateBundleEsmConfig({ + source: { + entry: { + index: ['./src/main.ts'], + }, + }, + }), + ], +}); diff --git a/tests/integration/entry/glob-bundle/package.json b/tests/integration/entry/validate/package.json similarity index 64% rename from tests/integration/entry/glob-bundle/package.json rename to tests/integration/entry/validate/package.json index 56e7528b9..cf44308ba 100644 --- a/tests/integration/entry/glob-bundle/package.json +++ b/tests/integration/entry/validate/package.json @@ -1,5 +1,5 @@ { - "name": "entry-glob-bundle-test", + "name": "entry-validate-test", "version": "1.0.0", "private": true, "type": "module" diff --git a/tests/integration/entry/glob-bundle/src/bar.ts b/tests/integration/entry/validate/src/bar.ts similarity index 100% rename from tests/integration/entry/glob-bundle/src/bar.ts rename to tests/integration/entry/validate/src/bar.ts diff --git a/tests/integration/entry/glob-bundle/src/foo.ts b/tests/integration/entry/validate/src/foo.ts similarity index 100% rename from tests/integration/entry/glob-bundle/src/foo.ts rename to tests/integration/entry/validate/src/foo.ts