@storybook/core-server 7.0.0-alpha.3 → 7.0.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -124,8 +124,8 @@ async function buildStaticStandalone(options) {
124
124
  managerBuilder = _await$getBuilders2[1];
125
125
 
126
126
  presets = (0, _coreCommon.loadAllPresets)(_objectSpread({
127
- corePresets: [require.resolve('./presets/common-preset'), ...managerBuilder.corePresets, ...previewBuilder.corePresets, ...corePresets, require.resolve('./presets/babel-cache-preset')],
128
- overridePresets: previewBuilder.overridePresets
127
+ corePresets: [require.resolve('./presets/common-preset'), ...(managerBuilder.corePresets || []), ...(previewBuilder.corePresets || []), ...corePresets, require.resolve('./presets/babel-cache-preset')],
128
+ overridePresets: previewBuilder.overridePresets || []
129
129
  }, options));
130
130
  var staticDirs = await presets.apply('staticDirs');
131
131
 
@@ -163,12 +163,13 @@ async function buildStaticStandalone(options) {
163
163
  var generator = new _StoryIndexGenerator.StoryIndexGenerator(normalizedStories, _objectSpread(_objectSpread({}, directories), {}, {
164
164
  storyIndexers: storyIndexers,
165
165
  storiesV2Compatibility: !(features !== null && features !== void 0 && features.breakingChangesV7) && !(features !== null && features !== void 0 && features.storyStoreV7),
166
- storyStoreV7: features === null || features === void 0 ? void 0 : features.storyStoreV7
166
+ storyStoreV7: !!(features !== null && features !== void 0 && features.storyStoreV7)
167
167
  }));
168
168
  initializedStoryIndexGenerator = generator.initialize().then(function () {
169
169
  return generator;
170
170
  });
171
- extractTasks.push((0, _storiesJson.extractStoriesJson)(_path.default.join(options.outputDir, 'stories.json'), initializedStoryIndexGenerator));
171
+ extractTasks.push((0, _storiesJson.extractStoriesJson)(_path.default.join(options.outputDir, 'stories.json'), initializedStoryIndexGenerator, _storiesJson.convertToIndexV3));
172
+ extractTasks.push((0, _storiesJson.extractStoriesJson)(_path.default.join(options.outputDir, 'index.json'), initializedStoryIndexGenerator));
172
173
  }
173
174
 
174
175
  var core = await presets.apply('core');
@@ -182,7 +183,7 @@ async function buildStaticStandalone(options) {
182
183
  var storyIndex = await generator.getIndex();
183
184
  var payload = storyIndex ? {
184
185
  storyIndex: {
185
- storyCount: Object.keys(storyIndex.stories).length,
186
+ storyCount: Object.keys(storyIndex.entries).length,
186
187
  version: storyIndex.v
187
188
  }
188
189
  } : undefined;
@@ -121,7 +121,7 @@ async function storybookDevServer(options) {
121
121
  var storyIndex = await generator.getIndex();
122
122
  var payload = storyIndex ? {
123
123
  storyIndex: {
124
- storyCount: Object.keys(storyIndex.stories).length,
124
+ storyCount: Object.keys(storyIndex.entries).length,
125
125
  version: storyIndex.v
126
126
  }
127
127
  } : undefined;
@@ -11,10 +11,6 @@ require("core-js/modules/es.promise.js");
11
11
 
12
12
  require("core-js/modules/es.array.sort.js");
13
13
 
14
- require("core-js/modules/es.array.flat.js");
15
-
16
- require("core-js/modules/es.array.unscopables.flat.js");
17
-
18
14
  require("core-js/modules/es.array.flat-map.js");
19
15
 
20
16
  require("core-js/modules/es.array.unscopables.flat-map.js");
@@ -35,13 +31,9 @@ var _nodeLogger = require("@storybook/node-logger");
35
31
 
36
32
  var _csfTools = require("@storybook/csf-tools");
37
33
 
38
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
39
-
40
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
34
+ var _csf = require("@storybook/csf");
41
35
 
42
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
43
-
44
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
36
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
45
37
 
46
38
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
47
39
 
@@ -55,6 +47,16 @@ function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Sy
55
47
 
56
48
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
57
49
 
50
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
51
+
52
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
53
+
54
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
55
+
56
+ var makeAbsolute = function (otherImport, normalizedPath, workingDir) {
57
+ return otherImport.startsWith('.') ? (0, _slash.default)(_path.default.resolve(workingDir, (0, _coreCommon.normalizeStoryPath)(_path.default.join(_path.default.dirname(normalizedPath), otherImport)))) : otherImport;
58
+ };
59
+
58
60
  class StoryIndexGenerator {
59
61
  // An internal cache mapping specifiers to a set of path=><set of stories>
60
62
  // Later, we'll combine each of these subsets together to form the full index
@@ -64,9 +66,9 @@ class StoryIndexGenerator {
64
66
  constructor(specifiers, options) {
65
67
  this.specifiers = specifiers;
66
68
  this.options = options;
67
- this.storyIndexEntries = void 0;
69
+ this.specifierToCache = void 0;
68
70
  this.lastIndex = void 0;
69
- this.storyIndexEntries = new Map();
71
+ this.specifierToCache = new Map();
70
72
  }
71
73
 
72
74
  async initialize() {
@@ -91,22 +93,157 @@ class StoryIndexGenerator {
91
93
  pathToSubIndex[absolutePath] = false;
92
94
  });
93
95
 
94
- _this.storyIndexEntries.set(specifier, pathToSubIndex);
96
+ _this.specifierToCache.set(specifier, pathToSubIndex);
95
97
  })); // Extract stories for each file
96
98
 
97
99
  await this.ensureExtracted();
98
100
  }
101
+ /**
102
+ * Run the updater function over all the empty cache entries
103
+ */
99
104
 
100
- async ensureExtracted() {
105
+
106
+ async updateExtracted(updater) {
101
107
  var _this2 = this;
102
108
 
103
- return (await Promise.all(this.specifiers.map(async function (specifier) {
104
- var entry = _this2.storyIndexEntries.get(specifier);
109
+ await Promise.all(this.specifiers.map(async function (specifier) {
110
+ var entry = _this2.specifierToCache.get(specifier);
105
111
 
106
112
  return Promise.all(Object.keys(entry).map(async function (absolutePath) {
107
- return entry[absolutePath] || _this2.extractStories(specifier, absolutePath);
113
+ entry[absolutePath] = entry[absolutePath] || (await updater(specifier, absolutePath));
108
114
  }));
109
- }))).flat();
115
+ }));
116
+ }
117
+
118
+ isDocsMdx(absolutePath) {
119
+ return /(?<!\.stories)\.mdx$/i.test(absolutePath);
120
+ }
121
+
122
+ async ensureExtracted() {
123
+ var _this3 = this;
124
+
125
+ // First process all the story files. Then, in a second pass,
126
+ // process the docs files. The reason for this is that the docs
127
+ // files may use the `<Meta of={XStories} />` syntax, which requires
128
+ // that the story file that contains the meta be processed first.
129
+ await this.updateExtracted(async function (specifier, absolutePath) {
130
+ return _this3.isDocsMdx(absolutePath) ? false : _this3.extractStories(specifier, absolutePath);
131
+ });
132
+ await this.updateExtracted(async function (specifier, absolutePath) {
133
+ return _this3.extractDocs(specifier, absolutePath);
134
+ });
135
+ return this.specifiers.flatMap(function (specifier) {
136
+ var cache = _this3.specifierToCache.get(specifier);
137
+
138
+ return Object.values(cache).flatMap(function (entry) {
139
+ if (!entry) return [];
140
+ if (entry.type === 'docs') return [entry];
141
+ return entry.entries;
142
+ });
143
+ });
144
+ }
145
+
146
+ findDependencies(absoluteImports) {
147
+ var dependencies = [];
148
+ var foundImports = new Set();
149
+ this.specifierToCache.forEach(function (cache) {
150
+ var fileNames = Object.keys(cache).filter(function (fileName) {
151
+ var foundImport = absoluteImports.find(function (storyImport) {
152
+ return fileName.startsWith(storyImport);
153
+ });
154
+ if (foundImport) foundImports.add(foundImport);
155
+ return !!foundImport;
156
+ });
157
+ fileNames.forEach(function (fileName) {
158
+ var cacheEntry = cache[fileName];
159
+
160
+ if (cacheEntry && cacheEntry.type === 'stories') {
161
+ dependencies.push(cacheEntry);
162
+ } else {
163
+ throw new Error(`Unexpected dependency: ${cacheEntry}`);
164
+ }
165
+ });
166
+ }); // imports can include non-story imports, so it's ok if
167
+ // there are fewer foundImports than absoluteImports
168
+ // if (absoluteImports.length !== foundImports.size) {
169
+ // throw new Error(`Missing dependencies: ${absoluteImports.filter((p) => !foundImports.has(p))}`));
170
+ // }
171
+
172
+ return dependencies;
173
+ }
174
+
175
+ async extractDocs(specifier, absolutePath) {
176
+ var _this4 = this;
177
+
178
+ var relativePath = _path.default.relative(this.options.workingDir, absolutePath);
179
+
180
+ try {
181
+ if (!this.options.storyStoreV7) {
182
+ throw new Error(`You cannot use \`.mdx\` files without using \`storyStoreV7\`.`);
183
+ }
184
+
185
+ var normalizedPath = (0, _coreCommon.normalizeStoryPath)(relativePath);
186
+ var importPath = (0, _slash.default)(normalizedPath); // This `await require(...)` is a bit of a hack. It's necessary because
187
+ // `docs-mdx` depends on ESM code, which must be asynchronously imported
188
+ // to be used in CJS. Unfortunately, we cannot use `import()` here, because
189
+ // it will be transpiled down to `require()` by Babel. So instead, we require
190
+ // a CJS export from `@storybook/docs-mdx` that does the `async import` for us.
191
+ // eslint-disable-next-line global-require
192
+
193
+ var _await$require = await require('@storybook/docs-mdx'),
194
+ analyze = _await$require.analyze;
195
+
196
+ var content = await _fsExtra.default.readFile(absolutePath, 'utf8'); // { title?, of?, imports? }
197
+
198
+ var result = analyze(content);
199
+ var absoluteImports = result.imports.map(function (p) {
200
+ return makeAbsolute(p, normalizedPath, _this4.options.workingDir);
201
+ }); // Go through the cache and collect all of the cache entries that this docs file depends on.
202
+ // We'll use this to make sure this docs cache entry is invalidated when any of its dependents
203
+ // are invalidated.
204
+
205
+ var dependencies = this.findDependencies(absoluteImports); // Also, if `result.of` is set, it means that we're using the `<Meta of={XStories} />` syntax,
206
+ // so find the `title` defined the file that `meta` points to.
207
+
208
+ var ofTitle;
209
+
210
+ if (result.of) {
211
+ var absoluteOf = makeAbsolute(result.of, normalizedPath, this.options.workingDir);
212
+ dependencies.forEach(function (dep) {
213
+ if (dep.entries.length > 0) {
214
+ var first = dep.entries[0];
215
+
216
+ if (_path.default.resolve(_this4.options.workingDir, first.importPath).startsWith(absoluteOf)) {
217
+ ofTitle = first.title;
218
+ }
219
+ }
220
+ });
221
+ if (!ofTitle) throw new Error(`Could not find "${result.of}" for docs file "${relativePath}".`);
222
+ } // Track that we depend on this for easy invalidation later.
223
+
224
+
225
+ dependencies.forEach(function (dep) {
226
+ dep.dependents.push(absolutePath);
227
+ });
228
+ var title = (0, _store.userOrAutoTitleFromSpecifier)(importPath, specifier, result.title || ofTitle);
229
+ var name = 'docs';
230
+ var id = (0, _csf.toId)(title, name);
231
+ var docsEntry = {
232
+ id: id,
233
+ title: title,
234
+ name: name,
235
+ importPath: importPath,
236
+ storiesImports: dependencies.map(function (dep) {
237
+ return dep.entries[0].importPath;
238
+ }),
239
+ type: 'docs'
240
+ };
241
+ return docsEntry;
242
+ } catch (err) {
243
+ _nodeLogger.logger.warn(`🚨 Extraction error on ${relativePath}: ${err}`);
244
+
245
+ throw err;
246
+ }
110
247
  }
111
248
 
112
249
  async index(filePath, options) {
@@ -124,8 +261,7 @@ class StoryIndexGenerator {
124
261
  async extractStories(specifier, absolutePath) {
125
262
  var relativePath = _path.default.relative(this.options.workingDir, absolutePath);
126
263
 
127
- var fileStories = {};
128
- var entry = this.storyIndexEntries.get(specifier);
264
+ var entries = [];
129
265
 
130
266
  try {
131
267
  var importPath = (0, _slash.default)((0, _coreCommon.normalizeStoryPath)(relativePath));
@@ -139,14 +275,23 @@ class StoryIndexGenerator {
139
275
  });
140
276
  csf.stories.forEach(function ({
141
277
  id: id,
142
- name: name
278
+ name: name,
279
+ parameters: parameters
143
280
  }) {
144
- fileStories[id] = {
281
+ var base = {
145
282
  id: id,
146
283
  title: csf.meta.title,
147
284
  name: name,
148
285
  importPath: importPath
149
286
  };
287
+ var entry = parameters !== null && parameters !== void 0 && parameters.docsOnly ? _objectSpread(_objectSpread({}, base), {}, {
288
+ type: 'docs',
289
+ storiesImports: [],
290
+ legacy: true
291
+ }) : _objectSpread(_objectSpread({}, base), {}, {
292
+ type: 'story'
293
+ });
294
+ entries.push(entry);
150
295
  });
151
296
  } catch (err) {
152
297
  if (err.name === 'NoMetaError') {
@@ -158,16 +303,19 @@ class StoryIndexGenerator {
158
303
  }
159
304
  }
160
305
 
161
- entry[absolutePath] = fileStories;
162
- return fileStories;
306
+ return {
307
+ entries: entries,
308
+ type: 'stories',
309
+ dependents: []
310
+ };
163
311
  }
164
312
 
165
313
  async sortStories(storiesList) {
166
- var stories = {};
167
- storiesList.forEach(function (subStories) {
168
- Object.assign(stories, subStories);
314
+ var entries = {};
315
+ storiesList.forEach(function (entry) {
316
+ entries[entry.id] = entry;
169
317
  });
170
- var sortableStories = Object.values(stories); // Skip sorting if we're in v6 mode because we don't have
318
+ var sortableStories = Object.values(entries); // Skip sorting if we're in v6 mode because we don't have
171
319
  // all the info we need here
172
320
 
173
321
  if (this.options.storyStoreV7) {
@@ -194,14 +342,15 @@ class StoryIndexGenerator {
194
342
  var titleToStoryCount = Object.values(sorted).reduce(function (acc, story) {
195
343
  acc[story.title] = (acc[story.title] || 0) + 1;
196
344
  return acc;
197
- }, {});
345
+ }, {}); // @ts-ignore
346
+
198
347
  compat = Object.entries(sorted).reduce(function (acc, entry) {
199
348
  var _entry = _slicedToArray(entry, 2),
200
349
  id = _entry[0],
201
350
  story = _entry[1];
202
351
 
352
+ if (story.type === 'docs') return acc;
203
353
  acc[id] = _objectSpread(_objectSpread({}, story), {}, {
204
- id: id,
205
354
  kind: story.title,
206
355
  story: story.name,
207
356
  parameters: {
@@ -215,30 +364,65 @@ class StoryIndexGenerator {
215
364
  }
216
365
 
217
366
  this.lastIndex = {
218
- v: 3,
219
- stories: compat
367
+ v: 4,
368
+ entries: compat
220
369
  };
221
370
  return this.lastIndex;
222
371
  }
223
372
 
224
373
  invalidate(specifier, importPath, removed) {
374
+ var _this5 = this;
375
+
225
376
  var absolutePath = (0, _slash.default)(_path.default.resolve(this.options.workingDir, importPath));
226
- var pathToEntries = this.storyIndexEntries.get(specifier);
377
+ var cache = this.specifierToCache.get(specifier);
378
+ var cacheEntry = cache[absolutePath];
379
+
380
+ if (cacheEntry && cacheEntry.type === 'stories') {
381
+ var dependents = cacheEntry.dependents;
382
+ var invalidated = new Set(); // the dependent can be in ANY cache, so we loop over all of them
383
+
384
+ this.specifierToCache.forEach(function (otherCache) {
385
+ dependents.forEach(function (dep) {
386
+ if (otherCache[dep]) {
387
+ invalidated.add(dep); // eslint-disable-next-line no-param-reassign
388
+
389
+ otherCache[dep] = false;
390
+ }
391
+ });
392
+ });
393
+ var notFound = dependents.filter(function (dep) {
394
+ return !invalidated.has(dep);
395
+ });
396
+
397
+ if (notFound.length > 0) {
398
+ throw new Error(`Could not invalidate ${notFound.length} deps: ${notFound.join(', ')}`);
399
+ }
400
+ }
227
401
 
228
402
  if (removed) {
229
- delete pathToEntries[absolutePath];
403
+ if (cacheEntry && cacheEntry.type === 'docs') {
404
+ var absoluteImports = cacheEntry.storiesImports.map(function (p) {
405
+ return _path.default.resolve(_this5.options.workingDir, p);
406
+ });
407
+ var dependencies = this.findDependencies(absoluteImports);
408
+ dependencies.forEach(function (dep) {
409
+ return dep.dependents.splice(dep.dependents.indexOf(absolutePath), 1);
410
+ });
411
+ }
412
+
413
+ delete cache[absolutePath];
230
414
  } else {
231
- pathToEntries[absolutePath] = false;
415
+ cache[absolutePath] = false;
232
416
  }
233
417
 
234
418
  this.lastIndex = null;
235
419
  }
236
420
 
237
421
  async getStorySortParameter() {
238
- var _this3 = this;
422
+ var _this6 = this;
239
423
 
240
424
  var previewFile = ['js', 'jsx', 'ts', 'tsx'].map(function (ext) {
241
- return _path.default.join(_this3.options.configDir, `preview.${ext}`);
425
+ return _path.default.join(_this6.options.configDir, `preview.${ext}`);
242
426
  }).find(function (fname) {
243
427
  return _fsExtra.default.existsSync(fname);
244
428
  });
@@ -254,7 +438,7 @@ class StoryIndexGenerator {
254
438
 
255
439
 
256
440
  storyFileNames() {
257
- return Array.from(this.storyIndexEntries.values()).flatMap(function (r) {
441
+ return Array.from(this.specifierToCache.values()).flatMap(function (r) {
258
442
  return Object.keys(r);
259
443
  });
260
444
  }
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.DEBOUNCE = void 0;
6
+ exports.convertToIndexV3 = exports.DEBOUNCE = void 0;
7
7
  exports.extractStoriesJson = extractStoriesJson;
8
8
  exports.useStoriesJson = useStoriesJson;
9
9
 
@@ -11,21 +11,33 @@ require("core-js/modules/es.promise.js");
11
11
 
12
12
  var _fsExtra = _interopRequireDefault(require("fs-extra"));
13
13
 
14
- var _lodash = require("lodash");
14
+ var _debounce = _interopRequireDefault(require("lodash/debounce"));
15
15
 
16
16
  var _coreEvents = require("@storybook/core-events");
17
17
 
18
18
  var _watchStorySpecifiers = require("./watch-story-specifiers");
19
19
 
20
+ var _excluded = ["type"];
21
+
20
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
23
 
24
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
25
+
26
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
27
+
28
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
29
+
30
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
31
+
32
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
33
+
22
34
  var DEBOUNCE = 100;
23
35
  exports.DEBOUNCE = DEBOUNCE;
24
36
 
25
- async function extractStoriesJson(outputFile, initializedStoryIndexGenerator) {
37
+ async function extractStoriesJson(outputFile, initializedStoryIndexGenerator, transform) {
26
38
  var generator = await initializedStoryIndexGenerator;
27
39
  var storyIndex = await generator.getIndex();
28
- await _fsExtra.default.writeJson(outputFile, storyIndex);
40
+ await _fsExtra.default.writeJson(outputFile, transform ? transform(storyIndex) : storyIndex);
29
41
  }
30
42
 
31
43
  function useStoriesJson({
@@ -35,7 +47,7 @@ function useStoriesJson({
35
47
  serverChannel: serverChannel,
36
48
  normalizedStories: normalizedStories
37
49
  }) {
38
- var maybeInvalidate = (0, _lodash.debounce)(function () {
50
+ var maybeInvalidate = (0, _debounce.default)(function () {
39
51
  return serverChannel.emit(_coreEvents.STORY_INDEX_INVALIDATED);
40
52
  }, DEBOUNCE, {
41
53
  leading: true
@@ -47,15 +59,55 @@ function useStoriesJson({
47
59
  generator.invalidate(specifier, path, removed);
48
60
  maybeInvalidate();
49
61
  });
62
+ router.use('/index.json', async function (req, res) {
63
+ try {
64
+ var generator = await initializedStoryIndexGenerator;
65
+
66
+ var _index = await generator.getIndex();
67
+
68
+ res.header('Content-Type', 'application/json');
69
+ res.send(JSON.stringify(_index));
70
+ } catch (err) {
71
+ res.status(500);
72
+ res.send(err.message);
73
+ }
74
+ });
50
75
  router.use('/stories.json', async function (req, res) {
51
76
  try {
52
77
  var generator = await initializedStoryIndexGenerator;
53
- var index = await generator.getIndex();
78
+
79
+ var _index2 = convertToIndexV3(await generator.getIndex());
80
+
54
81
  res.header('Content-Type', 'application/json');
55
- res.send(JSON.stringify(index));
82
+ res.send(JSON.stringify(_index2));
56
83
  } catch (err) {
57
84
  res.status(500);
58
85
  res.send(err.message);
59
86
  }
60
87
  });
61
- }
88
+ }
89
+
90
+ var convertToIndexV3 = function (index) {
91
+ var entries = index.entries;
92
+ var stories = Object.entries(entries).reduce(function (acc, [id, entry]) {
93
+ var type = entry.type,
94
+ rest = _objectWithoutProperties(entry, _excluded);
95
+
96
+ acc[id] = _objectSpread(_objectSpread({}, rest), {}, {
97
+ kind: rest.title,
98
+ story: rest.name,
99
+ parameters: {
100
+ __id: rest.id,
101
+ docsOnly: type === 'docs',
102
+ fileName: rest.importPath
103
+ }
104
+ });
105
+ return acc;
106
+ }, {});
107
+ return {
108
+ v: 3,
109
+ stories: stories
110
+ };
111
+ };
112
+
113
+ exports.convertToIndexV3 = convertToIndexV3;
@@ -17,6 +17,8 @@ var _path = _interopRequireDefault(require("path"));
17
17
 
18
18
  var _globby = _interopRequireDefault(require("globby"));
19
19
 
20
+ var _uniq = _interopRequireDefault(require("lodash/uniq"));
21
+
20
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
23
 
22
24
  var isDirectory = function (directory) {
@@ -43,9 +45,9 @@ function watchStorySpecifiers(specifiers, options, onInvalidate) {
43
45
  ignored: ['**/.git', 'node_modules']
44
46
  });
45
47
  wp.watch({
46
- directories: specifiers.map(function (ns) {
48
+ directories: (0, _uniq.default)(specifiers.map(function (ns) {
47
49
  return ns.directory;
48
- })
50
+ }))
49
51
  });
50
52
 
51
53
  async function onChangeOrRemove(watchpackPath, removed) {
@@ -30,7 +30,7 @@ import { loadAllPresets, normalizeStories, logConfig, loadMainConfig } from '@st
30
30
  import { outputStats } from './utils/output-stats';
31
31
  import { copyAllStaticFiles, copyAllStaticFilesRelativeToMain } from './utils/copy-all-static-files';
32
32
  import { getBuilders } from './utils/get-builders';
33
- import { extractStoriesJson } from './utils/stories-json';
33
+ import { extractStoriesJson, convertToIndexV3 } from './utils/stories-json';
34
34
  import { extractStorybookMetadata } from './utils/metadata';
35
35
  import { StoryIndexGenerator } from './utils/StoryIndexGenerator';
36
36
  export async function buildStaticStandalone(options) {
@@ -91,8 +91,8 @@ export async function buildStaticStandalone(options) {
91
91
  managerBuilder = _await$getBuilders2[1];
92
92
 
93
93
  presets = loadAllPresets(_objectSpread({
94
- corePresets: [require.resolve('./presets/common-preset'), ...managerBuilder.corePresets, ...previewBuilder.corePresets, ...corePresets, require.resolve('./presets/babel-cache-preset')],
95
- overridePresets: previewBuilder.overridePresets
94
+ corePresets: [require.resolve('./presets/common-preset'), ...(managerBuilder.corePresets || []), ...(previewBuilder.corePresets || []), ...corePresets, require.resolve('./presets/babel-cache-preset')],
95
+ overridePresets: previewBuilder.overridePresets || []
96
96
  }, options));
97
97
  var staticDirs = await presets.apply('staticDirs');
98
98
 
@@ -130,12 +130,13 @@ export async function buildStaticStandalone(options) {
130
130
  var generator = new StoryIndexGenerator(normalizedStories, _objectSpread(_objectSpread({}, directories), {}, {
131
131
  storyIndexers: storyIndexers,
132
132
  storiesV2Compatibility: !(features !== null && features !== void 0 && features.breakingChangesV7) && !(features !== null && features !== void 0 && features.storyStoreV7),
133
- storyStoreV7: features === null || features === void 0 ? void 0 : features.storyStoreV7
133
+ storyStoreV7: !!(features !== null && features !== void 0 && features.storyStoreV7)
134
134
  }));
135
135
  initializedStoryIndexGenerator = generator.initialize().then(function () {
136
136
  return generator;
137
137
  });
138
- extractTasks.push(extractStoriesJson(path.join(options.outputDir, 'stories.json'), initializedStoryIndexGenerator));
138
+ extractTasks.push(extractStoriesJson(path.join(options.outputDir, 'stories.json'), initializedStoryIndexGenerator, convertToIndexV3));
139
+ extractTasks.push(extractStoriesJson(path.join(options.outputDir, 'index.json'), initializedStoryIndexGenerator));
139
140
  }
140
141
 
141
142
  var core = await presets.apply('core');
@@ -149,7 +150,7 @@ export async function buildStaticStandalone(options) {
149
150
  var storyIndex = await generator.getIndex();
150
151
  var payload = storyIndex ? {
151
152
  storyIndex: {
152
- storyCount: Object.keys(storyIndex.stories).length,
153
+ storyCount: Object.keys(storyIndex.entries).length,
153
154
  version: storyIndex.v
154
155
  }
155
156
  } : undefined;
@@ -88,7 +88,7 @@ export async function storybookDevServer(options) {
88
88
  var storyIndex = await generator.getIndex();
89
89
  var payload = storyIndex ? {
90
90
  storyIndex: {
91
- storyCount: Object.keys(storyIndex.stories).length,
91
+ storyCount: Object.keys(storyIndex.entries).length,
92
92
  version: storyIndex.v
93
93
  }
94
94
  } : undefined;
@@ -1,9 +1,3 @@
1
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
2
-
3
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
4
-
5
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
-
7
1
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
8
2
 
9
3
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
@@ -16,10 +10,14 @@ function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Sy
16
10
 
17
11
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
18
12
 
13
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
14
+
15
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
16
+
17
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
18
+
19
19
  import "core-js/modules/es.promise.js";
20
20
  import "core-js/modules/es.array.sort.js";
21
- import "core-js/modules/es.array.flat.js";
22
- import "core-js/modules/es.array.unscopables.flat.js";
23
21
  import "core-js/modules/es.array.flat-map.js";
24
22
  import "core-js/modules/es.array.unscopables.flat-map.js";
25
23
  import "core-js/modules/es.symbol.description.js";
@@ -31,6 +29,12 @@ import { userOrAutoTitleFromSpecifier, sortStoriesV7 } from '@storybook/store';
31
29
  import { normalizeStoryPath } from '@storybook/core-common';
32
30
  import { logger } from '@storybook/node-logger';
33
31
  import { getStorySortParameter } from '@storybook/csf-tools';
32
+ import { toId } from '@storybook/csf';
33
+
34
+ var makeAbsolute = function (otherImport, normalizedPath, workingDir) {
35
+ return otherImport.startsWith('.') ? slash(path.resolve(workingDir, normalizeStoryPath(path.join(path.dirname(normalizedPath), otherImport)))) : otherImport;
36
+ };
37
+
34
38
  export class StoryIndexGenerator {
35
39
  // An internal cache mapping specifiers to a set of path=><set of stories>
36
40
  // Later, we'll combine each of these subsets together to form the full index
@@ -40,9 +44,9 @@ export class StoryIndexGenerator {
40
44
  constructor(specifiers, options) {
41
45
  this.specifiers = specifiers;
42
46
  this.options = options;
43
- this.storyIndexEntries = void 0;
47
+ this.specifierToCache = void 0;
44
48
  this.lastIndex = void 0;
45
- this.storyIndexEntries = new Map();
49
+ this.specifierToCache = new Map();
46
50
  }
47
51
 
48
52
  async initialize() {
@@ -65,22 +69,156 @@ export class StoryIndexGenerator {
65
69
  pathToSubIndex[absolutePath] = false;
66
70
  });
67
71
 
68
- _this.storyIndexEntries.set(specifier, pathToSubIndex);
72
+ _this.specifierToCache.set(specifier, pathToSubIndex);
69
73
  })); // Extract stories for each file
70
74
 
71
75
  await this.ensureExtracted();
72
76
  }
77
+ /**
78
+ * Run the updater function over all the empty cache entries
79
+ */
73
80
 
74
- async ensureExtracted() {
81
+
82
+ async updateExtracted(updater) {
75
83
  var _this2 = this;
76
84
 
77
- return (await Promise.all(this.specifiers.map(async function (specifier) {
78
- var entry = _this2.storyIndexEntries.get(specifier);
85
+ await Promise.all(this.specifiers.map(async function (specifier) {
86
+ var entry = _this2.specifierToCache.get(specifier);
79
87
 
80
88
  return Promise.all(Object.keys(entry).map(async function (absolutePath) {
81
- return entry[absolutePath] || _this2.extractStories(specifier, absolutePath);
89
+ entry[absolutePath] = entry[absolutePath] || (await updater(specifier, absolutePath));
82
90
  }));
83
- }))).flat();
91
+ }));
92
+ }
93
+
94
+ isDocsMdx(absolutePath) {
95
+ return /(?<!\.stories)\.mdx$/i.test(absolutePath);
96
+ }
97
+
98
+ async ensureExtracted() {
99
+ var _this3 = this;
100
+
101
+ // First process all the story files. Then, in a second pass,
102
+ // process the docs files. The reason for this is that the docs
103
+ // files may use the `<Meta of={XStories} />` syntax, which requires
104
+ // that the story file that contains the meta be processed first.
105
+ await this.updateExtracted(async function (specifier, absolutePath) {
106
+ return _this3.isDocsMdx(absolutePath) ? false : _this3.extractStories(specifier, absolutePath);
107
+ });
108
+ await this.updateExtracted(async function (specifier, absolutePath) {
109
+ return _this3.extractDocs(specifier, absolutePath);
110
+ });
111
+ return this.specifiers.flatMap(function (specifier) {
112
+ var cache = _this3.specifierToCache.get(specifier);
113
+
114
+ return Object.values(cache).flatMap(function (entry) {
115
+ if (!entry) return [];
116
+ if (entry.type === 'docs') return [entry];
117
+ return entry.entries;
118
+ });
119
+ });
120
+ }
121
+
122
+ findDependencies(absoluteImports) {
123
+ var dependencies = [];
124
+ var foundImports = new Set();
125
+ this.specifierToCache.forEach(function (cache) {
126
+ var fileNames = Object.keys(cache).filter(function (fileName) {
127
+ var foundImport = absoluteImports.find(function (storyImport) {
128
+ return fileName.startsWith(storyImport);
129
+ });
130
+ if (foundImport) foundImports.add(foundImport);
131
+ return !!foundImport;
132
+ });
133
+ fileNames.forEach(function (fileName) {
134
+ var cacheEntry = cache[fileName];
135
+
136
+ if (cacheEntry && cacheEntry.type === 'stories') {
137
+ dependencies.push(cacheEntry);
138
+ } else {
139
+ throw new Error(`Unexpected dependency: ${cacheEntry}`);
140
+ }
141
+ });
142
+ }); // imports can include non-story imports, so it's ok if
143
+ // there are fewer foundImports than absoluteImports
144
+ // if (absoluteImports.length !== foundImports.size) {
145
+ // throw new Error(`Missing dependencies: ${absoluteImports.filter((p) => !foundImports.has(p))}`));
146
+ // }
147
+
148
+ return dependencies;
149
+ }
150
+
151
+ async extractDocs(specifier, absolutePath) {
152
+ var _this4 = this;
153
+
154
+ var relativePath = path.relative(this.options.workingDir, absolutePath);
155
+
156
+ try {
157
+ if (!this.options.storyStoreV7) {
158
+ throw new Error(`You cannot use \`.mdx\` files without using \`storyStoreV7\`.`);
159
+ }
160
+
161
+ var normalizedPath = normalizeStoryPath(relativePath);
162
+ var importPath = slash(normalizedPath); // This `await require(...)` is a bit of a hack. It's necessary because
163
+ // `docs-mdx` depends on ESM code, which must be asynchronously imported
164
+ // to be used in CJS. Unfortunately, we cannot use `import()` here, because
165
+ // it will be transpiled down to `require()` by Babel. So instead, we require
166
+ // a CJS export from `@storybook/docs-mdx` that does the `async import` for us.
167
+ // eslint-disable-next-line global-require
168
+
169
+ var _await$require = await require('@storybook/docs-mdx'),
170
+ analyze = _await$require.analyze;
171
+
172
+ var content = await fs.readFile(absolutePath, 'utf8'); // { title?, of?, imports? }
173
+
174
+ var result = analyze(content);
175
+ var absoluteImports = result.imports.map(function (p) {
176
+ return makeAbsolute(p, normalizedPath, _this4.options.workingDir);
177
+ }); // Go through the cache and collect all of the cache entries that this docs file depends on.
178
+ // We'll use this to make sure this docs cache entry is invalidated when any of its dependents
179
+ // are invalidated.
180
+
181
+ var dependencies = this.findDependencies(absoluteImports); // Also, if `result.of` is set, it means that we're using the `<Meta of={XStories} />` syntax,
182
+ // so find the `title` defined the file that `meta` points to.
183
+
184
+ var ofTitle;
185
+
186
+ if (result.of) {
187
+ var absoluteOf = makeAbsolute(result.of, normalizedPath, this.options.workingDir);
188
+ dependencies.forEach(function (dep) {
189
+ if (dep.entries.length > 0) {
190
+ var first = dep.entries[0];
191
+
192
+ if (path.resolve(_this4.options.workingDir, first.importPath).startsWith(absoluteOf)) {
193
+ ofTitle = first.title;
194
+ }
195
+ }
196
+ });
197
+ if (!ofTitle) throw new Error(`Could not find "${result.of}" for docs file "${relativePath}".`);
198
+ } // Track that we depend on this for easy invalidation later.
199
+
200
+
201
+ dependencies.forEach(function (dep) {
202
+ dep.dependents.push(absolutePath);
203
+ });
204
+ var title = userOrAutoTitleFromSpecifier(importPath, specifier, result.title || ofTitle);
205
+ var name = 'docs';
206
+ var id = toId(title, name);
207
+ var docsEntry = {
208
+ id: id,
209
+ title: title,
210
+ name: name,
211
+ importPath: importPath,
212
+ storiesImports: dependencies.map(function (dep) {
213
+ return dep.entries[0].importPath;
214
+ }),
215
+ type: 'docs'
216
+ };
217
+ return docsEntry;
218
+ } catch (err) {
219
+ logger.warn(`🚨 Extraction error on ${relativePath}: ${err}`);
220
+ throw err;
221
+ }
84
222
  }
85
223
 
86
224
  async index(filePath, options) {
@@ -97,8 +235,7 @@ export class StoryIndexGenerator {
97
235
 
98
236
  async extractStories(specifier, absolutePath) {
99
237
  var relativePath = path.relative(this.options.workingDir, absolutePath);
100
- var fileStories = {};
101
- var entry = this.storyIndexEntries.get(specifier);
238
+ var entries = [];
102
239
 
103
240
  try {
104
241
  var importPath = slash(normalizeStoryPath(relativePath));
@@ -112,14 +249,23 @@ export class StoryIndexGenerator {
112
249
  });
113
250
  csf.stories.forEach(function ({
114
251
  id: id,
115
- name: name
252
+ name: name,
253
+ parameters: parameters
116
254
  }) {
117
- fileStories[id] = {
255
+ var base = {
118
256
  id: id,
119
257
  title: csf.meta.title,
120
258
  name: name,
121
259
  importPath: importPath
122
260
  };
261
+ var entry = parameters !== null && parameters !== void 0 && parameters.docsOnly ? _objectSpread(_objectSpread({}, base), {}, {
262
+ type: 'docs',
263
+ storiesImports: [],
264
+ legacy: true
265
+ }) : _objectSpread(_objectSpread({}, base), {}, {
266
+ type: 'story'
267
+ });
268
+ entries.push(entry);
123
269
  });
124
270
  } catch (err) {
125
271
  if (err.name === 'NoMetaError') {
@@ -130,16 +276,19 @@ export class StoryIndexGenerator {
130
276
  }
131
277
  }
132
278
 
133
- entry[absolutePath] = fileStories;
134
- return fileStories;
279
+ return {
280
+ entries: entries,
281
+ type: 'stories',
282
+ dependents: []
283
+ };
135
284
  }
136
285
 
137
286
  async sortStories(storiesList) {
138
- var stories = {};
139
- storiesList.forEach(function (subStories) {
140
- Object.assign(stories, subStories);
287
+ var entries = {};
288
+ storiesList.forEach(function (entry) {
289
+ entries[entry.id] = entry;
141
290
  });
142
- var sortableStories = Object.values(stories); // Skip sorting if we're in v6 mode because we don't have
291
+ var sortableStories = Object.values(entries); // Skip sorting if we're in v6 mode because we don't have
143
292
  // all the info we need here
144
293
 
145
294
  if (this.options.storyStoreV7) {
@@ -166,14 +315,15 @@ export class StoryIndexGenerator {
166
315
  var titleToStoryCount = Object.values(sorted).reduce(function (acc, story) {
167
316
  acc[story.title] = (acc[story.title] || 0) + 1;
168
317
  return acc;
169
- }, {});
318
+ }, {}); // @ts-ignore
319
+
170
320
  compat = Object.entries(sorted).reduce(function (acc, entry) {
171
321
  var _entry = _slicedToArray(entry, 2),
172
322
  id = _entry[0],
173
323
  story = _entry[1];
174
324
 
325
+ if (story.type === 'docs') return acc;
175
326
  acc[id] = _objectSpread(_objectSpread({}, story), {}, {
176
- id: id,
177
327
  kind: story.title,
178
328
  story: story.name,
179
329
  parameters: {
@@ -187,30 +337,65 @@ export class StoryIndexGenerator {
187
337
  }
188
338
 
189
339
  this.lastIndex = {
190
- v: 3,
191
- stories: compat
340
+ v: 4,
341
+ entries: compat
192
342
  };
193
343
  return this.lastIndex;
194
344
  }
195
345
 
196
346
  invalidate(specifier, importPath, removed) {
347
+ var _this5 = this;
348
+
197
349
  var absolutePath = slash(path.resolve(this.options.workingDir, importPath));
198
- var pathToEntries = this.storyIndexEntries.get(specifier);
350
+ var cache = this.specifierToCache.get(specifier);
351
+ var cacheEntry = cache[absolutePath];
352
+
353
+ if (cacheEntry && cacheEntry.type === 'stories') {
354
+ var dependents = cacheEntry.dependents;
355
+ var invalidated = new Set(); // the dependent can be in ANY cache, so we loop over all of them
356
+
357
+ this.specifierToCache.forEach(function (otherCache) {
358
+ dependents.forEach(function (dep) {
359
+ if (otherCache[dep]) {
360
+ invalidated.add(dep); // eslint-disable-next-line no-param-reassign
361
+
362
+ otherCache[dep] = false;
363
+ }
364
+ });
365
+ });
366
+ var notFound = dependents.filter(function (dep) {
367
+ return !invalidated.has(dep);
368
+ });
369
+
370
+ if (notFound.length > 0) {
371
+ throw new Error(`Could not invalidate ${notFound.length} deps: ${notFound.join(', ')}`);
372
+ }
373
+ }
199
374
 
200
375
  if (removed) {
201
- delete pathToEntries[absolutePath];
376
+ if (cacheEntry && cacheEntry.type === 'docs') {
377
+ var absoluteImports = cacheEntry.storiesImports.map(function (p) {
378
+ return path.resolve(_this5.options.workingDir, p);
379
+ });
380
+ var dependencies = this.findDependencies(absoluteImports);
381
+ dependencies.forEach(function (dep) {
382
+ return dep.dependents.splice(dep.dependents.indexOf(absolutePath), 1);
383
+ });
384
+ }
385
+
386
+ delete cache[absolutePath];
202
387
  } else {
203
- pathToEntries[absolutePath] = false;
388
+ cache[absolutePath] = false;
204
389
  }
205
390
 
206
391
  this.lastIndex = null;
207
392
  }
208
393
 
209
394
  async getStorySortParameter() {
210
- var _this3 = this;
395
+ var _this6 = this;
211
396
 
212
397
  var previewFile = ['js', 'jsx', 'ts', 'tsx'].map(function (ext) {
213
- return path.join(_this3.options.configDir, `preview.${ext}`);
398
+ return path.join(_this6.options.configDir, `preview.${ext}`);
214
399
  }).find(function (fname) {
215
400
  return fs.existsSync(fname);
216
401
  });
@@ -226,7 +411,7 @@ export class StoryIndexGenerator {
226
411
 
227
412
 
228
413
  storyFileNames() {
229
- return Array.from(this.storyIndexEntries.values()).flatMap(function (r) {
414
+ return Array.from(this.specifierToCache.values()).flatMap(function (r) {
230
415
  return Object.keys(r);
231
416
  });
232
417
  }
@@ -1,13 +1,25 @@
1
+ var _excluded = ["type"];
2
+
3
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
4
+
5
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
6
+
7
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
+
9
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
10
+
11
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
12
+
1
13
  import "core-js/modules/es.promise.js";
2
14
  import fs from 'fs-extra';
3
- import { debounce } from 'lodash';
15
+ import debounce from 'lodash/debounce';
4
16
  import { STORY_INDEX_INVALIDATED } from '@storybook/core-events';
5
17
  import { watchStorySpecifiers } from './watch-story-specifiers';
6
18
  export var DEBOUNCE = 100;
7
- export async function extractStoriesJson(outputFile, initializedStoryIndexGenerator) {
19
+ export async function extractStoriesJson(outputFile, initializedStoryIndexGenerator, transform) {
8
20
  var generator = await initializedStoryIndexGenerator;
9
21
  var storyIndex = await generator.getIndex();
10
- await fs.writeJson(outputFile, storyIndex);
22
+ await fs.writeJson(outputFile, transform ? transform(storyIndex) : storyIndex);
11
23
  }
12
24
  export function useStoriesJson({
13
25
  router: router,
@@ -28,15 +40,52 @@ export function useStoriesJson({
28
40
  generator.invalidate(specifier, path, removed);
29
41
  maybeInvalidate();
30
42
  });
43
+ router.use('/index.json', async function (req, res) {
44
+ try {
45
+ var generator = await initializedStoryIndexGenerator;
46
+
47
+ var _index = await generator.getIndex();
48
+
49
+ res.header('Content-Type', 'application/json');
50
+ res.send(JSON.stringify(_index));
51
+ } catch (err) {
52
+ res.status(500);
53
+ res.send(err.message);
54
+ }
55
+ });
31
56
  router.use('/stories.json', async function (req, res) {
32
57
  try {
33
58
  var generator = await initializedStoryIndexGenerator;
34
- var index = await generator.getIndex();
59
+
60
+ var _index2 = convertToIndexV3(await generator.getIndex());
61
+
35
62
  res.header('Content-Type', 'application/json');
36
- res.send(JSON.stringify(index));
63
+ res.send(JSON.stringify(_index2));
37
64
  } catch (err) {
38
65
  res.status(500);
39
66
  res.send(err.message);
40
67
  }
41
68
  });
42
- }
69
+ }
70
+ export var convertToIndexV3 = function (index) {
71
+ var entries = index.entries;
72
+ var stories = Object.entries(entries).reduce(function (acc, [id, entry]) {
73
+ var type = entry.type,
74
+ rest = _objectWithoutProperties(entry, _excluded);
75
+
76
+ acc[id] = _objectSpread(_objectSpread({}, rest), {}, {
77
+ kind: rest.title,
78
+ story: rest.name,
79
+ parameters: {
80
+ __id: rest.id,
81
+ docsOnly: type === 'docs',
82
+ fileName: rest.importPath
83
+ }
84
+ });
85
+ return acc;
86
+ }, {});
87
+ return {
88
+ v: 3,
89
+ stories: stories
90
+ };
91
+ };
@@ -4,6 +4,7 @@ import slash from 'slash';
4
4
  import fs from 'fs';
5
5
  import path from 'path';
6
6
  import glob from 'globby';
7
+ import uniq from 'lodash/uniq';
7
8
 
8
9
  var isDirectory = function (directory) {
9
10
  try {
@@ -29,9 +30,9 @@ export function watchStorySpecifiers(specifiers, options, onInvalidate) {
29
30
  ignored: ['**/.git', 'node_modules']
30
31
  });
31
32
  wp.watch({
32
- directories: specifiers.map(function (ns) {
33
+ directories: uniq(specifiers.map(function (ns) {
33
34
  return ns.directory;
34
- })
35
+ }))
35
36
  });
36
37
 
37
38
  async function onChangeOrRemove(watchpackPath, removed) {
@@ -1,2 +1,4 @@
1
1
  import type { LoadOptions, CLIOptions, BuilderOptions } from '@storybook/core-common';
2
- export declare function buildStaticStandalone(options: CLIOptions & LoadOptions & BuilderOptions): Promise<void>;
2
+ export declare function buildStaticStandalone(options: CLIOptions & LoadOptions & BuilderOptions & {
3
+ outputDir: string;
4
+ }): Promise<void>;
@@ -1,5 +1,12 @@
1
- import type { Path, StoryIndex } from '@storybook/store';
1
+ import type { Path, StoryIndex, IndexEntry, DocsIndexEntry } from '@storybook/store';
2
2
  import type { StoryIndexer, IndexerOptions, NormalizedStoriesSpecifier } from '@storybook/core-common';
3
+ declare type DocsCacheEntry = DocsIndexEntry;
4
+ declare type StoriesCacheEntry = {
5
+ entries: IndexEntry[];
6
+ dependents: Path[];
7
+ type: 'stories';
8
+ };
9
+ declare type CacheEntry = false | StoriesCacheEntry | DocsCacheEntry;
3
10
  export declare class StoryIndexGenerator {
4
11
  readonly specifiers: NormalizedStoriesSpecifier[];
5
12
  readonly options: {
@@ -9,7 +16,7 @@ export declare class StoryIndexGenerator {
9
16
  storyStoreV7: boolean;
10
17
  storyIndexers: StoryIndexer[];
11
18
  };
12
- private storyIndexEntries;
19
+ private specifierToCache;
13
20
  private lastIndex?;
14
21
  constructor(specifiers: NormalizedStoriesSpecifier[], options: {
15
22
  workingDir: Path;
@@ -19,12 +26,20 @@ export declare class StoryIndexGenerator {
19
26
  storyIndexers: StoryIndexer[];
20
27
  });
21
28
  initialize(): Promise<void>;
22
- ensureExtracted(): Promise<StoryIndex['stories'][]>;
29
+ /**
30
+ * Run the updater function over all the empty cache entries
31
+ */
32
+ updateExtracted(updater: (specifier: NormalizedStoriesSpecifier, absolutePath: Path) => Promise<CacheEntry>): Promise<void>;
33
+ isDocsMdx(absolutePath: Path): boolean;
34
+ ensureExtracted(): Promise<IndexEntry[]>;
35
+ findDependencies(absoluteImports: Path[]): StoriesCacheEntry[];
36
+ extractDocs(specifier: NormalizedStoriesSpecifier, absolutePath: Path): Promise<DocsIndexEntry>;
23
37
  index(filePath: string, options: IndexerOptions): Promise<import("@storybook/core-common").StoryIndex>;
24
- extractStories(specifier: NormalizedStoriesSpecifier, absolutePath: Path): Promise<Record<string, import("@storybook/store").StoryIndexEntry>>;
25
- sortStories(storiesList: StoryIndex['stories'][]): Promise<Record<string, import("@storybook/store").StoryIndexEntry>>;
38
+ extractStories(specifier: NormalizedStoriesSpecifier, absolutePath: Path): Promise<StoriesCacheEntry>;
39
+ sortStories(storiesList: IndexEntry[]): Promise<Record<string, IndexEntry>>;
26
40
  getIndex(): Promise<StoryIndex>;
27
41
  invalidate(specifier: NormalizedStoriesSpecifier, importPath: Path, removed: boolean): void;
28
42
  getStorySortParameter(): Promise<any>;
29
43
  storyFileNames(): string[];
30
44
  }
45
+ export {};
@@ -1,9 +1,10 @@
1
1
  import { Router } from 'express';
2
2
  import type { NormalizedStoriesSpecifier } from '@storybook/core-common';
3
+ import type { StoryIndex, StoryIndexV3 } from '@storybook/store';
3
4
  import { StoryIndexGenerator } from './StoryIndexGenerator';
4
5
  import { ServerChannel } from './get-server-channel';
5
6
  export declare const DEBOUNCE = 100;
6
- export declare function extractStoriesJson(outputFile: string, initializedStoryIndexGenerator: Promise<StoryIndexGenerator>): Promise<void>;
7
+ export declare function extractStoriesJson(outputFile: string, initializedStoryIndexGenerator: Promise<StoryIndexGenerator>, transform?: (index: StoryIndex) => any): Promise<void>;
7
8
  export declare function useStoriesJson({ router, initializedStoryIndexGenerator, workingDir, serverChannel, normalizedStories, }: {
8
9
  router: Router;
9
10
  initializedStoryIndexGenerator: Promise<StoryIndexGenerator>;
@@ -11,3 +12,4 @@ export declare function useStoriesJson({ router, initializedStoryIndexGenerator,
11
12
  workingDir?: string;
12
13
  normalizedStories: NormalizedStoriesSpecifier[];
13
14
  }): void;
15
+ export declare const convertToIndexV3: (index: StoryIndex) => StoryIndexV3;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/core-server",
3
- "version": "7.0.0-alpha.3",
3
+ "version": "7.0.0-alpha.6",
4
4
  "description": "Storybook framework-agnostic API",
5
5
  "keywords": [
6
6
  "storybook"
@@ -33,16 +33,17 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@discoveryjs/json-ext": "^0.5.3",
36
- "@storybook/core-client": "7.0.0-alpha.3",
37
- "@storybook/core-common": "7.0.0-alpha.3",
38
- "@storybook/core-events": "7.0.0-alpha.3",
36
+ "@storybook/core-client": "7.0.0-alpha.6",
37
+ "@storybook/core-common": "7.0.0-alpha.6",
38
+ "@storybook/core-events": "7.0.0-alpha.6",
39
39
  "@storybook/csf": "0.0.2--canary.4566f4d.1",
40
- "@storybook/csf-tools": "7.0.0-alpha.3",
41
- "@storybook/manager-webpack5": "7.0.0-alpha.3",
42
- "@storybook/node-logger": "7.0.0-alpha.3",
40
+ "@storybook/csf-tools": "7.0.0-alpha.6",
41
+ "@storybook/docs-mdx": "0.0.1-canary.1.4bea5cc.0",
42
+ "@storybook/manager-webpack5": "7.0.0-alpha.6",
43
+ "@storybook/node-logger": "7.0.0-alpha.6",
43
44
  "@storybook/semver": "^7.3.2",
44
- "@storybook/store": "7.0.0-alpha.3",
45
- "@storybook/telemetry": "7.0.0-alpha.3",
45
+ "@storybook/store": "7.0.0-alpha.6",
46
+ "@storybook/telemetry": "7.0.0-alpha.6",
46
47
  "@types/node": "^14.0.10 || ^16.0.0",
47
48
  "@types/node-fetch": "^2.5.7",
48
49
  "@types/pretty-hrtime": "^1.0.0",
@@ -66,7 +67,6 @@
66
67
  "pretty-hrtime": "^1.0.3",
67
68
  "prompts": "^2.4.0",
68
69
  "read-pkg-up": "^7.0.1",
69
- "regenerator-runtime": "^0.13.7",
70
70
  "serve-favicon": "^2.5.0",
71
71
  "slash": "^3.0.0",
72
72
  "telejson": "^6.0.8",
@@ -78,7 +78,7 @@
78
78
  "x-default-browser": "^0.4.0"
79
79
  },
80
80
  "devDependencies": {
81
- "@storybook/builder-webpack5": "7.0.0-alpha.3",
81
+ "@storybook/builder-webpack5": "7.0.0-alpha.6",
82
82
  "@types/compression": "^1.7.0",
83
83
  "@types/ip": "^1.1.0",
84
84
  "@types/serve-favicon": "^2.5.2",
@@ -103,5 +103,5 @@
103
103
  "publishConfig": {
104
104
  "access": "public"
105
105
  },
106
- "gitHead": "629b056190993bcee6445471b8cb27208eb401a9"
106
+ "gitHead": "a88dcca40ba169a373bad33dd76e9a4bd4f1f5ec"
107
107
  }
package/typings.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  declare module 'global';
2
2
  declare module '@storybook/semver';
3
- declare module 'unfetch/dist/unfetch';
4
3
  declare module 'lazy-universal-dotenv';
5
4
  declare module 'pnp-webpack-plugin';
6
5
  declare module '@storybook/theming/paths';