Skip to content

Commit

Permalink
throw error when Storybook builder is missing
Browse files Browse the repository at this point in the history
  • Loading branch information
yannbf committed Sep 14, 2023
1 parent c05b719 commit 1c7e01f
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 4 deletions.
22 changes: 22 additions & 0 deletions code/lib/core-events/src/errors/server-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,3 +306,25 @@ export class CriticalPresetLoadError extends StorybookError {
`;
}
}

export class MissingBuilderError extends StorybookError {
readonly category = Category.CORE_SERVER;

readonly code = 3;

public readonly documentation = 'https://github.com/storybookjs/storybook/issues/24071';

template() {
return dedent`
Storybook could not find a builder configuration for your project.
Builders normally come from a framework package e.g. '@storybook/react-vite', or from builder packages e.g. '@storybook/builder-vite'.
- Does your main config file contain a 'framework' field configured correctly?
- Is the Storybook framework package installed correctly?
- If you don't use a framework, does your main config contain a 'core.builder' configured correctly?
- Are you in a monorepo and perhaps the framework package is hoisted incorrectly?
If you believe this is a bug, please describe your issue in detail on Github.
`;
}
}
5 changes: 4 additions & 1 deletion code/lib/core-server/src/build-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { global } from '@storybook/global';
import { telemetry } from '@storybook/telemetry';

import { join, resolve } from 'path';
import { MissingBuilderError } from '@storybook/core-events/server-errors';
import { storybookDevServer } from './dev-server';
import { outputStats } from './utils/output-stats';
import { outputStartupInformation } from './utils/output-startup-information';
Expand Down Expand Up @@ -89,7 +90,9 @@ export async function buildDevStandalone(

const { renderer, builder, disableTelemetry } = await presets.apply<CoreConfig>('core', {});

invariant(builder, 'No builder configured in core.builder');
if (!builder) {
throw new MissingBuilderError();
}

if (!options.disableTelemetry && !disableTelemetry) {
if (versionCheck.success && !versionCheck.cached) {
Expand Down
6 changes: 5 additions & 1 deletion code/lib/core-server/src/dev-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { CoreConfig, Options, StorybookConfig } from '@storybook/types';
import { logConfig } from '@storybook/core-common';

import { logger } from '@storybook/node-logger';
import { MissingBuilderError } from '@storybook/core-events/server-errors';
import { getMiddleware } from './utils/middleware';
import { getServerAddresses } from './utils/server-address';
import { getServer } from './utils/server-init';
Expand Down Expand Up @@ -67,7 +68,10 @@ export async function storybookDevServer(options: Options) {
server.listen({ port, host }, (error: Error) => (error ? reject(error) : resolve()));
});

invariant(core?.builder, 'no builder configured!');
if (!core?.builder) {
throw new MissingBuilderError();
}

const builderName = typeof core?.builder === 'string' ? core.builder : core?.builder?.name;

const [previewBuilder, managerBuilder] = await Promise.all([
Expand Down
8 changes: 6 additions & 2 deletions code/lib/core-server/src/utils/get-builders.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Builder, CoreConfig, Options } from '@storybook/types';
import { MissingBuilderError } from '@storybook/core-events/server-errors';
import { pathToFileURL } from 'node:url';
import invariant from 'tiny-invariant';

export async function getManagerBuilder(): Promise<Builder<unknown>> {
return import('@storybook/builder-manager');
Expand All @@ -20,7 +20,11 @@ export async function getPreviewBuilder(

export async function getBuilders({ presets, configDir }: Options): Promise<Builder<unknown>[]> {
const { builder } = await presets.apply<CoreConfig>('core', {});
invariant(builder, 'no builder configured!');

if (!builder) {
throw new MissingBuilderError();
}

const builderName = typeof builder === 'string' ? builder : builder.name;

return Promise.all([getPreviewBuilder(builderName, configDir), getManagerBuilder()]);
Expand Down

0 comments on commit 1c7e01f

Please sign in to comment.