stim 1.6.0 → 1.7.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 +1 -1
- package/dist/{android-BkYmndPp.mjs → android-DWssqHQ8.mjs} +165 -661
- package/dist/{android-DLJB8ljN.mjs → android-Da-G_o3n.mjs} +646 -548
- package/dist/{android-BW8i_YxU.mjs → android-DeYdjjBP.mjs} +6 -2
- package/dist/{android-cas-CrzI_Zha.mjs → android-cas-SWIjzeuL.mjs} +54 -18
- package/dist/android-cas-compiler.mjs +1 -1
- package/dist/{app-install--PAocWvq.mjs → app-install-DJg7bVv-.mjs} +36 -10
- package/dist/build-lock-CgtsB6TV.mjs +604 -0
- package/dist/{build-slots-CuPszJDu.mjs → build-slots-C-oAHRT1.mjs} +2 -2
- package/dist/{cache-manifest-uoOKhgUD.mjs → cache-manifest-CYJi8-Hx.mjs} +2 -2
- package/dist/cache-manifest.d.mts +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +14 -14
- package/dist/collector-run.d.mts +2 -0
- package/dist/collector-run.mjs +7 -7
- package/dist/{command-output-BuIb_ZOI.mjs → command-output-B3ycpsYv.mjs} +2 -2
- package/dist/{config-DMP7L7H6.mjs → config-B7iyKWkL.mjs} +56 -16
- package/dist/{dependency-state-CTL8A9p3.mjs → dependency-state-D0M7oKA7.mjs} +2 -2
- package/dist/{deps-C1zGnr61.mjs → deps-oCXVNEqQ.mjs} +6 -6
- package/dist/detached-entry-Bpo6ZY_I.mjs +65 -0
- package/dist/{dev-client-BaTXAAnC.mjs → dev-client-DDUkWgJL.mjs} +12 -12
- package/dist/{device-xoQxw8hR.mjs → device-CBSaC6BU.mjs} +7 -7
- package/dist/{device-XY_5eGdN.mjs → device-CLeDp-KH.mjs} +17 -15
- package/dist/{device-lease-DBW-IL4p.mjs → device-lease-Ffz_M5t0.mjs} +3 -3
- package/dist/{device-pool-C0s_83Og.mjs → device-pool-DNSHL5z8.mjs} +4 -4
- package/dist/{device-remote-D9wN3CdE.mjs → device-remote-BprxZp-m.mjs} +11 -11
- package/dist/{doctor-BRO8UKlK.mjs → doctor-CTAx9gMu.mjs} +90 -46
- package/dist/{error-diagnostics-B5STzxqN.mjs → error-diagnostics-D1Kaf-eT.mjs} +23 -17
- package/dist/{exec-CyylIdq9.mjs → exec-B29XNuhP.mjs} +14 -2
- package/dist/{gc-C-6grAQI.mjs → gc-CX0KRfLG.mjs} +17 -16
- package/dist/{guide-CYtd7xbA.mjs → guide-CPmAG9me.mjs} +38 -15
- package/dist/{guide-status-BF6RsJJp.mjs → guide-status-Craq9z0t.mjs} +3 -3
- package/dist/{ios-Ccm6c8Hj.mjs → ios-BRXYSxSc.mjs} +34 -37
- package/dist/{ios-device-DJOi9FR5.mjs → ios-device-CDbvn5H2.mjs} +2 -2
- package/dist/{ios-device-D3pzTKQE.mjs → ios-device-CFXA46ez.mjs} +1 -1
- package/dist/{ios-Deh5js5V.mjs → ios-lEJ5pKsq.mjs} +3 -3
- package/dist/{logs-D4Poojxy.mjs → logs-CakdBTtm.mjs} +6 -6
- package/dist/{logs-query-Cdp5aaCH.mjs → logs-query-BGL-Pl12.mjs} +1 -1
- package/dist/metro-C7bcJ0uo.mjs +233 -0
- package/dist/{named-ports-DH9SXd0f.mjs → named-ports-DzMOlmaX.mjs} +57 -42
- package/dist/{ownership-CD_XnpDu.mjs → ownership-Cp52QAK1.mjs} +3 -3
- package/dist/{ownership-CVY9cqCr.mjs → ownership-D5vkdm8H.mjs} +13 -13
- package/dist/{ports-A6uTJSPj.mjs → ports-BIbJaKNW.mjs} +3 -3
- package/dist/{process-output-C7IlIzd7.mjs → process-output-Dl5uKE03.mjs} +1 -1
- package/dist/{project-B_SDt4ip.mjs → project-DDZWf_16.mjs} +3 -3
- package/dist/{reclaim-WXTbXPX4.mjs → reclaim-D614jI6_.mjs} +11 -11
- package/dist/{reload-xlQvHKfN.mjs → reload-ChW46VDb.mjs} +9 -9
- package/dist/{server-bare-CCLb90FS.mjs → server-bare-BQkyxa_b.mjs} +1 -1
- package/dist/{server-expo-CX-zkgWl.mjs → server-expo-BVAA1OqJ.mjs} +23 -11
- package/dist/server-expo-YDDG3eP7.mjs +2 -0
- package/dist/{settings-CGHTt5vb.mjs → settings-BXXorVM2.mjs} +3 -3
- package/dist/{slot-launch-BYjnljAs.mjs → slot-launch-DbLvyrup.mjs} +4 -4
- package/dist/{start-DHYAyGzm.mjs → start-TTVILlUi.mjs} +111 -38
- package/dist/{state-CnWzvCWP.mjs → state-DZobzxLW.mjs} +2 -2
- package/dist/{stats-Fo9ACIv7.mjs → stats-BYcZ6n1h.mjs} +1 -1
- package/dist/{stats-DHrO0frH.mjs → stats-CLg5RuDS.mjs} +4 -4
- package/dist/{status-QeLZb8SM.mjs → status-DUNy_HZs.mjs} +14 -15
- package/dist/{stop-CHTaw65F.mjs → stop-CnUpnFT5.mjs} +2 -2
- package/dist/{stop-DsdOx9Hj.mjs → stop-ZrfODZ51.mjs} +13 -13
- package/dist/supervisor-run.mjs +7 -5
- package/dist/{teardown-sm1FwF6V.mjs → teardown-5J5UXz2P.mjs} +14 -17
- package/dist/{workspace-process-lock-Bz19_R9R.mjs → workspace-process-lock-BYfZz_S-.mjs} +1 -1
- package/dist/{workspace-state-WVwWw_hB.mjs → workspace-state-BT5E3SA2.mjs} +3 -3
- package/dist/{worktree-CCNPg_f0.mjs → worktree-BfE4lzHK.mjs} +21 -16
- package/dist/{worktree-DJnBbQZ9.mjs → worktree-FG_ZKKdb.mjs} +13 -9
- package/dist/{xcode-DUF7jrXj.mjs → xcode-B6YaWeg0.mjs} +8 -8
- package/package.json +12 -8
- package/shim/android-optimizations.gradle +6 -0
- package/dist/metro-ato6ef3J.mjs +0 -99
- package/dist/ports-BZprTJRa.mjs +0 -90
- package/dist/server-expo-CjeTJ273.mjs +0 -2
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { C as withConfigLock, E as ownership_claim_exports,
|
|
1
|
+
import { t as getExecutor } from "./exec-B29XNuhP.mjs";
|
|
2
|
+
import { C as withConfigLock, E as ownership_claim_exports, I as deviceSlotPlatforms, N as assignSlotDevice, R as projectDeviceSlots, T as acquireAvdClaim, d as getConfigPath, g as loadConfig, s as ensureConfig, u as getConfigDir, y as saveConfig, z as removeSlotDevice } from "./config-B7iyKWkL.mjs";
|
|
3
3
|
import { r as createNdjsonWriter } from "./ndjson-BZwI1NBv.mjs";
|
|
4
|
-
import { _ as workspaceLogsDir } from "./workspace-state-
|
|
5
|
-
import { l as resolvePackageJson } from "./project-
|
|
6
|
-
import { n as stripAnsi } from "./process-output-
|
|
7
|
-
import { l as
|
|
8
|
-
import {
|
|
9
|
-
import { n as expoBinFromPackage, r as expoBinPath, s as findBinUpward } from "./server-expo-
|
|
10
|
-
import { C as shutdownIosSim, _ as renameIosSim, a as deleteIosSim, d as listIosDeviceTypes, g as parseRuntimeVersion, h as parkedSimName, o as deleteParkedIosSim, r as clearAppDataContainer, s as findAppDataContainer, x as resolveOwnedIosSim } from "./ios-
|
|
4
|
+
import { _ as workspaceLogsDir } from "./workspace-state-BT5E3SA2.mjs";
|
|
5
|
+
import { l as resolvePackageJson } from "./project-DDZWf_16.mjs";
|
|
6
|
+
import { n as stripAnsi } from "./process-output-Dl5uKE03.mjs";
|
|
7
|
+
import { I as resolveOwnedAvdSerial, O as ownedAvdDirectory, R as shutdownAndroidEmulator, T as listOrphanedAvdDirectories, c as assertOwnedAvdStopped, d as avdStorageRoots, h as deleteAvd, j as ownedAvdSystemImage, k as ownedAvdMatchesConfiguration, l as avdPathExists, z as waitForAndroidEmulatorShutdown } from "./android-DWssqHQ8.mjs";
|
|
8
|
+
import { l as phaseLine } from "./command-output-B3ycpsYv.mjs";
|
|
9
|
+
import { n as expoBinFromPackage, r as expoBinPath, s as findBinUpward } from "./server-expo-BVAA1OqJ.mjs";
|
|
10
|
+
import { C as shutdownIosSim, _ as renameIosSim, a as deleteIosSim, d as listIosDeviceTypes, g as parseRuntimeVersion, h as parkedSimName, o as deleteParkedIosSim, r as clearAppDataContainer, s as findAppDataContainer, x as resolveOwnedIosSim } from "./ios-lEJ5pKsq.mjs";
|
|
11
11
|
import { createRequire } from "node:module";
|
|
12
12
|
import { existsSync, lstatSync, readFileSync, renameSync, rmSync } from "node:fs";
|
|
13
13
|
import { randomUUID } from "node:crypto";
|
|
@@ -202,7 +202,7 @@ function easAuthNote(status) {
|
|
|
202
202
|
if (code === "wrong-account") return `eas is authenticated as ${account}, and this project's owner is ${owner} -- run \`eas login\` as a member of ${owner} (or set EXPO_TOKEN); consulting the EAS cache anyway`;
|
|
203
203
|
return null;
|
|
204
204
|
}
|
|
205
|
-
function resolveEasCliBin(projectRoot, { lookupPath = null
|
|
205
|
+
function resolveEasCliBin(projectRoot, { lookupPath = null } = {}) {
|
|
206
206
|
const fromPackage = expoBinFromPackage(resolvePackageJson(projectRoot, EAS_CLI_PACKAGE), EAS_CLI_BIN);
|
|
207
207
|
if (fromPackage) return {
|
|
208
208
|
file: fromPackage,
|
|
@@ -213,7 +213,7 @@ function resolveEasCliBin(projectRoot, { lookupPath = null, timeoutMs = 5e3 } =
|
|
|
213
213
|
file: shim,
|
|
214
214
|
source: "project"
|
|
215
215
|
};
|
|
216
|
-
const onPath = lookupPath ? lookupPath() : getExecutor().
|
|
216
|
+
const onPath = lookupPath ? lookupPath() : getExecutor().findExecutable(EAS_CLI_BIN);
|
|
217
217
|
const file = (String(onPath || "").split("\n")[0] ?? "").trim();
|
|
218
218
|
return file ? {
|
|
219
219
|
file,
|
|
@@ -720,7 +720,7 @@ function dropParked(platform, udid) {
|
|
|
720
720
|
return removeParkedAfter(platform, udid, () => {}) !== null;
|
|
721
721
|
}
|
|
722
722
|
//#endregion
|
|
723
|
-
//#region src/agent-device-cleanup.ts
|
|
723
|
+
//#region src/devices/agent-device-cleanup.ts
|
|
724
724
|
function parseAgentDeviceSessions(output) {
|
|
725
725
|
const result = JSON.parse(output);
|
|
726
726
|
if (result?.success !== true || !Array.isArray(result.data?.sessions)) throw new Error("agent-device did not return a successful session list");
|
|
@@ -763,10 +763,7 @@ function closeOwnedDeviceSessions(device, stillOwned) {
|
|
|
763
763
|
"stim-teardown-inventory"
|
|
764
764
|
]));
|
|
765
765
|
try {
|
|
766
|
-
if (!exec.
|
|
767
|
-
timeoutMs: 2e3,
|
|
768
|
-
killSignal: "SIGKILL"
|
|
769
|
-
})) return;
|
|
766
|
+
if (!exec.findExecutable("agent-device")) return;
|
|
770
767
|
const sessions = list().filter((session) => session.platform === device.platform && session.id === device.id);
|
|
771
768
|
for (const session of sessions) try {
|
|
772
769
|
if (!list().some((current) => current.name === session.name && current.platform === session.platform && current.id === session.id && current.createdAt === session.createdAt)) continue;
|
|
@@ -791,7 +788,7 @@ function closeOwnedDeviceSessions(device, stillOwned) {
|
|
|
791
788
|
}
|
|
792
789
|
}
|
|
793
790
|
//#endregion
|
|
794
|
-
//#region src/teardown.ts
|
|
791
|
+
//#region src/devices/teardown.ts
|
|
795
792
|
function teardownParkedAvd(avdName) {
|
|
796
793
|
try {
|
|
797
794
|
return removeParkedAfter("android", avdName, () => {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { D as withDirLock, u as getConfigDir } from "./config-
|
|
1
|
+
import { D as withDirLock, u as getConfigDir } from "./config-B7iyKWkL.mjs";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname } from "node:path";
|
|
4
4
|
import { join as join$1, resolve as resolve$1 } from "path";
|
|
5
5
|
import { buildCacheRoot as sharedBuildCache, workspaceId, workspaceName as workspaceName$1, workspaceStateDir as workspaceDir } from "@stim-cli/core";
|
|
6
|
-
//#region src/paths.ts
|
|
6
|
+
//#region src/workspace/paths.ts
|
|
7
7
|
const WORKSPACE_METADATA_FILE_NAME = "workspace.json";
|
|
8
8
|
function workspaceMetadataFile(projectRoot) {
|
|
9
9
|
return join$1(workspaceDir(projectRoot), WORKSPACE_METADATA_FILE_NAME);
|
|
@@ -66,7 +66,7 @@ function sharedCcache() {
|
|
|
66
66
|
return join$1(getConfigDir(), "ccache");
|
|
67
67
|
}
|
|
68
68
|
//#endregion
|
|
69
|
-
//#region src/workspace-state.ts
|
|
69
|
+
//#region src/workspace/workspace-state.ts
|
|
70
70
|
function readWorkspaceState(root) {
|
|
71
71
|
try {
|
|
72
72
|
const parsed = JSON.parse(readFileSync(workspaceStateFile(root), "utf-8"));
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { E as ownership_claim_exports, S as upsertProject, f as getProject, g as loadConfig, h as isPathPrefix, u as getConfigDir, v as removeProject, w as process_identity_exports } from "./config-
|
|
3
|
-
import { S as warmWorktreePaths, _ as resolveFullRef, b as sourceCheckoutOf, c as hasRemote, d as listWorktrees, f as locallyKnownUpstream, h as removeWorktree, i as depsOutOfSync, l as hasUncommittedWork, m as readWorktreeExclude, n as cloneIgnoredEntries, o as dirtyPaths, p as podsOutOfSync, r as deleteBranch, s as gitCommonDir, t as branchExists, u as isPodInstallChurn, x as unpushedCommits, y as restoreFile } from "./worktree-
|
|
4
|
-
import { a as findProjectRoot } from "./project-
|
|
5
|
-
import { l as readRemoteSession, s as readMetroTunnel } from "./state-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { a as POOL_SETTING_REMEDY, l as parkedMaxSetting } from "./teardown-
|
|
9
|
-
import { h as podInstallCommand, n as HEARTBEAT_INTERVAL_MS } from "./xcode-
|
|
10
|
-
import { n as hasInstalledDependencies, r as installedNpmTreeIsValid, t as dependencyState } from "./dependency-state-
|
|
11
|
-
import { c as withManagedTunnelRemovalLock, o as withManagedRemoteWorktreeRemovalLock } from "./ownership-
|
|
12
|
-
import { n as reclaimProject } from "./reclaim-
|
|
13
|
-
import { a as runPodInstall, i as runCaptured, n as podsAreStale, r as readPodState, t as DEPS_ERROR } from "./deps-
|
|
1
|
+
import { t as getExecutor } from "./exec-B29XNuhP.mjs";
|
|
2
|
+
import { E as ownership_claim_exports, S as upsertProject, f as getProject, g as loadConfig, h as isPathPrefix, u as getConfigDir, v as removeProject, w as process_identity_exports } from "./config-B7iyKWkL.mjs";
|
|
3
|
+
import { S as warmWorktreePaths, _ as resolveFullRef, b as sourceCheckoutOf, c as hasRemote, d as listWorktrees, f as locallyKnownUpstream, h as removeWorktree, i as depsOutOfSync, l as hasUncommittedWork, m as readWorktreeExclude, n as cloneIgnoredEntries, o as dirtyPaths, p as podsOutOfSync, r as deleteBranch, s as gitCommonDir, t as branchExists, u as isPodInstallChurn, x as unpushedCommits, y as restoreFile } from "./worktree-FG_ZKKdb.mjs";
|
|
4
|
+
import { a as findProjectRoot } from "./project-DDZWf_16.mjs";
|
|
5
|
+
import { l as readRemoteSession, s as readMetroTunnel } from "./state-DZobzxLW.mjs";
|
|
6
|
+
import { A as resolveSettings, I as unknownSettingKeys, N as settingShapeErrors, a as SETTING_SHAPE_REMEDY } from "./settings-BXXorVM2.mjs";
|
|
7
|
+
import { a as formatElapsed, f as releasedLeaseFact, i as formatDuration, l as phaseLine, m as shortUdid, u as plural } from "./command-output-B3ycpsYv.mjs";
|
|
8
|
+
import { a as POOL_SETTING_REMEDY, l as parkedMaxSetting } from "./teardown-5J5UXz2P.mjs";
|
|
9
|
+
import { h as podInstallCommand, n as HEARTBEAT_INTERVAL_MS } from "./xcode-B6YaWeg0.mjs";
|
|
10
|
+
import { n as hasInstalledDependencies, r as installedNpmTreeIsValid, t as dependencyState } from "./dependency-state-D0M7oKA7.mjs";
|
|
11
|
+
import { c as withManagedTunnelRemovalLock, o as withManagedRemoteWorktreeRemovalLock } from "./ownership-D5vkdm8H.mjs";
|
|
12
|
+
import { n as reclaimProject } from "./reclaim-D614jI6_.mjs";
|
|
13
|
+
import { a as runPodInstall, i as runCaptured, n as podsAreStale, r as readPodState, t as DEPS_ERROR } from "./deps-oCXVNEqQ.mjs";
|
|
14
14
|
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
15
15
|
import { createHash, randomUUID } from "node:crypto";
|
|
16
16
|
import { join, relative } from "node:path";
|
|
@@ -198,7 +198,7 @@ async function withWarmClaim(options, fn) {
|
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
200
|
//#endregion
|
|
201
|
-
//#region src/worktree-refresh.ts
|
|
201
|
+
//#region src/workspace/worktree-refresh.ts
|
|
202
202
|
const DIRTY_PATHS_SHOWN = 5;
|
|
203
203
|
const FETCH_TIMEOUT_MS = 12e4;
|
|
204
204
|
function mainCheckoutRefusal(root, state) {
|
|
@@ -1278,9 +1278,14 @@ async function runRemove(target, opts = {}) {
|
|
|
1278
1278
|
}
|
|
1279
1279
|
restorePodChurn(path, inspection.podChurn);
|
|
1280
1280
|
try {
|
|
1281
|
-
removeWorktree(path, {
|
|
1281
|
+
removeWorktree(path, {
|
|
1282
|
+
from: source.path,
|
|
1283
|
+
force: opts.force
|
|
1284
|
+
});
|
|
1282
1285
|
} catch (error) {
|
|
1283
|
-
|
|
1286
|
+
const message = String(error?.message || error);
|
|
1287
|
+
console.error(chalk.red(`git worktree remove failed: ${message}`));
|
|
1288
|
+
if (process.platform === "win32" && /Permission denied/i.test(message)) console.error(chalk.dim("Another process holds a file or directory inside the worktree. An adb server or emulator started from it keeps its working directory open; `adb kill-server` releases the server, and Sysinternals handle.exe lists other holders."));
|
|
1284
1289
|
console.error(chalk.dim(`The directory and Stim ownership record for ${path} were kept.`));
|
|
1285
1290
|
printRemovalCleanup(result, true);
|
|
1286
1291
|
process.exitCode = 1;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { g as loadConfig, u as getConfigDir } from "./config-
|
|
1
|
+
import { t as getExecutor } from "./exec-B29XNuhP.mjs";
|
|
2
|
+
import { g as loadConfig, u as getConfigDir } from "./config-B7iyKWkL.mjs";
|
|
3
3
|
import { accessSync, chmodSync, constants, lstatSync, mkdirSync, mkdtempSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
|
|
4
4
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { chmodSync as chmodSync$1, existsSync as existsSync$1, lstatSync as lstatSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, utimesSync } from "fs";
|
|
@@ -84,7 +84,7 @@ function removeTemporaryEntry(path) {
|
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
86
|
//#endregion
|
|
87
|
-
//#region src/worktree.ts
|
|
87
|
+
//#region src/workspace/worktree.ts
|
|
88
88
|
const CARRY_SKIP_BASENAMES = /* @__PURE__ */ new Set([
|
|
89
89
|
".DerivedData",
|
|
90
90
|
".DS_Store",
|
|
@@ -93,6 +93,9 @@ const CARRY_SKIP_BASENAMES = /* @__PURE__ */ new Set([
|
|
|
93
93
|
function isCarrySkipped(rel) {
|
|
94
94
|
return /(^|\/)android\/build\/generated\/autolinking(\/|$)/.test(rel) || String(rel).split("/").some((seg) => CARRY_SKIP_BASENAMES.has(seg));
|
|
95
95
|
}
|
|
96
|
+
function nativePath(path) {
|
|
97
|
+
return sep$1 === "/" ? path : path.replaceAll("/", sep$1);
|
|
98
|
+
}
|
|
96
99
|
function gitCommonDir(cwd) {
|
|
97
100
|
const out = getExecutor().runFileQuiet("git", [
|
|
98
101
|
"-C",
|
|
@@ -101,7 +104,7 @@ function gitCommonDir(cwd) {
|
|
|
101
104
|
"--path-format=absolute",
|
|
102
105
|
"--git-common-dir"
|
|
103
106
|
]);
|
|
104
|
-
return out ? out.trim() : null;
|
|
107
|
+
return out ? nativePath(out.trim()) : null;
|
|
105
108
|
}
|
|
106
109
|
function repoRoot(cwd) {
|
|
107
110
|
const out = getExecutor().runFileQuiet("git", [
|
|
@@ -110,7 +113,7 @@ function repoRoot(cwd) {
|
|
|
110
113
|
"rev-parse",
|
|
111
114
|
"--show-toplevel"
|
|
112
115
|
]);
|
|
113
|
-
return out ? out.trim() : null;
|
|
116
|
+
return out ? nativePath(out.trim()) : null;
|
|
114
117
|
}
|
|
115
118
|
function locallyKnownUpstream(projectRoot) {
|
|
116
119
|
try {
|
|
@@ -440,7 +443,7 @@ function isPodInstallChurn(paths) {
|
|
|
440
443
|
if (!paths || paths.length === 0) return false;
|
|
441
444
|
return paths.every((line) => /(?:^|\/)(?:Podfile\.lock|project\.pbxproj)$/.test(line.slice(3).trim()));
|
|
442
445
|
}
|
|
443
|
-
const SAFE_BRANCH_NAME = /^[A-Za-z0-9
|
|
446
|
+
const SAFE_BRANCH_NAME = /^[A-Za-z0-9@._/-]+$/;
|
|
444
447
|
function unpushedCommits(dir) {
|
|
445
448
|
const exec = getExecutor();
|
|
446
449
|
const branch = exec.runFileQuiet("git", [
|
|
@@ -511,10 +514,11 @@ function resolveFullRef(cwd, ref) {
|
|
|
511
514
|
return null;
|
|
512
515
|
}
|
|
513
516
|
}
|
|
514
|
-
function removeWorktree(path, { force = false
|
|
517
|
+
function removeWorktree(path, { from, force = false, platform = process.platform }) {
|
|
515
518
|
const args = [
|
|
519
|
+
...platform === "win32" ? ["-c", "core.longpaths=true"] : [],
|
|
516
520
|
"-C",
|
|
517
|
-
|
|
521
|
+
from,
|
|
518
522
|
"worktree",
|
|
519
523
|
"remove",
|
|
520
524
|
...force ? ["--force"] : [],
|
|
@@ -539,7 +543,7 @@ function parseWorktrees(out) {
|
|
|
539
543
|
let current = {};
|
|
540
544
|
for (const line of out.split("\n")) if (line.startsWith("worktree ")) {
|
|
541
545
|
if (current.path) entries.push(current);
|
|
542
|
-
current = { path: line.slice(9) };
|
|
546
|
+
current = { path: nativePath(line.slice(9)) };
|
|
543
547
|
} else if (line.startsWith("branch ")) current.branch = line.slice(7).replace("refs/heads/", "");
|
|
544
548
|
else if (line === "prunable" || line.startsWith("prunable ")) current.prunable = true;
|
|
545
549
|
else if (line === "bare") current.bare = true;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { r as register } from "./cache-manifest-
|
|
3
|
-
import { d as sharedCompilationCache, m as workspaceDerivedData } from "./workspace-state-
|
|
4
|
-
import { l as resolvePackageJson } from "./project-
|
|
5
|
-
import { t as createLineReader } from "./process-output-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { t as cleanLine } from "./server-expo-
|
|
1
|
+
import { t as getExecutor } from "./exec-B29XNuhP.mjs";
|
|
2
|
+
import { r as register } from "./cache-manifest-CYJi8-Hx.mjs";
|
|
3
|
+
import { d as sharedCompilationCache, m as workspaceDerivedData } from "./workspace-state-BT5E3SA2.mjs";
|
|
4
|
+
import { l as resolvePackageJson } from "./project-DDZWf_16.mjs";
|
|
5
|
+
import { t as createLineReader } from "./process-output-Dl5uKE03.mjs";
|
|
6
|
+
import { U as resolveOptimizations } from "./settings-BXXorVM2.mjs";
|
|
7
|
+
import { a as formatElapsed, l as phaseLine } from "./command-output-B3ycpsYv.mjs";
|
|
8
|
+
import { t as cleanLine } from "./server-expo-BVAA1OqJ.mjs";
|
|
9
9
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
11
|
import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stim",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Stim: fast, isolated React Native environments for coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -42,20 +42,24 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@expo/fingerprint": "^0.20.10",
|
|
45
|
-
"@stim-cli/cache": "^1.
|
|
46
|
-
"@stim-cli/core": "^1.
|
|
47
|
-
"@stim-cli/metro": "^1.
|
|
48
|
-
"chalk": "^
|
|
49
|
-
"commander": "^
|
|
45
|
+
"@stim-cli/cache": "^1.7.0",
|
|
46
|
+
"@stim-cli/core": "^1.7.0",
|
|
47
|
+
"@stim-cli/metro": "^1.7.0",
|
|
48
|
+
"chalk": "^6.0.0",
|
|
49
|
+
"commander": "^15.0.0",
|
|
50
|
+
"cross-spawn": "^7.0.6",
|
|
51
|
+
"which": "^5.0.0",
|
|
50
52
|
"ws": "^8.21.3"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|
|
53
|
-
"@stim-cli/expo-build-cache": "1.
|
|
55
|
+
"@stim-cli/expo-build-cache": "1.7.0",
|
|
56
|
+
"@types/cross-spawn": "^6.0.6",
|
|
57
|
+
"@types/which": "^3.0.4",
|
|
54
58
|
"@types/ws": "^8.18.1",
|
|
55
59
|
"unique-pid": "0.1.1"
|
|
56
60
|
},
|
|
57
61
|
"engines": {
|
|
58
|
-
"node": "
|
|
62
|
+
"node": ">=22.12.0"
|
|
59
63
|
},
|
|
60
64
|
"scripts": {
|
|
61
65
|
"test": "node --test test/*.test.js",
|
|
@@ -7,6 +7,12 @@ gradle.beforeProject { project ->
|
|
|
7
7
|
def profile = System.getenv("STIM_ANDROID_NATIVE_PROFILE")
|
|
8
8
|
def staging = android.externalNativeBuild.cmake.buildStagingDirectory ?: new File(project.projectDir, ".cxx")
|
|
9
9
|
android.externalNativeBuild.cmake.buildStagingDirectory = new File(staging, "stim-" + profile)
|
|
10
|
+
// Windows caps a path at 260 characters and the SDK's ninja is not long-path aware, so the
|
|
11
|
+
// staging directory added above has to buy its room back: CMake replaces the mangled absolute
|
|
12
|
+
// source directory in an over-long object path with a hash of it.
|
|
13
|
+
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
|
|
14
|
+
android.defaultConfig.externalNativeBuild.cmake.arguments.add("-DCMAKE_OBJECT_PATH_MAX=240")
|
|
15
|
+
}
|
|
10
16
|
def configs = [android.defaultConfig] + android.buildTypes.toList() + android.productFlavors.toList()
|
|
11
17
|
def pch = System.getenv("STIM_ANDROID_PCH")
|
|
12
18
|
def ccache = System.getenv("STIM_ANDROID_CCACHE")
|
package/dist/metro-ato6ef3J.mjs
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
-
import { w as process_identity_exports } from "./config-DMP7L7H6.mjs";
|
|
3
|
-
import { r as readWorkspaceState } from "./workspace-state-WVwWw_hB.mjs";
|
|
4
|
-
import { t as isMetroRunning } from "./ports-BZprTJRa.mjs";
|
|
5
|
-
import { readlinkSync, realpathSync } from "fs";
|
|
6
|
-
import { sep } from "path";
|
|
7
|
-
//#region src/metro.ts
|
|
8
|
-
/**
|
|
9
|
-
* True when some process with this pid exists right now. It cannot tell a recycled pid from the
|
|
10
|
-
* process that first held it, so it is only valid for a pid this run spawned and still holds a
|
|
11
|
-
* handle on. For a pid read from a record on disk, decide with `inspectProcessIdentity` on that
|
|
12
|
-
* record's process token, or take an ownership claim (`ownership-claim.ts`): this answer would keep
|
|
13
|
-
* a dead holder's record looking live until some unrelated process exits.
|
|
14
|
-
*/
|
|
15
|
-
function pidExists(pid) {
|
|
16
|
-
if (!Number.isSafeInteger(pid) || pid <= 0) return false;
|
|
17
|
-
try {
|
|
18
|
-
process.kill(pid, 0);
|
|
19
|
-
return true;
|
|
20
|
-
} catch (error) {
|
|
21
|
-
return error.code !== "ESRCH";
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
function parseLsofPids(out) {
|
|
25
|
-
if (!out) return [];
|
|
26
|
-
return String(out).split("\n").map((s) => parseInt(s.trim(), 10)).filter((n) => Number.isFinite(n));
|
|
27
|
-
}
|
|
28
|
-
function parseLsofCwd(out) {
|
|
29
|
-
if (!out) return null;
|
|
30
|
-
const lines = String(out).split("\n");
|
|
31
|
-
const idx = lines.findIndex((l) => l === "fcwd");
|
|
32
|
-
if (idx === -1) return null;
|
|
33
|
-
const nLine = lines.slice(idx + 1).find((l) => l.startsWith("n"));
|
|
34
|
-
return nLine ? nLine.slice(1) : null;
|
|
35
|
-
}
|
|
36
|
-
function processCwd(pid) {
|
|
37
|
-
if (process.platform === "linux") try {
|
|
38
|
-
return readlinkSync(`/proc/${pid}/cwd`);
|
|
39
|
-
} catch {}
|
|
40
|
-
return parseLsofCwd(getExecutor().runQuiet(`lsof -a -p ${pid} -d cwd -Fn`));
|
|
41
|
-
}
|
|
42
|
-
function canonicalPath(path) {
|
|
43
|
-
try {
|
|
44
|
-
return realpathSync(path);
|
|
45
|
-
} catch {
|
|
46
|
-
return path;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
function isInsideProject(cwd, projectPath) {
|
|
50
|
-
if (!cwd || !projectPath) return false;
|
|
51
|
-
const a = canonicalPath(cwd);
|
|
52
|
-
const b = canonicalPath(projectPath);
|
|
53
|
-
return a === b || a.startsWith(b.endsWith(sep) ? b : b + sep);
|
|
54
|
-
}
|
|
55
|
-
const NOT_OURS_UNRESPONSIVE = "unresponsive";
|
|
56
|
-
const NOT_OURS_UNREADABLE_CWD = "unreadable-cwd";
|
|
57
|
-
const NOT_OURS_FOREIGN_CWD = "foreign-cwd";
|
|
58
|
-
async function resolveProjectMetro(port, projectPath, { probe = isMetroRunning } = {}) {
|
|
59
|
-
const pid = parseLsofPids(getExecutor().runQuiet(`lsof -nP -iTCP:${port} -sTCP:LISTEN -t`))[0];
|
|
60
|
-
if (pid === void 0) return { missing: true };
|
|
61
|
-
if (!await probe(port)) return {
|
|
62
|
-
notOurs: `pid ${pid} on port ${port} does not answer Metro's /status`,
|
|
63
|
-
kind: NOT_OURS_UNRESPONSIVE,
|
|
64
|
-
pid
|
|
65
|
-
};
|
|
66
|
-
const cwd = processCwd(pid);
|
|
67
|
-
if (!cwd) return {
|
|
68
|
-
notOurs: `pid ${pid} on port ${port}: working directory could not be read`,
|
|
69
|
-
kind: NOT_OURS_UNREADABLE_CWD,
|
|
70
|
-
pid
|
|
71
|
-
};
|
|
72
|
-
if (!isInsideProject(cwd, projectPath)) return {
|
|
73
|
-
notOurs: `pid ${pid} on port ${port} runs from ${cwd}, outside ${projectPath}`,
|
|
74
|
-
kind: NOT_OURS_FOREIGN_CWD,
|
|
75
|
-
pid
|
|
76
|
-
};
|
|
77
|
-
const supervisor = readWorkspaceState(canonicalPath(projectPath))?.supervisor;
|
|
78
|
-
const owned = supervisor?.port === port && (0, process_identity_exports.inspectProcessIdentity)(supervisor) === "same";
|
|
79
|
-
return { metro: {
|
|
80
|
-
pid,
|
|
81
|
-
leader: owned ? supervisor.pid : pid,
|
|
82
|
-
cwd,
|
|
83
|
-
...owned ? { processToken: supervisor.processToken } : {}
|
|
84
|
-
} };
|
|
85
|
-
}
|
|
86
|
-
function killMetroTree(leader, processToken) {
|
|
87
|
-
if (!leader || leader === process.pid || (0, process_identity_exports.inspectProcessIdentity)({
|
|
88
|
-
pid: leader,
|
|
89
|
-
processToken
|
|
90
|
-
}) !== "same") return false;
|
|
91
|
-
try {
|
|
92
|
-
process.kill(-leader, "SIGTERM");
|
|
93
|
-
return true;
|
|
94
|
-
} catch {
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
//#endregion
|
|
99
|
-
export { resolveProjectMetro as i, killMetroTree as n, pidExists as r, NOT_OURS_FOREIGN_CWD as t };
|
package/dist/ports-BZprTJRa.mjs
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { A as isOnMountedVolume, g as loadConfig, j as listMountedVolumes, n as allMetroPorts, r as claimMetroPort, v as removeProject } from "./config-DMP7L7H6.mjs";
|
|
2
|
-
import { existsSync } from "fs";
|
|
3
|
-
import { request } from "http";
|
|
4
|
-
import { connect } from "net";
|
|
5
|
-
//#region src/ports.ts
|
|
6
|
-
function isMetroRunning(port) {
|
|
7
|
-
return new Promise((resolve) => {
|
|
8
|
-
const req = request({
|
|
9
|
-
hostname: "localhost",
|
|
10
|
-
port,
|
|
11
|
-
path: "/status",
|
|
12
|
-
timeout: 2e3
|
|
13
|
-
}, (res) => {
|
|
14
|
-
let data = "";
|
|
15
|
-
res.on("data", (chunk) => {
|
|
16
|
-
data += chunk;
|
|
17
|
-
});
|
|
18
|
-
res.on("end", () => resolve(data.includes("packager-status:running")));
|
|
19
|
-
});
|
|
20
|
-
req.on("error", () => resolve(false));
|
|
21
|
-
req.on("timeout", () => {
|
|
22
|
-
req.destroy();
|
|
23
|
-
resolve(false);
|
|
24
|
-
});
|
|
25
|
-
req.end();
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
function isPortFree(port, { timeoutMs = 400 } = {}) {
|
|
29
|
-
return new Promise((resolve) => {
|
|
30
|
-
const sock = connect({
|
|
31
|
-
port,
|
|
32
|
-
host: "127.0.0.1"
|
|
33
|
-
});
|
|
34
|
-
const done = (free) => {
|
|
35
|
-
sock.removeAllListeners();
|
|
36
|
-
sock.destroy();
|
|
37
|
-
resolve(free);
|
|
38
|
-
};
|
|
39
|
-
sock.setTimeout(timeoutMs);
|
|
40
|
-
sock.once("connect", () => done(false));
|
|
41
|
-
sock.once("error", () => done(true));
|
|
42
|
-
sock.once("timeout", () => done(false));
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
const FIRST_PORT = 8082;
|
|
46
|
-
async function computeNextPort(isFree = isPortFree) {
|
|
47
|
-
const taken = new Set(allMetroPorts());
|
|
48
|
-
for (let port = FIRST_PORT; port < 8282; port++) {
|
|
49
|
-
if (taken.has(port)) continue;
|
|
50
|
-
if (await isFree(port)) return port;
|
|
51
|
-
}
|
|
52
|
-
throw new Error(`Found no free Metro port between ${FIRST_PORT} and 8281. Free one up, or stop a stale bundler (\`stim status\`, \`stim stop <port>\`).`);
|
|
53
|
-
}
|
|
54
|
-
async function findReclaimablePort(excludeProjectPath, probe = isMetroRunning, { isMounted = isOnMountedVolume, mountedVolumes } = {}) {
|
|
55
|
-
const cfg = loadConfig();
|
|
56
|
-
if (!cfg?.projects) return null;
|
|
57
|
-
const mounted = mountedVolumes || listMountedVolumes();
|
|
58
|
-
const candidates = [];
|
|
59
|
-
for (const [path, proj] of Object.entries(cfg.projects)) {
|
|
60
|
-
if (path === excludeProjectPath) continue;
|
|
61
|
-
if (Object.keys(proj.ports ?? {}).length) continue;
|
|
62
|
-
if (existsSync(path)) continue;
|
|
63
|
-
if (!isMounted(path, mounted)) continue;
|
|
64
|
-
if (typeof proj.metroPort === "number") candidates.push({
|
|
65
|
-
port: proj.metroPort,
|
|
66
|
-
ownerPath: path
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
for (const c of candidates) if (!await probe(c.port)) return c;
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
async function allocatePort(projectPath, probe = isMetroRunning, isFree = isPortFree) {
|
|
73
|
-
const reclaim = await findReclaimablePort(projectPath, probe);
|
|
74
|
-
if (reclaim && await isFree(reclaim.port)) {
|
|
75
|
-
removeProject(reclaim.ownerPath);
|
|
76
|
-
return reclaim.port;
|
|
77
|
-
}
|
|
78
|
-
return computeNextPort(isFree);
|
|
79
|
-
}
|
|
80
|
-
const RESERVE_ATTEMPTS = 5;
|
|
81
|
-
async function reserveMetroPort(projectPath, probe = isMetroRunning, isFree = isPortFree) {
|
|
82
|
-
for (let attempt = 0; attempt < RESERVE_ATTEMPTS; attempt++) {
|
|
83
|
-
const port = await allocatePort(projectPath, probe, isFree);
|
|
84
|
-
const claimed = claimMetroPort(projectPath, port);
|
|
85
|
-
if (claimed !== null) return claimed;
|
|
86
|
-
}
|
|
87
|
-
throw new Error(`Could not reserve a Metro port after ${RESERVE_ATTEMPTS} attempts: another Stim run claimed each one first. Retry.`);
|
|
88
|
-
}
|
|
89
|
-
//#endregion
|
|
90
|
-
export { isPortFree as n, reserveMetroPort as r, isMetroRunning as t };
|