UNPKG

8.79 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.JsPackageManager = void 0;
7exports.getPackageDetails = getPackageDetails;
8
9require("core-js/modules/es.promise.js");
10
11var _chalk = _interopRequireDefault(require("chalk"));
12
13var _semver = require("@storybook/semver");
14
15var _crossSpawn = require("cross-spawn");
16
17var _helpers = require("../helpers");
18
19var _PackageJsonHelper = require("./PackageJsonHelper");
20
21var _versions = _interopRequireDefault(require("../versions"));
22
23function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
25const logger = console;
26/**
27 * Extract package name and version from input
28 *
29 * @param pkg A string like `@storybook/cli`, `react` or `react@^16`
30 * @return A tuple of 2 elements: [packageName, packageVersion]
31 */
32
33function getPackageDetails(pkg) {
34 const idx = pkg.lastIndexOf('@'); // If the only `@` is the first character, it is a scoped package
35 // If it isn't in the string, it will be -1
36
37 if (idx <= 0) {
38 return [pkg, undefined];
39 }
40
41 const packageName = pkg.slice(0, idx);
42 const packageVersion = pkg.slice(idx + 1);
43 return [packageName, packageVersion];
44}
45
46class JsPackageManager {
47 constructor() {
48 this.type = void 0;
49 }
50
51 /**
52 * Install dependencies listed in `package.json`
53 */
54 installDependencies() {
55 let done = (0, _helpers.commandLog)('Preparing to install dependencies');
56 done();
57 logger.log();
58 logger.log();
59 done = (0, _helpers.commandLog)('Installing dependencies');
60
61 try {
62 this.runInstall();
63 } catch (e) {
64 done('An error occurred while installing dependencies.');
65 process.exit(1);
66 }
67
68 done();
69 }
70 /**
71 * Read the `package.json` file available in the directory the command was call from
72 * If there is no `package.json` it will create one.
73 */
74
75
76 retrievePackageJson() {
77 let packageJson;
78
79 try {
80 packageJson = (0, _PackageJsonHelper.readPackageJson)();
81 } catch (err) {
82 this.initPackageJson();
83 packageJson = (0, _PackageJsonHelper.readPackageJson)();
84 }
85
86 return Object.assign({}, packageJson, {
87 dependencies: Object.assign({}, packageJson.dependencies),
88 devDependencies: Object.assign({}, packageJson.devDependencies)
89 });
90 }
91 /**
92 * Add dependencies to a project using `yarn add` or `npm install`.
93 *
94 * @param {Object} options contains `skipInstall`, `packageJson` and `installAsDevDependencies` which we use to determine how we install packages.
95 * @param {Array} dependencies contains a list of packages to add.
96 * @example
97 * addDependencies(options, [
98 * `@storybook/react@${storybookVersion}`,
99 * `@storybook/addon-actions@${actionsVersion}`,
100 * `@storybook/addon-links@${linksVersion}`,
101 * `@storybook/addons@${addonsVersion}`,
102 * ]);
103 */
104
105
106 addDependencies(options, dependencies) {
107 const {
108 skipInstall
109 } = options;
110
111 if (skipInstall) {
112 const {
113 packageJson
114 } = options;
115 const dependenciesMap = dependencies.reduce((acc, dep) => {
116 const [packageName, packageVersion] = getPackageDetails(dep);
117 return Object.assign({}, acc, {
118 [packageName]: packageVersion
119 });
120 }, {});
121
122 if (options.installAsDevDependencies) {
123 packageJson.devDependencies = Object.assign({}, packageJson.devDependencies, dependenciesMap);
124 } else {
125 packageJson.dependencies = Object.assign({}, packageJson.dependencies, dependenciesMap);
126 }
127
128 (0, _PackageJsonHelper.writePackageJson)(packageJson);
129 } else {
130 try {
131 this.runAddDeps(dependencies, options.installAsDevDependencies);
132 } catch (e) {
133 logger.error('An error occurred while installing dependencies.');
134 logger.log(e.message);
135 process.exit(1);
136 }
137 }
138 }
139 /**
140 * Return an array of strings matching following format: `<package_name>@<package_latest_version>`
141 *
142 * @param packages
143 */
144
145
146 getVersionedPackages(...packages) {
147 return Promise.all(packages.map(async pkg => {
148 const [packageName, packageVersion] = getPackageDetails(pkg);
149 return `${packageName}@${await this.getVersion(packageName, packageVersion)}`;
150 }));
151 }
152 /**
153 * Return an array of string standing for the latest version of the input packages.
154 * To be able to identify which version goes with which package the order of the input array is keep.
155 *
156 * @param packageNames
157 */
158
159
160 getVersions(...packageNames) {
161 return Promise.all(packageNames.map(packageName => this.getVersion(packageName)));
162 }
163 /**
164 * Return the latest version of the input package available on npmjs registry.
165 * If constraint are provided it return the latest version matching the constraints.
166 *
167 * For `@storybook/*` packages the latest version is retrieved from `cli/src/versions.json` file directly
168 *
169 * @param packageName The name of the package
170 * @param constraint A valid semver constraint, example: '1.x || >=2.5.0 || 5.0.0 - 7.2.3'
171 */
172
173
174 async getVersion(packageName, constraint) {
175 let current;
176
177 if (/@storybook/.test(packageName)) {
178 // @ts-ignore
179 current = _versions.default[packageName];
180 }
181
182 let latest;
183
184 try {
185 latest = await this.latestVersion(packageName, constraint);
186 } catch (e) {
187 if (current) {
188 logger.warn(`\n ${_chalk.default.yellow(e.message)}`);
189 return current;
190 }
191
192 logger.error(`\n ${_chalk.default.red(e.message)}`);
193 process.exit(1);
194 }
195
196 const versionToUse = current && (!constraint || (0, _semver.satisfies)(current, constraint)) && (0, _semver.gt)(current, latest) ? current : latest;
197 return `^${versionToUse}`;
198 }
199 /**
200 * Get the latest version of the package available on npmjs.com.
201 * If constraint is set then it returns a version satisfying it, otherwise the latest version available is returned.
202 *
203 * @param packageName Name of the package
204 * @param constraint Version range to use to constraint the returned version
205 */
206
207
208 async latestVersion(packageName, constraint) {
209 if (!constraint) {
210 return this.runGetVersions(packageName, false);
211 }
212
213 const versions = await this.runGetVersions(packageName, true); // Get the latest version satisfying the constraint
214
215 return versions.reverse().find(version => (0, _semver.satisfies)(version, constraint));
216 }
217
218 addStorybookCommandInScripts(options) {
219 var _options$port;
220
221 const sbPort = (_options$port = options === null || options === void 0 ? void 0 : options.port) !== null && _options$port !== void 0 ? _options$port : 6006;
222 const storybookCmd = options !== null && options !== void 0 && options.staticFolder ? `start-storybook -p ${sbPort} -s ${options.staticFolder}` : `start-storybook -p ${sbPort}`;
223 const buildStorybookCmd = options !== null && options !== void 0 && options.staticFolder ? `build-storybook -s ${options.staticFolder}` : `build-storybook`;
224 const preCommand = options !== null && options !== void 0 && options.preCommand ? this.getRunCommand(options.preCommand) : undefined;
225 this.addScripts({
226 storybook: [preCommand, storybookCmd].filter(Boolean).join(' && '),
227 'build-storybook': [preCommand, buildStorybookCmd].filter(Boolean).join(' && ')
228 });
229 }
230
231 addESLintConfig() {
232 var _packageJson$eslintCo;
233
234 const packageJson = this.retrievePackageJson();
235 (0, _PackageJsonHelper.writePackageJson)(Object.assign({}, packageJson, {
236 eslintConfig: Object.assign({}, packageJson.eslintConfig, {
237 overrides: [...(((_packageJson$eslintCo = packageJson.eslintConfig) === null || _packageJson$eslintCo === void 0 ? void 0 : _packageJson$eslintCo.overrides) || []), {
238 files: ['**/*.stories.*'],
239 rules: {
240 'import/no-anonymous-default-export': 'off'
241 }
242 }]
243 })
244 }));
245 }
246
247 addScripts(scripts) {
248 const packageJson = this.retrievePackageJson();
249 (0, _PackageJsonHelper.writePackageJson)(Object.assign({}, packageJson, {
250 scripts: Object.assign({}, packageJson.scripts, scripts)
251 }));
252 }
253
254 executeCommand(command, args, stdio) {
255 var _commandResult$stdout;
256
257 const commandResult = (0, _crossSpawn.sync)(command, args, {
258 stdio: stdio !== null && stdio !== void 0 ? stdio : 'pipe',
259 encoding: 'utf-8'
260 });
261
262 if (commandResult.status !== 0) {
263 var _commandResult$stderr;
264
265 throw new Error((_commandResult$stderr = commandResult.stderr) !== null && _commandResult$stderr !== void 0 ? _commandResult$stderr : '');
266 }
267
268 return (_commandResult$stdout = commandResult.stdout) !== null && _commandResult$stdout !== void 0 ? _commandResult$stdout : '';
269 }
270
271}
272
273exports.JsPackageManager = JsPackageManager;
\No newline at end of file