Skip to content

Commit

Permalink
Merge pull request #24176 from storybookjs/yann/critical-preset-error
Browse files Browse the repository at this point in the history
Core: Throw an error when critical presets fail to load
  • Loading branch information
yannbf authored Sep 15, 2023
2 parents 896b2e7 + c05b719 commit 0b5dc9a
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 6 deletions.
6 changes: 6 additions & 0 deletions code/lib/core-common/src/presets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ describe('presets', () => {
await expect(testPresets()).resolves.toBeUndefined();
});

it('throws when preset can not be loaded and is critical', async () => {
const { getPresets } = jest.requireActual('./presets');

await expect(getPresets(['preset-foo'], { isCritical: true })).rejects.toThrow();
});

it('loads and applies presets when they are combined in another preset', async () => {
mockPreset('preset-foo', {
foo: (exec: string[]) => exec.concat('foo'),
Expand Down
26 changes: 20 additions & 6 deletions code/lib/core-common/src/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
Presets,
} from '@storybook/types';
import { join, parse } from 'path';
import { CriticalPresetLoadError } from '@storybook/core-events/server-errors';
import { loadCustomPresets } from './utils/load-custom-presets';
import { safeResolve, safeResolveFrom } from './utils/safeResolve';
import { interopRequireDefault } from './utils/interpret-require';
Expand Down Expand Up @@ -218,9 +219,10 @@ export async function loadPreset(
level: number,
storybookOptions: InterPresetOptions
): Promise<LoadedPreset[]> {
// @ts-expect-error (Converted from ts-ignore)
const presetName: string = input.name ? input.name : input;

try {
// @ts-expect-error (Converted from ts-ignore)
const name: string = input.name ? input.name : input;
// @ts-expect-error (Converted from ts-ignore)
const presetOptions = input.options ? input.options : {};

Expand Down Expand Up @@ -250,7 +252,7 @@ export async function loadPreset(
storybookOptions
)),
{
name,
name: presetName,
preset: rest,
options: presetOptions,
},
Expand All @@ -260,14 +262,21 @@ export async function loadPreset(
throw new Error(dedent`
${input} is not a valid preset
`);
} catch (e: any) {
} catch (error: any) {
if (storybookOptions?.isCritical) {
throw new CriticalPresetLoadError({
error,
presetName,
});
}

const warning =
level > 0
? ` Failed to load preset: ${JSON.stringify(input)} on level ${level}`
: ` Failed to load preset: ${JSON.stringify(input)}`;

logger.warn(warning);
logger.error(e);
logger.error(error);
return [];
}
}
Expand Down Expand Up @@ -345,7 +354,10 @@ function applyPresets(
}, presetResult);
}

type InterPresetOptions = Omit<CLIOptions & LoadOptions & BuilderOptions, 'frameworkPresets'>;
type InterPresetOptions = Omit<
CLIOptions & LoadOptions & BuilderOptions & { isCritical?: boolean },
'frameworkPresets'
>;

export async function getPresets(
presets: PresetConfig[],
Expand All @@ -365,6 +377,8 @@ export async function loadAllPresets(
BuilderOptions & {
corePresets: PresetConfig[];
overridePresets: PresetConfig[];
/** Whether preset failures should be critical or not */
isCritical?: boolean;
}
) {
const { corePresets = [], overridePresets = [], ...restOptions } = options;
Expand Down
27 changes: 27 additions & 0 deletions code/lib/core-events/src/errors/server-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,30 @@ export class AngularLegacyBuildOptionsError extends StorybookError {
`;
}
}

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

readonly code = 2;

constructor(
public data: {
error: Error;
presetName: string;
}
) {
super();
}

template() {
return dedent`
Storybook failed to load the following preset: ${this.data.presetName}.
Please check whether your setup is correct, the Storybook dependencies (and their peer dependencies) are installed correctly and there are no package version clashes.
If you believe this is a bug, please open an issue on Github.
${this.data.error.stack || this.data.error.message}
`;
}
}
1 change: 1 addition & 0 deletions code/lib/core-server/src/build-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export async function buildDevStandalone(
require.resolve('@storybook/core-server/dist/presets/common-override-preset'),
],
...options,
isCritical: true,
});

const { renderer, builder, disableTelemetry } = await presets.apply<CoreConfig>('core', {});
Expand Down
1 change: 1 addition & 0 deletions code/lib/core-server/src/build-static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption
overridePresets: [
require.resolve('@storybook/core-server/dist/presets/common-override-preset'),
],
isCritical: true,
...options,
});

Expand Down

0 comments on commit 0b5dc9a

Please sign in to comment.