stim 1.1.0 → 1.3.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.
- package/README.md +37 -0
- package/dist/{android-CC5bUer7.mjs → android-BW8i_YxU.mjs} +1 -1
- package/dist/android-BqVIJoG7.mjs +1368 -0
- package/dist/{android-DnZlT3aU.mjs → android-CqcW1hrP.mjs} +205 -58
- package/dist/{android-cas-DGlTStWu.mjs → android-cas-BR5YJBYv.mjs} +6 -6
- package/dist/android-cas-compiler.mjs +1 -1
- package/dist/{app-install-oZIQRbdD.mjs → app-install-DIp9riNx.mjs} +29 -21
- package/dist/{build-slots-CgacA9zQ.mjs → build-slots-C3-R4XQr.mjs} +3 -3
- package/dist/{cache-manifest-oeH18ERr.mjs → cache-manifest-CXR-Y8pH.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +13 -13
- package/dist/collector-run.d.mts +4 -1
- package/dist/collector-run.mjs +36 -11
- package/dist/{config-D7uu8Gbq.mjs → config-CcefMY2Q.mjs} +94 -13
- package/dist/{deps-64wVnpZc.mjs → deps-Spz8ozgo.mjs} +2 -2
- package/dist/{dev-client-Bvky1hya.mjs → dev-client-BjisHDB5.mjs} +250 -10
- package/dist/{device-DJKv5Qej.mjs → device-BkiW-gkk.mjs} +19 -11
- package/dist/{device-lease-D-G3SgVe.mjs → device-lease-BJYybF-2.mjs} +107 -83
- package/dist/{device-pool-BlHXnYYs.mjs → device-pool-CPbLGfrB.mjs} +19 -13
- package/dist/{device-remote-CCgkG82J.mjs → device-remote-AkYCKS8U.mjs} +8 -8
- package/dist/{doctor-DlVxTtMq.mjs → doctor-Bmv86UUW.mjs} +18 -26
- package/dist/{doctor-BRF9aAJ3.mjs → doctor-fAMXC4vl.mjs} +10 -10
- package/dist/{error-diagnostics-B5IJwv3-.mjs → error-diagnostics-DHC31rXA.mjs} +65 -55
- package/dist/{exec-bsN9MJXb.mjs → exec-CyylIdq9.mjs} +4 -2
- package/dist/{gc-DhXdgSdt.mjs → gc-GGu-8ULN.mjs} +90 -67
- package/dist/{guide-DrhrDBo5.mjs → guide-92CPA21s.mjs} +414 -47
- package/dist/{ios-CK1Vrk6Q.mjs → ios-BSXFeO5H.mjs} +200 -59
- package/dist/{ios-BZxKPuqP.mjs → ios-Deh5js5V.mjs} +147 -40
- package/dist/{ios-device-CdSm0GDw.mjs → ios-device-CWOM_S44.mjs} +2 -2
- package/dist/{ios-device-CYbuRNXR.mjs → ios-device-D3pzTKQE.mjs} +1 -1
- package/dist/{logs-Dxoy16Qv.mjs → logs-DPNF4C9s.mjs} +9 -6
- package/dist/{logs-query-oqn47Ffx.mjs → logs-query-R-Cqc6Qv.mjs} +22 -5
- package/dist/{metro-B01H3EuD.mjs → metro-CORqXyTL.mjs} +3 -3
- package/dist/{ndjson-DcAtEx_K.mjs → ndjson-BZwI1NBv.mjs} +5 -2
- package/dist/{ownership-D8HmSv2E.mjs → ownership-8O073GIC.mjs} +3 -3
- package/dist/{ownership-B9QIdQOw.mjs → ownership-BpCKiRlQ.mjs} +4 -4
- package/dist/{ownership-claim-CeJLEpjD.mjs → ownership-claim-Bf2CAfw3.mjs} +4 -3
- package/dist/{project-COj6nzzh.mjs → project-fKmuIaMI.mjs} +2 -2
- package/dist/{reclaim-BPvN2HlP.mjs → reclaim-iW9Cad7k.mjs} +80 -73
- package/dist/{reload-DYZEBbZy.mjs → reload-DazHDSFA.mjs} +32 -24
- package/dist/{server-bare-BYHqEeyw.mjs → server-bare-DEzPZLvf.mjs} +7 -2
- package/dist/server-expo-44em5Pmg.mjs +2 -0
- package/dist/{server-expo-BEMr_m6p.mjs → server-expo-DizT4OMk.mjs} +5 -5
- package/dist/{settings-BSwrY4FZ.mjs → settings-DEJf6_kJ.mjs} +26 -5
- package/dist/slot-launch-cci0xvmC.mjs +19 -0
- package/dist/{start-ByCylYtB.mjs → start-mObjQH2W.mjs} +12 -12
- package/dist/{state-IYEY-zi8.mjs → state-B3XA2wp2.mjs} +9 -9
- package/dist/{stats-wqxPm7Tv.mjs → stats-BR-kwj0B.mjs} +1 -1
- package/dist/{stats-DZ4Q5J-7.mjs → stats-CaaQr4yN.mjs} +3 -3
- package/dist/{status-Dia0XTqG.mjs → status-BxQNqu9t.mjs} +86 -25
- package/dist/{stop-D6o5zAdm.mjs → stop-CrHGcjrV.mjs} +2 -2
- package/dist/{stop-BApyaF21.mjs → stop-DimGXEKY.mjs} +93 -42
- package/dist/supervisor-run.d.mts +1 -2
- package/dist/supervisor-run.mjs +5 -5
- package/dist/{remote-cache-DOi5-zLj.mjs → teardown-ClFp1Aax.mjs} +889 -830
- package/dist/{workspace-process-lock-CxOO9-pf.mjs → workspace-process-lock-3NcQnZ0X.mjs} +1 -1
- package/dist/{worktree-DxEmUI_n.mjs → worktree-DxTgN1CJ.mjs} +16 -16
- package/dist/{worktree-Dx3ZC5lS.mjs → worktree-Eq6TLH8N.mjs} +7 -3
- package/dist/{xcode-CDB6fytw.mjs → xcode-D7sAp-Zy.mjs} +256 -103
- package/package.json +5 -5
- package/shim/bundle-response.cjs +5 -0
- package/dist/android-xmyGBNy5.mjs +0 -665
- package/dist/build-lock-vE45ZzJZ.mjs +0 -645
- package/dist/server-expo-rb0k-0w7.mjs +0 -2
|
@@ -1,35 +1,37 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { S as upsertProject, f as getProject, l as getConcurrencyLimits } from "./config-
|
|
3
|
-
import { r as createNdjsonWriter } from "./ndjson-
|
|
4
|
-
import { D as workspaceLogsDir, T as workspaceDir, _ as writeWorkspaceState, g as writeWorkspaceLaunch, n as MODE_EXPO, p as readWorkspaceState, t as MODE_BARE } from "./state-
|
|
5
|
-
import { C as removeTemporaryEntry, S as makeTemporaryDirectory, g as repoRoot, s as gitCommonDir } from "./worktree-
|
|
6
|
-
import { a as findProjectRoot, c as projectShortcut, i as detectIsExpo, r as detectBundleId, t as appProjectProblem } from "./project-
|
|
7
|
-
import { i as resolveProjectMetro, r as pidExists } from "./metro-
|
|
8
|
-
import { n as verifyCollectorOwnership } from "./ownership-
|
|
9
|
-
import { a as easAuthNote, c as loadProjectProvider, d as resolveEasCliBin, f as resolveRemote, i as checkEasAuth, n as UPLOAD_TIMEOUT_MS, o as exitAfterFlush, p as uploadRemote, r as cacheLevel, s as isEasAuthFailureText, t as RESOLVE_TIMEOUT_MS, v as POOL_SETTING_REMEDY, x as parkedMaxSetting } from "./remote-cache-DOi5-zLj.mjs";
|
|
10
|
-
import { D as remoteIosSetting, E as remoteDeviceSettingError, F as unknownSettingKeys, H as resolveOptimizations, L as detectProviders, M as settingShapeErrors, O as resolveCacheProviderConfig, P as tunnelModeSetting, V as optimizationBuildProfile, _ as iosSigningIdentitySha1SettingError, a as SETTING_SHAPE_REMEDY, d as cacheProviderSettingError, f as iosLanHostSetting, g as iosSigningIdentitySha1Setting, h as iosSigningIdentitySettingError, k as resolveSettings, m as iosSigningIdentitySetting, p as iosLanHostSettingError, r as REMOTE_DEVICE_BACKENDS, w as publicUrlSetting, z as artifactCachePolicy } from "./settings-BSwrY4FZ.mjs";
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
+
import { I as deviceSlotKey, S as upsertProject, V as validateDeviceSlot, f as getProject, l as getConcurrencyLimits } from "./config-CcefMY2Q.mjs";
|
|
3
|
+
import { r as createNdjsonWriter } from "./ndjson-BZwI1NBv.mjs";
|
|
4
|
+
import { D as workspaceLogsDir, T as workspaceDir, _ as writeWorkspaceState, g as writeWorkspaceLaunch, n as MODE_EXPO, p as readWorkspaceState, t as MODE_BARE } from "./state-B3XA2wp2.mjs";
|
|
5
|
+
import { C as removeTemporaryEntry, S as makeTemporaryDirectory, g as repoRoot, s as gitCommonDir } from "./worktree-Eq6TLH8N.mjs";
|
|
6
|
+
import { a as findProjectRoot, c as projectShortcut, i as detectIsExpo, r as detectBundleId, t as appProjectProblem } from "./project-fKmuIaMI.mjs";
|
|
7
|
+
import { i as resolveProjectMetro, r as pidExists } from "./metro-CORqXyTL.mjs";
|
|
8
|
+
import { n as verifyCollectorOwnership } from "./ownership-8O073GIC.mjs";
|
|
11
9
|
import { _ as launchErrorPreview, c as launchErrorReport, g as stepTimer, h as stepClock, i as formatDuration, l as phaseLine, m as shortUdid, n as appReadinessMessage, p as shortHash } from "./command-output-8wHMEde0.mjs";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { a as
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
10
|
+
import { r as claimFailure } from "./ownership-claim-Bf2CAfw3.mjs";
|
|
11
|
+
import { $ as providerDownloadPath, G as buildCacheKey, J as filesystemBuildCapability, K as describeFingerprintMiss, Q as prepareProviderDownloadDir, R as WAIT_CEILING_MS, U as takeoverLine, V as releaseBuildLock, W as waitForBuild, X as fingerprintDiffSuffix, Y as fingerprintDiffRecord, Z as fingerprintProject, at as untrackedMissLine, et as providerUploadOutcome, nt as resolveBuild, ot as untrackedNativeFiles, rt as storeBuild, tt as refingerprintAfterMutation, z as acquireBuildLock } from "./android-BqVIJoG7.mjs";
|
|
12
|
+
import { A as resolveSettings, B as artifactCachePolicy, D as remoteDeviceSettingError, F as tunnelModeSetting, H as optimizationBuildProfile, I as unknownSettingKeys, N as settingShapeErrors, O as remoteIosSetting, R as detectProviders, T as publicUrlSetting, U as resolveOptimizations, _ as iosSigningIdentitySha1SettingError, a as SETTING_SHAPE_REMEDY, d as cacheProviderSettingError, f as iosLanHostSetting, g as iosSigningIdentitySha1Setting, h as iosSigningIdentitySettingError, k as resolveCacheProviderConfig, m as iosSigningIdentitySetting, p as iosLanHostSettingError, r as REMOTE_DEVICE_BACKENDS, x as metroWarmupUrlSetting } from "./settings-DEJf6_kJ.mjs";
|
|
13
|
+
import { C as uploadRemote, S as resolveRemote, _ as isEasAuthFailureText, a as POOL_SETTING_REMEDY, c as parkedMaxSetting, d as RESOLVE_TIMEOUT_MS, f as UPLOAD_TIMEOUT_MS, g as exitAfterFlush, h as easAuthNote, m as checkEasAuth, p as cacheLevel, v as loadProjectProvider, x as resolveEasCliBin } from "./teardown-ClFp1Aax.mjs";
|
|
14
|
+
import { _ as easDeviceBuildRemedy, a as swapJsBundle, c as ensureWorkspaceStorageSafely, d as launchOutcomeRecord, f as noMetroMessage, g as warmMetro, h as sleep, l as gateShouldRetry, m as resolveMetroWithRetry, n as pickDevClientScheme, o as needsPrebuild, p as noMetroRemedy, r as schemesFromInfoPlist, s as runPrebuild, t as devClientScheme, u as isPhysicalDeviceRequest, v as isEasBuildFailure, y as resolveEasDevelopmentBuild } from "./dev-client-BjisHDB5.mjs";
|
|
15
|
+
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-3NcQnZ0X.mjs";
|
|
16
|
+
import { C as launchIosApp, E as unverifiedLaunchLines, O as verifyLaunch, T as readMetroRecords, b as isBundleProof, c as RELEASE_VERIFY_WAIT_MS, f as clearOtherUserApps, i as LAUNCH_BUNDLING, k as verifyReleaseLaunch, m as devClientUrl, n as DEFAULT_METRO_PORT, o as LAUNCH_FATAL, s as LAUNCH_UNVERIFIED, v as installIosApp, w as readCollectorRecords, y as iosAppProcess } from "./app-install-DIp9riNx.mjs";
|
|
17
|
+
import { f as listIosRuntimes } from "./ios-Deh5js5V.mjs";
|
|
18
|
+
import { a as lostLine, c as releaseLeaseOnSignal, i as leaseExpiryText, l as runLease, n as DEBUG_VERIFY_STEP_MS, o as lostRefusal, r as acquireRunLease, s as parseDeviceWait, t as selectFromPool, u as waitFlagConflict } from "./device-pool-CPbLGfrB.mjs";
|
|
19
|
+
import { r as releaseBuildSlot, t as acquireBuildSlot } from "./build-slots-C3-R4XQr.mjs";
|
|
20
|
+
import { a as statsProjectKey, i as recordRunStats, n as readRunEstimates, t as createRunRecorder } from "./stats-BR-kwj0B.mjs";
|
|
21
|
+
import { T as unknownIosRuntimeRefusal, b as ensureBooted, c as discoverXcodeProject, d as resolveScheme, i as buildIos, l as readBundleExecutable, m as describeDiagnostic, n as COMPILATION_CACHE_UNAVAILABLE, o as compilationCacheActivityLine, t as COMPILATION_CACHE_NOT_RUN, u as readBundleId, v as checkDeviceCapacity, w as unknownIosDeviceTypeRefusal, x as ensureOwnedDevice, y as clearIosAdoptionPending } from "./xcode-D7sAp-Zy.mjs";
|
|
22
|
+
import { a as ensureMetroReachable, b as ownedSessionName, c as remoteIosDeps, l as resolveRemoteContext, n as binOnPath, o as ensureRemoteBootOwned, r as bundleEntryPoint, w as gateMetroOrigin } from "./device-remote-AkYCKS8U.mjs";
|
|
23
|
+
import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-cci0xvmC.mjs";
|
|
22
24
|
import { t as spawnEntry } from "./spawn-entry-nCE6m770.mjs";
|
|
23
|
-
import { a as printNativeCrashReport, n as IOS_CRASH_REPORT_RETRY, o as simulatorConsolePaths, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-
|
|
24
|
-
import { a as iosDeviceProcess, c as listIosDevices, d as verifyIosDeviceReleaseLaunch, i as installIosDeviceApp, l as localNetworkPending, n as LAUNCH_PROBE_TIMEOUT_MS, o as iosPoolCandidates, r as awaitIosDeviceLaunch, s as iosPoolNoCandidatesRefusal, t as DEVICECTL_INSTALL_TIMEOUT_MS, u as resolveIosPhysicalDevice } from "./ios-device-
|
|
25
|
-
import { a as runPodInstall, n as podsAreStale, r as readPodState } from "./deps-
|
|
25
|
+
import { a as printNativeCrashReport, n as IOS_CRASH_REPORT_RETRY, o as simulatorConsolePaths, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-DHC31rXA.mjs";
|
|
26
|
+
import { a as iosDeviceProcess, c as listIosDevices, d as verifyIosDeviceReleaseLaunch, i as installIosDeviceApp, l as localNetworkPending, n as LAUNCH_PROBE_TIMEOUT_MS, o as iosPoolCandidates, r as awaitIosDeviceLaunch, s as iosPoolNoCandidatesRefusal, t as DEVICECTL_INSTALL_TIMEOUT_MS, u as resolveIosPhysicalDevice } from "./ios-device-CWOM_S44.mjs";
|
|
27
|
+
import { a as runPodInstall, n as podsAreStale, r as readPodState } from "./deps-Spz8ozgo.mjs";
|
|
26
28
|
import { existsSync, mkdirSync, mkdtempSync, openSync, rmSync, writeFileSync } from "node:fs";
|
|
27
29
|
import { InvalidArgumentError } from "commander";
|
|
28
30
|
import { X509Certificate } from "node:crypto";
|
|
29
31
|
import { basename, join } from "node:path";
|
|
30
32
|
import { networkInterfaces, tmpdir } from "node:os";
|
|
31
|
-
import chalk from "chalk";
|
|
32
33
|
import { createWarnOnce, loadCacheProvider, resolveTieredBuild, storeTieredBuild } from "@stim-cli/cache";
|
|
34
|
+
import chalk from "chalk";
|
|
33
35
|
//#region src/engine/ios-profile.ts
|
|
34
36
|
const TAG = /<(\/?)\s*([A-Za-z0-9_]+)(?:\s[^>]*?)?(\/?)>/g;
|
|
35
37
|
const ENTITIES = {
|
|
@@ -633,7 +635,12 @@ function resolveDeviceType(flag, settings) {
|
|
|
633
635
|
function resolveRuntime(flag, settings) {
|
|
634
636
|
return (typeof flag === "string" && flag.trim() !== "" ? flag.trim() : null) || iosStringSetting(settings, "runtime");
|
|
635
637
|
}
|
|
636
|
-
function deviceModelRefusal({ deviceTypeFlag, runtimeFlag, deviceType, runtime, physical, remoteBackend, listRuntimes }) {
|
|
638
|
+
function deviceModelRefusal({ slot, deviceTypeFlag, runtimeFlag, deviceType, runtime, physical, remoteBackend, listRuntimes }) {
|
|
639
|
+
if (slot && slot !== "default" && remoteBackend) return {
|
|
640
|
+
code: "STIM_BAD_ARG",
|
|
641
|
+
message: "Named slots currently support local simulators and physical devices.",
|
|
642
|
+
remedy: "Use the default slot for a remote session."
|
|
643
|
+
};
|
|
637
644
|
if (typeof deviceTypeFlag === "string" && deviceTypeFlag.trim() === "") return {
|
|
638
645
|
code: "STIM_BAD_ARG",
|
|
639
646
|
message: "--device-type was given an empty name.",
|
|
@@ -699,22 +706,22 @@ function printDiagnostics(note, result) {
|
|
|
699
706
|
}
|
|
700
707
|
//#endregion
|
|
701
708
|
//#region src/commands/ios/collector.ts
|
|
702
|
-
function collectorLogFile(root) {
|
|
703
|
-
return join(workspaceLogsDir(root), `collector
|
|
709
|
+
function collectorLogFile(root, slot) {
|
|
710
|
+
return join(workspaceLogsDir(root), `collector-${deviceSlotKey("ios", slot)}.log`);
|
|
704
711
|
}
|
|
705
712
|
function collectorEntry() {
|
|
706
713
|
return spawnEntry("collector-run");
|
|
707
714
|
}
|
|
708
715
|
const COLLECTOR_EXIT_WAIT_MS = 2e3;
|
|
709
716
|
const COLLECTOR_POLL_MS = 25;
|
|
710
|
-
async function stopPreviousCollector({ root, kill = (pid, signal) => process.kill(pid, signal), alive = pidExists, readState = readWorkspaceState, verify = verifyCollectorOwnership, waitMs = COLLECTOR_EXIT_WAIT_MS, note = (_line) => {} }) {
|
|
711
|
-
const previous = (readState(root)?.collectors)?.["ios"] || null;
|
|
717
|
+
async function stopPreviousCollector({ root, slot = "default", kill = (pid, signal) => process.kill(pid, signal), alive = pidExists, readState = readWorkspaceState, verify = verifyCollectorOwnership, waitMs = COLLECTOR_EXIT_WAIT_MS, note = (_line) => {} }) {
|
|
718
|
+
const previous = (readState(root)?.collectors)?.[deviceSlotKey("ios", slot)] || null;
|
|
712
719
|
const previousPid = Number(previous?.pid) || null;
|
|
713
720
|
let killed = null;
|
|
714
721
|
if (previousPid) {
|
|
715
722
|
const ownership = verify({
|
|
716
723
|
pid: previousPid,
|
|
717
|
-
platform: "ios",
|
|
724
|
+
platform: deviceSlotKey("ios", slot),
|
|
718
725
|
root,
|
|
719
726
|
isAlive: alive,
|
|
720
727
|
expected: previous
|
|
@@ -732,9 +739,10 @@ async function stopPreviousCollector({ root, kill = (pid, signal) => process.kil
|
|
|
732
739
|
}
|
|
733
740
|
return { killed };
|
|
734
741
|
}
|
|
735
|
-
async function replaceCollector({ root, udid, bundleId, appName, appExecutable, physical = false, payloadUrl = null, spawn = (cmd, args, opts) => getExecutor().spawn(cmd, args, opts), kill = (pid, signal) => process.kill(pid, signal), alive = pidExists, readState = readWorkspaceState, verify = verifyCollectorOwnership, waitMs = COLLECTOR_EXIT_WAIT_MS, note = (_line) => {} }) {
|
|
742
|
+
async function replaceCollector({ root, slot = "default", udid, bundleId, appName, appExecutable, physical = false, payloadUrl = null, spawn = (cmd, args, opts) => getExecutor().spawn(cmd, args, opts), kill = (pid, signal) => process.kill(pid, signal), alive = pidExists, readState = readWorkspaceState, verify = verifyCollectorOwnership, waitMs = COLLECTOR_EXIT_WAIT_MS, note = (_line) => {} }) {
|
|
736
743
|
const { killed } = await stopPreviousCollector({
|
|
737
744
|
root,
|
|
745
|
+
slot,
|
|
738
746
|
kill,
|
|
739
747
|
alive,
|
|
740
748
|
readState,
|
|
@@ -753,6 +761,7 @@ async function replaceCollector({ root, udid, bundleId, appName, appExecutable,
|
|
|
753
761
|
"--bundle",
|
|
754
762
|
bundleId
|
|
755
763
|
];
|
|
764
|
+
if (slot !== "default") args.push("--slot", slot);
|
|
756
765
|
if (appName) args.push("--app-name", appName);
|
|
757
766
|
if (appExecutable) args.push("--app-executable", appExecutable);
|
|
758
767
|
if (physical) args.push("--physical");
|
|
@@ -760,7 +769,7 @@ async function replaceCollector({ root, udid, bundleId, appName, appExecutable,
|
|
|
760
769
|
let stdio = "ignore";
|
|
761
770
|
try {
|
|
762
771
|
mkdirSync(workspaceLogsDir(root), { recursive: true });
|
|
763
|
-
const fd = openSync(collectorLogFile(root), "a");
|
|
772
|
+
const fd = openSync(collectorLogFile(root, slot), "a");
|
|
764
773
|
stdio = [
|
|
765
774
|
"ignore",
|
|
766
775
|
fd,
|
|
@@ -791,6 +800,7 @@ async function replaceCollector({ root, udid, bundleId, appName, appExecutable,
|
|
|
791
800
|
//#endregion
|
|
792
801
|
//#region src/commands/ios/dependencies.ts
|
|
793
802
|
const DEFAULT_DEPS = {
|
|
803
|
+
resolveEasDevelopmentBuild,
|
|
794
804
|
findProjectRoot,
|
|
795
805
|
resolveSettings,
|
|
796
806
|
gitCommonDir,
|
|
@@ -812,6 +822,7 @@ const DEFAULT_DEPS = {
|
|
|
812
822
|
detectProviders,
|
|
813
823
|
resolveProjectMetro,
|
|
814
824
|
resolveMetroWithRetry,
|
|
825
|
+
warmMetro,
|
|
815
826
|
readWorkspaceState,
|
|
816
827
|
pidExists,
|
|
817
828
|
getConcurrencyLimits,
|
|
@@ -889,9 +900,10 @@ function lastBuildRecord({ fingerprint = null, cacheKey = null, cacheHit = false
|
|
|
889
900
|
if (errorCode) record.errorCode = errorCode;
|
|
890
901
|
return record;
|
|
891
902
|
}
|
|
892
|
-
function iosFacts({ udid, deviceName, deviceType = null, runtime = null, fingerprint, configuration = null, scheme = null, cacheKey, cacheHit, cacheSkipped = false, compilationCache = COMPILATION_CACHE_NOT_RUN, waitedForBuild = null, appPath, bundleId, installSkipped = false, metroPort, logsDir, durationMs, launched = true, webPreviewUrl = null, lease }) {
|
|
903
|
+
function iosFacts({ slot, udid, deviceName, deviceType = null, runtime = null, fingerprint, configuration = null, scheme = null, cacheKey, cacheHit, cacheSkipped = false, compilationCache = COMPILATION_CACHE_NOT_RUN, waitedForBuild = null, appPath, bundleId, installSkipped = false, metroPort, logsDir, durationMs, launched = true, webPreviewUrl = null, lease }) {
|
|
893
904
|
return {
|
|
894
905
|
platform: "ios",
|
|
906
|
+
...slot && slot !== "default" ? { slot } : {},
|
|
895
907
|
udid,
|
|
896
908
|
deviceName: deviceName ?? null,
|
|
897
909
|
deviceType: deviceType ?? null,
|
|
@@ -941,7 +953,7 @@ async function finishIosUpload(uploadPending, remote, phase, note) {
|
|
|
941
953
|
}
|
|
942
954
|
return false;
|
|
943
955
|
}
|
|
944
|
-
function reportIosResult({ d, root, json, release, configuration, buildScheme = null, metroCheck, metroPort, logsDir, device, udid, appPath, bundleId, installSkipped, elapsed, startedAt, storeHash, storeKey, cacheHit, compilationCache, useBuildCache, waitedForBuild, launchState, launchWarning, remote, providerName, closeWriter, webPreviewUrl, lease, recordRun }) {
|
|
956
|
+
function reportIosResult({ slot, d, root, json, release, configuration, buildScheme = null, metroCheck, metroPort, logsDir, device, udid, appPath, bundleId, installSkipped, elapsed, startedAt, storeHash, storeKey, cacheHit, compilationCache, useBuildCache, waitedForBuild, launchState, launchWarning, remote, providerName, closeWriter, webPreviewUrl, lease, recordRun }) {
|
|
945
957
|
const durationMs = elapsed();
|
|
946
958
|
recordRun({
|
|
947
959
|
failed: false,
|
|
@@ -962,6 +974,7 @@ function reportIosResult({ d, root, json, release, configuration, buildScheme =
|
|
|
962
974
|
}), { write: d.writeWorkspaceState });
|
|
963
975
|
closeWriter();
|
|
964
976
|
const facts = iosFacts({
|
|
977
|
+
slot,
|
|
965
978
|
udid,
|
|
966
979
|
deviceName: device?.deviceName ?? null,
|
|
967
980
|
deviceType: device?.deviceType,
|
|
@@ -1014,9 +1027,14 @@ function cacheDescription(cacheHit, providerName = null) {
|
|
|
1014
1027
|
function missingCrashReportHint({ physical, remote, crashed }) {
|
|
1015
1028
|
return crashed && !physical && !remote ? `No attributable native crash report captured yet. ${IOS_CRASH_REPORT_RETRY}` : "No attributable native crash report captured. Read `stim logs --source device` for available output.";
|
|
1016
1029
|
}
|
|
1017
|
-
async function verifyIosRun({ root, appPath, d, release, launched, configuration, phase, note, metroCheck, logsDir, launchedAt, metroPort, isExpo, bundleId, udid, scheme, physical, appName, lanAddress, lanOrigin, remoteDevice, metroOrigin }) {
|
|
1030
|
+
async function verifyIosRun({ root, slot, appPath, d, release, launched, configuration, phase, note, metroCheck, logsDir, launchedAt, metroPort, isExpo, bundleId, udid, scheme, physical, appName, lanAddress, lanOrigin, remoteDevice, metroOrigin }) {
|
|
1031
|
+
const runCommand = nativeRunCommand("ios", slot, {
|
|
1032
|
+
physical,
|
|
1033
|
+
deviceId: udid
|
|
1034
|
+
});
|
|
1018
1035
|
const readNativeCrashes = () => remoteDevice ? [] : captureNativeCrashes({
|
|
1019
1036
|
root,
|
|
1037
|
+
slot,
|
|
1020
1038
|
platform: "ios",
|
|
1021
1039
|
deviceId: udid,
|
|
1022
1040
|
appId: bundleId,
|
|
@@ -1052,6 +1070,8 @@ async function verifyIosRun({ root, appPath, d, release, launched, configuration
|
|
|
1052
1070
|
return { state: crashes.length || processCheck?.reason === "exited" ? LAUNCH_FATAL : LAUNCH_UNVERIFIED };
|
|
1053
1071
|
}
|
|
1054
1072
|
const verification = metroCheck ? await d.verifyLaunch({
|
|
1073
|
+
requireBundleResponse: true,
|
|
1074
|
+
slot: launchSlotScope(root, slot),
|
|
1055
1075
|
onReadinessPending: () => phase("readiness", "waiting for app readiness (up to 30s after bundle load)"),
|
|
1056
1076
|
logsDir,
|
|
1057
1077
|
since: launchedAt,
|
|
@@ -1088,10 +1108,10 @@ async function verifyIosRun({ root, appPath, d, release, launched, configuration
|
|
|
1088
1108
|
remote: Boolean(remoteDevice),
|
|
1089
1109
|
crashed: true
|
|
1090
1110
|
})));
|
|
1091
|
-
if (nativeFatal || verification.processAlive === false) note(chalk.yellow(phaseLine("remedy",
|
|
1111
|
+
if (nativeFatal || verification.processAlive === false) note(chalk.yellow(phaseLine("remedy", `Fix the crash, then run \`${runCommand}\` again. A Metro reload cannot restart an exited app.`)));
|
|
1092
1112
|
else if (verification.processAlive === true && metroPort !== null) {
|
|
1093
1113
|
const reloadRemedy = `press Reload on the app's own error screen -- run \`agent-device snapshot -i --platform ios --udid ${udid}\` in your existing automation session to reach it. Neither \`stim reload ios\` nor \`agent-device metro reload\` can: this app never connected to Metro.`;
|
|
1094
|
-
note(chalk.yellow(phaseLine("remedy", `The native app is still running. ${deliveryFailed ? "Check the Metro logs and device connection, then" : "Fix the JavaScript or TypeScript error, then"} ${reloadRemedy} Do not run \`
|
|
1114
|
+
note(chalk.yellow(phaseLine("remedy", `The native app is still running. ${deliveryFailed ? "Check the Metro logs and device connection, then" : "Fix the JavaScript or TypeScript error, then"} ${reloadRemedy} Do not run \`${runCommand}\` unless native inputs changed or the app process exits.`)));
|
|
1095
1115
|
}
|
|
1096
1116
|
return { state: LAUNCH_FATAL };
|
|
1097
1117
|
}
|
|
@@ -1100,7 +1120,7 @@ async function verifyIosRun({ root, appPath, d, release, launched, configuration
|
|
|
1100
1120
|
const hasAppErrors = reportLaunchErrors(verification.errors ?? [], note, root);
|
|
1101
1121
|
if (hasAppErrors && verification.processAlive === true && metroPort !== null) {
|
|
1102
1122
|
const reloadRemedy = physical || remoteDevice ? `run \`agent-device metro reload --metro-port ${metroPort}\`.` : "run `stim reload ios`.";
|
|
1103
|
-
note(chalk.yellow(phaseLine("remedy", `The native app is still running. Fix the JavaScript or TypeScript error; Fast Refresh should apply the edit. If the error screen remains, ${reloadRemedy} Do not run \`
|
|
1123
|
+
note(chalk.yellow(phaseLine("remedy", `The native app is still running. Fix the JavaScript or TypeScript error; Fast Refresh should apply the edit. If the error screen remains, ${reloadRemedy} Do not run \`${runCommand}\` unless native inputs changed or the app process exits.`)));
|
|
1104
1124
|
}
|
|
1105
1125
|
return {
|
|
1106
1126
|
state: true,
|
|
@@ -1144,14 +1164,14 @@ function reportLaunchErrors(errors, note, root) {
|
|
|
1144
1164
|
for (const line of report.lines) note(chalk.yellow(phaseLine("launch", line)));
|
|
1145
1165
|
return report.lines.length > 0;
|
|
1146
1166
|
}
|
|
1147
|
-
function cleanAdoptedIosApps({ d, root, udid, bundleId, phase, note }) {
|
|
1167
|
+
function cleanAdoptedIosApps({ d, root, slot, udid, bundleId, phase, note }) {
|
|
1148
1168
|
const swept = d.clearOtherUserApps({
|
|
1149
1169
|
udid,
|
|
1150
1170
|
keep: bundleId
|
|
1151
1171
|
});
|
|
1152
1172
|
if (swept.removed.length) phase("install", `removed ${swept.removed.join(", ")}, left by the previous workspace`);
|
|
1153
1173
|
if (swept.listed && swept.failed.length === 0) {
|
|
1154
|
-
d.clearIosAdoptionPending(root);
|
|
1174
|
+
d.clearIosAdoptionPending(root, slot);
|
|
1155
1175
|
return null;
|
|
1156
1176
|
}
|
|
1157
1177
|
if (!swept.listed) return "Could not list apps left by the previous workspace.";
|
|
@@ -1190,7 +1210,14 @@ function recordIosReloadTarget({ d, root, physical, remoteDevice, bundleId, udid
|
|
|
1190
1210
|
note(chalk.yellow(phaseLine("state", `could not record iOS launch: ${error?.message || error}`)));
|
|
1191
1211
|
}
|
|
1192
1212
|
}
|
|
1193
|
-
|
|
1213
|
+
function simulatorLaunchFailureRemedy(remote, udid, bundleId, logFile) {
|
|
1214
|
+
return `${remote ? "Run" : "If the simulator timed out, run `stim doctor --platform ios` and resolve any reported host memory pressure before retrying. Otherwise run"} \`xcrun simctl launch --console ${udid} ${bundleId}\` to see what the app reports, and check ${logFile}.`;
|
|
1215
|
+
}
|
|
1216
|
+
async function finishIosRun({ d, root, slot, json, release, configuration, buildScheme, isExpo, metroCheck, metroPort, logsDir, logFile, device, udid, physical, lanAddress, lanOriginUrl, remoteDevice, bootPromise, bootDuration, appPath, bundleId: initialBundleId, swapDir, buildFailure, fail, phase, note, logWriter, uploadPending, providerUpload, providerName, remote, abandonedRemote: remoteWasAbandoned, elapsed, startedAt, storeHash, storeKey, cacheHit, compilationCache, useBuildCache, waitedForBuild, closeWriter, lease, releaseLease, recordRun }) {
|
|
1217
|
+
const runCommand = nativeRunCommand("ios", slot, {
|
|
1218
|
+
physical,
|
|
1219
|
+
deviceId: udid
|
|
1220
|
+
});
|
|
1194
1221
|
let bundleId = initialBundleId;
|
|
1195
1222
|
let leaseWarned = false;
|
|
1196
1223
|
const raiseLeaseFor = (boundMs, beforeInstall) => {
|
|
@@ -1226,7 +1253,7 @@ async function finishIosRun({ d, root, json, release, configuration, buildScheme
|
|
|
1226
1253
|
if (!booted?.ok) return fail({
|
|
1227
1254
|
code: booted?.code || "STIM_NO_DEVICE",
|
|
1228
1255
|
message: booted?.reason || "The owned simulator could not be booted.",
|
|
1229
|
-
remedy: booted?.remedy ||
|
|
1256
|
+
remedy: booted?.remedy || `Run \`${runCommand}\` again to re-establish an owned simulator for this workspace.`
|
|
1230
1257
|
});
|
|
1231
1258
|
const deviceOutcome = physical ? "connected" : `${device?.adopted ? "adopted" : "booted"} ${bootDuration()}`;
|
|
1232
1259
|
phase("device", `${deviceLabel(device, udid)} ${deviceOutcome}`);
|
|
@@ -1293,6 +1320,7 @@ async function finishIosRun({ d, root, json, release, configuration, buildScheme
|
|
|
1293
1320
|
});
|
|
1294
1321
|
const collector = await d.replaceCollector({
|
|
1295
1322
|
root,
|
|
1323
|
+
slot,
|
|
1296
1324
|
udid,
|
|
1297
1325
|
bundleId,
|
|
1298
1326
|
appName,
|
|
@@ -1315,7 +1343,7 @@ async function finishIosRun({ d, root, json, release, configuration, buildScheme
|
|
|
1315
1343
|
bundleId,
|
|
1316
1344
|
appName: appName ?? bundleId,
|
|
1317
1345
|
collectorPid: collector.pid,
|
|
1318
|
-
readRecords: () => readCollectorRecords(logsDir).filter((entry) => Number(entry.ts) >= launchedAt)
|
|
1346
|
+
readRecords: () => readCollectorRecords(logsDir).filter((entry) => Number(entry.ts) >= launchedAt && (entry.slot ?? "default") === (slot ?? "default"))
|
|
1319
1347
|
});
|
|
1320
1348
|
if (started.failed || !started.pid) return fail({
|
|
1321
1349
|
code: "STIM_LAUNCH_FAILED",
|
|
@@ -1351,7 +1379,7 @@ async function finishIosRun({ d, root, json, release, configuration, buildScheme
|
|
|
1351
1379
|
if (cleanupFailure) return fail({
|
|
1352
1380
|
code: "STIM_INSTALL_FAILED",
|
|
1353
1381
|
message: `${cleanupFailure} Stim kept the adoption cleanup pending and did not install or launch the app.`,
|
|
1354
|
-
remedy:
|
|
1382
|
+
remedy: `Run \`${runCommand}\` again after simulator tooling is responsive.`,
|
|
1355
1383
|
build: {
|
|
1356
1384
|
...buildFailure,
|
|
1357
1385
|
appPath,
|
|
@@ -1384,6 +1412,7 @@ async function finishIosRun({ d, root, json, release, configuration, buildScheme
|
|
|
1384
1412
|
dropSwapDir();
|
|
1385
1413
|
if (!remoteDevice) await d.replaceCollector({
|
|
1386
1414
|
root,
|
|
1415
|
+
slot,
|
|
1387
1416
|
udid,
|
|
1388
1417
|
bundleId,
|
|
1389
1418
|
appName,
|
|
@@ -1419,6 +1448,7 @@ async function finishIosRun({ d, root, json, release, configuration, buildScheme
|
|
|
1419
1448
|
if (launched?.failed) {
|
|
1420
1449
|
printNativeCrashReport({
|
|
1421
1450
|
root,
|
|
1451
|
+
slot,
|
|
1422
1452
|
platform: "ios",
|
|
1423
1453
|
deviceId: udid,
|
|
1424
1454
|
appId: bundleId,
|
|
@@ -1428,7 +1458,7 @@ async function finishIosRun({ d, root, json, release, configuration, buildScheme
|
|
|
1428
1458
|
return fail({
|
|
1429
1459
|
code: launched.code || "STIM_LAUNCH_FAILED",
|
|
1430
1460
|
message: launched.reason,
|
|
1431
|
-
remedy:
|
|
1461
|
+
remedy: simulatorLaunchFailureRemedy(Boolean(remoteDevice), udid, bundleId, logFile),
|
|
1432
1462
|
build: {
|
|
1433
1463
|
...buildFailure,
|
|
1434
1464
|
appPath,
|
|
@@ -1441,6 +1471,7 @@ async function finishIosRun({ d, root, json, release, configuration, buildScheme
|
|
|
1441
1471
|
recordIosReloadTarget({
|
|
1442
1472
|
d,
|
|
1443
1473
|
root,
|
|
1474
|
+
slot,
|
|
1444
1475
|
physical,
|
|
1445
1476
|
remoteDevice: Boolean(remoteDevice),
|
|
1446
1477
|
bundleId,
|
|
@@ -1458,6 +1489,7 @@ async function finishIosRun({ d, root, json, release, configuration, buildScheme
|
|
|
1458
1489
|
});
|
|
1459
1490
|
if (remoteDevice) await d.replaceCollector({
|
|
1460
1491
|
root,
|
|
1492
|
+
slot,
|
|
1461
1493
|
udid,
|
|
1462
1494
|
bundleId,
|
|
1463
1495
|
appName,
|
|
@@ -1467,6 +1499,7 @@ async function finishIosRun({ d, root, json, release, configuration, buildScheme
|
|
|
1467
1499
|
if (physical) raiseLeaseFor(release ? RELEASE_VERIFY_WAIT_MS : DEBUG_VERIFY_STEP_MS, false);
|
|
1468
1500
|
const { state: launchState, warning: launchWarning } = await verifyIosRun({
|
|
1469
1501
|
root,
|
|
1502
|
+
slot,
|
|
1470
1503
|
appPath,
|
|
1471
1504
|
d,
|
|
1472
1505
|
release,
|
|
@@ -1518,6 +1551,7 @@ async function finishIosRun({ d, root, json, release, configuration, buildScheme
|
|
|
1518
1551
|
const facts = reportIosResult({
|
|
1519
1552
|
d,
|
|
1520
1553
|
root,
|
|
1554
|
+
slot,
|
|
1521
1555
|
json,
|
|
1522
1556
|
release,
|
|
1523
1557
|
configuration,
|
|
@@ -1565,14 +1599,20 @@ function iosCommand(program) {
|
|
|
1565
1599
|
registerIos(program);
|
|
1566
1600
|
}
|
|
1567
1601
|
function registerIos(program, deps = {}) {
|
|
1568
|
-
program.command("ios").description("Build (or restore from the fingerprint cache), install and launch this workspace's app on its owned simulator, wired to the reserved Metro port. Requires a running dev server (`stim start`).").option("--json", "Emit the facts as a single JSON line on stdout; every other line goes to stderr").option("--scheme <name>", "Shared Xcode app scheme to build; overrides automatic scheme selection, not the app URL scheme").option("--no-metro-check", "Skip the \"is this workspace's dev server running?\" gate and build anyway").option("--no-build-cache", "Build fresh, ignoring cached artifacts (local and the project's build-cache provider); the fresh build still replaces the cache entry").option("--configuration <name>", "Xcode configuration to build (e.g. Release). A non-Debug configuration embeds the JS bundle and skips Metro entirely. Overrides the ios.configuration setting. Default: Debug").option("--device-type <name>", "Simulator model to create this workspace's owned sim as, exactly as `xcrun simctl list devicetypes` names it (e.g. \"iPad Pro 13-inch (M4)\"). Overrides the ios.deviceType setting for this invocation. A model no installed runtime can create refuses with STIM_BAD_ARG and prints the models they do offer.").option("--runtime <version>", "Simulator runtime to create this workspace's owned sim on, as a version (\"18.5\") or a runtime's full name (\"iOS 18.5\"); nothing else matches. Overrides the ios.runtime setting for this invocation. An unknown version refuses with STIM_BAD_ARG and prints the installed runtimes.").option("--device [udid]", "Build the iphoneos slice for a connected iPhone, install it, and launch it, instead of using this workspace's owned simulator. With no UDID, the first connected device this workspace can lease is used. In Debug the app is wired to this workspace's Metro over the LAN. Stim never creates, boots, or deletes a physical device.").option("--remote <backend>", "Install and launch on a remote device with proxy or EAS.
|
|
1602
|
+
program.command("ios").description("Build (or restore from the fingerprint cache), install and launch this workspace's app on its owned simulator, wired to the reserved Metro port. Requires a running dev server (`stim start`).").option("--eas-profile <name>", "Download a matching EAS development build; on a miss, print the build command without running it").option("--slot <name>", "Reusable device slot within this workspace (default: default)", validateDeviceSlot).option("--json", "Emit the facts as a single JSON line on stdout; every other line goes to stderr").option("--scheme <name>", "Shared Xcode app scheme to build; overrides automatic scheme selection, not the app URL scheme").option("--no-metro-check", "Skip the \"is this workspace's dev server running?\" gate and build anyway").option("--no-build-cache", "Build fresh, ignoring cached artifacts (local and the project's build-cache provider); the fresh build still replaces the cache entry").option("--configuration <name>", "Xcode configuration to build (e.g. Release). A non-Debug configuration embeds the JS bundle and skips Metro entirely. Overrides the ios.configuration setting. Default: Debug").option("--device-type <name>", "Simulator model to create this workspace's owned sim as, exactly as `xcrun simctl list devicetypes` names it (e.g. \"iPad Pro 13-inch (M4)\"). Overrides the ios.deviceType setting for this invocation. A model no installed runtime can create refuses with STIM_BAD_ARG and prints the models they do offer.").option("--runtime <version>", "Simulator runtime to create this workspace's owned sim on, as a version (\"18.5\") or a runtime's full name (\"iOS 18.5\"); nothing else matches. Overrides the ios.runtime setting for this invocation. An unknown version refuses with STIM_BAD_ARG and prints the installed runtimes.").option("--device [udid]", "Build the iphoneos slice for a connected iPhone, install it, and launch it, instead of using this workspace's owned simulator. With no UDID, the first connected device this workspace can lease is used. In Debug the app is wired to this workspace's Metro over the LAN. Stim never creates, boots, or deletes a physical device.").option("--remote <backend>", "Install and launch on a remote device with proxy or EAS. Builds are local unless --eas-profile selects an existing EAS build.", (value) => {
|
|
1569
1603
|
if (REMOTE_DEVICE_BACKENDS.includes(value)) return value;
|
|
1570
1604
|
throw new InvalidArgumentError(`expected one of: ${REMOTE_DEVICE_BACKENDS.join(", ")}`);
|
|
1571
1605
|
}).option("--wait <seconds>", "How long to wait for another workspace to release the phone it leases, before refusing with STIM_DEVICE_BUSY (default 60, 0 refuses at once). Only with --device.").option("--no-wait", "Install on a phone another workspace leases instead of waiting: this run takes no lease and, when both workspaces build the same app id, the install terminates the holder's running app. Only with --device.").action(async (opts) => {
|
|
1572
|
-
|
|
1606
|
+
const root = (deps.findProjectRoot ?? DEFAULT_DEPS.findProjectRoot)(process.cwd());
|
|
1607
|
+
const run = () => runIos({
|
|
1573
1608
|
...opts,
|
|
1574
1609
|
waitConflict: waitFlagConflict(process.argv)
|
|
1575
1610
|
}, deps);
|
|
1611
|
+
if (!root) await run();
|
|
1612
|
+
else await withWorkspaceProcessLock(workspaceDir(root), "native-run", run, {
|
|
1613
|
+
external: true,
|
|
1614
|
+
waitMs: 18e5
|
|
1615
|
+
});
|
|
1576
1616
|
});
|
|
1577
1617
|
}
|
|
1578
1618
|
function explicitSchemeRefusal(root, scheme, isExpo, d) {
|
|
@@ -1587,11 +1627,58 @@ function explicitSchemeRefusal(root, scheme, isExpo, d) {
|
|
|
1587
1627
|
if (project.error) return project.error;
|
|
1588
1628
|
return d.resolveScheme(project, { scheme }).error ?? null;
|
|
1589
1629
|
}
|
|
1630
|
+
function iosSlotLogFile(root, slot) {
|
|
1631
|
+
return slot === "default" ? buildLogFile(root) : join(workspaceLogsDir(root), `build-${deviceSlotKey("ios", slot)}.ndjson`);
|
|
1632
|
+
}
|
|
1633
|
+
function iosSlotDeps(d, slot) {
|
|
1634
|
+
if (slot !== "default") {
|
|
1635
|
+
const base = d;
|
|
1636
|
+
d = {
|
|
1637
|
+
...base,
|
|
1638
|
+
ensureOwnedDevice: (args) => base.ensureOwnedDevice({
|
|
1639
|
+
...args,
|
|
1640
|
+
slot
|
|
1641
|
+
}),
|
|
1642
|
+
checkDeviceCapacity: (args) => base.checkDeviceCapacity({
|
|
1643
|
+
...args,
|
|
1644
|
+
slot
|
|
1645
|
+
}),
|
|
1646
|
+
selectFromPool: (args) => base.selectFromPool({
|
|
1647
|
+
...args,
|
|
1648
|
+
slot
|
|
1649
|
+
}),
|
|
1650
|
+
acquireRunLease: (args) => base.acquireRunLease({
|
|
1651
|
+
...args,
|
|
1652
|
+
slot
|
|
1653
|
+
}),
|
|
1654
|
+
runLease: (args) => base.runLease({
|
|
1655
|
+
...args,
|
|
1656
|
+
slot
|
|
1657
|
+
}),
|
|
1658
|
+
replaceCollector: (args) => base.replaceCollector({
|
|
1659
|
+
...args,
|
|
1660
|
+
slot
|
|
1661
|
+
}),
|
|
1662
|
+
stopPreviousCollector: (args) => base.stopPreviousCollector({
|
|
1663
|
+
...args,
|
|
1664
|
+
slot
|
|
1665
|
+
}),
|
|
1666
|
+
clearIosAdoptionPending: (root) => base.clearIosAdoptionPending(root, slot),
|
|
1667
|
+
writeWorkspaceLaunch: (root, platform, record) => base.writeWorkspaceLaunch(root, platform, record, slot),
|
|
1668
|
+
createWriter: (file, options) => base.createWriter(file, {
|
|
1669
|
+
...options,
|
|
1670
|
+
fields: { slot }
|
|
1671
|
+
})
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
return d;
|
|
1675
|
+
}
|
|
1590
1676
|
async function runIos(opts = {}, overrides = {}) {
|
|
1591
|
-
|
|
1677
|
+
const slot = validateDeviceSlot(opts.slot);
|
|
1678
|
+
let d = iosSlotDeps({
|
|
1592
1679
|
...DEFAULT_DEPS,
|
|
1593
1680
|
...overrides
|
|
1594
|
-
};
|
|
1681
|
+
}, slot);
|
|
1595
1682
|
const json = Boolean(opts.json);
|
|
1596
1683
|
const metroCheck = opts.metroCheck !== false;
|
|
1597
1684
|
let useBuildCache = opts.buildCache !== false;
|
|
@@ -1637,7 +1724,7 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
1637
1724
|
return null;
|
|
1638
1725
|
}
|
|
1639
1726
|
const logsDir = workspaceLogsDir(root);
|
|
1640
|
-
const logFile =
|
|
1727
|
+
const logFile = iosSlotLogFile(root, slot);
|
|
1641
1728
|
let writer = null;
|
|
1642
1729
|
const logWriter = () => writer ||= d.createWriter(logFile, { truncate: true });
|
|
1643
1730
|
let buildLock = null;
|
|
@@ -1776,7 +1863,7 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
1776
1863
|
message: settingError,
|
|
1777
1864
|
remedy: SETTING_SHAPE_REMEDY
|
|
1778
1865
|
});
|
|
1779
|
-
const configuration = resolveConfiguration(opts.configuration, settings);
|
|
1866
|
+
const configuration = opts.easProfile !== void 0 ? null : resolveConfiguration(opts.configuration, settings);
|
|
1780
1867
|
const buildScheme = opts.scheme;
|
|
1781
1868
|
const release = isReleaseConfiguration(configuration);
|
|
1782
1869
|
const cachePolicy = artifactCachePolicy(optimizations, useBuildCache, release);
|
|
@@ -1784,7 +1871,7 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
1784
1871
|
const deviceType = resolveDeviceType(opts.deviceType, settings);
|
|
1785
1872
|
const runtime = resolveRuntime(opts.runtime, settings);
|
|
1786
1873
|
const deviceFlag = opts.device;
|
|
1787
|
-
const physical = deviceFlag
|
|
1874
|
+
const physical = isPhysicalDeviceRequest(deviceFlag);
|
|
1788
1875
|
if (physical && deviceFlag === "") return fail({
|
|
1789
1876
|
code: "STIM_BAD_ARG",
|
|
1790
1877
|
message: "--device was given an empty UDID.",
|
|
@@ -1819,6 +1906,7 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
1819
1906
|
if (schemeRefusal) return fail(schemeRefusal);
|
|
1820
1907
|
const remoteBackend = physical ? null : opts.remote ?? remoteIosSetting(settings);
|
|
1821
1908
|
const modelRefusal = deviceModelRefusal({
|
|
1909
|
+
slot,
|
|
1822
1910
|
deviceTypeFlag: opts.deviceType,
|
|
1823
1911
|
runtimeFlag: opts.runtime,
|
|
1824
1912
|
deviceType,
|
|
@@ -1828,6 +1916,17 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
1828
1916
|
listRuntimes: d.listIosRuntimes
|
|
1829
1917
|
});
|
|
1830
1918
|
if (modelRefusal) return fail(modelRefusal);
|
|
1919
|
+
const easBuild = await d.resolveEasDevelopmentBuild({
|
|
1920
|
+
root,
|
|
1921
|
+
platform: "ios",
|
|
1922
|
+
profile: opts.easProfile,
|
|
1923
|
+
note,
|
|
1924
|
+
isExpo,
|
|
1925
|
+
physical,
|
|
1926
|
+
selectors: [opts.scheme, opts.configuration],
|
|
1927
|
+
buildCache: opts.buildCache
|
|
1928
|
+
});
|
|
1929
|
+
if (isEasBuildFailure(easBuild)) return fail(easBuild);
|
|
1831
1930
|
const registerProject = () => d.upsertProject(root, {
|
|
1832
1931
|
bundleId: d.detectBundleId(root) ?? void 0,
|
|
1833
1932
|
isExpo
|
|
@@ -2032,6 +2131,13 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
2032
2131
|
return false;
|
|
2033
2132
|
}
|
|
2034
2133
|
}
|
|
2134
|
+
if (!release && metroCheck && optimizations.metroWarmup) d.warmMetro({
|
|
2135
|
+
port: metroPort,
|
|
2136
|
+
platform: "ios",
|
|
2137
|
+
isExpo,
|
|
2138
|
+
appId: proj?.bundleId,
|
|
2139
|
+
bundleUrl: metroWarmupUrlSetting(settings, "ios")
|
|
2140
|
+
});
|
|
2035
2141
|
return true;
|
|
2036
2142
|
}
|
|
2037
2143
|
async function resolveLanOrigin() {
|
|
@@ -2100,6 +2206,38 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
2100
2206
|
return result;
|
|
2101
2207
|
});
|
|
2102
2208
|
udid = device.deviceUdid ?? (await bootPromise)?.udid ?? "";
|
|
2209
|
+
if (easBuild?.ok) {
|
|
2210
|
+
fingerprint = storeHash = easBuild.fingerprint;
|
|
2211
|
+
cacheKey = storeKey = easBuild.cacheKey;
|
|
2212
|
+
appPath = easBuild.path;
|
|
2213
|
+
cacheHit = easBuild.cacheHit;
|
|
2214
|
+
providerName = "eas";
|
|
2215
|
+
stats.setCacheKey(cacheKey);
|
|
2216
|
+
if (physical) {
|
|
2217
|
+
const gate = d.gateProfileForDevice({
|
|
2218
|
+
appPath,
|
|
2219
|
+
udid,
|
|
2220
|
+
configuration
|
|
2221
|
+
});
|
|
2222
|
+
if (!gate.ok) {
|
|
2223
|
+
fail({
|
|
2224
|
+
code: gate.code,
|
|
2225
|
+
message: gate.reason,
|
|
2226
|
+
remedy: easDeviceBuildRemedy(opts.easProfile)
|
|
2227
|
+
});
|
|
2228
|
+
return false;
|
|
2229
|
+
}
|
|
2230
|
+
if (!d.devClientScheme(root, appPath)) {
|
|
2231
|
+
fail({
|
|
2232
|
+
code: "STIM_BAD_ARG",
|
|
2233
|
+
message: "The EAS device app has no development-client URL scheme.",
|
|
2234
|
+
remedy: "Install expo-dev-client with npx expo install expo-dev-client, then rebuild the EAS profile and retry."
|
|
2235
|
+
});
|
|
2236
|
+
return false;
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
return true;
|
|
2240
|
+
}
|
|
2103
2241
|
const fingerprintTimer = stepTimer(d.now);
|
|
2104
2242
|
let computedFingerprint;
|
|
2105
2243
|
try {
|
|
@@ -2267,7 +2405,7 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
2267
2405
|
releasedWait = null;
|
|
2268
2406
|
const held = attempt.held;
|
|
2269
2407
|
const who = held.projectRoot || "another workspace";
|
|
2270
|
-
phase("build", `${who} is already building ${shortHash(fingerprint)} (pid ${held.pid})${held.logFile ? ` -- tail ${held.logFile}` : ""}`);
|
|
2408
|
+
phase("build", `${who} is already building ${shortHash(fingerprint)} (pid ${held.pid})${held.logFile ? ` -- tail ${held.logFile}` : ""} -- stim guide lifecycle concurrency`);
|
|
2271
2409
|
let waited = null;
|
|
2272
2410
|
try {
|
|
2273
2411
|
const ceilingMs = WAIT_CEILING_MS - (d.now() - waitStarted);
|
|
@@ -2319,7 +2457,7 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
2319
2457
|
pid: held.pid,
|
|
2320
2458
|
ms: waited.waitedMs
|
|
2321
2459
|
};
|
|
2322
|
-
phase("build", `waited ${formatDuration(waited.waitedMs)} for ${who}'s build -> installed from cache`);
|
|
2460
|
+
phase("build", `waited ${formatDuration(waited.waitedMs)} for ${who}'s build -> installed from cache -- stim guide lifecycle concurrency`);
|
|
2323
2461
|
} else if (waited?.lockReleased) {
|
|
2324
2462
|
failedHolder = void 0;
|
|
2325
2463
|
releasedWait = {
|
|
@@ -2540,7 +2678,7 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
2540
2678
|
phase("cache", `hit ${shortHash(storeHash)} (post-${mutatingSteps.join("/")} key)`);
|
|
2541
2679
|
if (releasedWait) {
|
|
2542
2680
|
waitedForBuild = releasedWait.facts;
|
|
2543
|
-
phase("build", `waited ${formatDuration(waitedForBuild.ms)} for ${releasedWait.who}'s build -> installed from cache`);
|
|
2681
|
+
phase("build", `waited ${formatDuration(waitedForBuild.ms)} for ${releasedWait.who}'s build -> installed from cache -- stim guide lifecycle concurrency`);
|
|
2544
2682
|
}
|
|
2545
2683
|
}
|
|
2546
2684
|
}
|
|
@@ -2623,10 +2761,12 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
2623
2761
|
}
|
|
2624
2762
|
try {
|
|
2625
2763
|
if (!await resolveInitialFingerprint()) return null;
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2764
|
+
if (!easBuild) {
|
|
2765
|
+
await resolveRemoteArtifact();
|
|
2766
|
+
if (!await waitForSharedBuild()) return null;
|
|
2767
|
+
await prepareCachedArtifact();
|
|
2768
|
+
if (!await buildArtifact()) return null;
|
|
2769
|
+
}
|
|
2630
2770
|
if (physicalDevice) {
|
|
2631
2771
|
const acquired = await d.acquireRunLease({
|
|
2632
2772
|
root,
|
|
@@ -2661,6 +2801,7 @@ async function runIos(opts = {}, overrides = {}) {
|
|
|
2661
2801
|
}
|
|
2662
2802
|
try {
|
|
2663
2803
|
return await finishIosRun({
|
|
2804
|
+
slot,
|
|
2664
2805
|
d,
|
|
2665
2806
|
root,
|
|
2666
2807
|
json,
|