From c754755cd81b8e25ce90f34278c242e6998f95c1 Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Mon, 29 Apr 2024 05:04:26 -0700 Subject: [PATCH] CLI supports ordering of tasks Summary: This gives Frameworks more control in selecting specific tasks and integrating the return types data in their UI. For example piping `stdout` to the user or using packages like [Listr2](https://www.npmjs.com/package/listr2) to run tasks in parallel and show progress. The ordering is suggestive (but also enforced by some assertions). Frameworks are free to do what they want. The order was implicit in the previous data structure with lists of Tasks, but made it difficult to tap into each async task. I've also had to rework how we transpile the code if directly executed from the monorepo. This keeps our: - flow types valid, - allows the core-cli-utils package to be built (to generate TypeScript types and a valid npm module), and - allows direct transpiled execution as a yarn script. Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D56242487 fbshipit-source-id: a1a18f14a4aef53a98770462c8ebdef4111f0ab4 --- .eslintrc.js | 2 +- .../src/commands/start/runServer.js | 2 +- packages/core-cli-utils/package.json | 10 +-- packages/core-cli-utils/src/index.js | 34 --------- packages/core-cli-utils/src/monorepo.js | 23 +++++++ .../core-cli-utils/src/private/android.js | 6 +- packages/core-cli-utils/src/private/apple.js | 1 + packages/core-cli-utils/src/private/utils.js | 1 + packages/helloworld/.gitignore | 23 +------ packages/helloworld/{App.tsx => App.jsx} | 0 packages/helloworld/__tests__/App.test.tsx | 24 ------- packages/helloworld/__tests__/cli-skip.js | 69 +++++++++++++++++++ packages/helloworld/android/app/build.gradle | 2 +- packages/helloworld/android/gradle.properties | 41 ++--------- packages/helloworld/android/settings.gradle | 5 +- packages/helloworld/app.json | 4 -- packages/helloworld/cli.flow.js | 67 ++++++++++++++++-- packages/helloworld/cli.js | 31 ++++++++- packages/helloworld/index.js | 5 +- packages/helloworld/metro.config.js | 19 ++++- packages/helloworld/package.json | 6 +- packages/helloworld/scripts/metro.js | 37 ++++++++++ packages/helloworld/scripts/monorepo.js | 42 +++++++++++ packages/helloworld/template/index.js | 14 ---- packages/helloworld/tsconfig.json | 3 - yarn.lock | 16 ++--- 26 files changed, 314 insertions(+), 173 deletions(-) delete mode 100644 packages/core-cli-utils/src/index.js create mode 100644 packages/core-cli-utils/src/monorepo.js rename packages/helloworld/{App.tsx => App.jsx} (100%) delete mode 100644 packages/helloworld/__tests__/App.test.tsx create mode 100644 packages/helloworld/__tests__/cli-skip.js delete mode 100644 packages/helloworld/app.json create mode 100644 packages/helloworld/scripts/metro.js create mode 100644 packages/helloworld/scripts/monorepo.js delete mode 100644 packages/helloworld/template/index.js delete mode 100644 packages/helloworld/tsconfig.json diff --git a/.eslintrc.js b/.eslintrc.js index c1e8f5e0e9b..d1335831550 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -24,7 +24,7 @@ module.exports = { // overriding the JS config from @react-native/eslint-config to ensure // that we use hermes-eslint for all js files { - files: ['*.js', '*.js.flow'], + files: ['*.js', '*.js.flow', '*.jsx'], parser: 'hermes-eslint', rules: { // These rules are not required with hermes-eslint diff --git a/packages/community-cli-plugin/src/commands/start/runServer.js b/packages/community-cli-plugin/src/commands/start/runServer.js index 15820167a52..18540fa1e2c 100644 --- a/packages/community-cli-plugin/src/commands/start/runServer.js +++ b/packages/community-cli-plugin/src/commands/start/runServer.js @@ -38,7 +38,7 @@ export type StartCommandArgs = { https?: boolean, maxWorkers?: number, key?: string, - platforms?: string[], + platforms: string[], port?: number, resetCache?: boolean, sourceExts?: string[], diff --git a/packages/core-cli-utils/package.json b/packages/core-cli-utils/package.json index 9107b6fdbe3..04f7d25b7dd 100644 --- a/packages/core-cli-utils/package.json +++ b/packages/core-cli-utils/package.json @@ -2,7 +2,7 @@ "name": "@react-native/core-cli-utils", "version": "0.75.0-main", "description": "React Native CLI library for Frameworks to build on", - "main": "./src/index.js", + "main": "./src/index.flow.js", "license": "MIT", "repository": { "type": "git", @@ -10,11 +10,11 @@ "directory": "packages/core-cli-utils" }, "exports": { - ".": "./src/index.js", + ".": "./src/index.flow.js", "./package.json": "./package.json", "./version.js": "./src/public/version.js" }, - "types": "./dist/index.d.ts", + "types": "./dist/index.flow.d.ts", "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/core-cli-utils#readme", "keywords": [ "cli-utils", @@ -25,8 +25,8 @@ "node": ">=18" }, "files": [ - "dist" + "src" ], "dependencies": {}, "devDependencies": {} -} +} \ No newline at end of file diff --git a/packages/core-cli-utils/src/index.js b/packages/core-cli-utils/src/index.js deleted file mode 100644 index 9d4c8354fc2..00000000000 --- a/packages/core-cli-utils/src/index.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - * @format - * @oncall react_native - */ - -const path = require('path'); - -/*:: -export type * from './index.flow.js'; -*/ - -if (!process.env.BUILD_EXCLUDE_BABEL_REGISTER) { - // Handle internal cases when we call this from the monorepo, and external cases where users call it from a plain-old-node_modules - let {root, dir} = path.parse(__dirname); - while (dir !== root) { - try { - // $FlowFixMe[unsupported-syntax] we're doing magic here - require( - path.resolve(dir, 'scripts/build/babel-register'), - ).registerForMonorepo(); - break; - } catch { - dir = path.resolve(dir, '..'); - } - } -} - -export * from './index.flow.js'; diff --git a/packages/core-cli-utils/src/monorepo.js b/packages/core-cli-utils/src/monorepo.js new file mode 100644 index 00000000000..be8075fc7c4 --- /dev/null +++ b/packages/core-cli-utils/src/monorepo.js @@ -0,0 +1,23 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @oncall react_native + */ + +// Should only used when called in the monorepo when we don't want to use the `yarn run build` +// step to transpile to project. When used as a vanilla npm package, it should be built and +// exported with `dist/index.flow.js` as main. +// +// The reason for this workaround is that flow-api-translator can't understand ESM and CJS style +// exports in the same file. Throw in a bit of Flow in the mix and it all goes to hell. +// +// See packages/helloworld/cli.js for an example of how to swap this out in the monorepo. +if (process.env.BUILD_EXCLUDE_BABEL_REGISTER == null) { + require('../../../scripts/build/babel-register').registerForMonorepo(); +} + +module.exports = require('./index.flow.js'); diff --git a/packages/core-cli-utils/src/private/android.js b/packages/core-cli-utils/src/private/android.js index 83ec922c0ac..9117f9130f4 100644 --- a/packages/core-cli-utils/src/private/android.js +++ b/packages/core-cli-utils/src/private/android.js @@ -24,12 +24,8 @@ type AndroidBuild = { gradleArgs?: Array, }; -async function gradle( - cwd: string, - ...args: string[] -): ReturnType { +function gradle(cwd: string, ...args: string[]): ExecaPromise { const gradlew = isWindows ? 'gradlew.bat' : './gradlew'; - // $FlowFixMe[incompatible-return] Mismatch between flow and TypeScript types return execa(gradlew, args, { cwd, stdio: 'inherit', diff --git a/packages/core-cli-utils/src/private/apple.js b/packages/core-cli-utils/src/private/apple.js index ed3414da6ac..9ec6a0bc9c5 100644 --- a/packages/core-cli-utils/src/private/apple.js +++ b/packages/core-cli-utils/src/private/apple.js @@ -39,6 +39,7 @@ type AppleInstallApp = { // `xcrun simctl list devices` device: string, appPath: string, + bundleId: string, ...AppleOptions, }; diff --git a/packages/core-cli-utils/src/private/utils.js b/packages/core-cli-utils/src/private/utils.js index 396d29eed20..3c2f096b5cd 100644 --- a/packages/core-cli-utils/src/private/utils.js +++ b/packages/core-cli-utils/src/private/utils.js @@ -41,6 +41,7 @@ type PathCheckResult = { export function isOnPath(dep: string, description: string): PathCheckResult { const cmd = isWindows ? ['where', [dep]] : ['command', ['-v', dep]]; try { + const args = isWindows ? ['where', [dep]] : ['command', ['-v', dep]]; return { dep, description, diff --git a/packages/helloworld/.gitignore b/packages/helloworld/.gitignore index d5ae456695e..08e1a6b5935 100644 --- a/packages/helloworld/.gitignore +++ b/packages/helloworld/.gitignore @@ -1,9 +1,7 @@ # OSX -# .DS_Store # Xcode -# build/ *.pbxuser !default.pbxuser @@ -23,7 +21,6 @@ DerivedData **/.xcode.env.local # Android/IntelliJ -# build/ .idea .gradle @@ -35,36 +32,20 @@ local.properties !debug.keystore # node.js -# node_modules/ npm-debug.log yarn-error.log -# fastlane -# -# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the -# screenshots whenever they are needed. -# For more information about the recommended setup visit: -# https://docs.fastlane.tools/best-practices/source-control/ - -**/fastlane/report.xml -**/fastlane/Preview.html -**/fastlane/screenshots -**/fastlane/test_output - # Bundle artifact *.jsbundle # Ruby / CocoaPods -**/Pods/ -/vendor/bundle/ +ios/Pods/ +vendor/bundle/ # Temporary files created by Metro to check the health of the file watcher .metro-health-check* -# testing -/coverage - # Yarn .yarn/* !.yarn/patches diff --git a/packages/helloworld/App.tsx b/packages/helloworld/App.jsx similarity index 100% rename from packages/helloworld/App.tsx rename to packages/helloworld/App.jsx diff --git a/packages/helloworld/__tests__/App.test.tsx b/packages/helloworld/__tests__/App.test.tsx deleted file mode 100644 index 222e662c22c..00000000000 --- a/packages/helloworld/__tests__/App.test.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** - * @format - */ - -import 'react-native'; -import React from 'react'; -import App from '../App'; - -// Note: import explicitly to use the types shipped with jest. -import {it} from '@jest/globals'; - -// Note: test renderer must be required after react-native. -import renderer from 'react-test-renderer'; - -it('renders correctly', () => { - renderer.create(); -}); diff --git a/packages/helloworld/__tests__/cli-skip.js b/packages/helloworld/__tests__/cli-skip.js new file mode 100644 index 00000000000..2b92acc1bc8 --- /dev/null +++ b/packages/helloworld/__tests__/cli-skip.js @@ -0,0 +1,69 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +// TODO(T187224491): js1 jest doesn't install the correct commander, instead +// using the one in xplat/js/node_modules/commander which is much older. +// Either roll back to that version or upgrade. +import cli from '../cli.flow.js'; +import fs from 'fs'; + +describe('cli.js', () => { + let pkgJson = { + name: 'helloworld-mock', + dependencies: { + 'react-native': '0.0.0', + }, + devDependencies: { + listr: '^1.2.3', + 'some-dev-dep': '1.0.0', + }, + }; + beforeEach(() => { + jest.resetAllMocks(); + }); + describe('set-version', () => { + it('without arguments this should not modify the package.json', () => { + const snapshot = JSON.stringify(pkgJson, null, 2); + jest.spyOn(fs, 'readFileSync').mockReturnValue(snapshot); + const spy = jest.spyOn(fs, 'writeFileSync'); + + cli.parse(['set-version'], {from: 'user'}); + + expect(spy.mock.lastCall[1]).toEqual(snapshot); + }); + + it('modified and adds dependencies', () => { + const snapshot = JSON.stringify(pkgJson, null, 2); + jest.spyOn(fs, 'readFileSync').mockReturnValue(snapshot); + const spy = jest.spyOn(fs, 'writeFileSync'); + + cli.parse( + [ + 'set-version', + 'react-native@^0.1.1', + 'foobar@file:/woot/berry', + 'some-dev-dep@*', + ], + {from: 'user'}, + ); + const updated = JSON.parse(spy.mock.lastCall[1]); + expect(updated).toMatchObject({ + dependencies: { + 'react-native': '^0.1.1', + foobar: 'file:/woot/berry', + }, + devDependencies: { + 'some-dev-dep': '*', + }, + }); + }); + }); +}); diff --git a/packages/helloworld/android/app/build.gradle b/packages/helloworld/android/app/build.gradle index 92894277ad9..f3db66d5ed3 100644 --- a/packages/helloworld/android/app/build.gradle +++ b/packages/helloworld/android/app/build.gradle @@ -123,4 +123,4 @@ dependencies { } // TODO: This needs to use the new autolinking code in the gradle-plugin instead -apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) +// apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) diff --git a/packages/helloworld/android/gradle.properties b/packages/helloworld/android/gradle.properties index b8bf0a51744..29fb5a6ad4f 100644 --- a/packages/helloworld/android/gradle.properties +++ b/packages/helloworld/android/gradle.properties @@ -1,42 +1,13 @@ -# Project-wide Gradle settings. +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true - -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app's APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn +org.gradle.parallel=true android.useAndroidX=true -# Automatically convert third-party libraries to use AndroidX android.enableJetifier=true - -# Use this property to specify which architecture you want to build. -# You can also override it from the CLI using -# ./gradlew -PreactNativeArchitectures=x86_64 -# TODO: Do we want to limit the architectures we test on? -reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 - -# Use this property to enable support to the new architecture. -# This will allow you to use TurboModules and the Fabric render in -# your application. You should enable this flag either if you want -# to write custom TurboModules/Fabric components OR use libraries that -# are providing them. +reactNativeArchitectures=arm64-v8a newArchEnabled=true - -# Use this property to enable or disable the Hermes JS engine. -# If set to false, you will be using JSC instead. hermesEnabled=true diff --git a/packages/helloworld/android/settings.gradle b/packages/helloworld/android/settings.gradle index d4b8bc5e713..0125930e708 100644 --- a/packages/helloworld/android/settings.gradle +++ b/packages/helloworld/android/settings.gradle @@ -6,7 +6,6 @@ */ rootProject.name = 'HelloWorld' -// TODO: Use the new autolinking feature in the gradle plugin (not that it's necessary as we don't have any native extensions here. Maybe we should have?) -// apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app' -includeBuild('../../../../react-native-gradle-plugin') +// Autolinking has now moved into the React Native Gradle Plugin +includeBuild('../../react-native-gradle-plugin') diff --git a/packages/helloworld/app.json b/packages/helloworld/app.json deleted file mode 100644 index cbbc305181a..00000000000 --- a/packages/helloworld/app.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "HelloWorld", - "displayName": "HelloWorld" -} diff --git a/packages/helloworld/cli.flow.js b/packages/helloworld/cli.flow.js index 59cc2033d35..177f64ce1ac 100644 --- a/packages/helloworld/cli.flow.js +++ b/packages/helloworld/cli.flow.js @@ -41,21 +41,23 @@ type IOSDevice = { name: string, }; -function observe(result: ExecaPromise): Observable { +type ExecaPromiseMetaized = Promise & child_process$ChildProcess; + +function observe(result: ExecaPromiseMetaized): Observable { return new Observable(observer => { result.stderr.on('data', data => data .toString('utf8') .split('\n') .filter(line => line.length > 0) - .forEach(line => observer.next('🟢 ' + line)), + .forEach(line => observer.next('🟢 ' + line.trim())), ); result.stdout.on('data', data => data .toString('utf8') .split('\n') .filter(line => line.length > 0) - .forEach(line => observer.next('🟠 ' + line)), + .forEach(line => observer.next('🟠 ' + line.trim())), ); for (const event of ['close', 'end']) { result.stdout.on(event, () => observer.complete()); @@ -70,6 +72,26 @@ function observe(result: ExecaPromise): Observable { }); } +function getXcodeBuildSettings(iosProjectFolder: string) { + const {stdout} = execa.sync( + 'xcodebuild', + [ + '-workspace', + 'HelloWorld.xcworkspace', + '-scheme', + 'HelloWorld', + '-configuration', + 'Debug', + '-sdk', + 'iphonesimulator', + '-showBuildSettings', + '-json', + ], + {cwd: iosProjectFolder}, + ); + return JSON.parse(stdout); +} + async function getSimulatorDetails(nameOrUDID: string): Promise { const {stdout} = execa.sync('xcrun', [ 'simctl', @@ -164,7 +186,9 @@ function run( title: task.label, task: () => { const action = task.action(); - return action != null ? observe(action) : action; + if (action != null) { + return observe(action); + } }, })); return new Listr(spec).run(); @@ -209,7 +233,38 @@ build }), ); - // TODO: Install + const settings = { + appPath: '', + bundleId: '', + }; + + await run({ + buildSettings: { + order: 1, + label: 'Getting your build settings', + action: (): void => { + const xcode = getXcodeBuildSettings(cwd.ios)[0].buildSettings; + settings.appPath = path.join( + xcode.TARGET_BUILD_DIR, + xcode.EXECUTABLE_FOLDER_PATH, + ); + settings.bundleId = xcode.PRODUCT_BUNDLE_IDENTIFIER; + }, + }, + }); + + await run( + apple.ios.install({ + cwd: cwd.ios, + device: device.udid, + appPath: settings.appPath, + bundleId: settings.bundleId, + }), + ); }); -program.parse(); +if (require.main === module) { + program.parse(); +} + +export default program; diff --git a/packages/helloworld/cli.js b/packages/helloworld/cli.js index b7c213c3f0e..b5ba1ed3c55 100644 --- a/packages/helloworld/cli.js +++ b/packages/helloworld/cli.js @@ -9,9 +9,38 @@ * @oncall react_native */ +/*:: +import {Command} from 'commander'; +*/ + +// eslint-disable-next-line lint/sort-imports +const {patchCoreCLIUtilsPackageJSON} = require('./scripts/monorepo'); + +function injectCoreCLIUtilsRuntimePatch() { + patchCoreCLIUtilsPackageJSON(true); + const cleared = { + status: false, + }; + ['exit', 'SIGUSR1', 'SIGUSR2', 'uncaughtException'].forEach(event => { + if (cleared.status) { + return; + } + patchCoreCLIUtilsPackageJSON(false); + cleared.status = true; + }); +} + if (process.env.BUILD_EXCLUDE_BABEL_REGISTER == null) { // $FlowFixMe[cannot-resolve-module] require('../../scripts/build/babel-register').registerForMonorepo(); } -require('./cli.flow.js'); +injectCoreCLIUtilsRuntimePatch(); + +const program /*: Command */ = require('./cli.flow.js').default; + +if (require.main === module) { + program.parse(); +} + +module.exports = program; diff --git a/packages/helloworld/index.js b/packages/helloworld/index.js index 040d10d9660..19836486c82 100644 --- a/packages/helloworld/index.js +++ b/packages/helloworld/index.js @@ -7,8 +7,7 @@ * @format */ -import {name as appName} from './app.json'; -import App from './SectionProps'; +import App from './App'; import {AppRegistry} from 'react-native'; -AppRegistry.registerComponent(appName, () => App); +AppRegistry.registerComponent('HelloWorld', () => App); diff --git a/packages/helloworld/metro.config.js b/packages/helloworld/metro.config.js index ed129355727..50855d5a705 100644 --- a/packages/helloworld/metro.config.js +++ b/packages/helloworld/metro.config.js @@ -8,6 +8,7 @@ */ const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); +const path = require('path'); /** * Metro configuration @@ -15,6 +16,22 @@ const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); * * @type {import('metro-config').MetroConfig} */ -const config = {}; +const config = { + // Make Metro able to resolve required external dependencies + watchFolders: [ + path.resolve(__dirname, '../../node_modules'), + path.resolve(__dirname, '../assets'), + path.resolve(__dirname, '../normalize-color'), + path.resolve(__dirname, '../polyfills'), + path.resolve(__dirname, '../react-native'), + path.resolve(__dirname, '../virtualized-lists'), + ], + resolver: { + blockList: [/..\/react-native\/sdks\/hermes/], + extraNodeModules: { + 'react-native': path.resolve(__dirname, '../react-native'), + }, + }, +}; module.exports = mergeConfig(getDefaultConfig(__dirname), config); diff --git a/packages/helloworld/package.json b/packages/helloworld/package.json index 885ca571c30..4d1c986fade 100644 --- a/packages/helloworld/package.json +++ b/packages/helloworld/package.json @@ -5,7 +5,7 @@ "scripts": { "bootstrap": "node ./cli.js bootstrap", "build": "node ./cli.js build", - "launch": "node ./cli.js launch", + "launch": "node ./scripts/metro.js", "lint": "eslint .", "test": "jest" }, @@ -22,13 +22,13 @@ "@react-native/eslint-config": "0.75.0-main", "@react-native/metro-config": "0.75.0-main", "babel-jest": "^29.6.3", + "chalk": "4", "commander": "^12.0.0", "eslint": "^8.19.0", "jest": "^29.6.3", "listr": "^0.14.3", "react-test-renderer": "18.2.0", - "rxjs": "^7.8.1", - "typescript": "5.0.4" + "rxjs": "^7.8.1" }, "engines": { "node": ">=18" diff --git a/packages/helloworld/scripts/metro.js b/packages/helloworld/scripts/metro.js new file mode 100644 index 00000000000..54a2fd43d13 --- /dev/null +++ b/packages/helloworld/scripts/metro.js @@ -0,0 +1,37 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @noflow + * @format + * @oncall react_native + */ + +const {startCommand} = require('@react-native/community-cli-plugin'); +const {program} = require('commander'); +const path = require('path'); + +program + .description('Starts the React Native Metro bundler for internal testing app') + .action(async options => { + await startCommand.func( + [], + { + platforms: { + ios: {}, + android: {}, + }, + root: path.join(__dirname, '../'), + reactNativePath: path.join(__dirname, '../../react-native'), + }, + { + experimentalDebugger: false, + interactive: false, + projectRoot: options.projectRoot, + platforms: ['ios', 'android'], + }, + ); + }) + .parse(); diff --git a/packages/helloworld/scripts/monorepo.js b/packages/helloworld/scripts/monorepo.js new file mode 100644 index 00000000000..7911f764b59 --- /dev/null +++ b/packages/helloworld/scripts/monorepo.js @@ -0,0 +1,42 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +// To be able to execute the cli as a yarn script, we have to strip our yarn types. +// This causes problems for some of our dependencies, because they live in Meta internals, +// Github and in NPM: +// - Github and Meta: dynamicly transpile our dependencies. They each have to register on the monorepo +// - NPM: `yarn run build`, and it should update the package.json's exports, main and files +function patchCoreCLIUtilsPackageJSON(patch /*: boolean */) { + const fs = require('fs'); + const log = require('debug'); + const pkg = JSON.parse( + fs.readFileSync('../core-cli-utils/package.json', 'utf8'), + ); + const target = patch ? './src/monorepo.js' : './src/index.flow.js'; + if (pkg.main === target) { + return; + } + pkg.main = target; + pkg.exports['.'] = target; + log( + `Patched: ${JSON.stringify( + {main: pkg.main, exports: pkg.exports}, + null, + 2, + )}`, + ); + fs.writeFileSync( + '../core-cli-utils/package.json', + JSON.stringify(pkg, null, 2), + ); +} + +module.exports.patchCoreCLIUtilsPackageJSON = patchCoreCLIUtilsPackageJSON; diff --git a/packages/helloworld/template/index.js b/packages/helloworld/template/index.js deleted file mode 100644 index f0888064722..00000000000 --- a/packages/helloworld/template/index.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -import App from './App'; -import {name as appName} from './app.json'; -import {AppRegistry} from 'react-native'; - -AppRegistry.registerComponent(appName, () => App); diff --git a/packages/helloworld/tsconfig.json b/packages/helloworld/tsconfig.json deleted file mode 100644 index ea3ea6b9595..00000000000 --- a/packages/helloworld/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../../typescript-config/tsconfig.json" -} diff --git a/yarn.lock b/yarn.lock index a1f3c822bd2..3dc0fb0e1dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3853,6 +3853,14 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= +chalk@4, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -3873,14 +3881,6 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"