Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: Migrate @storybook/core-server to strict TypeScript #23182

Merged
merged 11 commits into from
Jul 25, 2023
19 changes: 12 additions & 7 deletions code/lib/core-server/src/build-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
validateFrameworkName,
} from '@storybook/core-common';
import prompts from 'prompts';
import invariant from 'tiny-invariant';
import { global } from '@storybook/global';
import { telemetry } from '@storybook/telemetry';

Expand All @@ -31,7 +32,7 @@ export async function buildDevStandalone(
): Promise<{ port: number; address: string; networkAddress: string }> {
const { packageJson, versionUpdates } = options;
const { version } = packageJson;

invariant(version !== undefined, 'Expected package.json version to be defined.');
// updateInfo are cached, so this is typically pretty fast
const [port, versionCheck] = await Promise.all([
getServerPort(options.port),
Expand Down Expand Up @@ -63,9 +64,10 @@ export async function buildDevStandalone(

const config = await loadMainConfig(options);
const { framework } = config;
invariant(framework, 'framework is required in Storybook v7');
const corePresets = [];

const frameworkName = typeof framework === 'string' ? framework : framework?.name;
const frameworkName = typeof framework === 'string' ? framework : framework.name;
validateFrameworkName(frameworkName);

corePresets.push(join(frameworkName, 'preset'));
Expand All @@ -82,30 +84,34 @@ export async function buildDevStandalone(
});

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

if (!options.disableTelemetry && !disableTelemetry) {
if (versionCheck.success && !versionCheck.cached) {
telemetry('version-update');
}
}

const builderName = typeof builder === 'string' ? builder : builder?.name;
const builderName = typeof builder === 'string' ? builder : builder.name;
const [previewBuilder, managerBuilder] = await Promise.all([
getPreviewBuilder(builderName, options.configDir),
getManagerBuilder(),
]);

const resolvedRenderer = renderer
? resolveAddonName(options.configDir, renderer, options)
: undefined;
// Load second pass: all presets are applied in order
presets = await loadAllPresets({
corePresets: [
require.resolve('@storybook/core-server/dist/presets/common-preset'),
...(managerBuilder.corePresets || []),
...(previewBuilder.corePresets || []),
...(renderer ? [resolveAddonName(options.configDir, renderer, options)] : []),
...(resolvedRenderer ? [resolvedRenderer] : []),
...corePresets,
require.resolve('@storybook/core-server/dist/presets/babel-cache-preset'),
],
overridePresets: previewBuilder.overridePresets,
overridePresets: previewBuilder.overridePresets ?? [],
...options,
});

Expand All @@ -123,8 +129,7 @@ export async function buildDevStandalone(
);

const previewTotalTime = previewResult && previewResult.totalTime;
const managerTotalTime = managerResult && managerResult.totalTime;

const managerTotalTime = managerResult ? managerResult.totalTime : undefined;
const previewStats = previewResult && previewResult.stats;
const managerStats = managerResult && managerResult.stats;

Expand Down
19 changes: 13 additions & 6 deletions code/lib/core-server/src/build-static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,15 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption

const [previewBuilder, managerBuilder] = await getBuilders({ ...options, presets });
const { renderer } = await presets.apply<CoreConfig>('core', {});

const resolvedRenderer = renderer
? resolveAddonName(options.configDir, renderer, options)
: undefined;
presets = await loadAllPresets({
corePresets: [
require.resolve('@storybook/core-server/dist/presets/common-preset'),
...(managerBuilder.corePresets || []),
...(previewBuilder.corePresets || []),
...(renderer ? [resolveAddonName(options.configDir, renderer, options)] : []),
...(resolvedRenderer ? [resolvedRenderer] : []),
...corePresets,
require.resolve('@storybook/core-server/dist/presets/babel-cache-preset'),
],
Expand Down Expand Up @@ -151,7 +153,8 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption
);
effects.push(copy(coreServerPublicDir, options.outputDir));

let initializedStoryIndexGenerator: Promise<StoryIndexGenerator> = Promise.resolve(undefined);
let initializedStoryIndexGenerator: Promise<StoryIndexGenerator | undefined> =
Promise.resolve(undefined);
if ((features?.buildStoriesJson || features?.storyStoreV7) && !options.ignorePreview) {
const workingDir = process.cwd();
const directories = {
Expand All @@ -167,17 +170,21 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption
storyStoreV7: !!features?.storyStoreV7,
});

initializedStoryIndexGenerator = generator.initialize().then(() => generator);
const initializedStoryIndexGeneratorPromise = generator.initialize().then(() => generator);
effects.push(
extractStoriesJson(
join(options.outputDir, 'stories.json'),
initializedStoryIndexGenerator,
initializedStoryIndexGeneratorPromise,
convertToIndexV3
)
);
effects.push(
extractStoriesJson(join(options.outputDir, 'index.json'), initializedStoryIndexGenerator)
extractStoriesJson(
join(options.outputDir, 'index.json'),
initializedStoryIndexGeneratorPromise
)
);
initializedStoryIndexGenerator = initializedStoryIndexGeneratorPromise;
}

if (!core?.disableProjectJson) {
Expand Down
20 changes: 10 additions & 10 deletions code/lib/core-server/src/dev-server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import express from 'express';
import compression from 'compression';
import invariant from 'tiny-invariant';

import type { CoreConfig, Options, StorybookConfig } from '@storybook/types';

Expand Down Expand Up @@ -34,31 +35,29 @@ export async function storybookDevServer(options: Options) {
getServerChannel(server)
);

let indexError: Error;
let indexError: Error | undefined;
// try get index generator, if failed, send telemetry without storyCount, then rethrow the error
const initializedStoryIndexGenerator: Promise<StoryIndexGenerator> = getStoryIndexGenerator(
features,
options,
serverChannel
).catch((err) => {
indexError = err;
return undefined;
});
const initializedStoryIndexGenerator: Promise<StoryIndexGenerator | undefined> =
getStoryIndexGenerator(features ?? {}, options, serverChannel).catch((err) => {
indexError = err;
return undefined;
});

app.use(compression({ level: 1 }));

if (typeof options.extendServer === 'function') {
options.extendServer(server);
}

app.use(getAccessControlMiddleware(core?.crossOriginIsolated));
app.use(getAccessControlMiddleware(core?.crossOriginIsolated ?? false));
app.use(getCachingMiddleware());

getMiddleware(options.configDir)(router);

app.use(router);

const { port, host, initialPath } = options;
invariant(port, 'expected options to have a port');
const proto = options.https ? 'https' : 'http';
const { address, networkAddress } = getServerAddresses(port, host, proto, initialPath);

Expand All @@ -67,6 +66,7 @@ export async function storybookDevServer(options: Options) {
server.listen({ port, host }, (error: Error) => (error ? reject(error) : resolve()));
});

invariant(core?.builder, 'no builder configured!');
const builderName = typeof core?.builder === 'string' ? core.builder : core?.builder?.name;

const [previewBuilder, managerBuilder] = await Promise.all([
Expand Down
23 changes: 17 additions & 6 deletions code/lib/core-server/src/presets/common-preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const staticDirs: PresetPropertyFn<'staticDirs'> = async (values = []) =>
];

export const favicon = async (
value: string,
value: string | undefined,
options: Pick<Options, 'presets' | 'configDir' | 'staticDir'>
) => {
if (value) {
Expand Down Expand Up @@ -257,8 +257,13 @@ type WhatsNewResponse = {
excerpt: string;
};

type OptionsWithRequiredCache = Exclude<Options, 'cache'> & Required<Pick<Options, 'cache'>>;

// eslint-disable-next-line @typescript-eslint/naming-convention
export const experimental_serverChannel = async (channel: Channel, options: Options) => {
export const experimental_serverChannel = async (
channel: Channel,
options: OptionsWithRequiredCache
) => {
const coreOptions = await options.presets.apply('core');

channel.on(SET_WHATS_NEW_CACHE, async (data: WhatsNewCache) => {
Expand All @@ -277,7 +282,10 @@ export const experimental_serverChannel = async (channel: Channel, options: Opti
throw response;
})) as WhatsNewResponse;

const main = await readConfig(findConfigFile('main', options.configDir));
const configFileName = findConfigFile('main', options.configDir);
if (!configFileName)
throw new Error(`unable to find storybook main file in ${options.configDir}`);
const main = await readConfig(configFileName);
const disableWhatsNewNotifications = main.getFieldValue([
'core',
'disableWhatsNewNotifications',
Expand All @@ -293,7 +301,7 @@ export const experimental_serverChannel = async (channel: Channel, options: Opti
} satisfies WhatsNewData;
channel.emit(RESULT_WHATS_NEW_DATA, { data });
} catch (e) {
logger.verbose(e);
logger.verbose(e instanceof Error ? e.message : String(e));
channel.emit(RESULT_WHATS_NEW_DATA, {
data: { status: 'ERROR' } satisfies WhatsNewData,
});
Expand All @@ -305,7 +313,10 @@ export const experimental_serverChannel = async (channel: Channel, options: Opti
async ({ disableWhatsNewNotifications }: { disableWhatsNewNotifications: boolean }) => {
const isTelemetryEnabled = coreOptions.disableTelemetry !== true;
try {
const main = await readConfig(findConfigFile('main', options.configDir));
const configFileName = findConfigFile('main', options.configDir);
if (!configFileName)
throw new Error(`unable to find storybook main file in ${options.configDir}`);
const main = await readConfig(configFileName);
main.setFieldValue(['core', 'disableWhatsNewNotifications'], disableWhatsNewNotifications);
await writeConfig(main);

Expand All @@ -314,7 +325,7 @@ export const experimental_serverChannel = async (channel: Channel, options: Opti
}
} catch (error) {
if (isTelemetryEnabled) {
await sendTelemetryError(error, 'core-config', {
await sendTelemetryError(error as Error, 'core-config', {
cliOptions: options,
presetOptions: { ...options, corePresets: [], overridePresets: [] },
skipPrompt: true,
Expand Down
2 changes: 1 addition & 1 deletion code/lib/core-server/src/standalone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { buildDevStandalone } from './build-dev';

async function build(options: any = {}, frameworkOptions: any = {}) {
const { mode = 'dev' } = options;
const { packageJson } = readUpSync({ cwd: __dirname });
const packageJson = readUpSync({ cwd: __dirname })?.packageJson;

const commonOptions = {
...options,
Expand Down
Loading