/
config_api.ts
96 lines (81 loc) · 2.22 KB
/
config_api.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/* eslint no-underscore-dangle: 0 */
import Events from '@storybook/core-events';
import Channel from '@storybook/channels';
import { ErrorLike } from './types';
import StoryStore from './story_store';
import ClientApi from './client_api';
export default class ConfigApi {
_channel: Channel;
_storyStore: StoryStore;
_clearDecorators: () => void;
clientApi: ClientApi;
constructor({
channel,
storyStore,
clientApi,
clearDecorators,
}: {
channel: Channel | null;
storyStore: StoryStore;
clientApi: ClientApi;
clearDecorators: () => void;
}) {
// channel can be null when running in node
// always check whether channel is available
this._channel = channel;
this._storyStore = storyStore;
this._clearDecorators = clearDecorators;
this.clientApi = clientApi;
}
_renderMain() {
// do initial render of story
this._storyStore.emit(Events.STORY_INIT);
}
_renderError(err: Error) {
const { stack, message } = err;
const error: ErrorLike = { stack, message };
this._storyStore.setSelection(undefined, error);
}
configure = (loaders: () => void, module: NodeModule) => {
const render = () => {
const errors = [];
try {
if (loaders) {
loaders();
}
} catch (e) {
errors.push(e);
}
if (!errors.length) {
try {
this._renderMain();
} catch (e) {
errors.push(e);
}
}
if (errors.length) {
this._storyStore.setSelection(undefined, errors[0]);
throw errors[0];
} else {
this._storyStore.setSelection(undefined, null);
}
};
if (module.hot) {
module.hot.accept();
module.hot.dispose(() => {
this._clearDecorators();
});
}
if (this._channel) {
// in Browser
render();
// Send a signal to the manager that configure() is done. We do this in a timeout
// because the story_store sends stories in a debounced function, which results in
// as setTimeout. We want to ensure this happens after, to avoid a FOUC.
setTimeout(() => this._channel.emit(Events.STORIES_CONFIGURED), 0);
} else {
// in NodeJS
loaders();
}
};
}