@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
@@ -4,11 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- // auto generated file, do not edit
8
7
  var _default = {
9
8
  'cra/default-js': {
10
9
  name: 'Create React App (Javascript)',
11
10
  script: 'npx create-react-app .',
11
+ cadence: ['ci', 'daily', 'weekly'],
12
12
  expected: {
13
13
  framework: '@storybook/cra',
14
14
  renderer: '@storybook/react',
@@ -18,11 +18,24 @@ var _default = {
18
18
  'cra/default-ts': {
19
19
  name: 'Create React App (Typescript)',
20
20
  script: 'npx create-react-app . --template typescript',
21
+ cadence: ['ci', 'daily', 'weekly'],
21
22
  expected: {
22
23
  framework: '@storybook/cra',
23
24
  renderer: '@storybook/react',
24
25
  builder: '@storybook/builder-webpack5'
25
26
  }
26
- }
27
+ } // FIXME: missing documentation.json
28
+ // 'angular/latest': {
29
+ // name: 'Angular (latest)',
30
+ // script:
31
+ // 'npx -p @angular/cli ng new angular-latest --directory . --routing=true --minimal=true --style=scss --skip-install=true --strict',
32
+ // cadence: ['ci', 'daily', 'weekly'],
33
+ // expected: {
34
+ // framework: '@storybook/angular',
35
+ // renderer: '@storybook/angular',
36
+ // builder: '@storybook/builder-webpack5',
37
+ // },
38
+ // },
39
+
27
40
  };
28
41
  exports.default = _default;
@@ -6,80 +6,80 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  // auto generated file, do not edit
8
8
  var _default = {
9
- '@storybook/addon-a11y': '7.0.0-alpha.18',
10
- '@storybook/addon-actions': '7.0.0-alpha.18',
11
- '@storybook/addon-backgrounds': '7.0.0-alpha.18',
12
- '@storybook/addon-controls': '7.0.0-alpha.18',
13
- '@storybook/addon-docs': '7.0.0-alpha.18',
14
- '@storybook/addon-essentials': '7.0.0-alpha.18',
15
- '@storybook/addon-highlight': '7.0.0-alpha.18',
16
- '@storybook/addon-interactions': '7.0.0-alpha.18',
17
- '@storybook/addon-jest': '7.0.0-alpha.18',
18
- '@storybook/addon-links': '7.0.0-alpha.18',
19
- '@storybook/addon-measure': '7.0.0-alpha.18',
20
- '@storybook/addon-outline': '7.0.0-alpha.18',
21
- '@storybook/addon-storyshots': '7.0.0-alpha.18',
22
- '@storybook/addon-storyshots-puppeteer': '7.0.0-alpha.18',
23
- '@storybook/addon-storysource': '7.0.0-alpha.18',
24
- '@storybook/addon-toolbars': '7.0.0-alpha.18',
25
- '@storybook/addon-viewport': '7.0.0-alpha.18',
26
- '@storybook/addons': '7.0.0-alpha.18',
27
- '@storybook/angular': '7.0.0-alpha.18',
28
- '@storybook/api': '7.0.0-alpha.18',
29
- '@storybook/blocks': '7.0.0-alpha.18',
30
- '@storybook/builder-manager': '7.0.0-alpha.18',
31
- '@storybook/builder-webpack5': '7.0.0-alpha.18',
32
- '@storybook/channel-postmessage': '7.0.0-alpha.18',
33
- '@storybook/channel-websocket': '7.0.0-alpha.18',
34
- '@storybook/channels': '7.0.0-alpha.18',
35
- '@storybook/cli': '7.0.0-alpha.18',
36
- '@storybook/client-api': '7.0.0-alpha.18',
37
- '@storybook/client-logger': '7.0.0-alpha.18',
38
- '@storybook/codemod': '7.0.0-alpha.18',
39
- '@storybook/components': '7.0.0-alpha.18',
40
- '@storybook/core-client': '7.0.0-alpha.18',
41
- '@storybook/core-common': '7.0.0-alpha.18',
42
- '@storybook/core-events': '7.0.0-alpha.18',
43
- '@storybook/core-server': '7.0.0-alpha.18',
44
- '@storybook/core-webpack': '7.0.0-alpha.18',
45
- '@storybook/csf-tools': '7.0.0-alpha.18',
46
- '@storybook/docs-tools': '7.0.0-alpha.18',
47
- '@storybook/ember': '7.0.0-alpha.18',
48
- '@storybook/html': '7.0.0-alpha.18',
49
- '@storybook/html-webpack5': '7.0.0-alpha.18',
50
- '@storybook/instrumenter': '7.0.0-alpha.18',
51
- '@storybook/node-logger': '7.0.0-alpha.18',
52
- '@storybook/postinstall': '7.0.0-alpha.18',
53
- '@storybook/preact': '7.0.0-alpha.18',
54
- '@storybook/preact-webpack5': '7.0.0-alpha.18',
55
- '@storybook/preset-html-webpack': '7.0.0-alpha.18',
56
- '@storybook/preset-preact-webpack': '7.0.0-alpha.18',
57
- '@storybook/preset-react-webpack': '7.0.0-alpha.18',
58
- '@storybook/preset-server-webpack': '7.0.0-alpha.18',
59
- '@storybook/preset-svelte-webpack': '7.0.0-alpha.18',
60
- '@storybook/preset-vue-webpack': '7.0.0-alpha.18',
61
- '@storybook/preset-vue3-webpack': '7.0.0-alpha.18',
62
- '@storybook/preset-web-components-webpack': '7.0.0-alpha.18',
63
- '@storybook/preview-web': '7.0.0-alpha.18',
64
- '@storybook/react': '7.0.0-alpha.18',
65
- '@storybook/react-webpack5': '7.0.0-alpha.18',
66
- '@storybook/router': '7.0.0-alpha.18',
67
- '@storybook/server': '7.0.0-alpha.18',
68
- '@storybook/server-webpack5': '7.0.0-alpha.18',
69
- '@storybook/source-loader': '7.0.0-alpha.18',
70
- '@storybook/store': '7.0.0-alpha.18',
71
- '@storybook/svelte': '7.0.0-alpha.18',
72
- '@storybook/svelte-webpack5': '7.0.0-alpha.18',
73
- '@storybook/telemetry': '7.0.0-alpha.18',
74
- '@storybook/theming': '7.0.0-alpha.18',
75
- '@storybook/ui': '7.0.0-alpha.18',
76
- '@storybook/vue': '7.0.0-alpha.18',
77
- '@storybook/vue-webpack5': '7.0.0-alpha.18',
78
- '@storybook/vue3': '7.0.0-alpha.18',
79
- '@storybook/vue3-webpack5': '7.0.0-alpha.18',
80
- '@storybook/web-components': '7.0.0-alpha.18',
81
- '@storybook/web-components-webpack5': '7.0.0-alpha.18',
82
- sb: '7.0.0-alpha.18',
83
- storybook: '7.0.0-alpha.18'
9
+ '@storybook/addon-a11y': '7.0.0-alpha.20',
10
+ '@storybook/addon-actions': '7.0.0-alpha.20',
11
+ '@storybook/addon-backgrounds': '7.0.0-alpha.20',
12
+ '@storybook/addon-controls': '7.0.0-alpha.20',
13
+ '@storybook/addon-docs': '7.0.0-alpha.20',
14
+ '@storybook/addon-essentials': '7.0.0-alpha.20',
15
+ '@storybook/addon-highlight': '7.0.0-alpha.20',
16
+ '@storybook/addon-interactions': '7.0.0-alpha.20',
17
+ '@storybook/addon-jest': '7.0.0-alpha.20',
18
+ '@storybook/addon-links': '7.0.0-alpha.20',
19
+ '@storybook/addon-measure': '7.0.0-alpha.20',
20
+ '@storybook/addon-outline': '7.0.0-alpha.20',
21
+ '@storybook/addon-storyshots': '7.0.0-alpha.20',
22
+ '@storybook/addon-storyshots-puppeteer': '7.0.0-alpha.20',
23
+ '@storybook/addon-storysource': '7.0.0-alpha.20',
24
+ '@storybook/addon-toolbars': '7.0.0-alpha.20',
25
+ '@storybook/addon-viewport': '7.0.0-alpha.20',
26
+ '@storybook/addons': '7.0.0-alpha.20',
27
+ '@storybook/angular': '7.0.0-alpha.20',
28
+ '@storybook/api': '7.0.0-alpha.20',
29
+ '@storybook/blocks': '7.0.0-alpha.20',
30
+ '@storybook/builder-manager': '7.0.0-alpha.20',
31
+ '@storybook/builder-webpack5': '7.0.0-alpha.20',
32
+ '@storybook/channel-postmessage': '7.0.0-alpha.20',
33
+ '@storybook/channel-websocket': '7.0.0-alpha.20',
34
+ '@storybook/channels': '7.0.0-alpha.20',
35
+ '@storybook/cli': '7.0.0-alpha.20',
36
+ '@storybook/client-api': '7.0.0-alpha.20',
37
+ '@storybook/client-logger': '7.0.0-alpha.20',
38
+ '@storybook/codemod': '7.0.0-alpha.20',
39
+ '@storybook/components': '7.0.0-alpha.20',
40
+ '@storybook/core-client': '7.0.0-alpha.20',
41
+ '@storybook/core-common': '7.0.0-alpha.20',
42
+ '@storybook/core-events': '7.0.0-alpha.20',
43
+ '@storybook/core-server': '7.0.0-alpha.20',
44
+ '@storybook/core-webpack': '7.0.0-alpha.20',
45
+ '@storybook/csf-tools': '7.0.0-alpha.20',
46
+ '@storybook/docs-tools': '7.0.0-alpha.20',
47
+ '@storybook/ember': '7.0.0-alpha.20',
48
+ '@storybook/html': '7.0.0-alpha.20',
49
+ '@storybook/html-webpack5': '7.0.0-alpha.20',
50
+ '@storybook/instrumenter': '7.0.0-alpha.20',
51
+ '@storybook/node-logger': '7.0.0-alpha.20',
52
+ '@storybook/postinstall': '7.0.0-alpha.20',
53
+ '@storybook/preact': '7.0.0-alpha.20',
54
+ '@storybook/preact-webpack5': '7.0.0-alpha.20',
55
+ '@storybook/preset-html-webpack': '7.0.0-alpha.20',
56
+ '@storybook/preset-preact-webpack': '7.0.0-alpha.20',
57
+ '@storybook/preset-react-webpack': '7.0.0-alpha.20',
58
+ '@storybook/preset-server-webpack': '7.0.0-alpha.20',
59
+ '@storybook/preset-svelte-webpack': '7.0.0-alpha.20',
60
+ '@storybook/preset-vue-webpack': '7.0.0-alpha.20',
61
+ '@storybook/preset-vue3-webpack': '7.0.0-alpha.20',
62
+ '@storybook/preset-web-components-webpack': '7.0.0-alpha.20',
63
+ '@storybook/preview-web': '7.0.0-alpha.20',
64
+ '@storybook/react': '7.0.0-alpha.20',
65
+ '@storybook/react-webpack5': '7.0.0-alpha.20',
66
+ '@storybook/router': '7.0.0-alpha.20',
67
+ '@storybook/server': '7.0.0-alpha.20',
68
+ '@storybook/server-webpack5': '7.0.0-alpha.20',
69
+ '@storybook/source-loader': '7.0.0-alpha.20',
70
+ '@storybook/store': '7.0.0-alpha.20',
71
+ '@storybook/svelte': '7.0.0-alpha.20',
72
+ '@storybook/svelte-webpack5': '7.0.0-alpha.20',
73
+ '@storybook/telemetry': '7.0.0-alpha.20',
74
+ '@storybook/theming': '7.0.0-alpha.20',
75
+ '@storybook/ui': '7.0.0-alpha.20',
76
+ '@storybook/vue': '7.0.0-alpha.20',
77
+ '@storybook/vue-webpack5': '7.0.0-alpha.20',
78
+ '@storybook/vue3': '7.0.0-alpha.20',
79
+ '@storybook/vue3-webpack5': '7.0.0-alpha.20',
80
+ '@storybook/web-components': '7.0.0-alpha.20',
81
+ '@storybook/web-components-webpack5': '7.0.0-alpha.20',
82
+ sb: '7.0.0-alpha.20',
83
+ storybook: '7.0.0-alpha.20'
84
84
  };
85
85
  exports.default = _default;
@@ -6,5 +6,7 @@ import { mainjsFramework } from './mainjsFramework';
6
6
  import { eslintPlugin } from './eslint-plugin';
7
7
  import { builderVite } from './builder-vite';
8
8
  import { npm7 } from './npm7';
9
+ import { sbScripts } from './sb-scripts';
10
+ import { newFrameworks } from './new-frameworks';
9
11
  export * from '../types';
10
- export const fixes = [cra5, webpack5, angular12, vue3, mainjsFramework, eslintPlugin, builderVite, npm7];
12
+ export const fixes = [cra5, webpack5, angular12, vue3, mainjsFramework, eslintPlugin, builderVite, npm7, sbScripts, newFrameworks];
@@ -0,0 +1,225 @@
1
+ import chalk from 'chalk';
2
+ import dedent from 'ts-dedent';
3
+ import semver from '@storybook/semver';
4
+ import { readConfig, writeConfig } from '@storybook/csf-tools';
5
+ import { getStorybookInfo } from '@storybook/core-common';
6
+ import { getStorybookVersionSpecifier } from '../../helpers';
7
+ const logger = console;
8
+ const packagesMap = {
9
+ '@storybook/react': {
10
+ webpack5: '@storybook/react-webpack5',
11
+ vite: '@storybook/react-vite'
12
+ },
13
+ '@storybook/preact': {
14
+ webpack5: '@storybook/preact-webpack5'
15
+ },
16
+ '@storybook/server': {
17
+ webpack5: '@storybook/server-webpack5'
18
+ },
19
+ '@storybook/angular': {
20
+ webpack5: '@storybook/angular'
21
+ },
22
+ '@storybook/vue': {
23
+ webpack5: '@storybook/vue-webpack5',
24
+ vite: '@storybook/vue-vite'
25
+ },
26
+ '@storybook/vue3': {
27
+ webpack5: '@storybook/vue3-webpack5',
28
+ vite: '@storybook/vue3-vite'
29
+ },
30
+ '@storybook/svelte': {
31
+ webpack5: '@storybook/svelte-webpack5',
32
+ vite: '@storybook/svelte-vite'
33
+ },
34
+ '@storybook/web-components': {
35
+ webpack5: '@storybook/web-components-webpack5'
36
+ },
37
+ '@storybook/html': {
38
+ webpack5: '@storybook/html-webpack5'
39
+ }
40
+ };
41
+ export const getBuilder = builder => {
42
+ if (typeof builder === 'string') {
43
+ return builder.includes('vite') ? 'vite' : 'webpack5';
44
+ }
45
+
46
+ return builder?.name.includes('vite') ? 'vite' : 'webpack5';
47
+ };
48
+ export const getFrameworkOptions = (framework, main) => {
49
+ const frameworkOptions = main.getFieldValue([`${framework}Options`]);
50
+ return frameworkOptions || {};
51
+ };
52
+ /**
53
+ * Does the user have separate framework and builders (e.g. @storybook/react + core.builder -> webpack5?
54
+ *
55
+ * If so:
56
+ * - Remove the dependencies (@storybook/react + @storybook/builder-webpack5 + @storybook/manager-webpack5)
57
+ * - Install the correct new package e.g. (@storybook/react-webpack5)
58
+ * - Update the main config to use the new framework
59
+ * -- moving core.builder into framework.options.builder
60
+ * -- moving frameworkOptions (e.g. reactOptions) into framework.options
61
+ */
62
+
63
+ export const newFrameworks = {
64
+ id: 'newFrameworks',
65
+
66
+ async check({
67
+ packageManager
68
+ }) {
69
+ const packageJson = packageManager.retrievePackageJson();
70
+ const allDeps = Object.assign({}, packageJson.dependencies, packageJson.devDependencies);
71
+ const config = getStorybookInfo(packageJson);
72
+ const {
73
+ mainConfig,
74
+ version: storybookVersion,
75
+ framework
76
+ } = config;
77
+
78
+ if (!mainConfig) {
79
+ logger.warn('Unable to find storybook main.js config, skipping');
80
+ return null;
81
+ }
82
+
83
+ const storybookCoerced = storybookVersion && semver.coerce(storybookVersion)?.version;
84
+
85
+ if (!storybookCoerced) {
86
+ logger.warn(dedent`
87
+ ❌ Unable to determine storybook version, skipping ${chalk.cyan('newFrameworks')} fix.
88
+ 🤔 Are you running automigrate from your project directory?
89
+ `);
90
+ return null;
91
+ }
92
+
93
+ if (!semver.gte(storybookCoerced, '7.0.0')) {
94
+ return null;
95
+ } // If in the future the eslint plugin has a framework option, using main to extract the framework field will be very useful
96
+
97
+
98
+ const main = await readConfig(mainConfig);
99
+ const frameworkPackage = main.getFieldValue(['framework']);
100
+ const builder = main.getFieldValue(['core', 'builder']);
101
+
102
+ if (!frameworkPackage) {
103
+ return null;
104
+ }
105
+
106
+ const supportedPackages = Object.keys(packagesMap);
107
+
108
+ if (!supportedPackages.includes(frameworkPackage)) {
109
+ return null;
110
+ }
111
+
112
+ const builderInfo = {
113
+ name: getBuilder(builder),
114
+ options: main.getFieldValue(['core', 'builder', 'options']) || {}
115
+ }; // TODO: once we have vite frameworks e.g. @storybook/react-vite, then we support it here
116
+ // and remove ['storybook-builder-vite', '@storybook/builder-vite'] from deps
117
+
118
+ if (builderInfo.name === 'vite') {
119
+ return null;
120
+ }
121
+
122
+ const frameworkOptions = getFrameworkOptions(framework, main);
123
+ const dependenciesToRemove = ['@storybook/builder-webpack5', '@storybook/manager-webpack5', '@storybook/builder-webpack4', '@storybook/manager-webpack4'].filter(dep => allDeps[dep]);
124
+ const newFrameworkPackage = packagesMap[frameworkPackage][builderInfo.name];
125
+ const dependenciesToAdd = []; // some frameworks didn't change e.g. Angular, Ember
126
+
127
+ if (newFrameworkPackage !== frameworkPackage) {
128
+ dependenciesToRemove.push(frameworkPackage);
129
+ dependenciesToAdd.push(newFrameworkPackage);
130
+ }
131
+
132
+ return {
133
+ main,
134
+ dependenciesToAdd,
135
+ dependenciesToRemove,
136
+ frameworkPackage: newFrameworkPackage,
137
+ frameworkOptions,
138
+ builderInfo,
139
+ packageJson
140
+ };
141
+ },
142
+
143
+ prompt() {
144
+ return dedent`
145
+ We've detected you are using an older format of Storybook frameworks and builders.
146
+
147
+ In Storybook 7, frameworks also specify the builder to be used.
148
+
149
+ We can remove the dependencies that are no longer needed and install the new framework that already includes the builder.
150
+
151
+ To learn more about the framework field, see: ${chalk.yellow('https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#framework-field-mandatory')}
152
+
153
+ ${chalk.underline(chalk.bold(chalk.cyan('Webpack4 users')))}
154
+
155
+ Unless you're using Storybook's Vite builder, this automigration will install a Webpack5-based framework.
156
+
157
+ If you were using Storybook's Webpack4 builder (default in 6.x, discontinued in 7.0), this could be a breaking
158
+ change--especially if your project has a custom webpack configuration.
159
+
160
+ To learn more about migrating from Webpack4, see: ${chalk.yellow('https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#webpack4-support-discontinued')}
161
+ `;
162
+ },
163
+
164
+ async run({
165
+ result: {
166
+ dependenciesToAdd,
167
+ dependenciesToRemove,
168
+ main,
169
+ frameworkPackage,
170
+ frameworkOptions,
171
+ builderInfo,
172
+ packageJson
173
+ },
174
+ packageManager,
175
+ dryRun
176
+ }) {
177
+ logger.info(`✅ Removing legacy dependencies: ${dependenciesToRemove.join(', ')}`);
178
+
179
+ if (!dryRun) {
180
+ packageManager.removeDependencies({
181
+ skipInstall: dependenciesToAdd.length > 0,
182
+ packageJson
183
+ }, dependenciesToRemove);
184
+ }
185
+
186
+ if (dependenciesToAdd.length > 0) {
187
+ logger.info(`✅ Installing new dependencies: ${dependenciesToAdd.join(', ')}`);
188
+
189
+ if (!dryRun) {
190
+ const versionToInstall = getStorybookVersionSpecifier(packageJson);
191
+ const depsToAdd = dependenciesToAdd.map(dep => `${dep}@${versionToInstall}`);
192
+ packageManager.addDependencies({
193
+ installAsDevDependencies: true
194
+ }, depsToAdd);
195
+ }
196
+ }
197
+
198
+ if (!dryRun) {
199
+ logger.info(`✅ Updating framework field in main.js`);
200
+ const currentCore = main.getFieldValue(['core']);
201
+ main.setFieldValue(['framework', 'name'], frameworkPackage);
202
+ main.setFieldValue(['framework', 'options'], frameworkOptions);
203
+
204
+ if (currentCore?.builder) {
205
+ delete currentCore.builder;
206
+ }
207
+
208
+ if (Object.keys(builderInfo.options).length > 0) {
209
+ main.setFieldValue(['framework', 'options', 'builder'], builderInfo.options);
210
+ }
211
+
212
+ if (currentCore) {
213
+ if (Object.keys(currentCore).length === 0) {
214
+ // TODO: this should delete the field instead
215
+ main.setFieldValue(['core'], {});
216
+ } else {
217
+ main.setFieldValue(['core'], currentCore);
218
+ }
219
+ }
220
+
221
+ await writeConfig(main);
222
+ }
223
+ }
224
+
225
+ };
@@ -0,0 +1,119 @@
1
+ import chalk from 'chalk';
2
+ import { dedent } from 'ts-dedent';
3
+ import semver from '@storybook/semver';
4
+ import { getStorybookInfo } from '@storybook/core-common';
5
+ import { getStorybookVersionSpecifier } from '../../helpers';
6
+ const logger = console;
7
+ export const getStorybookScripts = scripts => {
8
+ const storybookScripts = {
9
+ custom: {},
10
+ official: {}
11
+ };
12
+ Object.keys(scripts).forEach(key => {
13
+ if (key === 'storybook' || key === 'build-storybook') {
14
+ storybookScripts.official[key] = scripts[key];
15
+ } else if (scripts[key].match(/start-storybook/) || scripts[key].match(/build-storybook/)) {
16
+ storybookScripts.custom[key] = scripts[key];
17
+ }
18
+ });
19
+ return storybookScripts;
20
+ };
21
+ /**
22
+ * Is the user using start-storybook
23
+ *
24
+ * If so:
25
+ * - Add storybook dependency
26
+ * - Change start-storybook and build-storybook scripts
27
+ */
28
+
29
+ export const sbScripts = {
30
+ id: 'sb-scripts',
31
+
32
+ async check({
33
+ packageManager
34
+ }) {
35
+ const packageJson = packageManager.retrievePackageJson();
36
+ const {
37
+ scripts = {},
38
+ devDependencies,
39
+ dependencies
40
+ } = packageJson;
41
+ const {
42
+ version: storybookVersion
43
+ } = getStorybookInfo(packageJson);
44
+ const allDeps = Object.assign({}, dependencies, devDependencies);
45
+ const storybookCoerced = storybookVersion && semver.coerce(storybookVersion)?.version;
46
+
47
+ if (!storybookCoerced) {
48
+ logger.warn(dedent`
49
+ ❌ Unable to determine storybook version, skipping ${chalk.cyan('sb-scripts')} fix.
50
+ 🤔 Are you running automigrate from your project directory?
51
+ `);
52
+ return null;
53
+ }
54
+
55
+ if (allDeps.sb || allDeps.storybook) {
56
+ return null;
57
+ }
58
+
59
+ const storybookScripts = getStorybookScripts(scripts);
60
+
61
+ if (Object.keys(storybookScripts.official).length === 0 && Object.keys(storybookScripts.custom).length === 0) {
62
+ return null;
63
+ }
64
+
65
+ Object.keys(storybookScripts.official).forEach(key => {
66
+ storybookScripts.official[key] = storybookScripts.official[key].replace('start-storybook', 'storybook dev').replace('build-storybook', 'storybook build');
67
+ });
68
+ return semver.gte(storybookCoerced, '7.0.0') ? {
69
+ packageJson,
70
+ storybookScripts,
71
+ storybookVersion
72
+ } : null;
73
+ },
74
+
75
+ prompt({
76
+ storybookVersion
77
+ }) {
78
+ const sbFormatted = chalk.cyan(`Storybook ${storybookVersion}`);
79
+ const explanationMessage = [`Starting in Storybook 7, the ${chalk.yellow('start-storybook')} and ${chalk.yellow('build-storybook')} binaries have changed to ${chalk.magenta('storybook dev')} and ${chalk.magenta('storybook build')} respectively.`, `In order to work with ${sbFormatted}, Storybook's ${chalk.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');
80
+ return [`We've detected you are using ${sbFormatted} with scripts from previous versions of Storybook.`, explanationMessage, `More info: ${chalk.yellow('https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#start-storybook--build-storybook-binaries-removed')}`].filter(Boolean).join('\n\n');
81
+ },
82
+
83
+ async run({
84
+ result: {
85
+ storybookScripts,
86
+ packageJson
87
+ },
88
+ packageManager,
89
+ dryRun
90
+ }) {
91
+ logger.log();
92
+ logger.info(`Adding 'storybook' as dev dependency`);
93
+ logger.log();
94
+
95
+ if (!dryRun) {
96
+ const versionToInstall = getStorybookVersionSpecifier(packageJson);
97
+ packageManager.addDependencies({
98
+ installAsDevDependencies: true
99
+ }, [`storybook@${versionToInstall}`]);
100
+ }
101
+
102
+ logger.info(`Updating scripts in package.json`);
103
+ logger.log();
104
+
105
+ if (!dryRun && Object.keys(storybookScripts.official).length > 0) {
106
+ const message = [`Migrating your scripts to:`, chalk.yellow(JSON.stringify(storybookScripts.official, null, 2))].join('\n');
107
+ logger.log(message);
108
+ logger.log();
109
+ packageManager.addScripts(storybookScripts.official);
110
+ }
111
+
112
+ if (!dryRun && Object.keys(storybookScripts.custom).length > 0) {
113
+ const message = [`We detected custom scripts that we can't automigrate:`, chalk.yellow(JSON.stringify(storybookScripts.custom, null, 2)), '\n', `Please manually migrate the ones applicable and use the documentation below for reference: ${chalk.yellow('https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#start-storybook--build-storybook-binaries-removed')}`].join('\n');
114
+ logger.log(message);
115
+ logger.log();
116
+ }
117
+ }
118
+
119
+ };
@@ -63,7 +63,7 @@ export const automigrate = async ({
63
63
  logger.info(`✅ ran ${chalk.cyan(f.id)} migration`);
64
64
  } catch (error) {
65
65
  logger.info(`❌ error when running ${chalk.cyan(f.id)} migration:`);
66
- logger.info(error.message);
66
+ logger.info(error);
67
67
  logger.info();
68
68
  }
69
69
  } else {
@@ -88,7 +88,7 @@ program.command('repro [outputDirectory]').description('Create a reproduction fr
88
88
  logger.error(e);
89
89
  process.exit(1);
90
90
  }));
91
- program.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) => reproNext(Object.assign({
91
+ program.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) => reproNext(Object.assign({
92
92
  filterValue
93
93
  }, options)).catch(e => {
94
94
  logger.error(e);
@@ -6,6 +6,7 @@ import chalk from 'chalk';
6
6
  import { satisfies } from '@storybook/semver';
7
7
  import stripJsonComments from 'strip-json-comments';
8
8
  import { getBaseDir } from './dirs';
9
+ import storybookMonorepoPackages from './versions';
9
10
  const logger = console;
10
11
  export function getBowerJson() {
11
12
  const bowerJsonPath = path.resolve('bower.json');
@@ -190,4 +191,18 @@ export async function copyComponents(framework, language) {
190
191
  await fse.copy(join(getBaseDir(), 'frameworks/common'), destinationPath, {
191
192
  overwrite: true
192
193
  });
194
+ } // Given a package.json, finds any official storybook package within it
195
+ // and if it exists, returns the version of that package from the specified package.json
196
+
197
+ export function getStorybookVersionSpecifier(packageJson) {
198
+ const allDeps = Object.assign({}, packageJson.dependencies, packageJson.devDependencies);
199
+ const storybookPackage = Object.keys(allDeps).find(name => {
200
+ return storybookMonorepoPackages[name];
201
+ });
202
+
203
+ if (!storybookPackage) {
204
+ throw new Error(`Couldn't find any official storybook packages in package.json`);
205
+ }
206
+
207
+ return allDeps[storybookPackage];
193
208
  }
@@ -117,6 +117,48 @@ export class JsPackageManager {
117
117
  }
118
118
  }
119
119
  }
120
+ /**
121
+ * Remove dependencies from a project using `yarn remove` or `npm uninstall`.
122
+ *
123
+ * @param {Object} options contains `skipInstall`, `packageJson` and `installAsDevDependencies` which we use to determine how we install packages.
124
+ * @param {Array} dependencies contains a list of packages to remove.
125
+ * @example
126
+ * removeDependencies(options, [
127
+ * `@storybook/react`,
128
+ * `@storybook/addon-actions`,
129
+ * ]);
130
+ */
131
+
132
+
133
+ removeDependencies(options, dependencies) {
134
+ const {
135
+ skipInstall
136
+ } = options;
137
+
138
+ if (skipInstall) {
139
+ const {
140
+ packageJson
141
+ } = options;
142
+ dependencies.forEach(dep => {
143
+ if (packageJson.devDependencies) {
144
+ delete packageJson.devDependencies[dep];
145
+ }
146
+
147
+ if (packageJson.dependencies) {
148
+ delete packageJson.dependencies[dep];
149
+ }
150
+ });
151
+ writePackageJson(packageJson);
152
+ } else {
153
+ try {
154
+ this.runRemoveDeps(dependencies);
155
+ } catch (e) {
156
+ logger.error('An error occurred while removing dependencies.');
157
+ logger.log(e.message);
158
+ process.exit(1);
159
+ }
160
+ }
161
+ }
120
162
  /**
121
163
  * Return an array of strings matching following format: `<package_name>@<package_latest_version>`
122
164
  *