diff --git a/code/lib/core-server/src/build-dev.ts b/code/lib/core-server/src/build-dev.ts index ef3d7e3cc3f8..7d1a223e1703 100644 --- a/code/lib/core-server/src/build-dev.ts +++ b/code/lib/core-server/src/build-dev.ts @@ -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'; @@ -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), @@ -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')); @@ -82,6 +84,7 @@ export async function buildDevStandalone( }); const { renderer, builder, disableTelemetry } = await presets.apply('core', {}); + invariant(builder, 'no builder configured!'); if (!options.disableTelemetry && !disableTelemetry) { if (versionCheck.success && !versionCheck.cached) { @@ -89,23 +92,26 @@ export async function buildDevStandalone( } } - 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, }); @@ -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; diff --git a/code/lib/core-server/src/build-static.ts b/code/lib/core-server/src/build-static.ts index 8bbfff506316..6682046662aa 100644 --- a/code/lib/core-server/src/build-static.ts +++ b/code/lib/core-server/src/build-static.ts @@ -91,13 +91,15 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption const [previewBuilder, managerBuilder] = await getBuilders({ ...options, presets }); const { renderer } = await presets.apply('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'), ], @@ -151,7 +153,8 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption ); effects.push(copy(coreServerPublicDir, options.outputDir)); - let initializedStoryIndexGenerator: Promise = Promise.resolve(undefined); + let initializedStoryIndexGenerator: Promise = + Promise.resolve(undefined); if ((features?.buildStoriesJson || features?.storyStoreV7) && !options.ignorePreview) { const workingDir = process.cwd(); const directories = { @@ -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) { diff --git a/code/lib/core-server/src/dev-server.ts b/code/lib/core-server/src/dev-server.ts index 6843c194e180..2eb1ea420cda 100644 --- a/code/lib/core-server/src/dev-server.ts +++ b/code/lib/core-server/src/dev-server.ts @@ -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'; @@ -34,16 +35,13 @@ 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 = getStoryIndexGenerator( - features, - options, - serverChannel - ).catch((err) => { - indexError = err; - return undefined; - }); + const initializedStoryIndexGenerator: Promise = + getStoryIndexGenerator(features ?? {}, options, serverChannel).catch((err) => { + indexError = err; + return undefined; + }); app.use(compression({ level: 1 })); @@ -51,7 +49,7 @@ export async function storybookDevServer(options: Options) { options.extendServer(server); } - app.use(getAccessControlMiddleware(core?.crossOriginIsolated)); + app.use(getAccessControlMiddleware(core?.crossOriginIsolated ?? false)); app.use(getCachingMiddleware()); getMiddleware(options.configDir)(router); @@ -59,6 +57,7 @@ export async function storybookDevServer(options: Options) { 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); @@ -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([ diff --git a/code/lib/core-server/src/presets/common-preset.ts b/code/lib/core-server/src/presets/common-preset.ts index 800f7ccaf0f7..76240e469f4e 100644 --- a/code/lib/core-server/src/presets/common-preset.ts +++ b/code/lib/core-server/src/presets/common-preset.ts @@ -44,7 +44,7 @@ export const staticDirs: PresetPropertyFn<'staticDirs'> = async (values = []) => ]; export const favicon = async ( - value: string, + value: string | undefined, options: Pick ) => { if (value) { @@ -257,8 +257,13 @@ type WhatsNewResponse = { excerpt: string; }; +type OptionsWithRequiredCache = Exclude & Required>; + // 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) => { @@ -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', @@ -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, }); @@ -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); @@ -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, diff --git a/code/lib/core-server/src/standalone.ts b/code/lib/core-server/src/standalone.ts index 392f9027a000..bef85d55023d 100644 --- a/code/lib/core-server/src/standalone.ts +++ b/code/lib/core-server/src/standalone.ts @@ -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, diff --git a/code/lib/core-server/src/utils/StoryIndexGenerator.ts b/code/lib/core-server/src/utils/StoryIndexGenerator.ts index 221fa7665189..cceef09459fc 100644 --- a/code/lib/core-server/src/utils/StoryIndexGenerator.ts +++ b/code/lib/core-server/src/utils/StoryIndexGenerator.ts @@ -94,10 +94,10 @@ export class StoryIndexGenerator { // Cache the last value of `getStoryIndex`. We invalidate (by unsetting) when: // - any file changes, including deletions // - the preview changes [not yet implemented] - private lastIndex?: StoryIndex; + private lastIndex?: StoryIndex | null; // Same as the above but for the error case - private lastError?: Error; + private lastError?: Error | null; constructor( public readonly specifiers: NormalizedStoriesSpecifier[], @@ -171,6 +171,10 @@ export class StoryIndexGenerator { await Promise.all( this.specifiers.map(async (specifier) => { const entry = this.specifierToCache.get(specifier); + if (!entry) + throw new Error( + `specifier ${specifier} does not have a matching cache entry in specifierToCache` + ); return Promise.all( Object.keys(entry).map(async (absolutePath) => { if (entry[absolutePath] && !overwrite) return; @@ -185,7 +189,11 @@ export class StoryIndexGenerator { entry[absolutePath] = { type: 'error', - err: new IndexingError(err.message, [relativePath], err.stack), + err: new IndexingError( + err instanceof Error ? err.message : String(err), + [relativePath], + err instanceof Error ? err.stack : undefined + ), }; } }) @@ -213,6 +221,10 @@ export class StoryIndexGenerator { return this.specifiers.flatMap((specifier) => { const cache = this.specifierToCache.get(specifier); + if (!cache) + throw new Error( + `specifier ${specifier} does not have a matching cache entry in specifierToCache` + ); return Object.values(cache).flatMap((entry): (IndexEntry | ErrorEntry)[] => { if (!entry) return []; if (entry.type === 'docs') return [entry]; @@ -245,7 +257,12 @@ export class StoryIndexGenerator { const entries = [] as IndexEntry[]; const importPath = slash(normalizeStoryPath(relativePath)); const makeTitle = (userTitle?: string) => { - return userOrAutoTitleFromSpecifier(importPath, specifier, userTitle); + const title = userOrAutoTitleFromSpecifier(importPath, specifier, userTitle); + if (!title) + throw new Error( + "makeTitle created an undefined title. This happens when a specifier's doesn't have any matches in its fileName" + ); + return title; }; const storyIndexer = this.options.storyIndexers.find((indexer) => @@ -255,11 +272,11 @@ export class StoryIndexGenerator { throw new Error(`No matching story indexer found for ${absolutePath}`); } const csf = await storyIndexer.indexer(absolutePath, { makeTitle }); - const componentTags = csf.meta.tags || []; csf.stories.forEach(({ id, name, tags: storyTags, parameters }) => { if (!parameters?.docsOnly) { const tags = [...(storyTags || componentTags), 'story']; + invariant(csf.meta.title); entries.push({ id, title: csf.meta.title, name, importPath, tags, type: 'story' }); } }); @@ -273,6 +290,8 @@ export class StoryIndexGenerator { // b) we have docs page enabled for this file if (componentTags.includes(STORIES_MDX_TAG) || autodocsOptedIn) { const name = this.options.docs.defaultName; + if (!name) throw new Error('expected a defaultName property in options.docs'); + invariant(csf.meta.title); const id = toId(csf.meta.title, name); entries.unshift({ id, @@ -332,7 +351,7 @@ export class StoryIndexGenerator { // Also, if `result.of` is set, it means that we're using the `` syntax, // so find the `title` defined the file that `meta` points to. - let csfEntry: StoryIndexEntry; + let csfEntry: StoryIndexEntry | undefined; if (result.of) { const absoluteOf = makeAbsolute(result.of, normalizedPath, this.options.workingDir); dependencies.forEach((dep) => { @@ -369,7 +388,13 @@ export class StoryIndexGenerator { const title = csfEntry?.title || userOrAutoTitleFromSpecifier(importPath, specifier, result.title); + if (!title) + throw new Error( + "makeTitle created an undefined title. This happens when a specifier's doesn't have any matches in its fileName" + ); const { defaultName } = this.options.docs; + if (!defaultName) throw new Error('expected a defaultName property in options.docs'); + const name = result.name || (csfEntry ? autoName(importPath, csfEntry.importPath, defaultName) : defaultName); @@ -386,7 +411,7 @@ export class StoryIndexGenerator { }; return docsEntry; } catch (err) { - if (err.source?.match(/mdast-util-mdx-jsx/g)) { + if (err && (err as { source: any }).source?.match(/mdast-util-mdx-jsx/g)) { logger.warn( `💡 This seems to be an MDX2 syntax error. Please refer to the MDX section in the following resource for assistance on how to fix this: ${chalk.yellow( 'https://storybook.js.org/migration-guides/7.0' @@ -512,7 +537,7 @@ export class StoryIndexGenerator { indexEntries[entry.id] = entry; } } catch (err) { - duplicateErrors.push(err); + if (err instanceof IndexingError) duplicateErrors.push(err); } }); if (duplicateErrors.length) throw new MultipleIndexingError(duplicateErrors); @@ -552,9 +577,9 @@ export class StoryIndexGenerator { return this.lastIndex; } catch (err) { - this.lastError = err; - logger.warn(`🚨 ${this.lastError.toString()}`); + this.lastError = err == null || err instanceof Error ? err : undefined; invariant(this.lastError); + logger.warn(`🚨 ${this.lastError.toString()}`); throw this.lastError; } } @@ -562,7 +587,7 @@ export class StoryIndexGenerator { invalidate(specifier: NormalizedStoriesSpecifier, importPath: Path, removed: boolean) { const absolutePath = slash(path.resolve(this.options.workingDir, importPath)); const cache = this.specifierToCache.get(specifier); - + if (!cache) throw new Error(`no `); const cacheEntry = cache[absolutePath]; if (cacheEntry && cacheEntry.type === 'stories') { const { dependents } = cacheEntry; diff --git a/code/lib/core-server/src/utils/copy-all-static-files.ts b/code/lib/core-server/src/utils/copy-all-static-files.ts index 2e6475acc8c2..44f7bf12d31f 100644 --- a/code/lib/core-server/src/utils/copy-all-static-files.ts +++ b/code/lib/core-server/src/utils/copy-all-static-files.ts @@ -22,7 +22,7 @@ export async function copyAllStaticFiles(staticDirs: any[] | undefined, outputDi filter: (_, dest) => !skipPaths.includes(dest), }); } catch (e) { - logger.error(e.message); + if (e instanceof Error) logger.error(e.message); process.exit(-1); } }) @@ -37,7 +37,7 @@ export async function copyAllStaticFilesRelativeToMain( ) { const workingDir = process.cwd(); - return staticDirs.reduce(async (acc, dir) => { + return staticDirs?.reduce(async (acc, dir) => { await acc; const staticDirAndTarget = typeof dir === 'string' ? dir : `${dir.from}:${dir.to}`; diff --git a/code/lib/core-server/src/utils/doTelemetry.ts b/code/lib/core-server/src/utils/doTelemetry.ts index 1a5b62d6ce92..ecb494fc45f5 100644 --- a/code/lib/core-server/src/utils/doTelemetry.ts +++ b/code/lib/core-server/src/utils/doTelemetry.ts @@ -1,3 +1,4 @@ +import invariant from 'tiny-invariant'; import type { CoreConfig, Options, StoryIndex } from '@storybook/types'; import { telemetry, getPrecedingUpgrade } from '@storybook/telemetry'; import { useStorybookMetadata } from './metadata'; @@ -9,17 +10,18 @@ import { sendTelemetryError } from '../withTelemetry'; export async function doTelemetry( core: CoreConfig, - initializedStoryIndexGenerator: Promise, + initializedStoryIndexGenerator: Promise, options: Options ) { if (!core?.disableTelemetry) { initializedStoryIndexGenerator.then(async (generator) => { - let storyIndex: StoryIndex; + let storyIndex: StoryIndex | undefined; try { storyIndex = await generator?.getIndex(); } catch (err) { // If we fail to get the index, treat it as a recoverable error, but send it up to telemetry // as if we crashed. In the future we will revisit this to send a distinct error + if (!(err instanceof Error)) throw new Error('encountered a non-recoverable error'); sendTelemetryError(err, 'dev', { cliOptions: options, presetOptions: { ...options, corePresets: [], overridePresets: [] }, @@ -27,12 +29,16 @@ export async function doTelemetry( return; } const { versionCheck, versionUpdates } = options; + invariant( + !versionUpdates || (versionUpdates && versionCheck), + 'versionCheck should be defined when versionUpdates is true' + ); const payload = { precedingUpgrade: await getPrecedingUpgrade(), }; if (storyIndex) { Object.assign(payload, { - versionStatus: versionUpdates ? versionStatus(versionCheck) : 'disabled', + versionStatus: versionUpdates && versionCheck ? versionStatus(versionCheck) : 'disabled', storyIndex: summarizeIndex(storyIndex), }); } diff --git a/code/lib/core-server/src/utils/get-builders.ts b/code/lib/core-server/src/utils/get-builders.ts index 1b43381c02cc..7ed83e293613 100644 --- a/code/lib/core-server/src/utils/get-builders.ts +++ b/code/lib/core-server/src/utils/get-builders.ts @@ -1,5 +1,6 @@ import type { Builder, CoreConfig, Options } from '@storybook/types'; import { pathToFileURL } from 'node:url'; +import invariant from 'tiny-invariant'; export async function getManagerBuilder(): Promise> { return import('@storybook/builder-manager'); @@ -24,7 +25,8 @@ export async function getPreviewBuilder( export async function getBuilders({ presets, configDir }: Options): Promise[]> { const { builder } = await presets.apply('core', {}); - const builderName = typeof builder === 'string' ? builder : builder?.name; + invariant(builder, 'no builder configured!'); + const builderName = typeof builder === 'string' ? builder : builder.name; return Promise.all([getPreviewBuilder(builderName, configDir), getManagerBuilder()]); } diff --git a/code/lib/core-server/src/utils/get-server-channel.ts b/code/lib/core-server/src/utils/get-server-channel.ts index f43f0dcf5b0e..c44c51b36307 100644 --- a/code/lib/core-server/src/utils/get-server-channel.ts +++ b/code/lib/core-server/src/utils/get-server-channel.ts @@ -3,7 +3,7 @@ import { isJSON, parse, stringify } from 'telejson'; import type { ChannelHandler } from '@storybook/channels'; import { Channel } from '@storybook/channels'; -type Server = ConstructorParameters[0]['server']; +type Server = NonNullable[0]>['server']>; /** * This class represents a channel transport that allows for a one-to-many relationship between the server and clients. @@ -28,7 +28,7 @@ export class ServerChannelTransport { wss.on('message', (raw) => { const data = raw.toString(); const event = typeof data === 'string' && isJSON(data) ? parse(data) : data; - this.handler(event); + this.handler?.(event); }); }); } diff --git a/code/lib/core-server/src/utils/getStoryIndexGenerator.ts b/code/lib/core-server/src/utils/getStoryIndexGenerator.ts index c1f75831806c..f7de41266822 100644 --- a/code/lib/core-server/src/utils/getStoryIndexGenerator.ts +++ b/code/lib/core-server/src/utils/getStoryIndexGenerator.ts @@ -15,7 +15,6 @@ export async function getStoryIndexGenerator( options: Options, serverChannel: ServerChannel ) { - let initializedStoryIndexGenerator: Promise = Promise.resolve(undefined); if (features?.buildStoriesJson || features?.storyStoreV7) { const workingDir = process.cwd(); const directories = { @@ -33,10 +32,10 @@ export async function getStoryIndexGenerator( docs: await docsOptions, workingDir, storiesV2Compatibility: !features?.storyStoreV7, - storyStoreV7: features?.storyStoreV7, + storyStoreV7: features.storyStoreV7 ?? false, }); - initializedStoryIndexGenerator = generator.initialize().then(() => generator); + const initializedStoryIndexGenerator = generator.initialize().then(() => generator); useStoriesJson({ router, @@ -45,6 +44,8 @@ export async function getStoryIndexGenerator( serverChannel, workingDir, }); + + return initializedStoryIndexGenerator; } - return initializedStoryIndexGenerator; + return Promise.resolve(undefined); } diff --git a/code/lib/core-server/src/utils/server-address.ts b/code/lib/core-server/src/utils/server-address.ts index 3332fa53b0d3..5e4ae1b18b72 100644 --- a/code/lib/core-server/src/utils/server-address.ts +++ b/code/lib/core-server/src/utils/server-address.ts @@ -5,7 +5,7 @@ import detectFreePort from 'detect-port'; export function getServerAddresses( port: number, - host: string, + host: string | undefined, proto: string, initialPath?: string ) { @@ -26,7 +26,7 @@ export function getServerAddresses( }; } -export const getServerPort = (port: number) => +export const getServerPort = (port?: number) => detectFreePort(port).catch((error) => { logger.error(error); process.exit(-1); diff --git a/code/lib/core-server/src/utils/server-statics.ts b/code/lib/core-server/src/utils/server-statics.ts index 96386df1d05a..a5ccc59fbd21 100644 --- a/code/lib/core-server/src/utils/server-statics.ts +++ b/code/lib/core-server/src/utils/server-statics.ts @@ -26,7 +26,7 @@ export async function useStatics(router: any, options: Options) { } const statics = [ - ...staticDirs.map((dir) => (typeof dir === 'string' ? dir : `${dir.from}:${dir.to}`)), + ...(staticDirs ?? []).map((dir) => (typeof dir === 'string' ? dir : `${dir.from}:${dir.to}`)), ...(options.staticDir || []), ]; @@ -52,7 +52,7 @@ export async function useStatics(router: any, options: Options) { router.use(targetEndpoint, express.static(staticPath, { index: false })); } catch (e) { - logger.warn(e.message); + if (e instanceof Error) logger.warn(e.message); } }) ); diff --git a/code/lib/core-server/src/utils/stories-json.ts b/code/lib/core-server/src/utils/stories-json.ts index 6ab44e1dcf5b..7070245a6043 100644 --- a/code/lib/core-server/src/utils/stories-json.ts +++ b/code/lib/core-server/src/utils/stories-json.ts @@ -51,7 +51,7 @@ export function useStoriesJson({ res.send(JSON.stringify(index)); } catch (err) { res.status(500); - res.send(err.toString()); + res.send(err instanceof Error ? err.toString() : String(err)); } }); @@ -63,7 +63,7 @@ export function useStoriesJson({ res.send(JSON.stringify(index)); } catch (err) { res.status(500); - res.send(err.toString()); + res.send(err instanceof Error ? err.toString() : String(err)); } }); } diff --git a/code/lib/core-server/src/withTelemetry.ts b/code/lib/core-server/src/withTelemetry.ts index 82bd7488dd21..1888f733cd04 100644 --- a/code/lib/core-server/src/withTelemetry.ts +++ b/code/lib/core-server/src/withTelemetry.ts @@ -42,11 +42,7 @@ async function getErrorLevel({ if (!presetOptions) return 'full'; // should we load the preset? - const presets = await loadAllPresets({ - corePresets: [require.resolve('@storybook/core-server/dist/presets/common-preset')], - overridePresets: [], - ...presetOptions, - }); + const presets = await loadAllPresets(presetOptions); // If the user has chosen to enable/disable crash reports in main.js // or disabled telemetry, we can return that @@ -108,7 +104,7 @@ export async function withTelemetry( eventType: EventType, options: TelemetryOptions, run: () => Promise -): Promise { +): Promise { let canceled = false; async function cancelTelemetry() { @@ -136,8 +132,8 @@ export async function withTelemetry( } const { printError = logger.error } = options; - printError(error); - await sendTelemetryError(error, eventType, options); + printError(error instanceof Error ? error.message : String(error)); + if (error instanceof Error) await sendTelemetryError(error, eventType, options); throw error; } finally { diff --git a/code/lib/core-server/tsconfig.json b/code/lib/core-server/tsconfig.json index a6f65038a17b..1dc5a72190bd 100644 --- a/code/lib/core-server/tsconfig.json +++ b/code/lib/core-server/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "skipLibCheck": true, - "strict": false + "strict": true }, "include": ["src/**/*"] }