@nx/expo 24.0.0-beta.1 → 24.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/plugins/plugin.js +8 -4
  2. package/dist/src/executors/install/{install.impl.d.ts → install-packages.d.ts} +0 -4
  3. package/dist/src/executors/install/{install.impl.js → install-packages.js} +0 -17
  4. package/dist/src/executors/update/update.impl.js +2 -2
  5. package/dist/src/generators/application/application.js +2 -3
  6. package/dist/src/generators/application/files/base/package.json.template +1 -0
  7. package/dist/src/generators/application/lib/add-e2e.js +4 -5
  8. package/dist/src/generators/application/lib/add-eas-scripts.d.ts +3 -0
  9. package/dist/src/generators/application/lib/add-eas-scripts.js +103 -3
  10. package/dist/src/generators/application/lib/add-project.js +1 -82
  11. package/dist/src/generators/application/lib/normalize-options.js +0 -4
  12. package/dist/src/generators/application/schema.d.ts +0 -1
  13. package/dist/src/generators/init/init.js +18 -32
  14. package/dist/src/generators/init/schema.d.ts +0 -1
  15. package/dist/src/generators/library/lib/normalize-options.js +0 -5
  16. package/dist/src/generators/library/library.js +2 -3
  17. package/dist/src/generators/library/schema.d.ts +0 -1
  18. package/dist/src/migrations/update-24-0-0/add-eas-build-pre-install.d.ts +2 -0
  19. package/dist/src/migrations/update-24-0-0/add-eas-build-pre-install.js +42 -0
  20. package/dist/src/migrations/update-24-0-0/add-eas-build-pre-install.md +32 -0
  21. package/dist/src/migrations/update-24-0-0/finish-inferred-conversion.md +12 -0
  22. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.d.ts +6 -0
  23. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.js +30 -0
  24. package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.md +72 -0
  25. package/dist/src/utils/add-linting.d.ts +0 -1
  26. package/dist/src/utils/add-linting.js +0 -1
  27. package/dist/src/utils/jest/add-jest.d.ts +1 -1
  28. package/dist/src/utils/jest/add-jest.js +1 -2
  29. package/executors.json +0 -40
  30. package/migrations.json +13 -0
  31. package/package.json +10 -10
  32. package/dist/docs/export-examples.md +0 -107
  33. package/dist/docs/prebuild-examples.md +0 -65
  34. package/dist/docs/run-examples.md +0 -86
  35. package/dist/docs/start-examples.md +0 -100
  36. package/dist/src/executors/build/build.impl.d.ts +0 -6
  37. package/dist/src/executors/build/build.impl.js +0 -142
  38. package/dist/src/executors/build/schema.d.ts +0 -18
  39. package/dist/src/executors/build/schema.json +0 -100
  40. package/dist/src/executors/export/export.impl.d.ts +0 -7
  41. package/dist/src/executors/export/export.impl.js +0 -81
  42. package/dist/src/executors/export/schema.d.ts +0 -13
  43. package/dist/src/executors/export/schema.json +0 -50
  44. package/dist/src/executors/install/schema.json +0 -40
  45. package/dist/src/executors/prebuild/prebuild.impl.d.ts +0 -7
  46. package/dist/src/executors/prebuild/prebuild.impl.js +0 -77
  47. package/dist/src/executors/prebuild/schema.d.ts +0 -7
  48. package/dist/src/executors/prebuild/schema.json +0 -37
  49. package/dist/src/executors/run/run.impl.d.ts +0 -6
  50. package/dist/src/executors/run/run.impl.js +0 -102
  51. package/dist/src/executors/run/schema.d.ts +0 -24
  52. package/dist/src/executors/run/schema.json +0 -67
  53. package/dist/src/executors/serve/lib/is-packager-running.d.ts +0 -1
  54. package/dist/src/executors/serve/lib/is-packager-running.js +0 -13
  55. package/dist/src/executors/serve/schema.d.ts +0 -7
  56. package/dist/src/executors/serve/schema.json +0 -37
  57. package/dist/src/executors/serve/serve.impl.d.ts +0 -10
  58. package/dist/src/executors/serve/serve.impl.js +0 -134
  59. package/dist/src/executors/start/schema.d.ts +0 -22
  60. package/dist/src/executors/start/schema.json +0 -95
  61. package/dist/src/executors/start/start.impl.d.ts +0 -7
  62. package/dist/src/executors/start/start.impl.js +0 -84
  63. package/dist/src/executors/submit/schema.d.ts +0 -12
  64. package/dist/src/executors/submit/schema.json +0 -58
  65. package/dist/src/executors/submit/submit.impl.d.ts +0 -6
  66. package/dist/src/executors/submit/submit.impl.js +0 -75
  67. package/dist/src/utils/deprecation.d.ts +0 -3
  68. package/dist/src/utils/deprecation.js +0 -23
  69. package/dist/src/utils/pod-install-task.d.ts +0 -17
  70. package/dist/src/utils/pod-install-task.js +0 -69
  71. package/dist/src/utils/resolve-expo-cli.d.ts +0 -11
  72. package/dist/src/utils/resolve-expo-cli.js +0 -21
@@ -63,7 +63,8 @@ function buildExpoTargets(projectRoot, options, context, pmc) {
63
63
  const namedInputs = (0, internal_1.getNamedInputs)(projectRoot, context);
64
64
  const targets = {
65
65
  [options.startTargetName]: {
66
- executor: `@nx/expo:start`,
66
+ command: `expo start`,
67
+ options: { cwd: projectRoot },
67
68
  continuous: true,
68
69
  },
69
70
  [options.serveTargetName]: {
@@ -90,15 +91,18 @@ function buildExpoTargets(projectRoot, options, context, pmc) {
90
91
  outputs: [getOutputs(projectRoot, 'dist')],
91
92
  },
92
93
  [options.installTargetName]: {
93
- executor: '@nx/expo:install',
94
+ command: `expo install`,
95
+ options: { cwd: projectRoot },
94
96
  continuous: false,
95
97
  },
96
98
  [options.prebuildTargetName]: {
97
- executor: `@nx/expo:prebuild`,
99
+ command: `expo prebuild`,
100
+ options: { cwd: projectRoot },
98
101
  continuous: false,
99
102
  },
100
103
  [options.buildTargetName]: {
101
- executor: `@nx/expo:build`,
104
+ command: `eas build`,
105
+ options: { cwd: projectRoot },
102
106
  continuous: false,
103
107
  },
104
108
  [options.submitTargetName]: {
@@ -1,7 +1,3 @@
1
1
  import { ExecutorContext } from '@nx/devkit';
2
2
  import { ExpoInstallOptions } from './schema';
3
- export interface ExpoInstallOutput {
4
- success: boolean;
5
- }
6
- export default function installExecutor(options: ExpoInstallOptions, context: ExecutorContext): AsyncGenerator<ExpoInstallOutput>;
7
3
  export declare function installAndUpdatePackageJson(context: ExecutorContext, options: ExpoInstallOptions): Promise<void>;
@@ -1,26 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = installExecutor;
4
3
  exports.installAndUpdatePackageJson = installAndUpdatePackageJson;
5
4
  const devkit_1 = require("@nx/devkit");
6
5
  const path_1 = require("path");
7
6
  const sync_deps_impl_1 = require("../sync-deps/sync-deps.impl");
8
- const deprecation_1 = require("../../utils/deprecation");
9
- let childProcess;
10
- async function* installExecutor(options, context) {
11
- (0, deprecation_1.warnExpoExecutorDeprecation)('install');
12
- try {
13
- await installAndUpdatePackageJson(context, options);
14
- yield {
15
- success: true,
16
- };
17
- }
18
- finally {
19
- if (childProcess) {
20
- childProcess.kill();
21
- }
22
- }
23
- }
24
7
  async function installAndUpdatePackageJson(context, options) {
25
8
  const { installAsync } = require('@expo/cli/build/src/install/installAsync');
26
9
  const packages = typeof options.packages === 'string'
@@ -6,12 +6,12 @@ const internal_1 = require("@nx/devkit/internal");
6
6
  const path_1 = require("path");
7
7
  const child_process_1 = require("child_process");
8
8
  const resolve_eas_1 = require("../../utils/resolve-eas");
9
- const install_impl_1 = require("../install/install.impl");
9
+ const install_packages_1 = require("../install/install-packages");
10
10
  let childProcess;
11
11
  async function* buildExecutor(options, context) {
12
12
  const projectRoot = context.projectsConfigurations.projects[context.projectName].root;
13
13
  try {
14
- await (0, install_impl_1.installAndUpdatePackageJson)(context, {
14
+ await (0, install_packages_1.installAndUpdatePackageJson)(context, {
15
15
  packages: ['expo-updates'],
16
16
  });
17
17
  await runCliUpdate(context.root, projectRoot, options);
@@ -20,7 +20,6 @@ const init_root_babel_config_1 = require("../../utils/init-root-babel-config");
20
20
  const versions_1 = require("../../utils/versions");
21
21
  async function expoApplicationGenerator(host, schema) {
22
22
  return await expoApplicationGeneratorInternal(host, {
23
- addPlugin: false,
24
23
  useProjectJson: true,
25
24
  ...schema,
26
25
  });
@@ -28,7 +27,7 @@ async function expoApplicationGenerator(host, schema) {
28
27
  async function expoApplicationGeneratorInternal(host, schema) {
29
28
  (0, versions_1.assertSupportedExpoVersion)(host);
30
29
  const tasks = [];
31
- const addTsPlugin = (0, internal_2.shouldConfigureTsSolutionSetup)(host, schema.addPlugin, schema.useTsSolution);
30
+ const addTsPlugin = (0, internal_2.shouldConfigureTsSolutionSetup)(host, schema.useTsSolution);
32
31
  const jsInitTask = await (0, js_1.initGenerator)(host, {
33
32
  ...schema,
34
33
  skipFormat: true,
@@ -58,7 +57,7 @@ async function expoApplicationGeneratorInternal(host, schema) {
58
57
  ],
59
58
  });
60
59
  tasks.push(lintTask);
61
- const jestTask = await (0, add_jest_1.addJest)(host, options.unitTestRunner, options.projectName, options.appProjectRoot, options.js, options.skipPackageJson, options.addPlugin);
60
+ const jestTask = await (0, add_jest_1.addJest)(host, options.unitTestRunner, options.projectName, options.appProjectRoot, options.js, options.skipPackageJson);
62
61
  tasks.push(jestTask);
63
62
  const e2eTask = await (0, add_e2e_1.addE2e)(host, options);
64
63
  tasks.push(e2eTask);
@@ -21,6 +21,7 @@
21
21
  "react-native-web": "*"
22
22
  },
23
23
  "scripts": {
24
+ "eas-build-pre-install": "cd <%= offsetFromRoot %> && node tools/scripts/eas-build-pre-install.mjs . <%= appProjectRoot %>",
24
25
  "eas-build-post-install": "cd <%= offsetFromRoot %> && node tools/scripts/eas-build-post-install.mjs . <%= appProjectRoot %>"
25
26
  }
26
27
  }
@@ -15,7 +15,7 @@ async function addE2e(tree, options) {
15
15
  targetName: 'serve-static',
16
16
  });
17
17
  }
18
- const e2eWebServerInfo = await getExpoE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'app.json'), options.addPlugin);
18
+ const e2eWebServerInfo = await getExpoE2EWebServerInfo(tree, options.projectName, (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'app.json'));
19
19
  switch (options.e2eTestRunner) {
20
20
  case 'cypress': {
21
21
  const { configurationGenerator } = (0, devkit_1.ensurePackage)('@nx/cypress', versions_1.nxVersion);
@@ -98,7 +98,6 @@ async function addE2e(tree, options) {
98
98
  webServerCommand: e2eWebServerInfo.e2eCiWebServerCommand,
99
99
  webServerAddress: e2eWebServerInfo.e2eCiBaseUrl,
100
100
  rootProject: options.rootProject,
101
- addPlugin: options.addPlugin,
102
101
  });
103
102
  return e2eTask;
104
103
  }
@@ -120,9 +119,9 @@ async function addE2e(tree, options) {
120
119
  return () => { };
121
120
  }
122
121
  }
123
- async function getExpoE2EWebServerInfo(tree, projectName, configFilePath, isPluginBeingAdded) {
122
+ async function getExpoE2EWebServerInfo(tree, projectName, configFilePath) {
124
123
  const nxJson = (0, devkit_1.readNxJson)(tree);
125
- let e2ePort = isPluginBeingAdded ? 8081 : 4200;
124
+ let e2ePort = 8081;
126
125
  const serveTargetOptions = (0, internal_1.readTargetDefaultsForTarget)('serve', nxJson.targetDefaults)?.options;
127
126
  if (serveTargetOptions?.port) {
128
127
  e2ePort = serveTargetOptions.port;
@@ -138,5 +137,5 @@ async function getExpoE2EWebServerInfo(tree, projectName, configFilePath, isPlug
138
137
  defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
139
138
  defaultE2ECiBaseUrl: 'http://localhost:4200',
140
139
  defaultE2EPort: e2ePort,
141
- }, isPluginBeingAdded);
140
+ });
142
141
  }
@@ -1,2 +1,5 @@
1
1
  import type { Tree } from '@nx/devkit';
2
+ export declare const easBuildPreInstallScriptPath = "tools/scripts/eas-build-pre-install.mjs";
3
+ export declare const easBuildPostInstallScriptPath = "tools/scripts/eas-build-post-install.mjs";
4
+ export declare function addEasBuildPreInstallScript(tree: Tree): void;
2
5
  export declare function addEasScripts(tree: Tree): void;
@@ -1,6 +1,101 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.easBuildPostInstallScriptPath = exports.easBuildPreInstallScriptPath = void 0;
4
+ exports.addEasBuildPreInstallScript = addEasBuildPreInstallScript;
3
5
  exports.addEasScripts = addEasScripts;
6
+ exports.easBuildPreInstallScriptPath = 'tools/scripts/eas-build-pre-install.mjs';
7
+ exports.easBuildPostInstallScriptPath = 'tools/scripts/eas-build-post-install.mjs';
8
+ const preInstallScript = `
9
+ /**
10
+ * This script prepares an Expo app for EAS Build in a workspace without package manager workspaces.
11
+ * It is run as a eas-build-pre-install script in the 'package.json' of expo app.
12
+ * It is executed as 'node tools/scripts/eas-build-pre-install.mjs <workspace root> <project root>'
13
+ * It copies the root dependencies, overrides or resolutions, and lock file into the project,
14
+ * so EAS installs the versions pinned at the workspace root.
15
+ */
16
+
17
+ import { copyFileSync, existsSync, readFileSync, writeFileSync } from 'fs';
18
+ import { join } from 'path';
19
+
20
+ const [workspaceRoot, projectRoot] = process.argv.slice(2);
21
+
22
+ const lockFiles = {
23
+ bun: ['bun.lock', 'bun.lockb'],
24
+ yarn: ['yarn.lock'],
25
+ pnpm: ['pnpm-lock.yaml'],
26
+ npm: ['package-lock.json'],
27
+ };
28
+
29
+ function readJson(path) {
30
+ return JSON.parse(readFileSync(path, 'utf-8'));
31
+ }
32
+
33
+ function detectPackageManager() {
34
+ const nxJsonPath = join(workspaceRoot, 'nx.json');
35
+ const configured = existsSync(nxJsonPath)
36
+ ? readJson(nxJsonPath).cli?.packageManager
37
+ : undefined;
38
+ if (configured) {
39
+ return configured;
40
+ }
41
+ for (const [packageManager, files] of Object.entries(lockFiles)) {
42
+ if (files.some((file) => existsSync(join(workspaceRoot, file)))) {
43
+ return packageManager;
44
+ }
45
+ }
46
+ return 'npm';
47
+ }
48
+
49
+ function isWorkspacesEnabled(packageManager, rootPackageJson) {
50
+ if (packageManager === 'pnpm') {
51
+ const pnpmWorkspacePath = join(workspaceRoot, 'pnpm-workspace.yaml');
52
+ return (
53
+ existsSync(pnpmWorkspacePath) &&
54
+ /^["']?packages["']?\\s*:/m.test(readFileSync(pnpmWorkspacePath, 'utf-8'))
55
+ );
56
+ }
57
+ return !!rootPackageJson.workspaces;
58
+ }
59
+
60
+ const packageManager = detectPackageManager();
61
+ const rootPackageJson = readJson(join(workspaceRoot, 'package.json'));
62
+
63
+ if (isWorkspacesEnabled(packageManager, rootPackageJson)) {
64
+ console.log('Package manager workspaces are enabled, nothing to copy');
65
+ process.exit(0);
66
+ }
67
+
68
+ const projectPackageJsonPath = join(projectRoot, 'package.json');
69
+ const projectPackageJson = readJson(projectPackageJsonPath);
70
+ projectPackageJson.dependencies = rootPackageJson.dependencies;
71
+ projectPackageJson.devDependencies = rootPackageJson.devDependencies;
72
+ if (rootPackageJson.overrides) {
73
+ projectPackageJson.overrides = rootPackageJson.overrides;
74
+ } else if (rootPackageJson.resolutions) {
75
+ projectPackageJson.resolutions = rootPackageJson.resolutions;
76
+ }
77
+ // EAS installs with a frozen lock file, and pnpm records its settings in the lock file.
78
+ if (rootPackageJson.pnpm) {
79
+ projectPackageJson.pnpm = rootPackageJson.pnpm;
80
+ }
81
+ // Yarn Berry keys the root workspace by name in the lock file.
82
+ if (packageManager === 'yarn') {
83
+ projectPackageJson.name = rootPackageJson.name;
84
+ }
85
+ writeFileSync(projectPackageJsonPath, JSON.stringify(projectPackageJson, null, 2));
86
+
87
+ const lockFile = Object.hasOwn(lockFiles, packageManager)
88
+ ? lockFiles[packageManager].find((file) =>
89
+ existsSync(join(workspaceRoot, file))
90
+ )
91
+ : undefined;
92
+ if (lockFile) {
93
+ copyFileSync(join(workspaceRoot, lockFile), join(projectRoot, lockFile));
94
+ console.log(\`Copied root dependencies and \${lockFile} into \${projectRoot}\`);
95
+ } else {
96
+ console.log(\`Copied root dependencies into \${projectRoot}, no lock file found\`);
97
+ }
98
+ `;
4
99
  const postInstallScript = `
5
100
  /**
6
101
  * This script is used to patch the '@nx/expo' package to work with EAS Build.
@@ -26,9 +121,14 @@ symlink(join(projectRoot, 'node_modules'), join(workspaceRoot, 'node_modules'),
26
121
  }
27
122
  });
28
123
  `;
124
+ function addEasBuildPreInstallScript(tree) {
125
+ if (!tree.exists(exports.easBuildPreInstallScriptPath)) {
126
+ tree.write(exports.easBuildPreInstallScriptPath, preInstallScript);
127
+ }
128
+ }
29
129
  function addEasScripts(tree) {
30
- const postInstallScriptPath = 'tools/scripts/eas-build-post-install.mjs';
31
- if (!tree.exists(postInstallScriptPath)) {
32
- tree.write(postInstallScriptPath, postInstallScript);
130
+ addEasBuildPreInstallScript(tree);
131
+ if (!tree.exists(exports.easBuildPostInstallScriptPath)) {
132
+ tree.write(exports.easBuildPostInstallScriptPath, postInstallScript);
33
133
  }
34
134
  }
@@ -1,21 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addProject = addProject;
4
- const internal_1 = require("@nx/devkit/internal");
5
4
  const devkit_1 = require("@nx/devkit");
6
- const has_expo_plugin_1 = require("../../../utils/has-expo-plugin");
7
- const deprecation_1 = require("../../../utils/deprecation");
8
5
  function addProject(host, options) {
9
- const hasPlugin = (0, has_expo_plugin_1.hasExpoPlugin)(host);
10
- if (!hasPlugin) {
11
- (0, deprecation_1.warnExpoExecutorGenerating)();
12
- (0, internal_1.addBuildTargetDefaults)(host, '@nx/expo:build');
13
- }
14
6
  const projectConfiguration = {
15
7
  root: options.appProjectRoot,
16
8
  sourceRoot: `${options.appProjectRoot}/src`,
17
9
  projectType: 'application',
18
- targets: hasPlugin ? {} : getTargets(options),
10
+ targets: {},
19
11
  tags: options.parsedTags,
20
12
  };
21
13
  const templatedPackageJson = (0, devkit_1.readJson)(host, (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'package.json'));
@@ -29,10 +21,6 @@ function addProject(host, options) {
29
21
  if (options.importPath !== options.projectName) {
30
22
  packageJson.nx = { name: options.projectName };
31
23
  }
32
- if (!hasPlugin) {
33
- packageJson.nx ??= {};
34
- packageJson.nx.targets = getTargets(options);
35
- }
36
24
  if (options.parsedTags?.length) {
37
25
  packageJson.nx ??= {};
38
26
  packageJson.nx.tags = options.parsedTags;
@@ -45,72 +33,3 @@ function addProject(host, options) {
45
33
  (0, devkit_1.writeJson)(host, (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'package.json'), packageJson);
46
34
  }
47
35
  }
48
- function getTargets(options) {
49
- const architect = {};
50
- architect.start = {
51
- executor: '@nx/expo:start',
52
- dependsOn: ['sync-deps'],
53
- options: {},
54
- };
55
- architect.serve = {
56
- executor: '@nx/expo:serve',
57
- dependsOn: ['sync-deps'],
58
- options: {
59
- port: 4200,
60
- },
61
- };
62
- architect['run-ios'] = {
63
- executor: '@nx/expo:run',
64
- dependsOn: ['sync-deps'],
65
- options: {
66
- platform: 'ios',
67
- },
68
- };
69
- architect['run-android'] = {
70
- executor: '@nx/expo:run',
71
- dependsOn: ['sync-deps'],
72
- options: {
73
- platform: 'android',
74
- },
75
- };
76
- architect['build'] = {
77
- executor: '@nx/expo:build',
78
- dependsOn: ['sync-deps'],
79
- options: {},
80
- };
81
- architect['submit'] = {
82
- executor: '@nx/expo:submit',
83
- options: {},
84
- };
85
- architect['build-list'] = {
86
- executor: '@nx/expo:build-list',
87
- options: {},
88
- };
89
- architect['sync-deps'] = {
90
- executor: '@nx/expo:sync-deps',
91
- options: {},
92
- };
93
- architect['prebuild'] = {
94
- executor: '@nx/expo:prebuild',
95
- dependsOn: ['sync-deps'],
96
- options: {},
97
- };
98
- architect['install'] = {
99
- executor: '@nx/expo:install',
100
- options: {},
101
- };
102
- architect['update'] = {
103
- executor: '@nx/expo:update',
104
- options: {},
105
- };
106
- architect['export'] = {
107
- executor: '@nx/expo:export',
108
- dependsOn: ['sync-deps'],
109
- outputs: ['{options.outputDir}'],
110
- options: {
111
- platform: 'all',
112
- outputDir: `${options.appProjectRoot}/dist`,
113
- },
114
- };
115
- return architect;
116
- }
@@ -11,10 +11,6 @@ async function normalizeOptions(host, options) {
11
11
  projectType: 'application',
12
12
  directory: options.directory,
13
13
  });
14
- const nxJson = (0, devkit_1.readNxJson)(host);
15
- const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
16
- nxJson.useInferencePlugins !== false;
17
- options.addPlugin ??= addPluginDefault;
18
14
  const { className } = (0, devkit_1.names)(projectName);
19
15
  const parsedTags = options.tags
20
16
  ? options.tags.split(',').map((s) => s.trim())
@@ -19,7 +19,6 @@ export interface Schema {
19
19
  e2eTestRunner: 'cypress' | 'playwright' | 'detox' | 'none'; // default is none
20
20
  skipPackageJson?: boolean; // default is false
21
21
  // Internal options
22
- addPlugin?: boolean;
23
22
  nxCloudToken?: string;
24
23
  useTsSolution?: boolean;
25
24
  formatter?: 'prettier' | 'oxfmt' | 'none';
@@ -11,42 +11,28 @@ const versions_1 = require("../../utils/versions");
11
11
  const version_utils_1 = require("../../utils/version-utils");
12
12
  const add_git_ignore_entry_1 = require("./lib/add-git-ignore-entry");
13
13
  function expoInitGenerator(tree, schema) {
14
- return expoInitGeneratorInternal(tree, { addPlugin: false, ...schema });
14
+ return expoInitGeneratorInternal(tree, schema);
15
15
  }
16
16
  async function expoInitGeneratorInternal(host, schema) {
17
17
  (0, versions_1.assertSupportedExpoVersion)(host);
18
- const nxJson = (0, devkit_1.readNxJson)(host);
19
- const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
20
- nxJson.useInferencePlugins !== false;
21
- schema.addPlugin ??= addPluginDefault;
22
18
  (0, add_git_ignore_entry_1.addGitIgnoreEntry)(host);
23
- if (schema.addPlugin) {
24
- await (0, internal_1.addPlugin)(host, await (0, devkit_1.createProjectGraphAsync)(), '@nx/expo/plugin', plugin_1.createNodesV2, {
25
- startTargetName: ['start', 'expo:start', 'expo-start'],
26
- buildTargetName: ['build', 'expo:build', 'expo-build'],
27
- prebuildTargetName: ['prebuild', 'expo:prebuild', 'expo-prebuild'],
28
- serveTargetName: ['serve', 'expo:serve', 'expo-serve'],
29
- installTargetName: ['install', 'expo:install', 'expo-install'],
30
- exportTargetName: ['export', 'expo:export', 'expo-export'],
31
- submitTargetName: ['submit', 'expo:submit', 'expo-submit'],
32
- runIosTargetName: ['run-ios', 'expo:run-ios', 'expo-run-ios'],
33
- runAndroidTargetName: [
34
- 'run-android',
35
- 'expo:run-android',
36
- 'expo-run-android',
37
- ],
38
- buildDepsTargetName: [
39
- 'build-deps',
40
- 'expo:build-deps',
41
- 'expo-build-deps',
42
- ],
43
- watchDepsTargetName: [
44
- 'watch-deps',
45
- 'expo:watch-deps',
46
- 'expo-watch-deps',
47
- ],
48
- }, schema.updatePackageScripts);
49
- }
19
+ await (0, internal_1.addPlugin)(host, await (0, devkit_1.createProjectGraphAsync)(), '@nx/expo/plugin', plugin_1.createNodesV2, {
20
+ startTargetName: ['start', 'expo:start', 'expo-start'],
21
+ buildTargetName: ['build', 'expo:build', 'expo-build'],
22
+ prebuildTargetName: ['prebuild', 'expo:prebuild', 'expo-prebuild'],
23
+ serveTargetName: ['serve', 'expo:serve', 'expo-serve'],
24
+ installTargetName: ['install', 'expo:install', 'expo-install'],
25
+ exportTargetName: ['export', 'expo:export', 'expo-export'],
26
+ submitTargetName: ['submit', 'expo:submit', 'expo-submit'],
27
+ runIosTargetName: ['run-ios', 'expo:run-ios', 'expo-run-ios'],
28
+ runAndroidTargetName: [
29
+ 'run-android',
30
+ 'expo:run-android',
31
+ 'expo-run-android',
32
+ ],
33
+ buildDepsTargetName: ['build-deps', 'expo:build-deps', 'expo-build-deps'],
34
+ watchDepsTargetName: ['watch-deps', 'expo:watch-deps', 'expo-watch-deps'],
35
+ }, schema.updatePackageScripts);
50
36
  const tasks = [];
51
37
  if (!schema.skipPackageJson) {
52
38
  tasks.push(moveDependency(host));
@@ -3,5 +3,4 @@ export interface Schema {
3
3
  skipPackageJson?: boolean; // default is false
4
4
  keepExistingVersions?: boolean; // default is true
5
5
  updatePackageScripts?: boolean;
6
- addPlugin?: boolean;
7
6
  }
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizeOptions = normalizeOptions;
4
- const devkit_1 = require("@nx/devkit");
5
4
  const internal_1 = require("@nx/devkit/internal");
6
5
  const internal_2 = require("@nx/js/internal");
7
6
  async function normalizeOptions(host, options) {
@@ -12,10 +11,6 @@ async function normalizeOptions(host, options) {
12
11
  directory: options.directory,
13
12
  importPath: options.importPath,
14
13
  });
15
- const nxJson = (0, devkit_1.readNxJson)(host);
16
- const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
17
- nxJson.useInferencePlugins !== false;
18
- options.addPlugin ??= addPluginDefault;
19
14
  const parsedTags = options.tags
20
15
  ? options.tags.split(',').map((s) => s.trim())
21
16
  : [];
@@ -20,7 +20,6 @@ const version_utils_1 = require("../../utils/version-utils");
20
20
  const versions_1 = require("../../utils/versions");
21
21
  async function expoLibraryGenerator(host, schema) {
22
22
  return await expoLibraryGeneratorInternal(host, {
23
- addPlugin: false,
24
23
  useProjectJson: true,
25
24
  ...schema,
26
25
  });
@@ -28,7 +27,7 @@ async function expoLibraryGenerator(host, schema) {
28
27
  async function expoLibraryGeneratorInternal(host, schema) {
29
28
  (0, versions_1.assertSupportedExpoVersion)(host);
30
29
  const tasks = [];
31
- const addTsPlugin = (0, internal_2.shouldConfigureTsSolutionSetup)(host, schema.addPlugin);
30
+ const addTsPlugin = (0, internal_2.shouldConfigureTsSolutionSetup)(host);
32
31
  const jsInitTask = await (0, js_1.initGenerator)(host, {
33
32
  ...schema,
34
33
  addTsPlugin,
@@ -84,7 +83,7 @@ async function expoLibraryGeneratorInternal(host, schema) {
84
83
  : undefined);
85
84
  // Update Jest tsconfig after general tsconfig updates to ensure Jest resolver configuration is preserved
86
85
  if (options.unitTestRunner === 'jest') {
87
- const jestTask = await (0, add_jest_1.addJest)(host, options.unitTestRunner, options.projectName, options.projectRoot, options.js, options.skipPackageJson, options.addPlugin);
86
+ const jestTask = await (0, add_jest_1.addJest)(host, options.unitTestRunner, options.projectName, options.projectRoot, options.js, options.skipPackageJson);
88
87
  tasks.push(jestTask);
89
88
  }
90
89
  (0, internal_2.sortPackageJsonFields)(host, options.projectRoot);
@@ -22,6 +22,5 @@ export interface Schema {
22
22
  */
23
23
  setParserOptionsProject?: boolean;
24
24
  skipPackageJson?: boolean; // default is false
25
- addPlugin?: boolean;
26
25
  useProjectJson?: boolean;
27
26
  }
@@ -0,0 +1,2 @@
1
+ import { type MigrationReturnObject, type Tree } from '@nx/devkit';
2
+ export default function update(tree: Tree): Promise<MigrationReturnObject>;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = update;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const add_eas_scripts_1 = require("../../generators/application/lib/add-eas-scripts");
6
+ const hookName = 'eas-build-pre-install';
7
+ async function update(tree) {
8
+ const conflicts = [];
9
+ let changed = false;
10
+ for (const [, project] of (0, devkit_1.getProjects)(tree)) {
11
+ const packageJsonPath = (0, devkit_1.joinPathFragments)(project.root, 'package.json');
12
+ if (!tree.exists((0, devkit_1.joinPathFragments)(project.root, 'eas.json')) ||
13
+ !tree.exists(packageJsonPath)) {
14
+ continue;
15
+ }
16
+ const hookCommand = `cd ${(0, devkit_1.offsetFromRoot)(project.root)} && node ${add_eas_scripts_1.easBuildPreInstallScriptPath} . ${project.root}`;
17
+ const existing = (0, devkit_1.readJson)(tree, packageJsonPath).scripts?.[hookName];
18
+ if (existing === hookCommand) {
19
+ continue;
20
+ }
21
+ if (existing) {
22
+ conflicts.push(`${packageJsonPath} already defines "${hookName}". Make it also run "${hookCommand}".`);
23
+ // The reported command runs this script, so it has to exist either way.
24
+ (0, add_eas_scripts_1.addEasBuildPreInstallScript)(tree);
25
+ changed = true;
26
+ continue;
27
+ }
28
+ (0, devkit_1.updateJson)(tree, packageJsonPath, (json) => {
29
+ json.scripts = { ...json.scripts, [hookName]: hookCommand };
30
+ return json;
31
+ });
32
+ (0, add_eas_scripts_1.addEasBuildPreInstallScript)(tree);
33
+ changed = true;
34
+ }
35
+ if (changed) {
36
+ await (0, devkit_1.formatFiles)(tree);
37
+ }
38
+ if (conflicts.length) {
39
+ return { nextSteps: conflicts, agentContext: conflicts };
40
+ }
41
+ return { skipAgentic: true };
42
+ }
@@ -0,0 +1,32 @@
1
+ #### Add the EAS Build pre-install script to Expo apps
2
+
3
+ Nx 24 removes the `@nx/expo:build` executor. In a workspace without package manager workspaces, that executor copied the root `dependencies`, `devDependencies`, `overrides` (or `resolutions`) and lock file into the app before running `eas build`, then restored the app's files. Without that step, EAS installs the app's `"*"` dependencies at whatever versions are latest.
4
+
5
+ The migration adds an `eas-build-pre-install` script to the `package.json` of every project with an `eas.json`, and writes `tools/scripts/eas-build-pre-install.mjs`. EAS Build runs the script on the build machine before installing dependencies, and it does the same copy there, so your own files are never modified. It also copies the root `pnpm` settings, and with Yarn it gives the app the root package name, because EAS installs with a frozen lock file and both package managers check those against it. A workspace with pnpm `patchedDependencies` still fails to install, because the patch paths resolve from the app directory. With package manager workspaces enabled, the script exits without changes.
6
+
7
+ A project that already defines `eas-build-pre-install` keeps its script and is listed in the migration's next steps, so you can add the new command to it.
8
+
9
+ #### Sample code changes
10
+
11
+ ##### Before
12
+
13
+ ```json title="apps/mobile/package.json"
14
+ {
15
+ "name": "mobile",
16
+ "scripts": {
17
+ "eas-build-post-install": "cd ../../ && node tools/scripts/eas-build-post-install.mjs . apps/mobile"
18
+ }
19
+ }
20
+ ```
21
+
22
+ ##### After
23
+
24
+ ```json title="apps/mobile/package.json"
25
+ {
26
+ "name": "mobile",
27
+ "scripts": {
28
+ "eas-build-post-install": "cd ../../ && node tools/scripts/eas-build-post-install.mjs . apps/mobile",
29
+ "eas-build-pre-install": "cd ../../ && node tools/scripts/eas-build-pre-install.mjs . apps/mobile"
30
+ }
31
+ }
32
+ ```
@@ -0,0 +1,12 @@
1
+ # Replace removed @nx/expo executors with inferred tasks
2
+
3
+ Nx 24 removed `@nx/expo:build`, `@nx/expo:export`, `@nx/expo:install`, `@nx/expo:prebuild`, `@nx/expo:run`, `@nx/expo:serve`, `@nx/expo:start`, `@nx/expo:submit` (including old `@nrwl` aliases).
4
+
5
+ Before changing anything, check for leftover work: a project target, a package.json target or a `targetDefaults` entry still uses a removed executor, or the advisory context reports a conversion error. If none applies, make no changes and stop. Treat each advisory-context item as pending work.
6
+
7
+ 1. Inspect all affected projects and workspace defaults. Repair config-loading errors first. Do not restore executor registrations or install older Nx packages.
8
+ 2. Preserve Expo/EAS profiles, platforms, environment settings and target names. Keep build-list, sync-deps, update and ensure-symlink executors. Inferred `install` runs plain `expo install` in the app directory, so it adds packages to the app's package.json and no longer to the root package.json; where a project relied on root-level installs, install there and use `@nx/expo:sync-deps` to copy them into the app. Do not submit or publish releases as validation; validate local builds where possible.
9
+ 3. Register `@nx/expo/plugin` with options/includes that preserve custom target names and mixed inferred/explicit projects. Replace remaining removed-executor targets, including those in package.json and filtered targetDefaults. Transfer their behavior before removing obsolete defaults. Preserve configurations, dependencies, cache inputs/outputs and environment behavior. Do not silently delete unsupported options or unrelated targets. Migrate old @nrwl aliases too.
10
+ 4. Run project graph creation with the daemon and graph cache disabled (`NX_DAEMON=false NX_CACHE_PROJECT_GRAPH=false`), using the workspace package manager. Inspect resolved project targets and verify each migrated entrypoint exists and is inferred (a thin alias to an inferred target is acceptable). Resolve graph errors before completing this migration, even if task validation was skipped. Configs must load for subsequent migrations.
11
+ 5. By default run relevant real builds/tests with task cache disabled, including alternate configurations. Honor an existing preference to skip expensive task validation; otherwise offer that option when validation is slow. Skipping expensive tasks never skips conversion or the graph check. Report each skipped task as unverified. Never weaken assertions or change application behavior to make checks pass.
12
+ 6. Report converted projects, graph validation, task results and any skipped checks. Unconverted targets or a broken graph mean the migration is incomplete. Investigate task failures and distinguish missing environment prerequisites from conversion regressions; do not claim a working workspace with unresolved regressions.
@@ -0,0 +1,6 @@
1
+ import type { Tree } from '@nx/devkit';
2
+ export default function update(tree: Tree): Promise<{
3
+ nextSteps?: string[];
4
+ agentContext?: string[];
5
+ skipAgentic?: boolean;
6
+ }>;