diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index b0bbfa06b3..85fe79f153 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -4808,6 +4808,14 @@ "children": [], "isExternal": false, "disableCollapsible": false + }, + { + "id": "submit", + "path": "/packages/expo/executors/submit", + "name": "submit", + "children": [], + "isExternal": false, + "disableCollapsible": false } ], "isExternal": false, diff --git a/docs/generated/manifests/packages.json b/docs/generated/manifests/packages.json index 35123dcb33..65756a0148 100644 --- a/docs/generated/manifests/packages.json +++ b/docs/generated/manifests/packages.json @@ -817,6 +817,15 @@ "originalFilePath": "/packages/expo/src/executors/export/schema.json", "path": "/packages/expo/executors/export", "type": "executor" + }, + "/packages/expo/executors/submit": { + "description": "Submit app binary to App Store and/or Play Store", + "file": "generated/packages/expo/executors/submit.json", + "hidden": false, + "name": "submit", + "originalFilePath": "/packages/expo/src/executors/submit/schema.json", + "path": "/packages/expo/executors/submit", + "type": "executor" } }, "generators": { diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 46d467ff50..cf87250bf6 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -804,6 +804,15 @@ "originalFilePath": "/packages/expo/src/executors/export/schema.json", "path": "expo/executors/export", "type": "executor" + }, + { + "description": "Submit app binary to App Store and/or Play Store", + "file": "generated/packages/expo/executors/submit.json", + "hidden": false, + "name": "submit", + "originalFilePath": "/packages/expo/src/executors/submit/schema.json", + "path": "expo/executors/submit", + "type": "executor" } ], "generators": [ diff --git a/docs/generated/packages/expo/executors/build.json b/docs/generated/packages/expo/executors/build.json index af3bac7809..c1bc9395e4 100644 --- a/docs/generated/packages/expo/executors/build.json +++ b/docs/generated/packages/expo/executors/build.json @@ -10,6 +10,12 @@ "title": "Expo EAS Build executor", "description": "Start an EAS build for your expo project.", "type": "object", + "presets": [ + { "name": "Build for a specific platform", "keys": ["platform"] }, + { "name": "Build using a specific profile", "keys": ["profile"] }, + { "name": "Run build locally", "keys": ["local"] }, + { "name": "Clear cache before the build", "keys": ["clearCache"] } + ], "properties": { "platform": { "enum": ["ios", "android", "all"], @@ -28,10 +34,10 @@ "examples": ["production", "development", "preview"], "x-priority": "important" }, - "nonInteractive": { + "interactive": { "type": "boolean", - "description": "Run command in non-interactive mode", - "default": false + "description": "Run command in interactive mode", + "default": true }, "local": { "type": "boolean", @@ -63,8 +69,7 @@ "examples": ["production", "development", "preview"] } }, - "required": [], - "presets": [] + "required": [] }, "description": "Start an EAS build for your expo project", "aliases": [], diff --git a/docs/generated/packages/expo/executors/prebuild.json b/docs/generated/packages/expo/executors/prebuild.json index 634210cb1f..510f01a5c5 100644 --- a/docs/generated/packages/expo/executors/prebuild.json +++ b/docs/generated/packages/expo/executors/prebuild.json @@ -19,7 +19,7 @@ "install": { "type": "boolean", "description": "Installing npm packages and CocoaPods.", - "default": false, + "default": true, "x-priority": "internal" }, "platform": { diff --git a/docs/generated/packages/expo/executors/run.json b/docs/generated/packages/expo/executors/run.json index f71a5f5140..668255c4e7 100644 --- a/docs/generated/packages/expo/executors/run.json +++ b/docs/generated/packages/expo/executors/run.json @@ -56,7 +56,7 @@ }, "install": { "type": "boolean", - "description": "Should install missing dependencies before building.", + "description": "Installing npm packages and CocoaPods before building.", "default": true }, "buildCache": { diff --git a/docs/generated/packages/expo/executors/start.json b/docs/generated/packages/expo/executors/start.json index ecb4fb5427..5a1de55370 100644 --- a/docs/generated/packages/expo/executors/start.json +++ b/docs/generated/packages/expo/executors/start.json @@ -84,6 +84,11 @@ "offline": { "type": "boolean", "description": "Allows this command to run while offline" + }, + "sync": { + "type": "boolean", + "description": "Syncs npm dependencies to package.json (for React Native autolink).", + "default": true } }, "examplesFile": "`project.json`:\n\n```json\n{\n \"name\": \"mobile\",\n //...\n \"targets\": {\n //...\n \"start\": {\n \"executor\": \"@nx/expo:start\",\n \"options\": {\n \"port\": 8081\n }\n }\n //...\n }\n}\n```\n\n```shell\nnx run mobile:start\n```\n\n## Examples\n\n{% tabs %}\n{% tab label=\"Specify starting on platform\" %}\nThe `ios`, `android` and `web` option allows you to start the server on different platforms.\n\nOpens your app in Expo Go in a currently running iOS simulator on your computer:\n\n```json\n \"start\": {\n \"executor\": \"@nx/expo:start\",\n \"options\": {\n \"port\": 8081,\n \"ios\": true\n }\n }\n```\n\nOpens your app in Expo Go on a connected Android device\n\n```json\n \"start\": {\n \"executor\": \"@nx/expo:start\",\n \"options\": {\n \"port\": 8081,\n \"android\": true\n }\n }\n```\n\nOpens your app in a web browser:\n\n```json\n \"start\": {\n \"executor\": \"@nx/expo:start\",\n \"options\": {\n \"port\": 8081,\n \"web\": true\n }\n }\n```\n\n{% /tab %}\n{% tab label=\"Specify the host\" %}\nThe `host` option allows you to specify the type of host to use. `lan` uses the local network; `tunnel` ues any network by tunnel through ngrok; `localhost` connects to the dev server over localhost.\n\n```json\n \"start\": {\n \"executor\": \"@nx/expo:start\",\n \"options\": {\n \"port\": 8081,\n \"host\": \"localhost\"\n }\n }\n```\n\n{% /tab %}\n{% tab label=\"Starts the server with cache reset\" %}\n\nThe `clear` option allows you to remove Metro bundler cache.\n\n```json\n \"start\": {\n \"executor\": \"@nx/expo:start\",\n \"options\": {\n \"port\": 8081,\n \"clear\": true\n }\n }\n```\n\n{% /tab %}\n{% /tabs %}\n\n---\n", diff --git a/docs/generated/packages/expo/executors/submit.json b/docs/generated/packages/expo/executors/submit.json new file mode 100644 index 0000000000..27a64ffc4f --- /dev/null +++ b/docs/generated/packages/expo/executors/submit.json @@ -0,0 +1,57 @@ +{ + "name": "submit", + "implementation": "/packages/expo/src/executors/submit/submit.impl.ts", + "schema": { + "$schema": "http://json-schema.org/schema", + "version": 2, + "title": "EXPO EAS Submit Executor", + "description": "Submit app binary to App Store and/or Play Store.", + "type": "object", + "presets": [ + { "name": "Submit for a specific platform", "keys": ["platform"] }, + { "name": "Submit using a specific profile", "keys": ["profile"] } + ], + "properties": { + "profile": { + "type": "string", + "description": "Name of the build profile from eas.json. Defaults to \"production\" if defined in eas.json.", + "examples": ["production", "development", "preview"], + "x-priority": "important" + }, + "platform": { + "enum": ["ios", "android", "all"], + "alias": "p", + "description": "The platform to build the app, example values: ios, android, all.", + "x-priority": "important" + }, + "id": { "type": "string", "description": "Build ID to submit" }, + "path": { + "type": "string", + "description": "Path to the .apk/.aab/.ipa file" + }, + "url": { + "type": "string", + "description": "URL to the .apk/.aab/.ipa file, app archive url" + }, + "latest": { + "type": "boolean", + "description": "Submit the latest build for specified platform" + }, + "interactive": { + "type": "boolean", + "description": "Run command in interactive mode", + "default": true + }, + "wait": { + "type": "boolean", + "description": "Wait for build(s) to complete", + "default": true + } + } + }, + "description": "Submit app binary to App Store and/or Play Store", + "aliases": [], + "hidden": false, + "path": "/packages/expo/src/executors/submit/schema.json", + "type": "executor" +} diff --git a/docs/generated/packages/expo/executors/update.json b/docs/generated/packages/expo/executors/update.json index de7365dbe8..e0e598b56e 100644 --- a/docs/generated/packages/expo/executors/update.json +++ b/docs/generated/packages/expo/executors/update.json @@ -10,6 +10,10 @@ "title": "Expo EAS Update executor", "description": "Start an EAS update for your expo project.", "type": "object", + "presets": [ + { "name": "Update for a specific platform", "keys": ["platform"] }, + { "name": "Update from a specific branch", "keys": ["branch"] } + ], "properties": { "branch": { "type": "string", @@ -52,14 +56,13 @@ "type": "string", "description": "File containing the PEM-encoded private key corresponding to the certificate in expo-updates' configuration. Defaults to a file named \"private-key.pem\" in the certificate's directory." }, - "nonInteractive": { + "interactive": { "type": "boolean", - "description": "Run command in non-interactive mode", - "default": false + "description": "Run command in interactive mode", + "default": true } }, - "required": [], - "presets": [] + "required": [] }, "description": "Start an EAS update for your expo project", "aliases": [], diff --git a/packages/expo/executors.json b/packages/expo/executors.json index 55cf02c3e6..810584ad5d 100644 --- a/packages/expo/executors.json +++ b/packages/expo/executors.json @@ -54,6 +54,11 @@ "implementation": "./src/executors/export/export.impl", "schema": "./src/executors/export/schema.json", "description": "Export the JavaScript and assets for your app using Metro/webpack bundler" + }, + "submit": { + "implementation": "./src/executors/submit/submit.impl", + "schema": "./src/executors/submit/schema.json", + "description": "Submit app binary to App Store and/or Play Store" } }, "builders": { @@ -111,6 +116,11 @@ "implementation": "./src/executors/export/compat", "schema": "./src/executors/export/schema.json", "description": "Export the JavaScript and assets for your app using Metro/webpack bundler" + }, + "submit": { + "implementation": "./src/executors/submit/compat", + "schema": "./src/executors/submit/schema.json", + "description": "Submit app binary to App Store and/or Play Store" } } } diff --git a/packages/expo/migrations.json b/packages/expo/migrations.json index 2a042e7a3e..7a727e8a38 100644 --- a/packages/expo/migrations.json +++ b/packages/expo/migrations.json @@ -817,6 +817,27 @@ "alwaysAddToPackageJson": false } } + }, + "16.2.2": { + "version": "16.2.2-beta.0", + "packages": { + "expo": { + "version": "^48.0.17", + "alwaysAddToPackageJson": false + }, + "eas-cli": { + "version": "~3.13.2", + "alwaysAddToPackageJson": false + }, + "react-native": { + "version": "0.71.8", + "alwaysAddToPackageJson": false + }, + "@types/react-native": { + "version": "0.71.7", + "alwaysAddToPackageJson": false + } + } } } } diff --git a/packages/expo/package.json b/packages/expo/package.json index 2b67bda20a..ae880b4aeb 100644 --- a/packages/expo/package.json +++ b/packages/expo/package.json @@ -43,7 +43,7 @@ "@nx/webpack": "file:../webpack" }, "peerDependencies": { - "expo": "^48.0.16" + "expo": "^48.0.17" }, "builders": "./executors.json", "ng-update": { diff --git a/packages/expo/src/executors/build/build.impl.ts b/packages/expo/src/executors/build/build.impl.ts index 97d42fc12d..6b12fa6331 100644 --- a/packages/expo/src/executors/build/build.impl.ts +++ b/packages/expo/src/executors/build/build.impl.ts @@ -81,6 +81,11 @@ function createBuildOptions(options: ExpoEasBuildOptions) { return Object.keys(options).reduce((acc, k) => { const v = options[k]; if (typeof v === 'boolean') { + if (k === 'interactive') { + if (v === false) { + acc.push('--non-interactive'); // when is false, the flag is --non-interactive + } + } if (v === true) { // when true, does not need to pass the value true, just need to pass the flag in kebob case acc.push(`--${names(k).fileName}`); diff --git a/packages/expo/src/executors/build/schema.d.ts b/packages/expo/src/executors/build/schema.d.ts index 809cdcd707..eddfa63522 100644 --- a/packages/expo/src/executors/build/schema.d.ts +++ b/packages/expo/src/executors/build/schema.d.ts @@ -3,7 +3,7 @@ export interface ExpoEasBuildOptions { platform: 'ios' | 'android' | 'all'; profile?: string; - nonInteractive: boolean; // default is false + interactive: boolean; // default is true local: boolean; // default is false output?: string; wait: boolean; // default is true diff --git a/packages/expo/src/executors/build/schema.json b/packages/expo/src/executors/build/schema.json index c18d315994..64c399d6cc 100644 --- a/packages/expo/src/executors/build/schema.json +++ b/packages/expo/src/executors/build/schema.json @@ -7,6 +7,24 @@ "title": "Expo EAS Build executor", "description": "Start an EAS build for your expo project.", "type": "object", + "presets": [ + { + "name": "Build for a specific platform", + "keys": ["platform"] + }, + { + "name": "Build using a specific profile", + "keys": ["profile"] + }, + { + "name": "Run build locally", + "keys": ["local"] + }, + { + "name": "Clear cache before the build", + "keys": ["clearCache"] + } + ], "properties": { "platform": { "enum": ["ios", "android", "all"], @@ -25,10 +43,10 @@ "examples": ["production", "development", "preview"], "x-priority": "important" }, - "nonInteractive": { + "interactive": { "type": "boolean", - "description": "Run command in non-interactive mode", - "default": false + "description": "Run command in interactive mode", + "default": true }, "local": { "type": "boolean", diff --git a/packages/expo/src/executors/prebuild/prebuild.impl.ts b/packages/expo/src/executors/prebuild/prebuild.impl.ts index 3f52b411f7..2747473cc8 100644 --- a/packages/expo/src/executors/prebuild/prebuild.impl.ts +++ b/packages/expo/src/executors/prebuild/prebuild.impl.ts @@ -25,12 +25,10 @@ export default async function* prebuildExecutor( await prebuildAsync(context.root, projectRoot, options); if (options.install) { - await installAsync(context.root, { fix: true }); + await installAsync(context.root, {}); if (options.platform === 'ios') { await podInstall(join(context.root, projectRoot, 'ios')); } - } else { - await installAsync(context.root, {}); } yield { diff --git a/packages/expo/src/executors/prebuild/schema.json b/packages/expo/src/executors/prebuild/schema.json index 2ad6900e49..5de6a0f19f 100644 --- a/packages/expo/src/executors/prebuild/schema.json +++ b/packages/expo/src/executors/prebuild/schema.json @@ -16,7 +16,7 @@ "install": { "type": "boolean", "description": "Installing npm packages and CocoaPods.", - "default": false, + "default": true, "x-priority": "internal" }, "platform": { diff --git a/packages/expo/src/executors/run/run.impl.ts b/packages/expo/src/executors/run/run.impl.ts index 360db77eed..f2075f1e2c 100644 --- a/packages/expo/src/executors/run/run.impl.ts +++ b/packages/expo/src/executors/run/run.impl.ts @@ -49,17 +49,12 @@ export default async function* runExecutor( clean: options.clean, }); } + if (options.install) { - await installAsync(context.root, { - fix: true, - }); + await installAsync(context.root, {}); if (options.platform === 'ios') { await podInstall(join(context.root, projectRoot, 'ios')); } - } else { - await installAsync(context.root, { - check: true, - }); } try { diff --git a/packages/expo/src/executors/run/schema.json b/packages/expo/src/executors/run/schema.json index 813cb413cf..3f96d58486 100644 --- a/packages/expo/src/executors/run/schema.json +++ b/packages/expo/src/executors/run/schema.json @@ -53,7 +53,7 @@ }, "install": { "type": "boolean", - "description": "Should install missing dependencies before building.", + "description": "Installing npm packages and CocoaPods before building.", "default": true }, "buildCache": { diff --git a/packages/expo/src/executors/start/schema.d.ts b/packages/expo/src/executors/start/schema.d.ts index 742555d6c5..f172b4fce1 100644 --- a/packages/expo/src/executors/start/schema.d.ts +++ b/packages/expo/src/executors/start/schema.d.ts @@ -19,4 +19,7 @@ export interface ExpoStartOptions { localhost?: boolean; tunnel?: boolean; offline?: boolean; + + // nx options + sync?: boolean; // default is true } diff --git a/packages/expo/src/executors/start/schema.json b/packages/expo/src/executors/start/schema.json index c7cee12527..85a433da9e 100644 --- a/packages/expo/src/executors/start/schema.json +++ b/packages/expo/src/executors/start/schema.json @@ -87,6 +87,11 @@ "offline": { "type": "boolean", "description": "Allows this command to run while offline" + }, + "sync": { + "type": "boolean", + "description": "Syncs npm dependencies to package.json (for React Native autolink).", + "default": true } }, "examplesFile": "../../../docs/start-examples.md" diff --git a/packages/expo/src/executors/start/start.impl.ts b/packages/expo/src/executors/start/start.impl.ts index 69afafc19b..28ee17bc06 100644 --- a/packages/expo/src/executors/start/start.impl.ts +++ b/packages/expo/src/executors/start/start.impl.ts @@ -5,6 +5,10 @@ import { join } from 'path'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; import { ExpoStartOptions } from './schema'; +import { + displayNewlyAddedDepsMessage, + syncDeps, +} from '../sync-deps/sync-deps.impl'; export interface ExpoStartOutput { baseUrl?: string; @@ -20,6 +24,17 @@ export default async function* startExecutor( const projectRoot = context.projectsConfigurations.projects[context.projectName].root; ensureNodeModulesSymlink(context.root, projectRoot); + if (options.sync) { + displayNewlyAddedDepsMessage( + context.projectName, + await syncDeps( + context.projectName, + projectRoot, + context.root, + context.projectGraph + ) + ); + } try { const baseUrl = `http://localhost:${options.port}`; @@ -68,12 +83,16 @@ function startAsync( } // options from https://github.com/expo/expo/blob/main/packages/%40expo/cli/src/start/index.ts +const nxOptions = ['sync']; function createStartOptions(options: ExpoStartOptions) { return Object.keys(options).reduce((acc, k) => { + if (nxOptions.includes(k)) { + return acc; + } const v = options[k]; if (k === 'dev') { if (v === false) { - acc.push(`--no-dev`); + acc.push(`--no-dev`); // only no-dev flag is supported } } else { if (typeof v === 'boolean') { diff --git a/packages/expo/src/executors/submit/compat.ts b/packages/expo/src/executors/submit/compat.ts new file mode 100644 index 0000000000..8a20bd7c54 --- /dev/null +++ b/packages/expo/src/executors/submit/compat.ts @@ -0,0 +1,5 @@ +import { convertNxExecutor } from '@nx/devkit'; + +import submitExecutor from './submit.impl'; + +export default convertNxExecutor(submitExecutor); diff --git a/packages/expo/src/executors/submit/schema.d.ts b/packages/expo/src/executors/submit/schema.d.ts new file mode 100644 index 0000000000..ca87da5f30 --- /dev/null +++ b/packages/expo/src/executors/submit/schema.d.ts @@ -0,0 +1,12 @@ +// command to run https://github.com/expo/eas-cli/tree/main#eas-submit +// options from https://github.com/expo/eas-cli/blob/main/packages/eas-cli/src/commands/submit.ts +export interface SubmitExecutorSchema { + profile?: string; + platform?: 'ios' | 'android' | 'all'; + id?: string; + latest?: boolean; + interactive: boolean; // default is true + path?: string; + url?: string; + wait: boolean; // default is true +} diff --git a/packages/expo/src/executors/submit/schema.json b/packages/expo/src/executors/submit/schema.json new file mode 100644 index 0000000000..c46ef16908 --- /dev/null +++ b/packages/expo/src/executors/submit/schema.json @@ -0,0 +1,57 @@ +{ + "$schema": "http://json-schema.org/schema", + "version": 2, + "title": "EXPO EAS Submit Executor", + "description": "Submit app binary to App Store and/or Play Store.", + "type": "object", + "presets": [ + { + "name": "Submit for a specific platform", + "keys": ["platform"] + }, + { + "name": "Submit using a specific profile", + "keys": ["profile"] + } + ], + "properties": { + "profile": { + "type": "string", + "description": "Name of the build profile from eas.json. Defaults to \"production\" if defined in eas.json.", + "examples": ["production", "development", "preview"], + "x-priority": "important" + }, + "platform": { + "enum": ["ios", "android", "all"], + "alias": "p", + "description": "The platform to build the app, example values: ios, android, all.", + "x-priority": "important" + }, + "id": { + "type": "string", + "description": "Build ID to submit" + }, + "path": { + "type": "string", + "description": "Path to the .apk/.aab/.ipa file" + }, + "url": { + "type": "string", + "description": "URL to the .apk/.aab/.ipa file, app archive url" + }, + "latest": { + "type": "boolean", + "description": "Submit the latest build for specified platform" + }, + "interactive": { + "type": "boolean", + "description": "Run command in interactive mode", + "default": true + }, + "wait": { + "type": "boolean", + "description": "Wait for build(s) to complete", + "default": true + } + } +} diff --git a/packages/expo/src/executors/submit/submit.impl.ts b/packages/expo/src/executors/submit/submit.impl.ts new file mode 100644 index 0000000000..d1bcbd7317 --- /dev/null +++ b/packages/expo/src/executors/submit/submit.impl.ts @@ -0,0 +1,89 @@ +import { ExecutorContext, names } from '@nx/devkit'; +import { join } from 'path'; +import { ChildProcess, fork } from 'child_process'; + +import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; + +import { SubmitExecutorSchema } from './schema'; + +export interface ReactNativeSubmitOutput { + success: boolean; +} + +let childProcess: ChildProcess; + +export default async function* submitExecutor( + options: SubmitExecutorSchema, + context: ExecutorContext +): AsyncGenerator { + const projectRoot = + context.projectsConfigurations.projects[context.projectName].root; + ensureNodeModulesSymlink(context.root, projectRoot); + + try { + await runCliSubmit(context.root, projectRoot, options); + + yield { success: true }; + } finally { + if (childProcess) { + childProcess.kill(); + } + } +} + +function runCliSubmit( + workspaceRoot: string, + projectRoot: string, + options: SubmitExecutorSchema +) { + return new Promise((resolve, reject) => { + childProcess = fork( + join(workspaceRoot, './node_modules/eas-cli/bin/run'), + ['submit', ...createSubmitOptions(options)], + { + cwd: join(workspaceRoot, projectRoot), + env: process.env, + } + ); + + // Ensure the child process is killed when the parent exits + process.on('exit', () => childProcess.kill()); + process.on('SIGTERM', () => childProcess.kill()); + + childProcess.on('error', (err) => { + reject(err); + }); + childProcess.on('exit', (code) => { + if (code === 0) { + resolve(code); + } else { + reject(code); + } + }); + }); +} + +function createSubmitOptions(options: SubmitExecutorSchema) { + return Object.keys(options).reduce((acc, k) => { + const v = options[k]; + if (typeof v === 'boolean') { + if (k === 'interactive') { + if (v === false) { + acc.push('--non-interactive'); // when is false, the flag is --non-interactive + } + } else if (k === 'wait') { + if (v === false) { + acc.push('--no-wait'); // when is false, the flag is --no-wait + } else { + acc.push('--wait'); + } + } else if (v === true) { + // when true, does not need to pass the value true, just need to pass the flag in kebob case + acc.push(`--${names(k).fileName}`); + } + } else { + acc.push(`--${names(k).fileName}`, v); + } + return acc; + }, []); +} diff --git a/packages/expo/src/executors/update/schema.d.ts b/packages/expo/src/executors/update/schema.d.ts index d7a74424e6..10f8061a10 100644 --- a/packages/expo/src/executors/update/schema.d.ts +++ b/packages/expo/src/executors/update/schema.d.ts @@ -11,5 +11,5 @@ export interface ExpoEasUpdateOptions { json: boolean; // default is false auto: boolean; // default is false privateKeyPath?: string; - nonInteractive: boolean; // default is false + interactive: boolean; // default is false } diff --git a/packages/expo/src/executors/update/schema.json b/packages/expo/src/executors/update/schema.json index 334d2a03bf..c9d72d9a5d 100644 --- a/packages/expo/src/executors/update/schema.json +++ b/packages/expo/src/executors/update/schema.json @@ -7,6 +7,16 @@ "title": "Expo EAS Update executor", "description": "Start an EAS update for your expo project.", "type": "object", + "presets": [ + { + "name": "Update for a specific platform", + "keys": ["platform"] + }, + { + "name": "Update from a specific branch", + "keys": ["branch"] + } + ], "properties": { "branch": { "type": "string", @@ -55,10 +65,10 @@ "type": "string", "description": "File containing the PEM-encoded private key corresponding to the certificate in expo-updates' configuration. Defaults to a file named \"private-key.pem\" in the certificate's directory." }, - "nonInteractive": { + "interactive": { "type": "boolean", - "description": "Run command in non-interactive mode", - "default": false + "description": "Run command in interactive mode", + "default": true } }, "required": [] diff --git a/packages/expo/src/executors/update/update.impl.ts b/packages/expo/src/executors/update/update.impl.ts index 212da4f437..81c04652dc 100644 --- a/packages/expo/src/executors/update/update.impl.ts +++ b/packages/expo/src/executors/update/update.impl.ts @@ -5,6 +5,11 @@ import { ChildProcess, fork } from 'child_process'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; import { ExpoEasUpdateOptions } from './schema'; +import { + displayNewlyAddedDepsMessage, + syncDeps, +} from '../sync-deps/sync-deps.impl'; +import { installAsync } from '../install/install.impl'; export interface ReactNativeUpdateOutput { success: boolean; @@ -18,6 +23,17 @@ export default async function* buildExecutor( ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; + await installAsync(context.root, { packages: ['expo-updates'] }); + displayNewlyAddedDepsMessage( + context.projectName, + await syncDeps( + context.projectName, + projectRoot, + context.root, + context.projectGraph, + ['expo-updates'] + ) + ); ensureNodeModulesSymlink(context.root, projectRoot); try { @@ -63,7 +79,11 @@ function createUpdateOptions(options: ExpoEasUpdateOptions) { return Object.keys(options).reduce((acc, k) => { const v = options[k]; if (typeof v === 'boolean') { - if (v === true) { + if (k === 'interactive') { + if (v === false) { + acc.push('--non-interactive'); + } + } else if (v === true) { // when true, does not need to pass the value true, just need to pass the flag in kebob case acc.push(`--${names(k).fileName}`); } diff --git a/packages/expo/src/generators/application/lib/add-project.ts b/packages/expo/src/generators/application/lib/add-project.ts index 6e56c3d5f4..f158ab6799 100644 --- a/packages/expo/src/generators/application/lib/add-project.ts +++ b/packages/expo/src/generators/application/lib/add-project.ts @@ -60,6 +60,11 @@ function getTargets(options: NormalizedSchema) { options: {}, }; + architect['submit'] = { + executor: '@nx/expo:submit', + options: {}, + }; + architect['build-list'] = { executor: '@nx/expo:build-list', options: {}, diff --git a/packages/expo/src/migrations/update-16-0-0/add-jest-expo.ts b/packages/expo/src/migrations/update-16-0-0/add-jest-expo.ts index 111d5176a7..9c09d3c2dc 100644 --- a/packages/expo/src/migrations/update-16-0-0/add-jest-expo.ts +++ b/packages/expo/src/migrations/update-16-0-0/add-jest-expo.ts @@ -12,7 +12,10 @@ export default async function update(tree: Tree) { const projects = getProjects(tree); for (const [name, config] of projects.entries()) { - if (config.targets?.['start']?.executor === '@nrwl/expo:start') { + if ( + config.targets?.['start']?.executor === '@nrwl/expo:start' || + config.targets?.['start']?.executor === '@nx/expo:start' + ) { const jestConfigPath = config.targets?.test?.options?.jestConfig; if (!jestConfigPath || !tree.exists(jestConfigPath)) return; try { diff --git a/packages/expo/src/migrations/update-16-0-0/remove-deprecated-targets.ts b/packages/expo/src/migrations/update-16-0-0/remove-deprecated-targets.ts index 188b715a3b..735c15aef0 100644 --- a/packages/expo/src/migrations/update-16-0-0/remove-deprecated-targets.ts +++ b/packages/expo/src/migrations/update-16-0-0/remove-deprecated-targets.ts @@ -12,7 +12,10 @@ export default async function update(tree: Tree) { const projects = getProjects(tree); for (const [name, config] of projects.entries()) { - if (config.targets?.['start']?.executor === '@nrwl/expo:start') { + if ( + config.targets?.['start']?.executor === '@nrwl/expo:start' || + config.targets?.['start']?.executor === '@nx/expo:start' + ) { const targetsToDelete = [ 'build-ios', 'build-android', @@ -28,9 +31,8 @@ export default async function update(tree: Tree) { delete config.targets[target]; } }); + updateProjectConfiguration(tree, name, config); } - - updateProjectConfiguration(tree, name, config); } await formatFiles(tree); diff --git a/packages/expo/src/migrations/update-16-1-4/add-detox-app-json.ts b/packages/expo/src/migrations/update-16-1-4/add-detox-app-json.ts index cea4aff2e9..15ba9df009 100644 --- a/packages/expo/src/migrations/update-16-1-4/add-detox-app-json.ts +++ b/packages/expo/src/migrations/update-16-1-4/add-detox-app-json.ts @@ -7,7 +7,10 @@ export default async function update(tree: Tree) { const projects = getProjects(tree); projects.forEach((config) => { - if (config.targets?.['start']?.executor === '@nrwl/expo:start') { + if ( + config.targets?.['start']?.executor === '@nrwl/expo:start' || + config.targets?.['start']?.executor === '@nx/expo:start' + ) { updateJson(tree, `${config.root}/app.json`, (json) => { if (!json.expo.plugins) { json.expo.plugins = []; diff --git a/packages/expo/src/migrations/update-16-1-4/update-eas-scripts.ts b/packages/expo/src/migrations/update-16-1-4/update-eas-scripts.ts index 2ef5b1e08d..77db80bcee 100644 --- a/packages/expo/src/migrations/update-16-1-4/update-eas-scripts.ts +++ b/packages/expo/src/migrations/update-16-1-4/update-eas-scripts.ts @@ -22,7 +22,10 @@ export default function update(tree: Tree) { }; for (const [name, config] of projects.entries()) { - if (config.targets?.['start']?.executor === '@nrwl/expo:start') { + if ( + config.targets?.['start']?.executor === '@nrwl/expo:start' || + config.targets?.['start']?.executor === '@nx/expo:start' + ) { try { addEasScripts(tree); updateJson(tree, join(config.root, 'package.json'), (packageJson) => { diff --git a/packages/expo/src/migrations/update-16-2-2/add-submit-target.spec.ts b/packages/expo/src/migrations/update-16-2-2/add-submit-target.spec.ts new file mode 100644 index 0000000000..1f512949d1 --- /dev/null +++ b/packages/expo/src/migrations/update-16-2-2/add-submit-target.spec.ts @@ -0,0 +1,31 @@ +import { addProjectConfiguration, getProjects, Tree } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import update from './add-submit-target'; + +describe('add-submit-target', () => { + let tree: Tree; + + beforeEach(async () => { + tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + addProjectConfiguration(tree, 'product', { + root: 'apps/product', + sourceRoot: 'apps/product/src', + targets: { + start: { + executor: '@nx/expo:start', + }, + }, + }); + }); + + it(`should update project.json with target submit`, async () => { + await update(tree); + + getProjects(tree).forEach((project) => { + expect(project.targets['submit']).toEqual({ + executor: '@nx/expo:submit', + options: {}, + }); + }); + }); +}); diff --git a/packages/expo/src/migrations/update-16-2-2/add-submit-target.ts b/packages/expo/src/migrations/update-16-2-2/add-submit-target.ts new file mode 100644 index 0000000000..53fc49f84a --- /dev/null +++ b/packages/expo/src/migrations/update-16-2-2/add-submit-target.ts @@ -0,0 +1,27 @@ +import { + Tree, + formatFiles, + getProjects, + updateProjectConfiguration, +} from '@nx/devkit'; + +/** + * Add new submit target + */ +export default async function update(tree: Tree) { + const projects = getProjects(tree); + + for (const [name, config] of projects.entries()) { + if (config.targets?.['start']?.executor === '@nx/expo:start') { + if (!config.targets['submit']) { + config.targets['submit'] = { + executor: '@nx/expo:submit', + options: {}, + }; + updateProjectConfiguration(tree, name, config); + } + } + } + + await formatFiles(tree); +} diff --git a/packages/expo/src/utils/versions.ts b/packages/expo/src/utils/versions.ts index 8d6d7bee39..9d3c7a90c7 100644 --- a/packages/expo/src/utils/versions.ts +++ b/packages/expo/src/utils/versions.ts @@ -1,11 +1,12 @@ export const nxVersion = require('../../package.json').version; -export const expoVersion = '48.0.16'; +export const expoVersion = '48.0.17'; export const expoMetroConfigVersion = '0.7.1'; export const expoSplashScreenVersion = '~0.18.2'; export const expoStatusBarVersion = '~1.4.4'; +export const expoUpdatesVersion = '~0.16.4'; export const expoCliVersion = '~0.7.1'; // @expo/cli -export const easCliVersion = '~3.12.0'; +export const easCliVersion = '~3.13.2'; export const babelPresetExpoVersion = '~9.3.2'; export const reactVersion = '18.2.0'; @@ -13,8 +14,8 @@ export const reactDomVersion = '18.2.0'; export const reactTestRendererVersion = '18.2.0'; export const typesReactVersion = '18.0.28'; -export const reactNativeVersion = '0.71.7'; -export const typesReactNativeVersion = '0.71.6'; +export const reactNativeVersion = '0.71.8'; +export const typesReactNativeVersion = '0.71.7'; export const reactNativeWebVersion = '~0.18.12'; export const reactNativeSvgTransformerVersion = '1.0.0'; diff --git a/packages/react-native/src/executors/run-ios/run-ios.impl.ts b/packages/react-native/src/executors/run-ios/run-ios.impl.ts index 70c4777d19..62b4581e7e 100644 --- a/packages/react-native/src/executors/run-ios/run-ios.impl.ts +++ b/packages/react-native/src/executors/run-ios/run-ios.impl.ts @@ -1,4 +1,4 @@ -import { ExecutorContext, logger, names } from '@nx/devkit'; +import { ExecutorContext } from '@nx/devkit'; import { join } from 'path'; import { ChildProcess, fork } from 'child_process'; import { platform } from 'os';