Skip to content

Commit

Permalink
Merge pull request #17381 from storybookjs/refactor/csf-logic-in-store
Browse files Browse the repository at this point in the history
Core: Move CSF-related logic to its own folder
  • Loading branch information
shilman committed Feb 4, 2022
2 parents 10657ba + 49b9bea commit 758e4ba
Show file tree
Hide file tree
Showing 16 changed files with 95 additions and 71 deletions.
6 changes: 2 additions & 4 deletions lib/store/src/GlobalsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import dedent from 'ts-dedent';
import { Globals, GlobalTypes } from '@storybook/csf';

import { deepDiff, DEEPLY_EQUAL } from './args';
import { getValuesFromArgTypes } from './csf/getValuesFromArgTypes';

const setUndeclaredWarning = deprecate(
() => {},
Expand All @@ -24,10 +25,7 @@ export class GlobalsStore {

this.allowedGlobalNames = new Set([...Object.keys(globals), ...Object.keys(globalTypes)]);

const defaultGlobals = Object.entries(globalTypes).reduce((acc, [key, { defaultValue }]) => {
if (defaultValue) acc[key] = defaultValue;
return acc;
}, {} as Globals);
const defaultGlobals: Globals = getValuesFromArgTypes(globalTypes);
this.initialGlobals = { ...defaultGlobals, ...globals };

this.globals = this.initialGlobals;
Expand Down
18 changes: 10 additions & 8 deletions lib/store/src/StoryStore.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { AnyFramework, ProjectAnnotations } from '@storybook/csf';
import global from 'global';

import { prepareStory } from './prepareStory';
import { processCSFFile } from './processCSFFile';
import { prepareStory, processCSFFile } from './csf';
import { StoryStore } from './StoryStore';
import { StoryIndex } from './types';
import { HooksContext } from './hooks';

// Spy on prepareStory/processCSFFile
jest.mock('./prepareStory', () => ({
prepareStory: jest.fn(jest.requireActual('./prepareStory').prepareStory),
}));
jest.mock('./processCSFFile', () => ({
processCSFFile: jest.fn(jest.requireActual('./processCSFFile').processCSFFile),
}));
jest.mock('./csf', () => {
const actualModule = jest.requireActual('./csf');

return {
...actualModule,
prepareStory: jest.fn(actualModule.prepareStory),
processCSFFile: jest.fn(actualModule.processCSFFile),
};
});

jest.mock('global', () => ({
...(jest.requireActual('global') as any),
Expand Down
28 changes: 1 addition & 27 deletions lib/store/src/StoryStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import { SynchronousPromise } from 'synchronous-promise';
import { StoryIndexStore } from './StoryIndexStore';
import { ArgsStore } from './ArgsStore';
import { GlobalsStore } from './GlobalsStore';
import { processCSFFile } from './processCSFFile';
import { prepareStory } from './prepareStory';
import { processCSFFile, prepareStory, normalizeProjectAnnotations } from './csf';
import {
CSFFile,
ModuleImportFn,
Expand All @@ -32,36 +31,11 @@ import {
V2CompatIndexEntry,
} from './types';
import { HooksContext } from './hooks';
import { normalizeInputTypes } from './normalizeInputTypes';
import { inferArgTypes } from './inferArgTypes';
import { inferControls } from './inferControls';

// TODO -- what are reasonable values for these?
const CSF_CACHE_SIZE = 1000;
const STORY_CACHE_SIZE = 10000;

function normalizeProjectAnnotations<TFramework extends AnyFramework>({
argTypes,
globalTypes,
argTypesEnhancers,
...annotations
}: ProjectAnnotations<TFramework>): NormalizedProjectAnnotations<TFramework> {
return {
...(argTypes && { argTypes: normalizeInputTypes(argTypes) }),
...(globalTypes && { globalTypes: normalizeInputTypes(globalTypes) }),
argTypesEnhancers: [
...(argTypesEnhancers || []),
inferArgTypes,
// inferControls technically should only run if the user is using the controls addon,
// and so should be added by a preset there. However, as it seems some code relies on controls
// annotations (in particular the angular implementation's `cleanArgsDecorator`), for backwards
// compatibility reasons, we will leave this in the store until 7.0
inferControls,
],
...annotations,
};
}

export class StoryStore<TFramework extends AnyFramework> {
storyIndex: StoryIndexStore;

Expand Down
9 changes: 9 additions & 0 deletions lib/store/src/csf/getValuesFromArgTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { ArgTypes } from '@storybook/csf';

export const getValuesFromArgTypes = (argTypes: ArgTypes = {}) =>
Object.entries(argTypes).reduce((acc, [arg, { defaultValue }]) => {
if (typeof defaultValue !== 'undefined') {
acc[arg] = defaultValue;
}
return acc;
}, {} as ArgTypes);
7 changes: 7 additions & 0 deletions lib/store/src/csf/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export * from './normalizeInputTypes';
export * from './normalizeStory';
export * from './processCSFFile';
export * from './prepareStory';
export * from './normalizeComponentAnnotations';
export * from './normalizeProjectAnnotations';
export * from './getValuesFromArgTypes';
22 changes: 22 additions & 0 deletions lib/store/src/csf/normalizeComponentAnnotations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { sanitize, AnyFramework } from '@storybook/csf';

import { ModuleExports, NormalizedComponentAnnotations } from '../types';
import { normalizeInputTypes } from './normalizeInputTypes';

export function normalizeComponentAnnotations<TFramework extends AnyFramework>(
defaultExport: ModuleExports['default'],
title: string = defaultExport.title,
importPath?: string
): NormalizedComponentAnnotations<TFramework> {
const { id, argTypes } = defaultExport;
return {
id: sanitize(id || title),
...defaultExport,
title,
...(argTypes && { argTypes: normalizeInputTypes(argTypes) }),
parameters: {
fileName: importPath,
...defaultExport.parameters,
},
};
}
File renamed without changes.
File renamed without changes.
28 changes: 28 additions & 0 deletions lib/store/src/csf/normalizeProjectAnnotations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { AnyFramework, ProjectAnnotations } from '@storybook/csf';

import { inferArgTypes } from '../inferArgTypes';
import { inferControls } from '../inferControls';
import { NormalizedProjectAnnotations } from '../types';
import { normalizeInputTypes } from './normalizeInputTypes';

export function normalizeProjectAnnotations<TFramework extends AnyFramework>({
argTypes,
globalTypes,
argTypesEnhancers,
...annotations
}: ProjectAnnotations<TFramework>): NormalizedProjectAnnotations<TFramework> {
return {
...(argTypes && { argTypes: normalizeInputTypes(argTypes) }),
...(globalTypes && { globalTypes: normalizeInputTypes(globalTypes) }),
argTypesEnhancers: [
...(argTypesEnhancers || []),
inferArgTypes,
// inferControls technically should only run if the user is using the controls addon,
// and so should be added by a preset there. However, as it seems some code relies on controls
// annotations (in particular the angular implementation's `cleanArgsDecorator`), for backwards
// compatibility reasons, we will leave this in the store until 7.0
inferControls,
],
...annotations,
};
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import dedent from 'ts-dedent';
import { logger } from '@storybook/client-logger';
import deprecate from 'util-deprecate';
import { NormalizedStoryAnnotations } from './types';
import { NormalizedStoryAnnotations } from '../types';
import { normalizeInputTypes } from './normalizeInputTypes';

const deprecatedStoryAnnotation = dedent`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
SBScalarType,
StoryContext,
} from '@storybook/csf';
import { NO_TARGET_NAME } from './args';
import { NO_TARGET_NAME } from '../args';
import { prepareStory } from './prepareStory';

jest.mock('global', () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ import {
Story,
NormalizedStoryAnnotations,
NormalizedProjectAnnotations,
} from './types';
import { combineParameters } from './parameters';
import { applyHooks } from './hooks';
import { defaultDecorateStory } from './decorators';
import { groupArgsByTarget, NO_TARGET_NAME } from './args';
} from '../types';
import { combineParameters } from '../parameters';
import { applyHooks } from '../hooks';
import { defaultDecorateStory } from '../decorators';
import { groupArgsByTarget, NO_TARGET_NAME } from '../args';
import { getValuesFromArgTypes } from './getValuesFromArgTypes';

const argTypeDefaultValueWarning = deprecate(
() => {},
Expand Down Expand Up @@ -121,15 +122,8 @@ export function prepareStory<TFramework extends AnyFramework>(

// Add argTypes[X].defaultValue to initial args (note this deprecated)
// We need to do this *after* the argTypesEnhancers as they may add defaultValues
const defaultArgs: Args = Object.entries(contextForEnhancers.argTypes).reduce(
(acc, [arg, { defaultValue }]) => {
if (typeof defaultValue !== 'undefined') {
acc[arg] = defaultValue;
}
return acc;
},
{} as Args
);
const defaultArgs = getValuesFromArgTypes(contextForEnhancers.argTypes);

if (Object.keys(defaultArgs).length > 0) {
argTypeDefaultValueWarning();
}
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { isExportStory, sanitize, Parameters, AnyFramework, ComponentTitle } from '@storybook/csf';
import { isExportStory, Parameters, AnyFramework, ComponentTitle } from '@storybook/csf';
import { logger } from '@storybook/client-logger';

import { ModuleExports, CSFFile, NormalizedComponentAnnotations } from './types';
import { normalizeStory } from './normalizeStory';
import { normalizeInputTypes } from './normalizeInputTypes';
import { Path } from '.';
import { normalizeComponentAnnotations } from './normalizeComponentAnnotations';
import type { ModuleExports, CSFFile, NormalizedComponentAnnotations, Path } from '../types';

const checkGlobals = (parameters: Parameters) => {
const { globals, globalTypes } = parameters;
Expand Down Expand Up @@ -40,17 +39,8 @@ export function processCSFFile<TFramework extends AnyFramework>(
): CSFFile<TFramework> {
const { default: defaultExport, __namedExportsOrder, ...namedExports } = moduleExports;

const { id, argTypes } = defaultExport;
const meta: NormalizedComponentAnnotations<TFramework> = {
id: sanitize(id || title),
...defaultExport,
title,
...(argTypes && { argTypes: normalizeInputTypes(argTypes) }),
parameters: {
fileName: importPath,
...defaultExport.parameters,
},
};
const meta: NormalizedComponentAnnotations<TFramework> =
normalizeComponentAnnotations<TFramework>(defaultExport, title, importPath);
checkDisallowedParameters(meta.parameters);

const csfFile: CSFFile<TFramework> = { meta, stories: {} };
Expand Down
2 changes: 1 addition & 1 deletion lib/store/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export { StoryStore } from './StoryStore';
export { combineParameters } from './parameters';
export { filterArgTypes } from './filterArgTypes';
export { normalizeInputTypes } from './normalizeInputTypes';
export type { PropDescriptor } from './filterArgTypes';
export { inferControls } from './inferControls';

export * from './types';

export * from './csf';
export * from './hooks';
export * from './decorators';
export * from './args';
Expand Down

0 comments on commit 758e4ba

Please sign in to comment.