UNPKG

@react-native-community/bob

Version:
395 lines (324 loc) 12.9 kB
"use strict"; var _path = _interopRequireDefault(require("path")); var _fsExtra = _interopRequireDefault(require("fs-extra")); var _chalk = _interopRequireDefault(require("chalk")); var _dedent = _interopRequireDefault(require("dedent")); var _yargs = _interopRequireDefault(require("yargs")); var _cosmiconfig = require("cosmiconfig"); var _isGitDirty = _interopRequireDefault(require("is-git-dirty")); var _create = _interopRequireWildcard(require("./create")); var _prompts = _interopRequireDefault(require("./utils/prompts")); var logger = _interopRequireWildcard(require("./utils/logger")); var _aar = _interopRequireDefault(require("./targets/aar")); var _commonjs = _interopRequireDefault(require("./targets/commonjs")); var _module = _interopRequireDefault(require("./targets/module")); var _typescript = _interopRequireDefault(require("./targets/typescript")); function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // eslint-disable-next-line import/no-commonjs const { name, version } = require('../package.json'); const root = process.cwd(); const explorer = (0, _cosmiconfig.cosmiconfigSync)(name, { searchPlaces: ['package.json', `bob.config.js`] }); const FLOW_PRGAMA_REGEX = /\*?\s*@(flow)\b/m; // eslint-disable-next-line babel/no-unused-expressions _yargs.default.command('create <name>', 'create a react native library', _create.args, _create.default).command('init', 'configure the package to use bob', {}, async () => { var _pkg$scripts; const pak = _path.default.join(root, 'package.json'); if ((0, _isGitDirty.default)()) { const { shouldContinue } = await (0, _prompts.default)({ type: 'confirm', name: 'shouldContinue', message: `The working directory is not clean. You should commit or stash your changes before configuring bob. Continue anyway?`, initial: false }); if (!shouldContinue) { process.exit(1); } } if (!(await _fsExtra.default.pathExists(pak))) { logger.exit(`Couldn't find a 'package.json' file in '${root}'. Are you in a project folder?`); } const { source } = await (0, _prompts.default)({ type: 'text', name: 'source', message: 'Where are your source files?', initial: 'src', validate: input => Boolean(input) }); let entryFile; if (await _fsExtra.default.pathExists(_path.default.join(root, source, 'index.js'))) { entryFile = 'index.js'; } else if (await _fsExtra.default.pathExists(_path.default.join(root, source, 'index.ts'))) { entryFile = 'index.ts'; } else if (await _fsExtra.default.pathExists(_path.default.join(root, source, 'index.tsx'))) { entryFile = 'index.tsx'; } if (!entryFile) { logger.exit(`Couldn't find a 'index.js'. 'index.ts' or 'index.tsx' file under '${source}'. Please re-run the CLI after creating it.`); return; } const pkg = JSON.parse(await _fsExtra.default.readFile(pak, 'utf-8')); pkg.devDependencies = Object.fromEntries([...Object.entries(pkg.devDependencies || {}), [name, `^${version}`]].sort(([a], [b]) => a.localeCompare(b))); const questions = [{ type: 'text', name: 'output', message: 'Where do you want to generate the output files?', initial: 'lib', validate: input => Boolean(input) }, { type: 'multiselect', name: 'targets', message: 'Which targets do you want to build?', choices: [{ title: 'commonjs - for running in Node (tests, SSR etc.)', value: 'commonjs', selected: true }, { title: 'module - for bundlers (metro, webpack etc.)', value: 'module', selected: true }, { title: 'typescript - declaration files for typechecking', value: 'typescript', selected: /\.tsx?$/.test(entryFile) }, { title: 'aar - bundle android code to a binary', value: 'aar', selected: false }], validate: input => Boolean(input.length) }]; if (entryFile.endsWith('.js') && FLOW_PRGAMA_REGEX.test(await _fsExtra.default.readFile(_path.default.join(root, source, entryFile), 'utf-8'))) { questions.push({ type: 'confirm', name: 'flow', message: 'Do you want to publish definitions for flow?', initial: Object.keys(pkg.devDependencies || {}).includes('flow-bin') }); } const { output, targets, flow } = await (0, _prompts.default)(questions); const target = targets[0] === 'commonjs' || targets[0] === 'module' ? targets[0] : undefined; const entries = { 'main': target ? _path.default.join(output, target, 'index.js') : _path.default.join(source, entryFile), 'react-native': _path.default.join(source, entryFile) }; if (targets.includes('module')) { entries.module = _path.default.join(output, 'module', 'index.js'); } if (targets.includes('typescript')) { entries.types = _path.default.join(output, 'typescript', source, 'index.d.ts'); if (!(await _fsExtra.default.pathExists(_path.default.join(root, 'tsconfig.json')))) { const { tsconfig } = await (0, _prompts.default)({ type: 'confirm', name: 'tsconfig', message: `You have enabled 'typescript' compilation, but we couldn't find a 'tsconfig.json' in project root. Generate one?`, initial: true }); if (tsconfig) { await _fsExtra.default.writeFile(_path.default.join(root, 'tsconfig.json'), JSON.stringify({ compilerOptions: { allowUnreachableCode: false, allowUnusedLabels: false, esModuleInterop: true, forceConsistentCasingInFileNames: true, jsx: 'react', lib: ['esnext'], module: 'esnext', moduleResolution: 'node', noFallthroughCasesInSwitch: true, noImplicitReturns: true, noImplicitUseStrict: false, noStrictGenericChecks: false, noUnusedLocals: true, noUnusedParameters: true, resolveJsonModule: true, skipLibCheck: true, strict: true, target: 'esnext' } }, null, 2)); } } } const prepare = 'bob build'; const files = [source, output, '!**/__tests__', '!**/__fixtures__', '!**/__mocks__']; for (const key in entries) { const entry = entries[key]; if (pkg[key] && pkg[key] !== entry) { const { replace } = await (0, _prompts.default)({ type: 'confirm', name: 'replace', message: `Your package.json has the '${key}' field set to '${pkg[key]}'. Do you want to replace it with '${entry}'?`, initial: true }); if (replace) { pkg[key] = entry; } } else { pkg[key] = entry; } } if ((_pkg$scripts = pkg.scripts) !== null && _pkg$scripts !== void 0 && _pkg$scripts.prepare && pkg.scripts.prepare !== prepare) { const { replace } = await (0, _prompts.default)({ type: 'confirm', name: 'replace', message: `Your package.json has the 'scripts.prepare' field set to '${pkg.scripts.prepare}'. Do you want to replace it with '${prepare}'?`, initial: true }); if (replace) { pkg.scripts.prepare = prepare; } } else { pkg.scripts = pkg.scripts || {}; pkg.scripts.prepare = prepare; } if (pkg.files && JSON.stringify(pkg.files.slice().sort()) !== JSON.stringify(files.slice().sort())) { const { update } = await (0, _prompts.default)({ type: 'confirm', name: 'update', message: `Your package.json already has a 'files' field. Do you want to update it?`, initial: true }); if (update) { pkg.files = [...files, ...pkg.files.filter(file => !files.includes(file.replace(/\/$/g, '')))]; } } else { pkg.files = files; } pkg[name] = { source, output, targets: targets.map(t => { if (t === target && flow) { return [t, { flow }]; } return t; }) }; if (pkg.jest) { const entry = `<rootDir>/${output}/`; if (pkg.jest.modulePathIgnorePatterns) { const { modulePathIgnorePatterns } = pkg.jest; if (!modulePathIgnorePatterns.includes(entry)) { modulePathIgnorePatterns.push(entry); } } else { pkg.jest.modulePathIgnorePatterns = [entry]; } } pkg.eslintIgnore = pkg.eslintIgnore || ['node_modules/']; if (!pkg.eslintIgnore.includes(`${output}/`)) { pkg.eslintIgnore.push(`${output}/`); } await _fsExtra.default.writeFile(pak, JSON.stringify(pkg, null, 2)); const ignorefiles = [_path.default.join(root, '.gitignore'), _path.default.join(root, '.eslintignore')]; for (const ignorefile of ignorefiles) { if (await _fsExtra.default.pathExists(ignorefile)) { const content = await _fsExtra.default.readFile(ignorefile, 'utf-8'); if (!content.split('\n').includes(`${output}/`)) { await _fsExtra.default.writeFile(ignorefile, `${content}\n# generated by bob\n${output}/\n`); } } } console.log((0, _dedent.default)((0, _chalk.default)` Project {yellow ${pkg.name}} configured successfully! {magenta {bold Perform last steps} by running}{gray :} {gray $} yarn {yellow Good luck!} `)); }).command('build', 'build files for publishing', {}, async argv => { var _options$targets; const result = explorer.search(); if (!(result !== null && result !== void 0 && result.config)) { logger.exit(`No configuration found. Run '${argv.$0} init' to create one automatically.`); } const options = result.config; if (!((_options$targets = options.targets) !== null && _options$targets !== void 0 && _options$targets.length)) { logger.exit(`No targets found in the configuration in '${_path.default.relative(root, result.filepath)}'.`); } const source = options.source; if (!source) { logger.exit(`No source option found in the configuration in '${_path.default.relative(root, result.filepath)}'.`); } const output = options.output; if (!output) { logger.exit(`No source option found in the configuration in '${_path.default.relative(root, result.filepath)}'.`); } const report = { info: logger.info, warn: logger.warn, error: logger.error, success: logger.success }; for (const target of options.targets) { const targetName = Array.isArray(target) ? target[0] : target; const targetOptions = Array.isArray(target) ? target[1] : undefined; report.info(`Building target ${_chalk.default.blue(targetName)}`); switch (targetName) { case 'aar': await (0, _aar.default)({ root, source: _path.default.resolve(root, source), output: _path.default.resolve(root, output, 'aar'), options: targetOptions, report }); break; case 'commonjs': await (0, _commonjs.default)({ root, source: _path.default.resolve(root, source), output: _path.default.resolve(root, output, 'commonjs'), options: targetOptions, report }); break; case 'module': await (0, _module.default)({ root, source: _path.default.resolve(root, source), output: _path.default.resolve(root, output, 'module'), options: targetOptions, report }); break; case 'typescript': await (0, _typescript.default)({ root, source: _path.default.resolve(root, source), output: _path.default.resolve(root, output, 'typescript'), options: targetOptions, report }); break; default: logger.exit(`Invalid target ${_chalk.default.blue(targetName)}.`); } } }).demandCommand().recommendCommands().strict().argv; //# sourceMappingURL=cli.js.map