@expo/build-tools 18.4.0 → 18.5.0

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 (37) hide show
  1. package/dist/builders/android.js +13 -1
  2. package/dist/builders/ios.js +1 -1
  3. package/dist/common/setup.js +4 -3
  4. package/dist/context.d.ts +1 -1
  5. package/dist/context.js +1 -1
  6. package/dist/steps/easFunctions.js +0 -2
  7. package/dist/steps/functionGroups/maestroTest.js +0 -3
  8. package/dist/steps/functions/calculateEASUpdateRuntimeVersion.js +2 -2
  9. package/dist/steps/functions/configureEASUpdateIfInstalled.js +2 -2
  10. package/dist/steps/functions/repack.js +20 -3
  11. package/dist/steps/functions/restoreBuildCache.d.ts +8 -0
  12. package/dist/steps/functions/restoreBuildCache.js +85 -0
  13. package/dist/steps/functions/saveBuildCache.d.ts +8 -0
  14. package/dist/steps/functions/saveBuildCache.js +57 -0
  15. package/dist/steps/functions/startAndroidEmulator.js +19 -0
  16. package/dist/steps/functions/uploadToAsc.d.ts +3 -0
  17. package/dist/steps/functions/uploadToAsc.js +24 -1
  18. package/dist/steps/utils/ios/AscApiClient.d.ts +1 -1
  19. package/dist/steps/utils/ios/AscApiUtils.d.ts +5 -0
  20. package/dist/steps/utils/ios/AscApiUtils.js +16 -13
  21. package/dist/utils/AndroidEmulatorUtils.d.ts +5 -0
  22. package/dist/utils/AndroidEmulatorUtils.js +17 -0
  23. package/dist/utils/appConfig.d.ts +4 -2
  24. package/dist/utils/appConfig.js +36 -5
  25. package/dist/utils/expoCli.d.ts +4 -0
  26. package/dist/utils/expoCli.js +37 -0
  27. package/dist/utils/expoUpdates.d.ts +1 -1
  28. package/dist/utils/expoUpdates.js +4 -4
  29. package/dist/utils/gradleCacheKey.d.ts +2 -0
  30. package/dist/utils/gradleCacheKey.js +56 -0
  31. package/dist/utils/packageManager.d.ts +10 -0
  32. package/dist/utils/packageManager.js +21 -0
  33. package/package.json +14 -13
  34. package/dist/steps/functions/internalMaestroTest.d.ts +0 -9
  35. package/dist/steps/functions/internalMaestroTest.js +0 -534
  36. package/dist/utils/findMaestroPathsFlowsToExecuteAsync.d.ts +0 -8
  37. package/dist/utils/findMaestroPathsFlowsToExecuteAsync.js +0 -184
@@ -275,6 +275,23 @@ var AndroidEmulatorUtils;
275
275
  });
276
276
  }
277
277
  AndroidEmulatorUtils.waitForReadyAsync = waitForReadyAsync;
278
+ async function disableWindowAndTransitionAnimationsAsync({ serialId, env, logger, }) {
279
+ logger.info('Disabling Android emulator window animations.');
280
+ try {
281
+ await (0, turtle_spawn_1.default)('adb', ['-s', serialId, 'shell', 'settings', 'put', 'global', 'window_animation_scale', '0'], { env });
282
+ }
283
+ catch (err) {
284
+ logger.warn({ err }, 'Failed to disable Android emulator window animations.');
285
+ }
286
+ logger.info('Disabling Android emulator transition animations.');
287
+ try {
288
+ await (0, turtle_spawn_1.default)('adb', ['-s', serialId, 'shell', 'settings', 'put', 'global', 'transition_animation_scale', '0'], { env });
289
+ }
290
+ catch (err) {
291
+ logger.warn({ err }, 'Failed to disable Android emulator transition animations.');
292
+ }
293
+ }
294
+ AndroidEmulatorUtils.disableWindowAndTransitionAnimationsAsync = disableWindowAndTransitionAnimationsAsync;
278
295
  async function hasNetworkConnectionAsync({ serialId, env, }) {
279
296
  const networkReadyCheckCommand = env.ANDROID_EMULATOR_NETWORK_READY_COMMAND?.trim();
280
297
  if (networkReadyCheckCommand) {
@@ -1,9 +1,11 @@
1
1
  import { ProjectConfig } from '@expo/config';
2
2
  import { Env } from '@expo/eas-build-job';
3
3
  import { bunyan } from '@expo/logger';
4
- export declare function readAppConfig({ projectDir, env, logger, sdkVersion, }: {
4
+ interface ReadAppConfigParams {
5
5
  projectDir: string;
6
6
  env: Env;
7
7
  logger: bunyan;
8
8
  sdkVersion?: string;
9
- }): ProjectConfig;
9
+ }
10
+ export declare function readAppConfig(params: ReadAppConfigParams): Promise<ProjectConfig>;
11
+ export {};
@@ -8,18 +8,49 @@ const config_1 = require("@expo/config");
8
8
  const env_1 = require("@expo/env");
9
9
  const logger_1 = require("@expo/logger");
10
10
  const semver_1 = __importDefault(require("semver"));
11
- function readAppConfig({ projectDir, env, logger, sdkVersion, }) {
11
+ const expoCli_1 = require("./expoCli");
12
+ async function readAppConfig(params) {
13
+ const shouldLoadEnvVarsFromDotenvFile = params.sdkVersion && semver_1.default.satisfies(params.sdkVersion, '>=49');
14
+ if (shouldLoadEnvVarsFromDotenvFile) {
15
+ const envVarsFromDotenvFile = (0, env_1.load)(params.projectDir);
16
+ const env = { ...params.env, ...envVarsFromDotenvFile };
17
+ params = { ...params, env };
18
+ }
19
+ // Reading the app config is done in two steps/attempts. We first attempt to run `expo config` as a CLI,
20
+ try {
21
+ return await getAppConfigFromExpo(params);
22
+ }
23
+ catch (error) {
24
+ params.logger.warn('Failed to read the app config file with `expo config` command:\n' +
25
+ `${error?.message || error}`);
26
+ }
27
+ // If this fails, we fall back to directly using `@expo/config`
28
+ // This can fail, since it's tied to a specific SDK version, so reading for older SDKs isn't guaranteed to work
29
+ return getAppConfigFromExpoConfig(params);
30
+ }
31
+ async function getAppConfigFromExpo({ projectDir, env, }) {
32
+ const result = await (0, expoCli_1.expoCommandAsync)(projectDir, ['config', '--json', '--full', '--type', 'public'], { env });
33
+ let parsed;
34
+ try {
35
+ parsed = JSON.parse(result.stdout);
36
+ }
37
+ catch {
38
+ throw new Error(`Failed to parse JSON output from 'expo config'.\nOutput: ${result.stdout.slice(0, 500)}`);
39
+ }
40
+ if (!('exp' in parsed)) {
41
+ throw new Error(`Unexpected output from 'expo config': missing 'exp' field.`);
42
+ }
43
+ return parsed;
44
+ }
45
+ function getAppConfigFromExpoConfig({ projectDir, env, logger, }) {
12
46
  const originalProcessExit = process.exit;
13
47
  const originalProcessCwd = process.cwd;
14
48
  const originalStdoutWrite = process.stdout.write;
15
49
  const originalStderrWrite = process.stderr.write;
16
50
  const originalProcessEnv = process.env;
17
51
  const stdoutStore = [];
18
- const shouldLoadEnvVarsFromDotenvFile = sdkVersion && semver_1.default.satisfies(sdkVersion, '>=49');
19
- const envVarsFromDotenvFile = shouldLoadEnvVarsFromDotenvFile ? (0, env_1.load)(projectDir) : {};
20
- const newEnvsToUse = { ...env, ...envVarsFromDotenvFile };
21
52
  try {
22
- process.env = newEnvsToUse;
53
+ process.env = env;
23
54
  process.exit = () => {
24
55
  throw new Error('Failed to evaluate app config file');
25
56
  };
@@ -0,0 +1,4 @@
1
+ import { type SpawnOptions } from '@expo/turtle-spawn';
2
+ export declare class ExpoCLIModuleNotFoundError extends Error {
3
+ }
4
+ export declare function expoCommandAsync(projectDir: string, args: string[], options: Omit<SpawnOptions, 'cwd'>): Promise<import("@expo/spawn-async").SpawnResult>;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ExpoCLIModuleNotFoundError = void 0;
7
+ exports.expoCommandAsync = expoCommandAsync;
8
+ const resolve_from_1 = __importDefault(require("resolve-from"));
9
+ const turtle_spawn_1 = __importDefault(require("@expo/turtle-spawn"));
10
+ class ExpoCLIModuleNotFoundError extends Error {
11
+ }
12
+ exports.ExpoCLIModuleNotFoundError = ExpoCLIModuleNotFoundError;
13
+ function resolveExpoCLI(projectRoot) {
14
+ try {
15
+ return (resolve_from_1.default.silent(projectRoot, 'expo/bin/cli') ?? (0, resolve_from_1.default)(projectRoot, 'expo/bin/cli.js'));
16
+ }
17
+ catch (e) {
18
+ if (e.code === 'MODULE_NOT_FOUND') {
19
+ throw new ExpoCLIModuleNotFoundError(`The \`expo\` package was not found.`);
20
+ }
21
+ throw e;
22
+ }
23
+ }
24
+ async function expoCommandAsync(projectDir, args, options) {
25
+ const expoCliPath = resolveExpoCLI(projectDir);
26
+ return (0, turtle_spawn_1.default)(expoCliPath, args, {
27
+ cwd: projectDir,
28
+ stdio: 'pipe',
29
+ ...options,
30
+ env: {
31
+ ...options.env,
32
+ // NOTE: If we're reading user configs, if a user has set this, it might cause excessive output
33
+ // that can stop the command from being readable
34
+ EXPO_DEBUG: '0',
35
+ },
36
+ });
37
+ }
@@ -27,5 +27,5 @@ export declare function resolveRuntimeVersionForExpoUpdatesIfConfiguredAsync({ c
27
27
  } | null>;
28
28
  export declare function getChannelAsync(ctx: BuildContext<Job>): Promise<string | null>;
29
29
  export declare function getRuntimeVersionAsync(ctx: BuildContext<Job>): Promise<string | null>;
30
- export declare function isEASUpdateConfigured(ctx: BuildContext<Job>): boolean;
30
+ export declare function isEASUpdateConfigured(ctx: BuildContext<Job>): Promise<boolean>;
31
31
  export {};
@@ -86,7 +86,7 @@ This would cause any updates published on the local machine to not be compatible
86
86
  await logDiffFingerprints({ resolvedRuntime, ctx });
87
87
  throw new Error('Runtime version calculated on local machine not equal to runtime version calculated during build.');
88
88
  }
89
- if (isEASUpdateConfigured(ctx)) {
89
+ if (await isEASUpdateConfigured(ctx)) {
90
90
  if (ctx.job.updates?.channel !== undefined) {
91
91
  await configureEASExpoUpdatesAsync(ctx);
92
92
  }
@@ -101,7 +101,7 @@ This would cause any updates published on the local machine to not be compatible
101
101
  // NO-OP: Development clients don't need to have a channel set
102
102
  }
103
103
  else {
104
- const easUpdateUrl = ctx.appConfig.updates?.url ?? null;
104
+ const easUpdateUrl = (await ctx.appConfig).updates?.url ?? null;
105
105
  const jobProfile = ctx.job.buildProfile ?? null;
106
106
  ctx.logger.warn(`This build has an invalid EAS Update configuration: update.url is set to "${easUpdateUrl}" in app config, but a channel is not specified${jobProfile ? '' : ` for the current build profile "${jobProfile}" in eas.json`}.`);
107
107
  ctx.logger.warn(`- No channel will be set and EAS Update will be disabled for the build.`);
@@ -156,8 +156,8 @@ async function getRuntimeVersionAsync(ctx) {
156
156
  throw new Error(`Platform is not supported.`);
157
157
  }
158
158
  }
159
- function isEASUpdateConfigured(ctx) {
160
- const rawUrl = ctx.appConfig.updates?.url;
159
+ async function isEASUpdateConfigured(ctx) {
160
+ const rawUrl = (await ctx.appConfig).updates?.url;
161
161
  if (!rawUrl) {
162
162
  return false;
163
163
  }
@@ -0,0 +1,2 @@
1
+ export declare const GRADLE_CACHE_KEY_PREFIX = "android-gradle-cache-";
2
+ export declare function generateGradleCacheKeyAsync(workingDirectory: string): Promise<string>;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.GRADLE_CACHE_KEY_PREFIX = void 0;
40
+ exports.generateGradleCacheKeyAsync = generateGradleCacheKeyAsync;
41
+ const PackageManagerUtils = __importStar(require("@expo/package-manager"));
42
+ const steps_1 = require("@expo/steps");
43
+ const path_1 = __importDefault(require("path"));
44
+ const packageManager_1 = require("./packageManager");
45
+ exports.GRADLE_CACHE_KEY_PREFIX = 'android-gradle-cache-';
46
+ async function generateGradleCacheKeyAsync(workingDirectory) {
47
+ const packagerRunDir = (0, packageManager_1.findPackagerRootDir)(workingDirectory);
48
+ const manager = PackageManagerUtils.createForProject(packagerRunDir);
49
+ const lockPath = path_1.default.join(packagerRunDir, manager.lockFile);
50
+ try {
51
+ return `${exports.GRADLE_CACHE_KEY_PREFIX}${(0, steps_1.hashFiles)([lockPath])}`;
52
+ }
53
+ catch (err) {
54
+ throw new Error(`Failed to read lockfile for Gradle cache key generation: ${err instanceof Error ? err.message : err}`);
55
+ }
56
+ }
@@ -1,3 +1,4 @@
1
+ import { type bunyan } from '@expo/logger';
1
2
  export declare enum PackageManager {
2
3
  YARN = "yarn",
3
4
  NPM = "npm",
@@ -5,6 +6,15 @@ export declare enum PackageManager {
5
6
  BUN = "bun"
6
7
  }
7
8
  export declare function resolvePackageManager(directory: string): PackageManager;
9
+ /**
10
+ * Get the version of a package from the dist-tags.
11
+ * Returns null if the version cannot be resolved.
12
+ */
13
+ export declare function resolvePackageVersionAsync({ logger, packageName, distTag, }: {
14
+ logger: bunyan;
15
+ packageName: string;
16
+ distTag: string;
17
+ }): Promise<string | null>;
8
18
  export declare function findPackagerRootDir(currentDir: string): string;
9
19
  export declare function isAtLeastNpm7Async(): Promise<boolean>;
10
20
  export declare function shouldUseFrozenLockfile({ env, sdkVersion, reactNativeVersion, }: {
@@ -38,6 +38,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.PackageManager = void 0;
40
40
  exports.resolvePackageManager = resolvePackageManager;
41
+ exports.resolvePackageVersionAsync = resolvePackageVersionAsync;
41
42
  exports.findPackagerRootDir = findPackagerRootDir;
42
43
  exports.isAtLeastNpm7Async = isAtLeastNpm7Async;
43
44
  exports.shouldUseFrozenLockfile = shouldUseFrozenLockfile;
@@ -73,6 +74,26 @@ function resolvePackageManager(directory) {
73
74
  return PackageManager.YARN;
74
75
  }
75
76
  }
77
+ /**
78
+ * Get the version of a package from the dist-tags.
79
+ * Returns null if the version cannot be resolved.
80
+ */
81
+ async function resolvePackageVersionAsync({ logger, packageName, distTag, }) {
82
+ try {
83
+ const { stdout } = await (0, turtle_spawn_1.default)('npm', ['view', packageName, 'dist-tags', '--json'], {
84
+ stdio: 'pipe',
85
+ });
86
+ const distTags = JSON.parse(stdout);
87
+ if (distTag in distTags) {
88
+ return distTags[distTag];
89
+ }
90
+ }
91
+ catch (e) {
92
+ const message = e instanceof Error ? e.message : String(e);
93
+ logger.warn(`Unable to resolve version for ${packageName}@${distTag}: ${message}`);
94
+ }
95
+ return null;
96
+ }
76
97
  function findPackagerRootDir(currentDir) {
77
98
  return PackageManagerUtils.resolveWorkspaceRoot(currentDir) ?? currentDir;
78
99
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/build-tools",
3
- "version": "18.4.0",
3
+ "version": "18.5.0",
4
4
  "bugs": "https://github.com/expo/eas-cli/issues",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Expo <support@expo.io>",
@@ -24,30 +24,30 @@
24
24
  "prebuild": "yarn gql",
25
25
  "build": "tsc",
26
26
  "typecheck": "tsc",
27
- "prepack": "rm -rf dist *.tsbuildinfo && yarn gql && tsc -p tsconfig.build.json",
27
+ "prepack": "rimraf dist \"*.tsbuildinfo\" && yarn gql && tsc -p tsconfig.build.json",
28
28
  "jest-unit": "jest --config jest/unit-config.ts",
29
29
  "jest-integration": "jest --config jest/integration-config.ts",
30
30
  "jest-unit-watch": "jest --config jest/unit-config.ts --watch",
31
31
  "jest-integration-watch": "jest --config jest/integration-config.ts --watch",
32
- "clean": "rm -rf node_modules dist coverage *.tsbuildinfo",
32
+ "clean": "rimraf node_modules dist coverage \"*.tsbuildinfo\"",
33
33
  "gql": "gql.tada generate-schema ${API_SERVER_URL:-https://api.expo.dev}/graphql --output ./schema.graphql && gql.tada generate-output",
34
34
  "gql:local": "API_SERVER_URL=http://api.expo.test yarn gql",
35
35
  "test": "yarn jest-unit"
36
36
  },
37
37
  "dependencies": {
38
- "@expo/config": "10.0.6",
39
- "@expo/config-plugins": "9.0.12",
40
- "@expo/downloader": "18.0.1",
41
- "@expo/eas-build-job": "18.4.0",
38
+ "@expo/config": "55.0.10",
39
+ "@expo/config-plugins": "55.0.7",
40
+ "@expo/downloader": "18.5.0",
41
+ "@expo/eas-build-job": "18.5.0",
42
42
  "@expo/env": "^0.4.0",
43
- "@expo/logger": "18.0.1",
43
+ "@expo/logger": "18.5.0",
44
44
  "@expo/package-manager": "1.9.10",
45
45
  "@expo/plist": "^0.2.0",
46
46
  "@expo/results": "^1.0.0",
47
47
  "@expo/spawn-async": "1.7.2",
48
- "@expo/steps": "18.4.0",
49
- "@expo/template-file": "18.0.1",
50
- "@expo/turtle-spawn": "18.0.1",
48
+ "@expo/steps": "18.5.0",
49
+ "@expo/template-file": "18.5.0",
50
+ "@expo/turtle-spawn": "18.5.0",
51
51
  "@expo/xcpretty": "^4.3.1",
52
52
  "@google-cloud/storage": "^7.11.2",
53
53
  "@urql/core": "^6.0.1",
@@ -75,7 +75,7 @@
75
75
  "zod": "^4.3.5"
76
76
  },
77
77
  "devDependencies": {
78
- "@expo/repack-app": "~0.2.5",
78
+ "@expo/repack-app": "~0.4.1",
79
79
  "@types/fs-extra": "^11.0.4",
80
80
  "@types/jest": "^29.5.12",
81
81
  "@types/lodash": "^4.17.4",
@@ -91,11 +91,12 @@
91
91
  "jest": "^29.7.0",
92
92
  "memfs": "^4.17.1",
93
93
  "nock": "13.4.0",
94
+ "rimraf": "3.0.2",
94
95
  "ts-jest": "^29.1.4",
95
96
  "ts-mockito": "^2.6.1",
96
97
  "tslib": "^2.6.3",
97
98
  "typescript": "^5.5.4",
98
99
  "uuid": "^9.0.1"
99
100
  },
100
- "gitHead": "4e202db843be2dca6450af4b45ee76b226a662ea"
101
+ "gitHead": "2e2dddb59ae9df5ad2395c74f77701341103b62e"
101
102
  }
@@ -1,9 +0,0 @@
1
- import { BuildFunction } from '@expo/steps';
2
- import { CustomBuildContext } from '../../customBuildContext';
3
- export declare function createInternalEasMaestroTestFunction(ctx: CustomBuildContext): BuildFunction;
4
- export declare function getMaestroTestCommand(params: {
5
- flow_path: string;
6
- output_format: string | undefined;
7
- /** Unused if `output_format` is undefined */
8
- output_path: string;
9
- }): [command: string, ...args: string[]];