UNPKG

create-react-native-library

Version:
283 lines (282 loc) 9.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.acceptedArgs = void 0; exports.createMetadata = createMetadata; exports.createQuestions = createQuestions; var _fsExtra = _interopRequireDefault(require("fs-extra")); var _githubUsername = _interopRequireDefault(require("github-username")); var _path = _interopRequireDefault(require("path")); var _validateNpmPackageName = _interopRequireDefault(require("validate-npm-package-name")); var _package = require("../package.json"); var _constants = require("./constants"); var _spawn = require("./utils/spawn"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const LANGUAGE_CHOICES = [{ title: 'Kotlin & Swift', value: 'kotlin-swift', types: ['nitro-module', 'nitro-view'] }, { title: 'Kotlin & Objective-C', value: 'kotlin-objc', types: ['turbo-module', 'fabric-view'] }, { title: 'JavaScript for Android, iOS & Web', value: 'js', types: ['library'] }]; const EXAMPLE_CHOICES = [{ title: 'App with Community CLI', value: 'vanilla', description: "provides access to app's native code", disabled: false }, { title: 'Test App by Microsoft', value: 'test-app', description: "app's native code is abstracted away", // Test App currently doesn't work with React Native 0.79.2 // due to missing `Gemfile` in the template disabled: !process.env.CRNL_ENABLE_TEST_APP }, { title: 'App with Expo CLI', value: 'expo', description: 'managed expo app with web support', disabled: false }].filter(choice => !choice.disabled); const TYPE_CHOICES = [{ title: 'Turbo module', value: 'turbo-module', description: 'integration for native APIs to JS' }, { title: 'Fabric view', value: 'fabric-view', description: 'integration for native views to JS' }, { title: 'Nitro module', value: 'nitro-module', description: 'type-safe, fast integration for native APIs to JS (experimental)' }, { title: 'Nitro view', value: 'nitro-view', description: 'integration for native views to JS using nitro for prop parsing (experimental)' }, { title: 'JavaScript library', value: 'library', description: 'supports Expo Go and Web' }]; const acceptedArgs = exports.acceptedArgs = { 'slug': { description: 'Name of the npm package', type: 'string' }, 'description': { description: 'Description of the npm package', type: 'string' }, 'author-name': { description: 'Name of the package author', type: 'string' }, 'author-email': { description: 'Email address of the package author', type: 'string' }, 'author-url': { description: 'URL for the package author', type: 'string' }, 'repo-url': { description: 'URL for the repository', type: 'string' }, 'languages': { description: 'Languages you want to use', choices: LANGUAGE_CHOICES.map(({ value }) => value) }, 'type': { description: 'Type of library you want to develop', choices: TYPE_CHOICES.map(({ value }) => value) }, 'react-native-version': { description: 'Version of React Native to use', type: 'string', default: _constants.SUPPORTED_REACT_NATIVE_VERSION }, 'local': { description: 'Whether to create a local library', type: 'boolean' }, 'example': { description: 'Type of the example app to create', type: 'string', choices: EXAMPLE_CHOICES.map(({ value }) => value) }, 'interactive': { description: 'Whether to run in interactive mode', type: 'boolean' } }; async function createQuestions({ name, local }) { let fullname, email; try { fullname = await (0, _spawn.spawn)('git', ['config', '--get', 'user.name']); email = await (0, _spawn.spawn)('git', ['config', '--get', 'user.email']); } catch (e) { // Ignore error } const questions = [{ type: local == null && (await _fsExtra.default.pathExists(_path.default.join(process.cwd(), 'package.json'))) ? 'confirm' : null, name: 'local', message: `Looks like you're under a project folder. Do you want to create a local library?`, initial: local, default: false }, { type: (_, answers) => name && !(answers.local ?? local) ? null : 'text', name: 'directory', message: `Where do you want to create the library?`, initial: (_, answers) => { if ((answers.local ?? local) && name && !name?.includes(_path.default.sep)) { return _path.default.join('modules', name); } return name ?? ''; }, validate: input => { if (!input) { return 'Cannot be empty'; } const targetPath = _path.default.join(process.cwd(), input); if (_fsExtra.default.pathExistsSync(targetPath)) { const stat = _fsExtra.default.statSync(targetPath); if (!stat.isDirectory()) { return 'Path exists and is not a directory'; } const files = _fsExtra.default.readdirSync(targetPath); const isEmpty = files.length === 0 || files.length === 1 && files[0] === '.git'; if (!isEmpty) { return 'Directory already exists'; } } return true; }, default: name }, { type: 'text', name: 'slug', message: 'What is the name of the npm package?', initial: (_, answers) => { const basename = _path.default.basename(typeof answers.directory === 'string' ? answers.directory : name ?? ''); if ((0, _validateNpmPackageName.default)(basename).validForNewPackages) { if (/^(@|react-native)/.test(basename)) { return basename; } return `react-native-${basename}`; } return ''; }, validate: input => (0, _validateNpmPackageName.default)(input).validForNewPackages || 'Must be a valid npm package name' }, { type: 'text', name: 'description', message: 'What is the description for the package?', validate: input => Boolean(input) || 'Cannot be empty' }, { type: (_, answers) => answers.local ?? local ? null : 'text', name: 'authorName', message: 'What is the name of package author?', initial: fullname, validate: input => Boolean(input) || 'Cannot be empty' }, { type: (_, answers) => answers.local ?? local ? null : 'text', name: 'authorEmail', message: 'What is the email address for the package author?', initial: email, validate: input => /^\S+@\S+$/.test(input) || 'Must be a valid email address' }, { type: (_, answers) => answers.local ?? local ? null : 'text', name: 'authorUrl', message: 'What is the URL for the package author?', initial: async (_, answers) => { if (typeof answers.authorEmail !== 'string') { return ''; } try { const username = await (0, _githubUsername.default)(answers.authorEmail); if (username) { return `https://github.com/${username}`; } } catch (e) { // Ignore error } return ''; }, validate: input => /^https?:\/\//.test(input) || 'Must be a valid URL' }, { type: (_, answers) => answers.local ?? local ? null : 'text', name: 'repoUrl', message: 'What is the URL for the repository?', initial: (_, answers) => { if (typeof answers.authorUrl === 'string' && typeof answers.slug === 'string' && /^https?:\/\/github.com\/[^/]+/.test(answers.authorUrl)) { return `${answers.authorUrl}/${answers.slug.replace(/^@/, '').replace(/\//g, '-')}`; } return ''; }, validate: input => /^https?:\/\//.test(input) || 'Must be a valid URL' }, { type: 'select', name: 'type', message: 'What type of library do you want to develop?', choices: TYPE_CHOICES }, { type: 'select', name: 'languages', message: 'Which languages do you want to use?', choices: (_, values) => { return LANGUAGE_CHOICES.filter(choice => { if (choice.types && typeof values.type === 'string') { // @ts-expect-error `includes doesn't support checking arbitrary types return choice.types.includes(values.type); } return true; }); } }, { type: 'select', name: 'example', message: 'What type of example app do you want to create?', choices: (_, values) => { if (local) { return [{ title: 'None', value: 'none' }]; } return EXAMPLE_CHOICES.filter(choice => { if (values.type) { return values.type === 'library' ? choice.value === 'expo' : choice.value !== 'expo'; } return true; }); } }]; return questions; } function createMetadata(answers) { // Some of the passed args can already be derived from the generated package.json file. const ignoredAnswers = ['name', 'directory', 'slug', 'description', 'authorName', 'authorEmail', 'authorUrl', 'repoUrl', 'example', 'reactNativeVersion', 'local', 'interactive']; const libraryMetadata = Object.fromEntries( // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion Object.entries(answers).filter(([answer]) => !ignoredAnswers.includes(answer))); libraryMetadata.version = _package.version; return libraryMetadata; } //# sourceMappingURL=input.js.map