@storybook/cli
Version:
Storybook's CLI - easiest method of adding storybook to your projects
211 lines (182 loc) โข 6.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createAndInit = exports.exec = void 0;
require("core-js/modules/es.promise.js");
var _path = _interopRequireDefault(require("path"));
var _fsExtra = require("fs-extra");
var _shelljs = _interopRequireDefault(require("shelljs"));
var _chalk = _interopRequireDefault(require("chalk"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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; }
const logger = console;
const useLocalSbCli = true;
const exec = async (command, options = {}, {
startMessage,
errorMessage
} = {}) => {
if (startMessage) {
logger.info(startMessage);
}
logger.debug(command);
return new Promise((resolve, reject) => {
const defaultOptions = {
silent: true
};
_shelljs.default.exec(command, Object.assign({}, defaultOptions, options), (code, stdout, stderr) => {
if (code === 0) {
resolve(undefined);
} else {
logger.error(_chalk.default.red(`An error occurred while executing: \`${command}\``));
logger.error(`Command output was:${_chalk.default.yellow(`\n${stdout}\n${stderr}`)}`);
if (errorMessage) {
logger.error(errorMessage);
}
reject(new Error(`command exited with code: ${code}: `));
}
});
});
};
exports.exec = exec;
const installYarn2 = async ({
cwd,
pnp
}) => {
const command = [`yarn set version berry`, `yarn config set enableGlobalCache true`, `yarn config set nodeLinker ${pnp ? 'pnp' : 'node-modules'}`].join(' && ');
await exec(command, {
cwd
}, {
startMessage: `๐งถ Installing Yarn 2`,
errorMessage: `๐จ Installing Yarn 2 failed`
});
};
const configureYarn2ForE2E = async ({
cwd
}) => {
const command = [// โ ๏ธ Need to set registry because Yarn 2 is not using the conf of Yarn 1 (URL is hardcoded in CircleCI config.yml)
`yarn config set npmScopes --json '{ "storybook": { "npmRegistryServer": "http://localhost:6000/" } }'`, // Some required magic to be able to fetch deps from local registry
`yarn config set unsafeHttpWhitelist --json '["localhost"]'`, // Disable fallback mode to make sure everything is required correctly
`yarn config set pnpFallbackMode none`, // We need to be able to update lockfile when bootstrapping the examples
`yarn config set enableImmutableInstalls false`, // Discard all YN0013 - FETCH_NOT_CACHED messages
`yarn config set logFilters --json '[ { "code": "YN0013", "level": "discard" } ]'`].join(' && ');
await exec(command, {
cwd
}, {
startMessage: `๐ Configuring Yarn 2`,
errorMessage: `๐จ Configuring Yarn 2 failed`
});
};
const generate = async ({
cwd,
name,
appName,
version,
generator
}) => {
const command = generator.replace(/{{appName}}/g, appName).replace(/{{version}}/g, version);
await exec(command, {
cwd
}, {
startMessage: `๐ Bootstrapping ${name} project (this might take a few minutes)`,
errorMessage: `๐จ Bootstrapping ${name} failed`
});
};
const initStorybook = async ({
cwd,
autoDetect = true,
name,
e2e
}) => {
const type = autoDetect ? '' : `--type ${name}`;
const linkable = e2e ? '' : '--linkable';
const sbCLICommand = useLocalSbCli ? `node ${_path.default.join(__dirname, '../../esm/generate')}` : `yarn dlx -p @storybook/cli sb`;
const command = `${sbCLICommand} init --yes ${type} ${linkable}`;
await exec(command, {
cwd
}, {
startMessage: `๐จ Initializing Storybook with @storybook/cli`,
errorMessage: `๐จ Storybook initialization failed`
});
};
const addRequiredDeps = async ({
cwd,
additionalDeps
}) => {
// Remove any lockfile generated without Yarn 2
_shelljs.default.rm('-f', _path.default.join(cwd, 'package-lock.json'), _path.default.join(cwd, 'yarn.lock'));
const command = additionalDeps && additionalDeps.length > 0 ? `yarn add -D ${additionalDeps.join(' ')}` : `yarn install`;
await exec(command, {
cwd
}, {
startMessage: `๐ Adding needed deps & installing all deps`,
errorMessage: `๐จ Dependencies installation failed`
});
};
const addTypescript = async ({
cwd
}) => {
logger.info(`๐ฎ Adding typescript and tsconfig.json`);
try {
await exec(`yarn add -D typescript@latest`, {
cwd
});
const tsConfig = {
compilerOptions: {
baseUrl: '.',
esModuleInterop: true,
jsx: 'preserve',
skipLibCheck: true,
strict: true
},
include: ['src/*']
};
const tsConfigJsonPath = _path.default.resolve(cwd, 'tsconfig.json');
await (0, _fsExtra.writeJSON)(tsConfigJsonPath, tsConfig, {
encoding: 'utf8',
spaces: 2
});
} catch (e) {
logger.error(`๐จ Creating tsconfig.json failed`);
throw e;
}
};
const doTask = async (task, options, condition = true) => {
if (condition) {
await task(options);
logger.log();
}
};
const createAndInit = async (cwd, _ref, {
e2e,
pnp
}) => {
let {
name,
version
} = _ref,
rest = _objectWithoutPropertiesLoose(_ref, ["name", "version"]);
const options = Object.assign({
name,
version,
appName: _path.default.basename(cwd),
creationPath: _path.default.join(cwd, '..'),
cwd,
e2e,
pnp
}, rest);
logger.log();
logger.info(`๐ Starting for ${name} ${version}`);
logger.log();
logger.debug(options);
logger.log();
await doTask(generate, Object.assign({}, options, {
cwd: options.creationPath
}));
await doTask(installYarn2, options);
await doTask(configureYarn2ForE2E, options, e2e);
await doTask(addTypescript, options, !!options.typescript);
await doTask(addRequiredDeps, options);
await doTask(initStorybook, options);
};
exports.createAndInit = createAndInit;