Skip to content

Commit

Permalink
Merge pull request #18498 from storybookjs/tom/sb-306-handle-v3-index…
Browse files Browse the repository at this point in the history
…-in-composition

Core: Handle v3 index in composition
  • Loading branch information
shilman authored Jun 20, 2022
2 parents ea47ed6 + b6ce456 commit 3803656
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 104 deletions.
31 changes: 19 additions & 12 deletions lib/api/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,20 +146,27 @@ export const combineParameters = (...parameterSets: Parameters[]) =>
return undefined;
});

export type ModuleFn<APIType = unknown, StateType = unknown> = (
m: ModuleArgs
) => Module<APIType, StateType>;

interface Module<APIType = unknown, StateType = unknown> {
init?: () => void;
api?: APIType;
state?: StateType;
interface ModuleWithInit<APIType = unknown, StateType = unknown> {
init: () => void | Promise<void>;
api: APIType;
state: StateType;
}

type ModuleWithoutInit<APIType = unknown, StateType = unknown> = Omit<
ModuleWithInit<APIType, StateType>,
'init'
>;

export type ModuleFn<APIType = unknown, StateType = unknown, HasInit = false> = (
m: ModuleArgs
) => HasInit extends true
? ModuleWithInit<APIType, StateType>
: ModuleWithoutInit<APIType, StateType>;

class ManagerProvider extends Component<ManagerProviderProps, State> {
api: API = {} as API;

modules: Module[];
modules: (ModuleWithInit | ModuleWithoutInit)[];

static displayName = 'Manager';

Expand Down Expand Up @@ -261,9 +268,9 @@ class ManagerProvider extends Component<ManagerProviderProps, State> {
initModules = () => {
// Now every module has had a chance to set its API, call init on each module which gives it
// a chance to do things that call other modules' APIs.
this.modules.forEach(({ init }) => {
if (init) {
init();
this.modules.forEach((module) => {
if ('init' in module) {
module.init();
}
});
};
Expand Down
35 changes: 33 additions & 2 deletions lib/api/src/lib/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import deprecate from 'util-deprecate';
import dedent from 'ts-dedent';
import mapValues from 'lodash/mapValues';
import countBy from 'lodash/countBy';
import global from 'global';
import type {
StoryId,
Expand Down Expand Up @@ -192,9 +193,13 @@ export type StoryIndexEntry = BaseIndexEntry & {
type?: 'story';
};

interface V3IndexEntry extends BaseIndexEntry {
parameters?: Parameters;
}

export interface StoryIndexV3 {
v: 3;
stories: Record<StoryId, Omit<StoryIndexEntry, 'type'>>;
stories: Record<StoryId, V3IndexEntry>;
}

export type DocsIndexEntry = BaseIndexEntry & {
Expand Down Expand Up @@ -302,6 +307,28 @@ const transformSetStoriesStoryDataToPreparedStoryIndex = (
return { v: 4, entries };
};

const transformStoryIndexV3toV4 = (index: StoryIndexV3): PreparedStoryIndex => {
const countByTitle = countBy(Object.values(index.stories), 'title');
return {
v: 4,
entries: Object.values(index.stories).reduce((acc, entry) => {
let type: IndexEntry['type'] = 'story';
if (
entry.parameters?.docsOnly ||
(entry.name === 'Page' && countByTitle[entry.title] === 1)
) {
type = 'docs';
}
acc[entry.id] = {
type,
...(type === 'docs' && { storiesImports: [] }),
...entry,
};
return acc;
}, {} as PreparedStoryIndex['entries']),
};
};

export const transformStoryIndexToStoriesHash = (
index: PreparedStoryIndex,
{
Expand All @@ -310,7 +337,11 @@ export const transformStoryIndexToStoriesHash = (
provider: Provider;
}
): StoriesHash => {
const entryValues = Object.values(index.entries);
if (!index.v) throw new Error('Composition: Missing stories.json version');

const v4Index = index.v === 4 ? index : transformStoryIndexV3toV4(index as any);

const entryValues = Object.values(v4Index.entries);
const { sidebar = {}, showRoots: deprecatedShowRoots } = provider.getConfig();
const { showRoots = deprecatedShowRoots, collapsedRoots = [], renderLabel } = sidebar;
const usesOldHierarchySeparator = entryValues.some(({ title }) => title.match(/\.|\|/)); // dot or pipe
Expand Down
9 changes: 4 additions & 5 deletions lib/api/src/modules/addons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,9 @@ type Panels = Collection<Addon>;

type StateMerger<S> = (input: S) => S;

interface StoryInput {
parameters: {
[parameterName: string]: any;
};
export interface SubState {
selectedPanel: string;
addons: Record<string, never>;
}

export interface SubAPI {
Expand Down Expand Up @@ -96,7 +95,7 @@ export function ensurePanel(panels: Panels, selectedPanel?: string, currentPanel
return currentPanel;
}

export const init: ModuleFn = ({ provider, store, fullAPI }) => {
export const init: ModuleFn<SubAPI, SubState> = ({ provider, store, fullAPI }) => {
const api: SubAPI = {
getElements: (type) => provider.getElements(type),
getPanels: () => api.getElements(types.PANEL),
Expand Down
6 changes: 4 additions & 2 deletions lib/api/src/modules/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ export interface SubAPI {
expandAll: () => void;
}

export const init: ModuleFn = ({ provider }) => {
export type SubState = Record<string, never>;

export const init: ModuleFn<SubAPI, SubState> = ({ provider }) => {
const api: SubAPI = {
getChannel: () => provider.channel,
on: (type, cb) => {
Expand All @@ -33,5 +35,5 @@ export const init: ModuleFn = ({ provider }) => {
api.emit(STORIES_EXPAND_ALL);
},
};
return { api };
return { api, state: {} };
};
3 changes: 2 additions & 1 deletion lib/api/src/modules/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ export interface SubAPI {
renderPreview?: Provider['renderPreview'];
}

export const init: ModuleFn = ({ provider, fullAPI }) => {
export const init: ModuleFn<SubAPI, {}, true> = ({ provider, fullAPI }) => {
return {
api: provider.renderPreview ? { renderPreview: provider.renderPreview } : {},
state: {},
init: () => {
provider.handleAPI(fullAPI);
},
Expand Down
78 changes: 42 additions & 36 deletions lib/api/src/modules/refs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {
SetStoriesStory,
StoriesHash,
transformStoryIndexToStoriesHash,
StoryIndexEntry,
SetStoriesStoryData,
StoryIndex,
} from '../lib/stories';

import type { ModuleFn, StoryId } from '../index';
import type { ModuleFn } from '../index';

const { location, fetch } = global;

Expand All @@ -20,9 +20,9 @@ export interface SubState {
type Versions = Record<string, string>;

export type SetRefData = Partial<
Omit<ComposedRef, 'stories'> & {
v: number;
stories?: SetStoriesStoryData;
ComposedRef & {
setStoriesData: SetStoriesStoryData;
storyIndex: StoryIndex;
}
>;

Expand Down Expand Up @@ -99,14 +99,24 @@ const addRefIds = (input: StoriesHash, ref: ComposedRef): StoriesHash => {
}, {} as StoriesHash);
};

const handle = async (request: Response | false): Promise<SetRefData> => {
if (request) {
return Promise.resolve(request)
.then((response) => (response.ok ? response.json() : {}))
.catch((error) => ({ error }));
async function handleRequest(request: Response | false): Promise<SetRefData> {
if (!request) return {};

try {
const response = await request;
if (!response.ok) return {};

const json = await response.json();

if (json.stories) {
return { storyIndex: json };
}

return json as SetRefData;
} catch (error) {
return { error };
}
return {};
};
}

const map = (
input: SetStoriesStoryData,
Expand All @@ -122,7 +132,10 @@ const map = (
return input;
};

export const init: ModuleFn = ({ store, provider, singleStory }, { runCheck = true } = {}) => {
export const init: ModuleFn<SubAPI, SubState, void> = (
{ store, provider, singleStory },
{ runCheck = true } = {}
) => {
const api: SubAPI = {
findRef: (source) => {
const refs = api.getRefs();
Expand Down Expand Up @@ -190,9 +203,9 @@ export const init: ModuleFn = ({ store, provider, singleStory }, { runCheck = tr
`,
} as Error;
} else if (storiesFetch.ok) {
const [stories, metadata] = await Promise.all([
handle(storiesFetch),
handle(
const [storyIndex, metadata] = await Promise.all([
handleRequest(storiesFetch),
handleRequest(
fetch(`${url}/metadata.json${query}`, {
headers: {
Accept: 'application/json',
Expand All @@ -203,7 +216,7 @@ export const init: ModuleFn = ({ store, provider, singleStory }, { runCheck = tr
),
]);

Object.assign(loadedData, { ...stories, ...metadata });
Object.assign(loadedData, { ...storyIndex, ...metadata });
}

const versions =
Expand All @@ -214,8 +227,7 @@ export const init: ModuleFn = ({ store, provider, singleStory }, { runCheck = tr
url,
...loadedData,
...(versions ? { versions } : {}),
error: loadedData.error,
type: !loadedData.stories ? 'auto-inject' : 'lazy',
type: !loadedData.storyIndex ? 'auto-inject' : 'lazy',
});
},

Expand All @@ -225,29 +237,23 @@ export const init: ModuleFn = ({ store, provider, singleStory }, { runCheck = tr
return refs;
},

setRef: (id, { stories, v, ...rest }, ready = false) => {
setRef: (id, { storyIndex, setStoriesData, ...rest }, ready = false) => {
if (singleStory) return;
const { storyMapper = defaultStoryMapper } = provider.getConfig();
const ref = api.getRefs()[id];

let storiesHash: StoriesHash;

if (stories) {
if (v === 2) {
storiesHash = transformSetStoriesStoryDataToStoriesHash(
map(stories, ref, { storyMapper }),
{
provider,
}
);
} else if (!v) {
throw new Error('Composition: Missing stories.json version');
} else {
const index = stories as unknown as Record<StoryId, StoryIndexEntry>;
storiesHash = transformStoryIndexToStoriesHash({ v, entries: index }, { provider });
}
storiesHash = addRefIds(storiesHash, ref);
if (setStoriesData) {
storiesHash = transformSetStoriesStoryDataToStoriesHash(
map(setStoriesData, ref, { storyMapper }),
{
provider,
}
);
} else if (storyIndex) {
storiesHash = transformStoryIndexToStoriesHash(storyIndex, { provider });
}
if (storiesHash) storiesHash = addRefIds(storiesHash, ref);

api.updateRef(id, { stories: storiesHash, ...rest, ready });
},
Expand Down
6 changes: 2 additions & 4 deletions lib/api/src/modules/release-notes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export interface SubState {
releaseNotesViewed: string[];
}

export const init: ModuleFn = ({ store }) => {
export const init: ModuleFn<SubAPI, SubState> = ({ store }) => {
const releaseNotesData = getReleaseNotesData();
const getReleaseNotesViewed = () => {
const { releaseNotesViewed: persistedReleaseNotesViewed } = store.getState();
Expand Down Expand Up @@ -58,7 +58,5 @@ export const init: ModuleFn = ({ store }) => {
},
};

const initModule = () => {};

return { init: initModule, api };
return { state: { releaseNotesViewed: [] }, api };
};
8 changes: 2 additions & 6 deletions lib/api/src/modules/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface SubState {
settings: Settings;
}

export const init: ModuleFn = ({ store, navigate, fullAPI }) => {
export const init: ModuleFn<SubAPI, SubState> = ({ store, navigate, fullAPI }) => {
const isSettingsScreenActive = () => {
const { path } = fullAPI.getUrlState();
return !!(path || '').match(/^\/settings/);
Expand Down Expand Up @@ -49,9 +49,5 @@ export const init: ModuleFn = ({ store, navigate, fullAPI }) => {
},
};

const initModule = async () => {
await store.setState({ settings: { lastTrackedStoryId: null } });
};

return { init: initModule, api };
return { state: { settings: { lastTrackedStoryId: null } }, api };
};
Loading

0 comments on commit 3803656

Please sign in to comment.