Clean code up a little

This commit is contained in:
Tom Coleman 2021-08-30 14:59:17 +10:00
parent b2a7949fcc
commit 22db095cdc
4 changed files with 99 additions and 82 deletions

View File

@ -12,6 +12,7 @@ import {
LoaderFunction,
StoryFn,
sanitize,
storyNameFromExport,
} from '@storybook/csf';
import {
CSFFile,
@ -20,7 +21,6 @@ import {
Path,
StoriesList,
combineParameters,
NormalizedStoryAnnotations,
ModuleExports,
} from '@storybook/store';
@ -316,6 +316,43 @@ Read more here: https://github.com/storybookjs/storybook/blob/master/MIGRATION.m
return api;
};
// NOTE: we could potentially share some of this code with the stories.json generation
addStoriesFromExports(fileName: Path, fileExports: ModuleExports) {
const { default: defaultExport, __namedExportsOrder, ...namedExports } = fileExports;
const { title } = defaultExport || {};
if (!title) {
throw new Error(
`Unexpected default export without title: ${JSON.stringify(fileExports.default)}`
);
}
this.csfExports[fileName] = fileExports;
let exports = namedExports;
if (Array.isArray(__namedExportsOrder)) {
exports = {};
__namedExportsOrder.forEach((name) => {
if (namedExports[name]) {
exports[name] = namedExports[name];
}
});
}
Object.entries(exports).forEach(([key, storyExport]: [string, any]) => {
const actualName: string =
(typeof storyExport !== 'function' && storyExport.name) ||
storyExport.storyName ||
storyExport.story?.name ||
storyNameFromExport(key);
// eslint-disable-next-line no-underscore-dangle
const id = storyExport.parameters?.__id || toId(title, actualName);
this.storiesList.stories[id] = {
name: actualName,
title,
importPath: fileName,
};
});
}
// TODO
getStorybook: () => [];

View File

@ -0,0 +1,52 @@
import { logger } from '@storybook/client-logger';
import { ModuleExports } from '@storybook/store';
import { Loadable, RequireContext, LoaderFunction } from './types';
/**
* Executes a Loadable (function that returns exports or require context(s))
* and returns a map of filename => module exports
*
* @param loadable Loadable
* @returns Map<string, ModuleExports>
*/
export function executeLoadable(loadable: Loadable) {
let reqs = null;
// todo discuss / improve type check
if (Array.isArray(loadable)) {
reqs = loadable;
} else if ((loadable as RequireContext).keys) {
reqs = [loadable as RequireContext];
}
let exportsMap = new Map<string, ModuleExports>();
if (reqs) {
reqs.forEach((req) => {
req.keys().forEach((filename: string) => {
try {
const fileExports = req(filename) as ModuleExports;
exportsMap.set(
typeof req.resolve === 'function' ? req.resolve(filename) : filename,
fileExports
);
} catch (error) {
logger.warn(`Unexpected error while loading ${filename}: ${error}`);
}
});
});
} else {
const exported = (loadable as LoaderFunction)();
if (Array.isArray(exported) && exported.every((obj) => obj.default != null)) {
exportsMap = new Map(
exported.map((fileExports, index) => [`exports-map-${index}`, fileExports])
);
} else if (exported) {
logger.warn(
`Loader function passed to 'configure' should return void or an array of module exports that all contain a 'default' export. Received: ${JSON.stringify(
exported
)}`
);
}
}
return exportsMap;
}

View File

@ -141,6 +141,7 @@ describe('start', () => {
expect.objectContaining({
storyContext: expect.objectContaining({
parameters: expect.objectContaining({
framework: 'test',
param: 'global',
}),
}),

View File

@ -1,55 +1,13 @@
import { ClientApi } from '@storybook/client-api';
import { ClientApi, ModuleExports } from '@storybook/client-api';
import { WebGlobalAnnotations, WebPreview } from '@storybook/web-preview';
import { Framework, toId, storyNameFromExport } from '@storybook/csf';
import { logger } from '@storybook/client-logger';
import createChannel from '@storybook/channel-postmessage';
import { addons } from '@storybook/addons';
import Events from '@storybook/core-events';
import { Path, ModuleExports } from '@storybook/store';
import { Path } from '@storybook/store';
import { Loadable, RequireContext, LoaderFunction } from './types';
function runLoadable(loadable: Loadable) {
let reqs = null;
// todo discuss / improve type check
if (Array.isArray(loadable)) {
reqs = loadable;
} else if ((loadable as RequireContext).keys) {
reqs = [loadable as RequireContext];
}
let exportsMap = new Map<string, ModuleExports>();
if (reqs) {
reqs.forEach((req) => {
req.keys().forEach((filename: string) => {
try {
const fileExports = req(filename) as ModuleExports;
exportsMap.set(
typeof req.resolve === 'function' ? req.resolve(filename) : filename,
fileExports
);
} catch (error) {
logger.warn(`Unexpected error while loading ${filename}: ${error}`);
}
});
});
} else {
const exported = (loadable as LoaderFunction)();
if (Array.isArray(exported) && exported.every((obj) => obj.default != null)) {
exportsMap = new Map(
exported.map((fileExports, index) => [`exports-map-${index}`, fileExports])
);
} else if (exported) {
logger.warn(
`Loader function passed to 'configure' should return void or an array of module exports that all contain a 'default' export. Received: ${JSON.stringify(
exported
)}`
);
}
}
return exportsMap;
}
import { Loadable } from './types';
import { executeLoadable } from './executeLoadable';
export function start<TFramework extends Framework>(
render: WebGlobalAnnotations<TFramework>['renderToDOM'],
@ -67,49 +25,18 @@ export function start<TFramework extends Framework>(
raw: (): void => {},
clientApi,
// TODO -- add framework to globalAnnotations.parameters?
configure(framework: string, loadable: Loadable, m?: NodeModule) {
clientApi.addParameters({ framework });
const getGlobalAnnotations = () => {
// TODO
// clientApi.resetGlobalAnnotations();
const exportsMap = runLoadable(loadable);
const exportsMap = executeLoadable(loadable);
Array.from(exportsMap.entries())
.filter(([, fileExports]) => !!fileExports.default)
.forEach(([fileName, fileExports]) => {
const { default: defaultExport, __namedExportsOrder, ...namedExports } = fileExports;
const { title } = defaultExport || {};
if (!title) {
throw new Error(
`Unexpected default export without title: ${JSON.stringify(fileExports.default)}`
);
}
clientApi.csfExports[fileName] = fileExports;
let exports = namedExports;
if (Array.isArray(__namedExportsOrder)) {
exports = {};
__namedExportsOrder.forEach((name) => {
if (namedExports[name]) {
exports[name] = namedExports[name];
}
});
}
Object.entries(exports).forEach(([key, storyExport]: [string, any]) => {
const actualName: string =
(typeof storyExport !== 'function' && storyExport.name) ||
storyExport.storyName ||
storyExport.story?.name ||
storyNameFromExport(key);
// eslint-disable-next-line no-underscore-dangle
const id = storyExport.parameters?.__id || toId(title, actualName);
clientApi.storiesList.stories[id] = {
name: actualName,
title,
importPath: fileName,
};
});
clientApi.addStoriesFromExports(fileName, fileExports);
});
return {