@storybook/cli 7.0.0-alpha.18 → 7.0.0-alpha.20

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.
Files changed (37) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/automigrate/fixes/index.js +5 -1
  3. package/dist/cjs/automigrate/fixes/new-frameworks.js +249 -0
  4. package/dist/cjs/automigrate/fixes/sb-scripts.js +140 -0
  5. package/dist/cjs/automigrate/index.js +1 -1
  6. package/dist/cjs/generate.js +1 -1
  7. package/dist/cjs/helpers.js +18 -0
  8. package/dist/cjs/js-package-manager/JsPackageManager.js +42 -0
  9. package/dist/cjs/js-package-manager/NPMProxy.js +14 -0
  10. package/dist/cjs/js-package-manager/Yarn1Proxy.js +5 -0
  11. package/dist/cjs/js-package-manager/Yarn2Proxy.js +5 -0
  12. package/dist/cjs/repro-next.js +23 -14
  13. package/dist/cjs/repro-templates.js +15 -2
  14. package/dist/cjs/versions.js +75 -75
  15. package/dist/esm/automigrate/fixes/index.js +3 -1
  16. package/dist/esm/automigrate/fixes/new-frameworks.js +225 -0
  17. package/dist/esm/automigrate/fixes/sb-scripts.js +119 -0
  18. package/dist/esm/automigrate/index.js +1 -1
  19. package/dist/esm/generate.js +1 -1
  20. package/dist/esm/helpers.js +15 -0
  21. package/dist/esm/js-package-manager/JsPackageManager.js +42 -0
  22. package/dist/esm/js-package-manager/NPMProxy.js +14 -0
  23. package/dist/esm/js-package-manager/Yarn1Proxy.js +5 -0
  24. package/dist/esm/js-package-manager/Yarn2Proxy.js +5 -0
  25. package/dist/esm/repro-next.js +22 -13
  26. package/dist/esm/repro-templates.js +15 -2
  27. package/dist/esm/versions.js +75 -75
  28. package/dist/types/automigrate/fixes/new-frameworks.d.ts +31 -0
  29. package/dist/types/automigrate/fixes/sb-scripts.d.ts +23 -0
  30. package/dist/types/helpers.d.ts +1 -0
  31. package/dist/types/js-package-manager/JsPackageManager.d.ts +16 -0
  32. package/dist/types/js-package-manager/NPMProxy.d.ts +3 -0
  33. package/dist/types/js-package-manager/Yarn1Proxy.d.ts +1 -0
  34. package/dist/types/js-package-manager/Yarn2Proxy.d.ts +1 -0
  35. package/dist/types/repro-next.d.ts +2 -1
  36. package/dist/types/repro-templates.d.ts +2 -0
  37. package/package.json +9 -10
package/README.md CHANGED
@@ -53,4 +53,4 @@ If the CLI cannot detect your project type, it will ask you. You can also force
53
53
  npx sb init --type <type>
54
54
  ```
55
55
 
56
- Where type is one of the project types defined in [project_types.js](https://github.com/storybookjs/storybook/blob/next/lib/cli/src/project_types.ts)
56
+ Where type is one of the project types defined in [project_types.ts](https://github.com/storybookjs/storybook/blob/next/code/lib/cli/src/project_types.ts)
@@ -24,6 +24,10 @@ var _builderVite = require("./builder-vite");
24
24
 
25
25
  var _npm = require("./npm7");
26
26
 
27
+ var _sbScripts = require("./sb-scripts");
28
+
29
+ var _newFrameworks = require("./new-frameworks");
30
+
27
31
  var _types = require("../types");
28
32
 
29
33
  Object.keys(_types).forEach(function (key) {
@@ -37,5 +41,5 @@ Object.keys(_types).forEach(function (key) {
37
41
  }
38
42
  });
39
43
  });
40
- const fixes = [_cra.cra5, _webpack.webpack5, _angular.angular12, _vue.vue3, _mainjsFramework.mainjsFramework, _eslintPlugin.eslintPlugin, _builderVite.builderVite, _npm.npm7];
44
+ const fixes = [_cra.cra5, _webpack.webpack5, _angular.angular12, _vue.vue3, _mainjsFramework.mainjsFramework, _eslintPlugin.eslintPlugin, _builderVite.builderVite, _npm.npm7, _sbScripts.sbScripts, _newFrameworks.newFrameworks];
41
45
  exports.fixes = fixes;
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.newFrameworks = exports.getFrameworkOptions = exports.getBuilder = void 0;
7
+
8
+ var _chalk = _interopRequireDefault(require("chalk"));
9
+
10
+ var _tsDedent = _interopRequireDefault(require("ts-dedent"));
11
+
12
+ var _semver = _interopRequireDefault(require("@storybook/semver"));
13
+
14
+ var _csfTools = require("@storybook/csf-tools");
15
+
16
+ var _coreCommon = require("@storybook/core-common");
17
+
18
+ var _helpers = require("../../helpers");
19
+
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
+
22
+ const logger = console;
23
+ const packagesMap = {
24
+ '@storybook/react': {
25
+ webpack5: '@storybook/react-webpack5',
26
+ vite: '@storybook/react-vite'
27
+ },
28
+ '@storybook/preact': {
29
+ webpack5: '@storybook/preact-webpack5'
30
+ },
31
+ '@storybook/server': {
32
+ webpack5: '@storybook/server-webpack5'
33
+ },
34
+ '@storybook/angular': {
35
+ webpack5: '@storybook/angular'
36
+ },
37
+ '@storybook/vue': {
38
+ webpack5: '@storybook/vue-webpack5',
39
+ vite: '@storybook/vue-vite'
40
+ },
41
+ '@storybook/vue3': {
42
+ webpack5: '@storybook/vue3-webpack5',
43
+ vite: '@storybook/vue3-vite'
44
+ },
45
+ '@storybook/svelte': {
46
+ webpack5: '@storybook/svelte-webpack5',
47
+ vite: '@storybook/svelte-vite'
48
+ },
49
+ '@storybook/web-components': {
50
+ webpack5: '@storybook/web-components-webpack5'
51
+ },
52
+ '@storybook/html': {
53
+ webpack5: '@storybook/html-webpack5'
54
+ }
55
+ };
56
+
57
+ const getBuilder = builder => {
58
+ if (typeof builder === 'string') {
59
+ return builder.includes('vite') ? 'vite' : 'webpack5';
60
+ }
61
+
62
+ return builder !== null && builder !== void 0 && builder.name.includes('vite') ? 'vite' : 'webpack5';
63
+ };
64
+
65
+ exports.getBuilder = getBuilder;
66
+
67
+ const getFrameworkOptions = (framework, main) => {
68
+ const frameworkOptions = main.getFieldValue([`${framework}Options`]);
69
+ return frameworkOptions || {};
70
+ };
71
+ /**
72
+ * Does the user have separate framework and builders (e.g. @storybook/react + core.builder -> webpack5?
73
+ *
74
+ * If so:
75
+ * - Remove the dependencies (@storybook/react + @storybook/builder-webpack5 + @storybook/manager-webpack5)
76
+ * - Install the correct new package e.g. (@storybook/react-webpack5)
77
+ * - Update the main config to use the new framework
78
+ * -- moving core.builder into framework.options.builder
79
+ * -- moving frameworkOptions (e.g. reactOptions) into framework.options
80
+ */
81
+
82
+
83
+ exports.getFrameworkOptions = getFrameworkOptions;
84
+ const newFrameworks = {
85
+ id: 'newFrameworks',
86
+
87
+ async check({
88
+ packageManager
89
+ }) {
90
+ var _semver$coerce;
91
+
92
+ const packageJson = packageManager.retrievePackageJson();
93
+ const allDeps = Object.assign({}, packageJson.dependencies, packageJson.devDependencies);
94
+ const config = (0, _coreCommon.getStorybookInfo)(packageJson);
95
+ const {
96
+ mainConfig,
97
+ version: storybookVersion,
98
+ framework
99
+ } = config;
100
+
101
+ if (!mainConfig) {
102
+ logger.warn('Unable to find storybook main.js config, skipping');
103
+ return null;
104
+ }
105
+
106
+ const storybookCoerced = storybookVersion && ((_semver$coerce = _semver.default.coerce(storybookVersion)) === null || _semver$coerce === void 0 ? void 0 : _semver$coerce.version);
107
+
108
+ if (!storybookCoerced) {
109
+ logger.warn((0, _tsDedent.default)`
110
+ ❌ Unable to determine storybook version, skipping ${_chalk.default.cyan('newFrameworks')} fix.
111
+ 🤔 Are you running automigrate from your project directory?
112
+ `);
113
+ return null;
114
+ }
115
+
116
+ if (!_semver.default.gte(storybookCoerced, '7.0.0')) {
117
+ return null;
118
+ } // If in the future the eslint plugin has a framework option, using main to extract the framework field will be very useful
119
+
120
+
121
+ const main = await (0, _csfTools.readConfig)(mainConfig);
122
+ const frameworkPackage = main.getFieldValue(['framework']);
123
+ const builder = main.getFieldValue(['core', 'builder']);
124
+
125
+ if (!frameworkPackage) {
126
+ return null;
127
+ }
128
+
129
+ const supportedPackages = Object.keys(packagesMap);
130
+
131
+ if (!supportedPackages.includes(frameworkPackage)) {
132
+ return null;
133
+ }
134
+
135
+ const builderInfo = {
136
+ name: getBuilder(builder),
137
+ options: main.getFieldValue(['core', 'builder', 'options']) || {}
138
+ }; // TODO: once we have vite frameworks e.g. @storybook/react-vite, then we support it here
139
+ // and remove ['storybook-builder-vite', '@storybook/builder-vite'] from deps
140
+
141
+ if (builderInfo.name === 'vite') {
142
+ return null;
143
+ }
144
+
145
+ const frameworkOptions = getFrameworkOptions(framework, main);
146
+ const dependenciesToRemove = ['@storybook/builder-webpack5', '@storybook/manager-webpack5', '@storybook/builder-webpack4', '@storybook/manager-webpack4'].filter(dep => allDeps[dep]);
147
+ const newFrameworkPackage = packagesMap[frameworkPackage][builderInfo.name];
148
+ const dependenciesToAdd = []; // some frameworks didn't change e.g. Angular, Ember
149
+
150
+ if (newFrameworkPackage !== frameworkPackage) {
151
+ dependenciesToRemove.push(frameworkPackage);
152
+ dependenciesToAdd.push(newFrameworkPackage);
153
+ }
154
+
155
+ return {
156
+ main,
157
+ dependenciesToAdd,
158
+ dependenciesToRemove,
159
+ frameworkPackage: newFrameworkPackage,
160
+ frameworkOptions,
161
+ builderInfo,
162
+ packageJson
163
+ };
164
+ },
165
+
166
+ prompt() {
167
+ return (0, _tsDedent.default)`
168
+ We've detected you are using an older format of Storybook frameworks and builders.
169
+
170
+ In Storybook 7, frameworks also specify the builder to be used.
171
+
172
+ We can remove the dependencies that are no longer needed and install the new framework that already includes the builder.
173
+
174
+ To learn more about the framework field, see: ${_chalk.default.yellow('https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#framework-field-mandatory')}
175
+
176
+ ${_chalk.default.underline(_chalk.default.bold(_chalk.default.cyan('Webpack4 users')))}
177
+
178
+ Unless you're using Storybook's Vite builder, this automigration will install a Webpack5-based framework.
179
+
180
+ If you were using Storybook's Webpack4 builder (default in 6.x, discontinued in 7.0), this could be a breaking
181
+ change--especially if your project has a custom webpack configuration.
182
+
183
+ To learn more about migrating from Webpack4, see: ${_chalk.default.yellow('https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#webpack4-support-discontinued')}
184
+ `;
185
+ },
186
+
187
+ async run({
188
+ result: {
189
+ dependenciesToAdd,
190
+ dependenciesToRemove,
191
+ main,
192
+ frameworkPackage,
193
+ frameworkOptions,
194
+ builderInfo,
195
+ packageJson
196
+ },
197
+ packageManager,
198
+ dryRun
199
+ }) {
200
+ logger.info(`✅ Removing legacy dependencies: ${dependenciesToRemove.join(', ')}`);
201
+
202
+ if (!dryRun) {
203
+ packageManager.removeDependencies({
204
+ skipInstall: dependenciesToAdd.length > 0,
205
+ packageJson
206
+ }, dependenciesToRemove);
207
+ }
208
+
209
+ if (dependenciesToAdd.length > 0) {
210
+ logger.info(`✅ Installing new dependencies: ${dependenciesToAdd.join(', ')}`);
211
+
212
+ if (!dryRun) {
213
+ const versionToInstall = (0, _helpers.getStorybookVersionSpecifier)(packageJson);
214
+ const depsToAdd = dependenciesToAdd.map(dep => `${dep}@${versionToInstall}`);
215
+ packageManager.addDependencies({
216
+ installAsDevDependencies: true
217
+ }, depsToAdd);
218
+ }
219
+ }
220
+
221
+ if (!dryRun) {
222
+ logger.info(`✅ Updating framework field in main.js`);
223
+ const currentCore = main.getFieldValue(['core']);
224
+ main.setFieldValue(['framework', 'name'], frameworkPackage);
225
+ main.setFieldValue(['framework', 'options'], frameworkOptions);
226
+
227
+ if (currentCore !== null && currentCore !== void 0 && currentCore.builder) {
228
+ delete currentCore.builder;
229
+ }
230
+
231
+ if (Object.keys(builderInfo.options).length > 0) {
232
+ main.setFieldValue(['framework', 'options', 'builder'], builderInfo.options);
233
+ }
234
+
235
+ if (currentCore) {
236
+ if (Object.keys(currentCore).length === 0) {
237
+ // TODO: this should delete the field instead
238
+ main.setFieldValue(['core'], {});
239
+ } else {
240
+ main.setFieldValue(['core'], currentCore);
241
+ }
242
+ }
243
+
244
+ await (0, _csfTools.writeConfig)(main);
245
+ }
246
+ }
247
+
248
+ };
249
+ exports.newFrameworks = newFrameworks;
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.sbScripts = exports.getStorybookScripts = void 0;
7
+
8
+ var _chalk = _interopRequireDefault(require("chalk"));
9
+
10
+ var _tsDedent = require("ts-dedent");
11
+
12
+ var _semver = _interopRequireDefault(require("@storybook/semver"));
13
+
14
+ var _coreCommon = require("@storybook/core-common");
15
+
16
+ var _helpers = require("../../helpers");
17
+
18
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
+
20
+ const logger = console;
21
+
22
+ const getStorybookScripts = scripts => {
23
+ const storybookScripts = {
24
+ custom: {},
25
+ official: {}
26
+ };
27
+ Object.keys(scripts).forEach(key => {
28
+ if (key === 'storybook' || key === 'build-storybook') {
29
+ storybookScripts.official[key] = scripts[key];
30
+ } else if (scripts[key].match(/start-storybook/) || scripts[key].match(/build-storybook/)) {
31
+ storybookScripts.custom[key] = scripts[key];
32
+ }
33
+ });
34
+ return storybookScripts;
35
+ };
36
+ /**
37
+ * Is the user using start-storybook
38
+ *
39
+ * If so:
40
+ * - Add storybook dependency
41
+ * - Change start-storybook and build-storybook scripts
42
+ */
43
+
44
+
45
+ exports.getStorybookScripts = getStorybookScripts;
46
+ const sbScripts = {
47
+ id: 'sb-scripts',
48
+
49
+ async check({
50
+ packageManager
51
+ }) {
52
+ var _semver$coerce;
53
+
54
+ const packageJson = packageManager.retrievePackageJson();
55
+ const {
56
+ scripts = {},
57
+ devDependencies,
58
+ dependencies
59
+ } = packageJson;
60
+ const {
61
+ version: storybookVersion
62
+ } = (0, _coreCommon.getStorybookInfo)(packageJson);
63
+ const allDeps = Object.assign({}, dependencies, devDependencies);
64
+ const storybookCoerced = storybookVersion && ((_semver$coerce = _semver.default.coerce(storybookVersion)) === null || _semver$coerce === void 0 ? void 0 : _semver$coerce.version);
65
+
66
+ if (!storybookCoerced) {
67
+ logger.warn((0, _tsDedent.dedent)`
68
+ ❌ Unable to determine storybook version, skipping ${_chalk.default.cyan('sb-scripts')} fix.
69
+ 🤔 Are you running automigrate from your project directory?
70
+ `);
71
+ return null;
72
+ }
73
+
74
+ if (allDeps.sb || allDeps.storybook) {
75
+ return null;
76
+ }
77
+
78
+ const storybookScripts = getStorybookScripts(scripts);
79
+
80
+ if (Object.keys(storybookScripts.official).length === 0 && Object.keys(storybookScripts.custom).length === 0) {
81
+ return null;
82
+ }
83
+
84
+ Object.keys(storybookScripts.official).forEach(key => {
85
+ storybookScripts.official[key] = storybookScripts.official[key].replace('start-storybook', 'storybook dev').replace('build-storybook', 'storybook build');
86
+ });
87
+ return _semver.default.gte(storybookCoerced, '7.0.0') ? {
88
+ packageJson,
89
+ storybookScripts,
90
+ storybookVersion
91
+ } : null;
92
+ },
93
+
94
+ prompt({
95
+ storybookVersion
96
+ }) {
97
+ const sbFormatted = _chalk.default.cyan(`Storybook ${storybookVersion}`);
98
+
99
+ const explanationMessage = [`Starting in Storybook 7, the ${_chalk.default.yellow('start-storybook')} and ${_chalk.default.yellow('build-storybook')} binaries have changed to ${_chalk.default.magenta('storybook dev')} and ${_chalk.default.magenta('storybook build')} respectively.`, `In order to work with ${sbFormatted}, Storybook's ${_chalk.default.magenta('storybook')} binary has to be installed and your storybook scripts have to be adjusted to use the binary. We can install the storybook binary and attempt to adjust your scripts for you.`].join('\n');
100
+ return [`We've detected you are using ${sbFormatted} with scripts from previous versions of Storybook.`, explanationMessage, `More info: ${_chalk.default.yellow('https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#start-storybook--build-storybook-binaries-removed')}`].filter(Boolean).join('\n\n');
101
+ },
102
+
103
+ async run({
104
+ result: {
105
+ storybookScripts,
106
+ packageJson
107
+ },
108
+ packageManager,
109
+ dryRun
110
+ }) {
111
+ logger.log();
112
+ logger.info(`Adding 'storybook' as dev dependency`);
113
+ logger.log();
114
+
115
+ if (!dryRun) {
116
+ const versionToInstall = (0, _helpers.getStorybookVersionSpecifier)(packageJson);
117
+ packageManager.addDependencies({
118
+ installAsDevDependencies: true
119
+ }, [`storybook@${versionToInstall}`]);
120
+ }
121
+
122
+ logger.info(`Updating scripts in package.json`);
123
+ logger.log();
124
+
125
+ if (!dryRun && Object.keys(storybookScripts.official).length > 0) {
126
+ const message = [`Migrating your scripts to:`, _chalk.default.yellow(JSON.stringify(storybookScripts.official, null, 2))].join('\n');
127
+ logger.log(message);
128
+ logger.log();
129
+ packageManager.addScripts(storybookScripts.official);
130
+ }
131
+
132
+ if (!dryRun && Object.keys(storybookScripts.custom).length > 0) {
133
+ const message = [`We detected custom scripts that we can't automigrate:`, _chalk.default.yellow(JSON.stringify(storybookScripts.custom, null, 2)), '\n', `Please manually migrate the ones applicable and use the documentation below for reference: ${_chalk.default.yellow('https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#start-storybook--build-storybook-binaries-removed')}`].join('\n');
134
+ logger.log(message);
135
+ logger.log();
136
+ }
137
+ }
138
+
139
+ };
140
+ exports.sbScripts = sbScripts;
@@ -79,7 +79,7 @@ const automigrate = async ({
79
79
  logger.info(`✅ ran ${_chalk.default.cyan(f.id)} migration`);
80
80
  } catch (error) {
81
81
  logger.info(`❌ error when running ${_chalk.default.cyan(f.id)} migration:`);
82
- logger.info(error.message);
82
+ logger.info(error);
83
83
  logger.info();
84
84
  }
85
85
  } else {
@@ -128,7 +128,7 @@ _commander.default.command('repro [outputDirectory]').description('Create a repr
128
128
  process.exit(1);
129
129
  }));
130
130
 
131
- _commander.default.command('repro-next [filterValue]').description('Create a reproduction from a set of possible templates').option('-o --output <outDir>', 'Define an output directory').option('-b --branch <branch>', 'Define the branch to degit from', 'next').action((filterValue, options) => (0, _reproNext.reproNext)(Object.assign({
131
+ _commander.default.command('repro-next [filterValue]').description('Create a reproduction from a set of possible templates').option('-o --output <outDir>', 'Define an output directory').option('-b --branch <branch>', 'Define the branch to degit from', 'next').option('--no-init', 'Whether to download a template without an initialized Storybook', false).action((filterValue, options) => (0, _reproNext.reproNext)(Object.assign({
132
132
  filterValue
133
133
  }, options)).catch(e => {
134
134
  _nodeLogger.logger.error(e);
@@ -11,6 +11,7 @@ exports.copyTemplate = copyTemplate;
11
11
  exports.getBabelDependencies = getBabelDependencies;
12
12
  exports.getBowerJson = getBowerJson;
13
13
  exports.getChars = getChars;
14
+ exports.getStorybookVersionSpecifier = getStorybookVersionSpecifier;
14
15
  exports.paddedLog = paddedLog;
15
16
  exports.readFileAsJson = readFileAsJson;
16
17
  exports.writeFileAsJson = void 0;
@@ -29,6 +30,8 @@ var _stripJsonComments = _interopRequireDefault(require("strip-json-comments"));
29
30
 
30
31
  var _dirs = require("./dirs");
31
32
 
33
+ var _versions = _interopRequireDefault(require("./versions"));
34
+
32
35
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
33
36
 
34
37
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
@@ -239,4 +242,19 @@ async function copyComponents(framework, language) {
239
242
  await _fsExtra.default.copy((0, _path.join)((0, _dirs.getBaseDir)(), 'frameworks/common'), destinationPath, {
240
243
  overwrite: true
241
244
  });
245
+ } // Given a package.json, finds any official storybook package within it
246
+ // and if it exists, returns the version of that package from the specified package.json
247
+
248
+
249
+ function getStorybookVersionSpecifier(packageJson) {
250
+ const allDeps = Object.assign({}, packageJson.dependencies, packageJson.devDependencies);
251
+ const storybookPackage = Object.keys(allDeps).find(name => {
252
+ return _versions.default[name];
253
+ });
254
+
255
+ if (!storybookPackage) {
256
+ throw new Error(`Couldn't find any official storybook packages in package.json`);
257
+ }
258
+
259
+ return allDeps[storybookPackage];
242
260
  }
@@ -134,6 +134,48 @@ class JsPackageManager {
134
134
  }
135
135
  }
136
136
  }
137
+ /**
138
+ * Remove dependencies from a project using `yarn remove` or `npm uninstall`.
139
+ *
140
+ * @param {Object} options contains `skipInstall`, `packageJson` and `installAsDevDependencies` which we use to determine how we install packages.
141
+ * @param {Array} dependencies contains a list of packages to remove.
142
+ * @example
143
+ * removeDependencies(options, [
144
+ * `@storybook/react`,
145
+ * `@storybook/addon-actions`,
146
+ * ]);
147
+ */
148
+
149
+
150
+ removeDependencies(options, dependencies) {
151
+ const {
152
+ skipInstall
153
+ } = options;
154
+
155
+ if (skipInstall) {
156
+ const {
157
+ packageJson
158
+ } = options;
159
+ dependencies.forEach(dep => {
160
+ if (packageJson.devDependencies) {
161
+ delete packageJson.devDependencies[dep];
162
+ }
163
+
164
+ if (packageJson.dependencies) {
165
+ delete packageJson.dependencies[dep];
166
+ }
167
+ });
168
+ (0, _PackageJsonHelper.writePackageJson)(packageJson);
169
+ } else {
170
+ try {
171
+ this.runRemoveDeps(dependencies);
172
+ } catch (e) {
173
+ logger.error('An error occurred while removing dependencies.');
174
+ logger.log(e.message);
175
+ process.exit(1);
176
+ }
177
+ }
178
+ }
137
179
  /**
138
180
  * Return an array of strings matching following format: `<package_name>@<package_latest_version>`
139
181
  *
@@ -16,6 +16,7 @@ class NPMProxy extends _JsPackageManager.JsPackageManager {
16
16
  super(...args);
17
17
  this.type = 'npm';
18
18
  this.installArgs = void 0;
19
+ this.uninstallArgs = void 0;
19
20
  }
20
21
 
21
22
  initPackageJson() {
@@ -55,6 +56,14 @@ class NPMProxy extends _JsPackageManager.JsPackageManager {
55
56
  return this.installArgs;
56
57
  }
57
58
 
59
+ getUninstallArgs() {
60
+ if (!this.uninstallArgs) {
61
+ this.uninstallArgs = this.needsLegacyPeerDeps(this.getNpmVersion()) ? ['uninstall', '--legacy-peer-deps'] : ['uninstall'];
62
+ }
63
+
64
+ return this.uninstallArgs;
65
+ }
66
+
58
67
  runInstall() {
59
68
  this.executeCommand('npm', this.getInstallArgs(), 'inherit');
60
69
  }
@@ -69,6 +78,11 @@ class NPMProxy extends _JsPackageManager.JsPackageManager {
69
78
  this.executeCommand('npm', [...this.getInstallArgs(), ...args], 'inherit');
70
79
  }
71
80
 
81
+ runRemoveDeps(dependencies) {
82
+ const args = [...dependencies];
83
+ this.executeCommand('npm', [...this.getUninstallArgs(), ...args], 'inherit');
84
+ }
85
+
72
86
  runGetVersions(packageName, fetchAllVersions) {
73
87
  const args = [fetchAllVersions ? 'versions' : 'version', '--json'];
74
88
  const commandResult = this.executeCommand('npm', ['info', packageName, ...args]);
@@ -39,6 +39,11 @@ class Yarn1Proxy extends _JsPackageManager.JsPackageManager {
39
39
  this.executeCommand('yarn', ['add', ...args], 'inherit');
40
40
  }
41
41
 
42
+ runRemoveDeps(dependencies) {
43
+ const args = ['--ignore-workspace-root-check', ...dependencies];
44
+ this.executeCommand('yarn', ['remove', ...args], 'inherit');
45
+ }
46
+
42
47
  runGetVersions(packageName, fetchAllVersions) {
43
48
  const args = [fetchAllVersions ? 'versions' : 'version', '--json'];
44
49
  const commandResult = this.executeCommand('yarn', ['info', packageName, ...args]);
@@ -39,6 +39,11 @@ class Yarn2Proxy extends _JsPackageManager.JsPackageManager {
39
39
  this.executeCommand('yarn', ['add', ...args], 'inherit');
40
40
  }
41
41
 
42
+ runRemoveDeps(dependencies) {
43
+ const args = [...dependencies];
44
+ this.executeCommand('yarn', ['remove', ...args], 'inherit');
45
+ }
46
+
42
47
  runGetVersions(packageName, fetchAllVersions) {
43
48
  const field = fetchAllVersions ? 'versions' : 'version';
44
49
  const args = ['--fields', field, '--json'];
@@ -7,8 +7,6 @@ exports.reproNext = void 0;
7
7
 
8
8
  var _prompts = _interopRequireDefault(require("prompts"));
9
9
 
10
- var _fs = _interopRequireDefault(require("fs"));
11
-
12
10
  var _path = _interopRequireDefault(require("path"));
13
11
 
14
12
  var _chalk = _interopRequireDefault(require("chalk"));
@@ -19,6 +17,8 @@ var _tsDedent = require("ts-dedent");
19
17
 
20
18
  var _degit = _interopRequireDefault(require("degit"));
21
19
 
20
+ var _fsExtra = require("fs-extra");
21
+
22
22
  var _reproTemplates = _interopRequireDefault(require("./repro-templates"));
23
23
 
24
24
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -33,7 +33,8 @@ const toChoices = c => ({
33
33
  const reproNext = async ({
34
34
  output: outputDirectory,
35
35
  filterValue,
36
- branch
36
+ branch,
37
+ init
37
38
  }) => {
38
39
  const keys = Object.keys(_reproTemplates.default); // get value from template and reduce through TEMPLATES to filter out the correct template
39
40
 
@@ -57,7 +58,8 @@ const reproNext = async ({
57
58
  if (choices.length === 0) {
58
59
  logger.info((0, _boxen.default)((0, _tsDedent.dedent)`
59
60
  🔎 You filtered out all templates. 🔍
60
- After filtering all the templates with "${_chalk.default.yellow(filterValue)}", we found no templates.
61
+
62
+ After filtering all the templates with "${_chalk.default.yellow(filterValue)}", we found no results. Please try again with a different filter.
61
63
 
62
64
  Available templates:
63
65
  ${keys.map(key => _chalk.default.blue`- ${key}`).join('\n')}
@@ -66,7 +68,7 @@ const reproNext = async ({
66
68
  padding: 1,
67
69
  borderColor: '#F1618C'
68
70
  }));
69
- return;
71
+ process.exit(1);
70
72
  }
71
73
 
72
74
  let selectedTemplate = null;
@@ -105,6 +107,11 @@ const reproNext = async ({
105
107
  }
106
108
 
107
109
  let selectedDirectory = outputDirectory;
110
+ const outputDirectoryName = outputDirectory || selectedTemplate;
111
+
112
+ if (selectedDirectory && (0, _fsExtra.existsSync)(`${selectedDirectory}`)) {
113
+ logger.info(`⚠️ ${selectedDirectory} already exists! Overwriting...`);
114
+ }
108
115
 
109
116
  if (!selectedDirectory) {
110
117
  const {
@@ -113,32 +120,34 @@ const reproNext = async ({
113
120
  type: 'text',
114
121
  message: 'Enter the output directory',
115
122
  name: 'directory',
116
- initial: selectedTemplate,
117
- validate: directoryName => _fs.default.existsSync(directoryName) ? `${directoryName} already exists. Please choose another name.` : true
123
+ initial: outputDirectoryName,
124
+ validate: async directoryName => (0, _fsExtra.existsSync)(directoryName) ? `${directoryName} already exists. Please choose another name.` : true
118
125
  });
119
126
  selectedDirectory = directory;
120
127
  }
121
128
 
122
129
  try {
123
- const cwd = _path.default.isAbsolute(selectedDirectory) ? selectedDirectory : _path.default.join(process.cwd(), selectedDirectory);
124
- logger.info(`🏃 Adding ${selectedConfig.name} into ${cwd}`);
130
+ const templateDestination = _path.default.isAbsolute(selectedDirectory) ? selectedDirectory : _path.default.join(process.cwd(), selectedDirectory);
131
+ logger.info(`🏃 Adding ${selectedConfig.name} into ${templateDestination}`);
125
132
  logger.log('📦 Downloading repro template...');
126
133
 
127
134
  try {
128
- // Download the repro based on subfolder "after-storybook" and selected branch
129
- await (0, _degit.default)(`storybookjs/repro-templates-temp/${selectedTemplate}/after-storybook#${branch}`, {
135
+ const templateType = init ? 'after-storybook' : 'before-storybook'; // Download the repro based on subfolder "after-storybook" and selected branch
136
+
137
+ await (0, _degit.default)(`storybookjs/repro-templates-temp/${selectedTemplate}/${templateType}#${branch}`, {
130
138
  force: true
131
- }).clone(selectedTemplate.replace('/', '-'));
139
+ }).clone(templateDestination);
132
140
  } catch (err) {
133
141
  logger.error(`🚨 Failed to download repro template: ${err.message}`);
134
- return;
142
+ throw err;
135
143
  }
136
144
 
145
+ const initMessage = init ? _chalk.default.yellow(`yarn storybook`) : `Recreate your setup, then ${_chalk.default.yellow(`run npx storybook init`)}`;
137
146
  logger.info((0, _boxen.default)((0, _tsDedent.dedent)`
138
147
  🎉 Your Storybook reproduction project is ready to use! 🎉
139
148
 
140
149
  ${_chalk.default.yellow(`cd ${selectedDirectory}`)}
141
- ${_chalk.default.yellow(`yarn storybook`)}
150
+ ${initMessage}
142
151
 
143
152
  Once you've recreated the problem you're experiencing, please:
144
153