@expo/build-tools 24.0.0 → 24.1.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.
@@ -49,7 +49,9 @@ exports.spawnDetached = spawnDetached;
49
49
  exports.metricsCorsOriginToServeSimArgs = metricsCorsOriginToServeSimArgs;
50
50
  exports.createServeSimArgs = createServeSimArgs;
51
51
  exports.createExpoDeviceHubArgs = createExpoDeviceHubArgs;
52
+ exports.findAvailablePortAsync = findAvailablePortAsync;
52
53
  exports.waitForWebPreviewReadyAsync = waitForWebPreviewReadyAsync;
54
+ exports.readServeSimPreviewTokenAsync = readServeSimPreviewTokenAsync;
53
55
  exports.startServeSimWithTunnelAsync = startServeSimWithTunnelAsync;
54
56
  exports.startExpoDeviceHubWithTunnelAsync = startExpoDeviceHubWithTunnelAsync;
55
57
  exports.startDeviceWebPreviewWithTunnelAsync = startDeviceWebPreviewWithTunnelAsync;
@@ -71,6 +73,7 @@ const promises_1 = require("node:timers/promises");
71
73
  const sentry_1 = require("../../sentry");
72
74
  const retry_1 = require("../../utils/retry");
73
75
  const turtleFetch_1 = require("../../utils/turtleFetch");
76
+ const serveSimMetricsRecorder_1 = require("./serveSimMetricsRecorder");
74
77
  const XCODE_DEVELOPER_DIR = '/Applications/Xcode.app/Contents/Developer';
75
78
  const WEB_PREVIEW_HOST = '127.0.0.1';
76
79
  const SERVE_SIM_PACKAGE_NAME = '@expo/serve-sim';
@@ -510,6 +513,7 @@ function createServeSimArgs({ port, turnArgs = [], metricsCorsArgs = [], package
510
513
  String(port),
511
514
  '--host',
512
515
  WEB_PREVIEW_HOST,
516
+ '--require-token',
513
517
  '--transport',
514
518
  'webrtc',
515
519
  '--webrtc-codec',
@@ -586,8 +590,8 @@ async function waitForWebPreviewReadyAsync({ previewServer, serverName, port, ti
586
590
  retries: 0,
587
591
  timeout: 2_000,
588
592
  });
589
- WebPreviewReadyResponseSchema.parse(await response.json());
590
- return;
593
+ const ready = WebPreviewReadyResponseSchema.parse(await response.json());
594
+ return ready.device;
591
595
  }
592
596
  catch (error) {
593
597
  lastError = error;
@@ -596,7 +600,7 @@ async function waitForWebPreviewReadyAsync({ previewServer, serverName, port, ti
596
600
  }
597
601
  throw new eas_build_job_1.SystemError(`Timed out waiting for ${serverName} readiness at ${readyUrl}${lastError instanceof Error ? `: ${lastError.message}` : ''}. Last output:\n${previewServer.getOutput() || '<empty>'}`);
598
602
  }
599
- async function startWebPreviewWithTunnelAsync(ctx, { baseDomain, env, logger, timeoutMs, serverName, packageSpec, createArgs, }) {
603
+ async function startWebPreviewWithTunnelAsync(ctx, { baseDomain, env, logger, timeoutMs, serverName, packageSpec, createArgs, readPreviewTokenAsync, }) {
600
604
  const port = await findAvailablePortAsync();
601
605
  logger.info(`Launching ${packageSpec} on ${WEB_PREVIEW_HOST}:${port}.`);
602
606
  const turnArgs = await fetchWebPreviewTurnArgsAsync(ctx, { env, logger });
@@ -607,7 +611,13 @@ async function startWebPreviewWithTunnelAsync(ctx, { baseDomain, env, logger, ti
607
611
  });
608
612
  try {
609
613
  logger.info(`Waiting for ${serverName} to become ready.`);
610
- await waitForWebPreviewReadyAsync({ previewServer, serverName, port, timeoutMs });
614
+ const device = await waitForWebPreviewReadyAsync({
615
+ previewServer,
616
+ serverName,
617
+ port,
618
+ timeoutMs,
619
+ });
620
+ const previewToken = await readPreviewTokenAsync?.(device);
611
621
  const tunnel = await startNgrokTunnelAsync({
612
622
  port,
613
623
  subdomainPrefix: 'web-preview',
@@ -617,6 +627,7 @@ async function startWebPreviewWithTunnelAsync(ctx, { baseDomain, env, logger, ti
617
627
  });
618
628
  return {
619
629
  previewUrl: tunnel.url,
630
+ previewToken,
620
631
  stopAsync: async () => {
621
632
  const results = await Promise.allSettled([tunnel.stopAsync(), previewServer.stopAsync()]);
622
633
  for (const result of results) {
@@ -632,6 +643,10 @@ async function startWebPreviewWithTunnelAsync(ctx, { baseDomain, env, logger, ti
632
643
  throw error;
633
644
  }
634
645
  }
646
+ async function readServeSimPreviewTokenAsync(udid, stateDir = serveSimMetricsRecorder_1.SERVE_SIM_STATE_DIR) {
647
+ const servers = await (0, serveSimMetricsRecorder_1.readServeSimServersAsync)(stateDir);
648
+ return servers.find(server => server.udid === udid)?.token;
649
+ }
635
650
  async function startServeSimWithTunnelAsync(ctx, { baseDomain, env, logger, timeoutMs, packageVersion, }) {
636
651
  const metricsCorsArgs = metricsCorsOriginToServeSimArgs(env);
637
652
  return await startWebPreviewWithTunnelAsync(ctx, {
@@ -642,6 +657,18 @@ async function startServeSimWithTunnelAsync(ctx, { baseDomain, env, logger, time
642
657
  serverName: 'serve-sim',
643
658
  packageSpec: createServeSimPackageSpec(packageVersion),
644
659
  createArgs: (port, turnArgs) => createServeSimArgs({ port, turnArgs, metricsCorsArgs, packageVersion }),
660
+ readPreviewTokenAsync: async (device) => {
661
+ const previewToken = await readServeSimPreviewTokenAsync(device);
662
+ if (!previewToken) {
663
+ // A serve-sim that does not know --require-token fails earlier, in the readiness check, so
664
+ // reaching here means it started and left no token in its state file.
665
+ throw new eas_build_job_1.SystemError(`serve-sim became ready but wrote no session token for device ${device}. The preview is ` +
666
+ 'on a public tunnel and would be reachable without one, so the session cannot continue. ' +
667
+ 'This usually means the state file was not written as expected; retry the session, and ' +
668
+ 'report it if it repeats.');
669
+ }
670
+ return previewToken;
671
+ },
645
672
  });
646
673
  }
647
674
  async function startExpoDeviceHubWithTunnelAsync(ctx, { runtimePlatform, baseDomain, env, logger, timeoutMs, packageVersion, }) {
@@ -1,7 +1,9 @@
1
1
  import { type bunyan } from '@expo/logger';
2
+ export declare const SERVE_SIM_STATE_DIR: string;
2
3
  type ServeSimServer = {
3
4
  udid: string;
4
5
  url: string;
6
+ token?: string;
5
7
  };
6
8
  export declare namespace ServeSimMetricsRecorder {
7
9
  function startAsync({ logger, stateDir, pollIntervalMs, }: {
@@ -18,8 +20,9 @@ export declare namespace ServeSimMetricsRecorder {
18
20
  }[]>;
19
21
  }
20
22
  export declare function readServeSimServersAsync(stateDir: string): Promise<ServeSimServer[]>;
21
- export declare function streamServeSimMetricsToFileAsync({ serveSimUrl, filePath, signal, logger, }: {
23
+ export declare function streamServeSimMetricsToFileAsync({ serveSimUrl, serveSimToken, filePath, signal, logger, }: {
22
24
  serveSimUrl: string;
25
+ serveSimToken?: string;
23
26
  filePath: string;
24
27
  signal: AbortSignal;
25
28
  logger: bunyan;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ServeSimMetricsRecorder = void 0;
6
+ exports.ServeSimMetricsRecorder = exports.SERVE_SIM_STATE_DIR = void 0;
7
7
  exports.readServeSimServersAsync = readServeSimServersAsync;
8
8
  exports.streamServeSimMetricsToFileAsync = streamServeSimMetricsToFileAsync;
9
9
  const node_fetch_1 = __importDefault(require("node-fetch"));
@@ -18,11 +18,11 @@ const POLL_INTERVAL_MS = 2_000;
18
18
  const MAX_CONSECUTIVE_STREAM_FAILURES_PER_DEVICE = 10;
19
19
  const END_STREAM_TIMEOUT_MS = 2_000;
20
20
  // serve-sim's own per-device registry while serving: `${tmpdir}/serve-sim/server-<udid>.json`.
21
- const SERVE_SIM_STATE_DIR = node_path_1.default.join(node_os_1.default.tmpdir(), 'serve-sim');
21
+ exports.SERVE_SIM_STATE_DIR = node_path_1.default.join(node_os_1.default.tmpdir(), 'serve-sim');
22
22
  let activeSession = null;
23
23
  var ServeSimMetricsRecorder;
24
24
  (function (ServeSimMetricsRecorder) {
25
- async function startAsync({ logger, stateDir = SERVE_SIM_STATE_DIR, pollIntervalMs = POLL_INTERVAL_MS, }) {
25
+ async function startAsync({ logger, stateDir = exports.SERVE_SIM_STATE_DIR, pollIntervalMs = POLL_INTERVAL_MS, }) {
26
26
  if (activeSession) {
27
27
  logger.info('serve-sim metrics polling is already running.');
28
28
  return;
@@ -101,6 +101,7 @@ async function pollServeSimMetricsAsync(session) {
101
101
  logger.info(`Collecting serve-sim metrics for ${server.udid}.`);
102
102
  const donePromise = streamServeSimMetricsToFileAsync({
103
103
  serveSimUrl: server.url,
104
+ serveSimToken: server.token,
104
105
  filePath,
105
106
  signal: streamSignal,
106
107
  logger,
@@ -140,7 +141,11 @@ async function readServeSimServersAsync(stateDir) {
140
141
  try {
141
142
  const state = JSON.parse(await (0, promises_1.readFile)(node_path_1.default.join(stateDir, entry), 'utf-8'));
142
143
  if (typeof state.device === 'string' && typeof state.url === 'string') {
143
- servers.push({ udid: state.device, url: state.url });
144
+ servers.push({
145
+ udid: state.device,
146
+ url: state.url,
147
+ ...(typeof state.token === 'string' ? { token: state.token } : {}),
148
+ });
144
149
  }
145
150
  }
146
151
  catch {
@@ -149,7 +154,7 @@ async function readServeSimServersAsync(stateDir) {
149
154
  }
150
155
  return servers;
151
156
  }
152
- async function streamServeSimMetricsToFileAsync({ serveSimUrl, filePath, signal, logger, }) {
157
+ async function streamServeSimMetricsToFileAsync({ serveSimUrl, serveSimToken, filePath, signal, logger, }) {
153
158
  const file = (0, node_fs_1.createWriteStream)(filePath, { flags: 'a' });
154
159
  file.on('error', err => {
155
160
  logger.warn({ err }, `serve-sim metrics file write failed for ${filePath}.`);
@@ -157,7 +162,10 @@ async function streamServeSimMetricsToFileAsync({ serveSimUrl, filePath, signal,
157
162
  let receivedData = false;
158
163
  let metadata;
159
164
  try {
160
- const response = await (0, node_fetch_1.default)(new URL('/metrics', serveSimUrl).toString(), { signal });
165
+ const response = await (0, node_fetch_1.default)(new URL('/metrics', serveSimUrl).toString(), {
166
+ signal,
167
+ ...(serveSimToken ? { headers: { Authorization: `Bearer ${serveSimToken}` } } : {}),
168
+ });
161
169
  if (!response.ok || !response.body) {
162
170
  logger.warn(`serve-sim /metrics responded ${response.status} for ${serveSimUrl}.`);
163
171
  return { receivedData, metadata };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/build-tools",
3
- "version": "24.0.0",
3
+ "version": "24.1.0",
4
4
  "bugs": "https://github.com/expo/eas-cli/issues",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Expo <support@expo.io>",
@@ -102,5 +102,5 @@
102
102
  "typescript": "^5.5.4",
103
103
  "uuid": "^9.0.1"
104
104
  },
105
- "gitHead": "5409c03d58c50b80e4ec9d5ca40f2fbdfaba9aa0"
105
+ "gitHead": "8373ae353ca615ba2170eac2399f7592ad72d36a"
106
106
  }