mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-07 07:21:17 +08:00
refactor(store): move csf related logic to its own folder
This commit is contained in:
parent
9cfc30d517
commit
e834efa94c
@ -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(
|
||||
() => {},
|
||||
@ -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;
|
||||
|
@ -1,18 +1,18 @@
|
||||
import { AnyFramework, ProjectAnnotations } from '@storybook/csf';
|
||||
import global from 'global';
|
||||
|
||||
import { prepareStory } from './prepareStory';
|
||||
import { processCSFFile } from './processCSFFile';
|
||||
import { prepareStory } from './csf/prepareStory';
|
||||
import { processCSFFile } from './csf/processCSFFile';
|
||||
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('./csf/prepareStory', () => ({
|
||||
prepareStory: jest.fn(jest.requireActual('./csf/prepareStory').prepareStory),
|
||||
}));
|
||||
jest.mock('./processCSFFile', () => ({
|
||||
processCSFFile: jest.fn(jest.requireActual('./processCSFFile').processCSFFile),
|
||||
jest.mock('./csf/processCSFFile', () => ({
|
||||
processCSFFile: jest.fn(jest.requireActual('./csf/processCSFFile').processCSFFile),
|
||||
}));
|
||||
|
||||
jest.mock('global', () => ({
|
||||
|
@ -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,
|
||||
@ -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;
|
||||
|
||||
|
9
lib/store/src/csf/getValuesFromArgTypes.ts
Normal file
9
lib/store/src/csf/getValuesFromArgTypes.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { 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
lib/store/src/csf/index.ts
Normal file
7
lib/store/src/csf/index.ts
Normal file
@ -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
lib/store/src/csf/normalizeComponentAnnotations.ts
Normal file
22
lib/store/src/csf/normalizeComponentAnnotations.ts
Normal file
@ -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,
|
||||
},
|
||||
};
|
||||
}
|
25
lib/store/src/csf/normalizeProjectAnnotations.ts
Normal file
25
lib/store/src/csf/normalizeProjectAnnotations.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { AnyFramework, ProjectAnnotations } from '@storybook/csf';
|
||||
import { inferControls, NormalizedProjectAnnotations, normalizeInputTypes } from '..';
|
||||
import { inferArgTypes } from '../inferArgTypes';
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
@ -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`
|
@ -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', () => ({
|
@ -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 '..';
|
||||
|
||||
const argTypeDefaultValueWarning = deprecate(
|
||||
() => {},
|
||||
@ -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();
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
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 { ModuleExports, CSFFile, NormalizedComponentAnnotations } from '../types';
|
||||
import { normalizeStory } from './normalizeStory';
|
||||
import { normalizeInputTypes } from './normalizeInputTypes';
|
||||
import { Path } from '.';
|
||||
import { Path } from '..';
|
||||
import { normalizeComponentAnnotations } from './normalizeComponentAnnotations';
|
||||
|
||||
const checkGlobals = (parameters: Parameters) => {
|
||||
const { globals, globalTypes } = parameters;
|
||||
@ -40,17 +40,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: {} };
|
@ -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';
|
||||
|
Loading…
x
Reference in New Issue
Block a user