UNPKG

7.14 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.exec = exports.createAndInit = void 0;
7
8require("core-js/modules/es.promise.js");
9
10var _path = _interopRequireDefault(require("path"));
11
12var _fsExtra = require("fs-extra");
13
14var _shelljs = _interopRequireDefault(require("shelljs"));
15
16var _chalk = _interopRequireDefault(require("chalk"));
17
18var _configs = require("./configs");
19
20var _versions = _interopRequireDefault(require("../versions"));
21
22const _excluded = ["name", "version"];
23
24function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
26function _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; }
27
28const logger = console;
29const useLocalSbCli = true;
30
31const exec = async (command, options = {}, {
32 startMessage,
33 errorMessage
34} = {}) => {
35 if (startMessage) {
36 logger.info(startMessage);
37 }
38
39 logger.debug(command);
40 return new Promise((resolve, reject) => {
41 const defaultOptions = {
42 silent: true
43 };
44
45 const child = _shelljs.default.exec(command, Object.assign({}, defaultOptions, options, {
46 async: true
47 }));
48
49 child.stderr.pipe(process.stderr);
50 child.stdout.pipe(process.stdout);
51 child.on('exit', code => {
52 if (code === 0) {
53 resolve(undefined);
54 } else {
55 logger.error(_chalk.default.red(`An error occurred while executing: \`${command}\``));
56 logger.log(errorMessage);
57 reject(new Error(`command exited with code: ${code}: `));
58 }
59 });
60 });
61};
62
63exports.exec = exec;
64
65const addPackageResolutions = async ({
66 cwd
67}) => {
68 logger.info(`๐Ÿ”ข Adding package resolutions:`);
69
70 const packageJsonPath = _path.default.join(cwd, 'package.json');
71
72 const packageJson = await (0, _fsExtra.readJSON)(packageJsonPath);
73 packageJson.resolutions = _versions.default;
74 await (0, _fsExtra.writeJSON)(packageJsonPath, packageJson, {
75 spaces: 2
76 });
77};
78
79const installYarn2 = async ({
80 cwd,
81 pnp,
82 name
83}) => {
84 const command = [`yarn set version berry`, `yarn config set enableGlobalCache true`, `yarn config set nodeLinker ${pnp ? 'pnp' : 'node-modules'}`]; // FIXME: Some dependencies used by CRA aren't listed in its package.json
85 // Next line is a hack to remove as soon as CRA will have added these missing deps
86 // for details see https://github.com/facebook/create-react-app/pull/11751
87
88 if ([_configs.cra.name, _configs.cra_typescript.name].includes(name)) {
89 command.push(`yarn config set packageExtensions --json '{ "babel-preset-react-app@10.0.x": { "dependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.16.0" } } }'`);
90 }
91
92 await exec(command.join(' && '), {
93 cwd
94 }, {
95 startMessage: `๐Ÿงถ Installing Yarn 2`,
96 errorMessage: `๐Ÿšจ Installing Yarn 2 failed`
97 });
98};
99
100const configureYarn2ForE2E = async ({
101 cwd
102}) => {
103 const command = [// โš ๏ธ Need to set registry because Yarn 2 is not using the conf of Yarn 1 (URL is hardcoded in CircleCI config.yml)
104 `yarn config set npmScopes --json '{ "storybook": { "npmRegistryServer": "http://localhost:6000/" } }'`, // Some required magic to be able to fetch deps from local registry
105 `yarn config set unsafeHttpWhitelist --json '["localhost"]'`, // Disable fallback mode to make sure everything is required correctly
106 `yarn config set pnpFallbackMode none`, // We need to be able to update lockfile when bootstrapping the examples
107 `yarn config set enableImmutableInstalls false`, // Discard all YN0013 - FETCH_NOT_CACHED messages
108 `yarn config set logFilters --json '[ { "code": "YN0013", "level": "discard" } ]'`].join(' && ');
109 await exec(command, {
110 cwd
111 }, {
112 startMessage: `๐ŸŽ› Configuring Yarn 2`,
113 errorMessage: `๐Ÿšจ Configuring Yarn 2 failed`
114 });
115};
116
117const generate = async ({
118 cwd,
119 name,
120 appName,
121 version,
122 generator
123}) => {
124 const command = generator.replace(/{{appName}}/g, appName).replace(/{{version}}/g, version);
125 await exec(command, {
126 cwd
127 }, {
128 startMessage: `๐Ÿ— Bootstrapping ${name} project (this might take a few minutes)`,
129 errorMessage: `๐Ÿšจ Bootstrapping ${name} failed`
130 });
131};
132
133const initStorybook = async ({
134 cwd,
135 autoDetect = true,
136 name,
137 e2e
138}) => {
139 const type = autoDetect ? '' : `--type ${name}`;
140 const linkable = e2e ? '' : '--linkable';
141 const sbCLICommand = useLocalSbCli ? `node ${_path.default.join(__dirname, '../../esm/generate')}` : `yarn dlx -p @storybook/cli sb`;
142 const command = `${sbCLICommand} init --yes ${type} ${linkable}`;
143 await exec(command, {
144 cwd
145 }, {
146 startMessage: `๐ŸŽจ Initializing Storybook with @storybook/cli`,
147 errorMessage: `๐Ÿšจ Storybook initialization failed`
148 });
149};
150
151const addRequiredDeps = async ({
152 cwd,
153 additionalDeps
154}) => {
155 // Remove any lockfile generated without Yarn 2
156 _shelljs.default.rm('-f', _path.default.join(cwd, 'package-lock.json'), _path.default.join(cwd, 'yarn.lock'));
157
158 const command = additionalDeps && additionalDeps.length > 0 ? `yarn add -D ${additionalDeps.join(' ')}` : `yarn install`;
159 await exec(command, {
160 cwd
161 }, {
162 startMessage: `๐ŸŒ Adding needed deps & installing all deps`,
163 errorMessage: `๐Ÿšจ Dependencies installation failed`
164 });
165};
166
167const addTypescript = async ({
168 cwd
169}) => {
170 logger.info(`๐Ÿ‘ฎ Adding typescript and tsconfig.json`);
171
172 try {
173 await exec(`yarn add -D typescript@latest`, {
174 cwd
175 });
176 const tsConfig = {
177 compilerOptions: {
178 baseUrl: '.',
179 esModuleInterop: true,
180 jsx: 'preserve',
181 skipLibCheck: true,
182 strict: true
183 },
184 include: ['src/*']
185 };
186
187 const tsConfigJsonPath = _path.default.resolve(cwd, 'tsconfig.json');
188
189 await (0, _fsExtra.writeJSON)(tsConfigJsonPath, tsConfig, {
190 encoding: 'utf8',
191 spaces: 2
192 });
193 } catch (e) {
194 logger.error(`๐Ÿšจ Creating tsconfig.json failed`);
195 throw e;
196 }
197};
198
199const doTask = async (task, options, condition = true) => {
200 if (condition) {
201 await task(options);
202 logger.log();
203 }
204};
205
206const createAndInit = async (cwd, _ref, {
207 e2e,
208 pnp
209}) => {
210 let {
211 name,
212 version
213 } = _ref,
214 rest = _objectWithoutPropertiesLoose(_ref, _excluded);
215
216 const options = Object.assign({
217 name,
218 version,
219 appName: _path.default.basename(cwd),
220 creationPath: _path.default.join(cwd, '..'),
221 cwd,
222 e2e,
223 pnp
224 }, rest);
225 logger.log();
226 logger.info(`๐Ÿƒ Starting for ${name} ${version}`);
227 logger.log();
228 await doTask(generate, Object.assign({}, options, {
229 cwd: options.creationPath
230 }));
231
232 if (e2e) {
233 await doTask(addPackageResolutions, options);
234 }
235
236 await doTask(installYarn2, options);
237 await doTask(configureYarn2ForE2E, options, e2e);
238 await doTask(addTypescript, options, !!options.typescript);
239 await doTask(addRequiredDeps, options);
240 await doTask(initStorybook, options);
241};
242
243exports.createAndInit = createAndInit;
\No newline at end of file