peachsim 0.1.639 → 0.1.641

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/cli/commands/control.ts +33 -1
  2. package/detox/index.ts +31 -11
  3. package/dist-lib/agent-daemon-client.cjs +1 -1
  4. package/dist-lib/agent-events.cjs +1 -1
  5. package/dist-lib/agent-identity.cjs +1 -1
  6. package/dist-lib/agent-sessions.cjs +1 -1
  7. package/dist-lib/attached-projects.cjs +1 -1
  8. package/dist-lib/auth/shared-session.cjs +1 -1
  9. package/dist-lib/backend-origin.cjs +1 -1
  10. package/dist-lib/beta.cjs +1 -1
  11. package/dist-lib/beta.mjs +1 -1
  12. package/dist-lib/bridge-constants.cjs +1 -1
  13. package/dist-lib/bridge-contract-input.cjs +1 -1
  14. package/dist-lib/bridge-contract-input.mjs +1 -1
  15. package/dist-lib/bridge-contract.cjs +1 -1
  16. package/dist-lib/bridge-contract.mjs +1 -1
  17. package/dist-lib/capture-contract.cjs +1 -1
  18. package/dist-lib/capture-contract.mjs +1 -1
  19. package/dist-lib/cli-constants.cjs +1 -1
  20. package/dist-lib/cloud-contract.cjs +1 -1
  21. package/dist-lib/cloud-contract.mjs +1 -1
  22. package/dist-lib/cloud-test-args.cjs +1 -1
  23. package/dist-lib/cloud-test-args.mjs +1 -1
  24. package/dist-lib/cloud.cjs +1 -1
  25. package/dist-lib/cloud.mjs +1 -1
  26. package/dist-lib/config.cjs +1 -1
  27. package/dist-lib/detox/index.cjs +24 -4
  28. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  29. package/dist-lib/home-paths.cjs +1 -1
  30. package/dist-lib/host/bridge-host.cjs +1 -1
  31. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  32. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  33. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  34. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  35. package/dist-lib/host/websocket-proxy.cjs +1 -1
  36. package/dist-lib/index.cjs +1 -1
  37. package/dist-lib/jump-to-source-babel.cjs +1 -1
  38. package/dist-lib/jump-to-source-native.cjs +1 -1
  39. package/dist-lib/kotlin-host.cjs +1 -1
  40. package/dist-lib/menu.cjs +1 -1
  41. package/dist-lib/menu.mjs +1 -1
  42. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  43. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  44. package/dist-lib/metro-production-bundle.cjs +1 -1
  45. package/dist-lib/metro-production-bundle.mjs +1 -1
  46. package/dist-lib/metro.cjs +1 -1
  47. package/dist-lib/native-app-identity.cjs +1 -1
  48. package/dist-lib/native-app-identity.mjs +1 -1
  49. package/dist-lib/profiles.cjs +1 -1
  50. package/dist-lib/public-brand.cjs +1 -1
  51. package/dist-lib/react-native-host-modules.cjs +1 -1
  52. package/dist-lib/react-native-host-modules.mjs +1 -1
  53. package/dist-lib/render-mode.cjs +1 -1
  54. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  55. package/dist-lib/sdk.cjs +1 -1
  56. package/dist-lib/sdk.mjs +1 -1
  57. package/dist-lib/skills.cjs +342 -200
  58. package/dist-lib/swift-compile.cjs +1 -1
  59. package/dist-lib/swift-compile.mjs +1 -1
  60. package/dist-lib/swift-package.cjs +1 -1
  61. package/dist-lib/swift-package.mjs +1 -1
  62. package/dist-lib/swift-submit.cjs +1 -1
  63. package/dist-lib/swift-submit.mjs +1 -1
  64. package/dist-lib/swift.cjs +1 -1
  65. package/dist-lib/vite-swift.cjs +1 -1
  66. package/dist-lib/vite.cjs +1 -1
  67. package/package.json +1 -1
  68. package/src/dot-env.ts +148 -0
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -4854,7 +4854,7 @@ var init_supported_native_packages = __esm({
4854
4854
  "react-native-compressor",
4855
4855
  // seam
4856
4856
  "react-native-config",
4857
- // coverage
4857
+ // seam+coverage
4858
4858
  "react-native-config-reader",
4859
4859
  // seam
4860
4860
  "react-native-contacts",
@@ -5628,7 +5628,7 @@ var init_registry = __esm({
5628
5628
  usage: 2,
5629
5629
  importance: 2,
5630
5630
  estimate: 0.98,
5631
- rationale: "Initial detents, sheet geometry, corner radius, grabber, undimmed range, dismissal, numeric-detent dragging, nearest settling, content interception, larger-detent scrolling, selected geometry and dimming, collapse callbacks and guarded dismissal are implemented. Fit-to-content and non-numeric detent modes and expandsWhenScrolledToEdge are not."
5631
+ rationale: "Initial detents, sheet geometry, corner radius, grabber, undimmed range, dismissal, numeric-detent dragging, nearest settling, content interception, larger-detent scrolling, selected geometry and dimming, collapse callbacks and guarded dismissal are implemented. Fit-to-content and legacy detents, edge-scroll expansion, velocity-driven settling and pointer cancellation are implemented. The remaining native fidelity deductions are the over-drag return spring and sheet-to-scroll handoff beyond the largest detent."
5632
5632
  },
5633
5633
  {
5634
5634
  id: "tabs-freeze-and-overlay",
@@ -5641,7 +5641,7 @@ var init_registry = __esm({
5641
5641
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-screens"],
5642
5642
  note: "screen container, stack, header and search chrome, native tabs, navigation props",
5643
5643
  working: "Screen, ScreenContainer, ScreenStack, enableFreeze/freezeEnabled with delayed React freeze, Android modal/pageSheet push fallback, Android statusBarHidden/statusBarStyle/navigationBarHidden traits, push/pop slide, replaceAnimation push/pop direction, zoom/fade/fade_from_bottom transitions, edge swipe-back, parallax behind-screen, large title collapse, header (back button, inline/large title, custom left/center/right/search bar subviews, native header bar buttons/menus/badges, crossfade), formSheet custom initial detents/corner radius/grabber/undimmed range, numeric-detent dragging and settling, eligible content scrolling, detent callbacks, guarded dismissal and stacked sheets, useHeaderHeight, useTransitionProgress, FullWindowOverlay, SearchBar with stacked and iOS 26 automatic/inline/integrated/integratedCentered/integratedButton toolbar placement, Tabs.Host/Screen with detached system Search on the Duo trailing column (inline fifth tab on iPhone per the iOS 27 oracle), regular/inline bottomAccessory, tabBarMinimizeBehavior never/automatic/onScrollDown/onScrollUp, active-tab restoration on reselect, lifecycle callbacks (onAppear/onDisappear/onWillAppear/onWillDisappear), onDismissed",
5644
- missing: "native velocity and spring fidelity, pointer cancellation, fit-to-content and non-numeric detents, numeric 1.0 native geometry, and expandsWhenScrolledToEdge remain incomplete or unverified"
5644
+ missing: "over-drag return spring fidelity, sheet-to-scroll handoff creep beyond the largest detent"
5645
5645
  }
5646
5646
  ]
5647
5647
  },
@@ -7599,9 +7599,10 @@ var init_registry = __esm({
7599
7599
  versions: [
7600
7600
  {
7601
7601
  range: ">=1.0.0",
7602
- coverage: 1,
7603
- note: "proxy reads all keys from process.env; supports any key via Proxy ownKeys/get",
7604
- working: "Config proxy (all keys via process.env), default and named Config export"
7602
+ coverage: 0.9,
7603
+ note: "native-seam: index.js runs unchanged from the bundle; only RNCConfigModule is ours. `peach open --load-env` reads the project's env file as the iOS build phase does (ENVFILE, .env fallback, the same line pattern and Objective-C string decoding) and getConfig() answers with it; without the flag it answers as a build that found no env file, with an empty config and a console warning",
7604
+ working: "Config and default exports from the real package, getConfig() in the native shape, ENVFILE selection and build-setting expansion, invalid-entry failure",
7605
+ missing: "Android build flavors (envConfigFiles); a cloud preview carries no env file"
7605
7606
  }
7606
7607
  ]
7607
7608
  },
@@ -19430,9 +19431,9 @@ function safeChildPlistName(value) {
19430
19431
  name: file.toLowerCase().endsWith(".plist") ? file : `${file}.plist`
19431
19432
  };
19432
19433
  }
19433
- async function readableSettingsBundle(path22) {
19434
+ async function readableSettingsBundle(path23) {
19434
19435
  try {
19435
- const root = await (0, import_promises.stat)((0, import_node_path.join)(path22, "Root.plist"));
19436
+ const root = await (0, import_promises.stat)((0, import_node_path.join)(path23, "Root.plist"));
19436
19437
  return root.isFile() && root.size <= MAX_PLIST_BYTES;
19437
19438
  } catch {
19438
19439
  return false;
@@ -19477,11 +19478,11 @@ async function settingsBundleFingerprint(bundlePath) {
19477
19478
  return null;
19478
19479
  }
19479
19480
  }
19480
- async function parsePlistRecord(path22) {
19481
+ async function parsePlistRecord(path23) {
19481
19482
  try {
19482
- const metadata = await (0, import_promises.stat)(path22);
19483
+ const metadata = await (0, import_promises.stat)(path23);
19483
19484
  if (!metadata.isFile() || metadata.size > MAX_PLIST_BYTES) return null;
19484
- const source = await (0, import_promises.readFile)(path22, "utf8");
19485
+ const source = await (0, import_promises.readFile)(path23, "utf8");
19485
19486
  const parsed = parsePlistSource(source);
19486
19487
  return isRecord2(parsed) ? parsed : null;
19487
19488
  } catch {
@@ -19805,7 +19806,7 @@ async function tcpPing(port, timeout = TCP_GATE_MS) {
19805
19806
  return null;
19806
19807
  }
19807
19808
  }
19808
- function httpGet(hostname, port, path22, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
19809
+ function httpGet(hostname, port, path23, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
19809
19810
  return new Promise((resolve9) => {
19810
19811
  let settled = false;
19811
19812
  let killing = false;
@@ -19814,7 +19815,7 @@ function httpGet(hostname, port, path22, method = "GET", timeout = TIMEOUT_MS, h
19814
19815
  settled = true;
19815
19816
  resolve9(value);
19816
19817
  };
19817
- const req = import_http.default.request({ hostname, port, path: path22, method, headers }, (res) => {
19818
+ const req = import_http.default.request({ hostname, port, path: path23, method, headers }, (res) => {
19818
19819
  let body = "";
19819
19820
  res.on("data", (c) => body += c.toString());
19820
19821
  const contentType = (() => {
@@ -21692,8 +21693,8 @@ function sourceEntryPath() {
21692
21693
  return null;
21693
21694
  }
21694
21695
  }
21695
- function isCliEntry(path22) {
21696
- const name2 = (0, import_node_path8.basename)(path22);
21696
+ function isCliEntry(path23) {
21697
+ const name2 = (0, import_node_path8.basename)(path23);
21697
21698
  return name2 === "bin.ts" || name2 === "bin.js";
21698
21699
  }
21699
21700
  function rnxSelfInvocation() {
@@ -26531,8 +26532,8 @@ function metroIosAssetDestRelatives(httpServerLocation, filename) {
26531
26532
  }
26532
26533
  const out = [];
26533
26534
  for (const dir of dirs) {
26534
- const path22 = `${dir}/${filename}`;
26535
- if (!out.includes(path22)) out.push(path22);
26535
+ const path23 = `${dir}/${filename}`;
26536
+ if (!out.includes(path23)) out.push(path23);
26536
26537
  }
26537
26538
  if (!out.includes(filename)) out.push(filename);
26538
26539
  return out;
@@ -27482,13 +27483,13 @@ function readFactoryStringLiterals(factory) {
27482
27483
  return literals;
27483
27484
  }
27484
27485
  function normalizeFingerprintLiteral(literal) {
27485
- const path22 = literal.replaceAll("\\\\", "/").replaceAll("\\/", "/");
27486
+ const path23 = literal.replaceAll("\\\\", "/").replaceAll("\\/", "/");
27486
27487
  const nodeModulesMarker = "/node_modules/";
27487
- const nodeModulesIndex = path22.lastIndexOf(nodeModulesMarker);
27488
+ const nodeModulesIndex = path23.lastIndexOf(nodeModulesMarker);
27488
27489
  if (nodeModulesIndex >= 0) {
27489
- return `node_modules/${path22.slice(nodeModulesIndex + nodeModulesMarker.length)}`;
27490
+ return `node_modules/${path23.slice(nodeModulesIndex + nodeModulesMarker.length)}`;
27490
27491
  }
27491
- if ((path22.startsWith("/") || /^[A-Za-z]:\//.test(path22) || path22.startsWith("file:/")) && /\.[cm]?[jt]sx?(?::\d+(?::\d+)?)?$/.test(path22)) {
27492
+ if ((path23.startsWith("/") || /^[A-Za-z]:\//.test(path23) || path23.startsWith("file:/")) && /\.[cm]?[jt]sx?(?::\d+(?::\d+)?)?$/.test(path23)) {
27492
27493
  return null;
27493
27494
  }
27494
27495
  return literal;
@@ -27726,10 +27727,10 @@ function templateAssignment(template, embeddings) {
27726
27727
  if (existingNode !== void 0 && existingNode !== nodeIndex) return null;
27727
27728
  nodesByModuleId.set(moduleId, nodeIndex);
27728
27729
  const node = template.nodes[nodeIndex];
27729
- const path22 = node.landmarkPath ?? `node_modules/${template.packageName}/__rnx_inferred__/${moduleId}.js`;
27730
+ const path23 = node.landmarkPath ?? `node_modules/${template.packageName}/__rnx_inferred__/${moduleId}.js`;
27730
27731
  const existingPath = pathsByModuleId.get(moduleId);
27731
- if (existingPath !== void 0 && existingPath !== path22) return null;
27732
- pathsByModuleId.set(moduleId, path22);
27732
+ if (existingPath !== void 0 && existingPath !== path23) return null;
27733
+ pathsByModuleId.set(moduleId, path23);
27733
27734
  }
27734
27735
  }
27735
27736
  return {
@@ -27891,14 +27892,14 @@ async function inferMetroModuleIdentity(args) {
27891
27892
  const packageClaims = claimsByPackage.values().next().value;
27892
27893
  if (!packageClaims) continue;
27893
27894
  const exactClaims = packageClaims.filter((assignment2) => {
27894
- const path22 = assignment2.pathsByModuleId.get(moduleId);
27895
- return path22 !== void 0 && !path22.includes("/__rnx_inferred__/");
27895
+ const path23 = assignment2.pathsByModuleId.get(moduleId);
27896
+ return path23 !== void 0 && !path23.includes("/__rnx_inferred__/");
27896
27897
  });
27897
27898
  const preferredClaims = exactClaims.length > 0 ? exactClaims : packageClaims;
27898
27899
  const routes = new Set(
27899
27900
  preferredClaims.flatMap((assignment2) => {
27900
- const path22 = assignment2.pathsByModuleId.get(moduleId);
27901
- return path22 ? [metroFingerprintModuleClaimRoute(assignment2.packageName, path22)] : [];
27901
+ const path23 = assignment2.pathsByModuleId.get(moduleId);
27902
+ return path23 ? [metroFingerprintModuleClaimRoute(assignment2.packageName, path23)] : [];
27902
27903
  })
27903
27904
  );
27904
27905
  if (routes.size !== 1) continue;
@@ -28219,11 +28220,11 @@ function detectProject(dir) {
28219
28220
  devCommand: typeof devCommand === "string" ? devCommand : null
28220
28221
  };
28221
28222
  }
28222
- function readProjectMetadata(path22) {
28223
+ function readProjectMetadata(path23) {
28223
28224
  try {
28224
- const info = (0, import_node_fs15.lstatSync)(path22);
28225
+ const info = (0, import_node_fs15.lstatSync)(path23);
28225
28226
  if (!info.isFile() || info.size > 4 * 1024 * 1024) return null;
28226
- return (0, import_node_fs15.readFileSync)(path22, "utf8");
28227
+ return (0, import_node_fs15.readFileSync)(path23, "utf8");
28227
28228
  } catch {
28228
28229
  return null;
28229
28230
  }
@@ -28232,8 +28233,8 @@ function metadataValue(value, key) {
28232
28233
  if (!value || typeof value !== "object") return void 0;
28233
28234
  return Object.getOwnPropertyDescriptor(value, key)?.value;
28234
28235
  }
28235
- function readProjectJson(path22) {
28236
- const text = readProjectMetadata(path22);
28236
+ function readProjectJson(path23) {
28237
+ const text = readProjectMetadata(path23);
28237
28238
  if (text === null) return null;
28238
28239
  try {
28239
28240
  const value = JSON.parse(text);
@@ -31975,11 +31976,11 @@ async function evalInBridge(bridge, code, opts = {}) {
31975
31976
  if (opts.acquireLock) payload.acquireLock = true;
31976
31977
  return bridge.send(payload);
31977
31978
  }
31978
- async function callInBridge(bridge, path22, ...args) {
31979
- return bridge.send({ type: "call", path: path22, args });
31979
+ async function callInBridge(bridge, path23, ...args) {
31980
+ return bridge.send({ type: "call", path: path23, args });
31980
31981
  }
31981
- async function callInBridgeWrite(bridge, path22, ...args) {
31982
- return bridge.send({ type: "call", path: path22, args, acquireLock: true });
31982
+ async function callInBridgeWrite(bridge, path23, ...args) {
31983
+ return bridge.send({ type: "call", path: path23, args, acquireLock: true });
31983
31984
  }
31984
31985
  var import_node_fs18, import_node_path19, import_ws2, PEACH_PLACEMENT_ENV, resolvedWorld, BridgeSimLockedError, BRIDGE_VALUE_FLAGS_TABLE, BRIDGE_VALUE_FLAGS;
31985
31986
  var init_ws_bridge = __esm({
@@ -32114,8 +32115,8 @@ function getDefaultPortForProtocol(protocol) {
32114
32115
  return protocol === "https:" ? 443 : 80;
32115
32116
  }
32116
32117
  function isBaseServerUrl(url) {
32117
- const path22 = url.pathname || "/";
32118
- return (path22 === "/" || path22 === "") && !url.search && !url.hash;
32118
+ const path23 = url.pathname || "/";
32119
+ return (path23 === "/" || path23 === "") && !url.search && !url.hash;
32119
32120
  }
32120
32121
  async function resolvePortViaServerScan(port) {
32121
32122
  try {
@@ -32277,6 +32278,124 @@ var init_dev_bundle_resolution = __esm({
32277
32278
  }
32278
32279
  });
32279
32280
 
32281
+ // src/dot-env.ts
32282
+ function selectEnvFile(env, notices) {
32283
+ if (import_node_fs19.default.existsSync("/tmp/envfile")) {
32284
+ return { name: import_node_fs19.default.readFileSync("/tmp/envfile", "utf8").trim(), fromEnvfile: false };
32285
+ }
32286
+ const requested = env.ENVFILE;
32287
+ if (!requested) return { name: DEFAULT_ENV_FILE, fromEnvfile: false };
32288
+ const unset = [];
32289
+ const name2 = requested.replace(BUILD_SETTING_PATTERN, (_, braced, bare) => {
32290
+ const variable = braced ?? bare;
32291
+ const value = env[variable];
32292
+ if (!value) unset.push(variable);
32293
+ return value ?? "";
32294
+ });
32295
+ notices.push(`ENVFILE=${requested}`);
32296
+ if (name2 !== requested) notices.push(` expands to ${name2}`);
32297
+ if (unset.length) {
32298
+ notices.push(
32299
+ ` note: ${[...new Set(unset)].join(", ")} resolved to nothing. Outside Xcode these build settings are not set - pass the file name directly, or run the build through Xcode.`
32300
+ );
32301
+ }
32302
+ return { name: name2, fromEnvfile: true };
32303
+ }
32304
+ function decodeObjCStringLiteral(source) {
32305
+ let out = "";
32306
+ for (let i = 0; i < source.length; i++) {
32307
+ const char = source[i];
32308
+ if (char === '"') throw new Error(`GeneratedDotEnv.m does not compile: ${source}`);
32309
+ if (char !== "\\") {
32310
+ out += char;
32311
+ continue;
32312
+ }
32313
+ const next = source[++i];
32314
+ if (next === void 0)
32315
+ throw new Error(`GeneratedDotEnv.m does not compile: ${source}`);
32316
+ const simple = {
32317
+ n: "\n",
32318
+ t: " ",
32319
+ r: "\r",
32320
+ a: "\x07",
32321
+ b: "\b",
32322
+ f: "\f",
32323
+ v: "\v",
32324
+ e: "\x1B"
32325
+ };
32326
+ if (next in simple) out += simple[next];
32327
+ else if (/[0-7]/.test(next)) {
32328
+ const digits = /^[0-7]{1,3}/.exec(source.slice(i))[0];
32329
+ out += String.fromCodePoint(Number.parseInt(digits, 8));
32330
+ i += digits.length - 1;
32331
+ } else if (next === "x" || next === "u" || next === "U") {
32332
+ const digits = next === "x" ? /^[0-9a-fA-F]+/.exec(source.slice(i + 1))?.[0] ?? "" : source.slice(i + 1, i + 1 + (next === "u" ? 4 : 8));
32333
+ const code = Number.parseInt(digits, 16);
32334
+ if (!/^[0-9a-fA-F]+$/.test(digits) || code > (next === "x" ? 255 : 1114111)) {
32335
+ throw new Error(`GeneratedDotEnv.m does not compile: ${source}`);
32336
+ }
32337
+ out += String.fromCodePoint(code);
32338
+ i += digits.length;
32339
+ } else out += next;
32340
+ }
32341
+ return out;
32342
+ }
32343
+ function readProjectDotEnv(envsRoot, env = process.env) {
32344
+ const notices = [];
32345
+ const selection = selectEnvFile(env, notices);
32346
+ const requestedPaths = [
32347
+ import_node_path20.default.resolve(import_node_path20.default.join(envsRoot, selection.name)),
32348
+ import_node_path20.default.resolve(selection.name)
32349
+ ];
32350
+ const candidates = [
32351
+ ...requestedPaths,
32352
+ import_node_path20.default.resolve(import_node_path20.default.join(envsRoot, DEFAULT_ENV_FILE))
32353
+ ];
32354
+ if (!import_node_fs19.default.existsSync(candidates[2])) candidates.push(import_node_path20.default.resolve(DEFAULT_ENV_FILE));
32355
+ const tried = [...new Set(candidates)];
32356
+ const resolved = tried.find((candidate) => import_node_fs19.default.existsSync(candidate));
32357
+ if (!resolved) {
32358
+ notices.push(
32359
+ "*** Missing .env file ****",
32360
+ "Tried, in order:",
32361
+ ...tried.map((candidate) => ` - ${candidate}`),
32362
+ "The build will succeed and Config will be empty at runtime."
32363
+ );
32364
+ return { config: {}, notices };
32365
+ }
32366
+ if (selection.fromEnvfile && !requestedPaths.includes(resolved)) {
32367
+ notices.push(
32368
+ "*** ENVFILE was set, but that file is missing ",
32369
+ `Asked for: ${selection.name}`,
32370
+ "Not found at:",
32371
+ ...requestedPaths.map((candidate) => ` - ${candidate}`),
32372
+ `Falling back to: ${resolved}`
32373
+ );
32374
+ }
32375
+ const config = {};
32376
+ for (const line of import_node_fs19.default.readFileSync(resolved, "utf8").split("\n")) {
32377
+ if (!line.trim()) continue;
32378
+ if (/^[ \t\n\v\f\r]*#/.test(line)) continue;
32379
+ const match = DOTENV_PATTERN.exec(line);
32380
+ if (!match?.groups) throw new Error(INVALID_ENTRY);
32381
+ const literal = (match.groups.val ?? "").replaceAll('"', '\\"').replace(/(\r\n|\n|\r)$/, "");
32382
+ config[match.groups.key] = decodeObjCStringLiteral(literal);
32383
+ }
32384
+ return { config, notices };
32385
+ }
32386
+ var import_node_fs19, import_node_path20, DEFAULT_ENV_FILE, DOTENV_PATTERN, BUILD_SETTING_PATTERN, INVALID_ENTRY;
32387
+ var init_dot_env = __esm({
32388
+ "src/dot-env.ts"() {
32389
+ "use strict";
32390
+ import_node_fs19 = __toESM(require("node:fs"), 1);
32391
+ import_node_path20 = __toESM(require("node:path"), 1);
32392
+ DEFAULT_ENV_FILE = ".env";
32393
+ DOTENV_PATTERN = /^(?:export[ \t\n\v\f\r]+|)(?<key>[\p{Alphabetic}\p{Nd}_]+)[ \t\n\v\f\r]*=[ \t\n\v\f\r]*((?<quote>["'])?(?<val>[^\n]*?[^\\\n])\k<quote>?|)$/u;
32394
+ BUILD_SETTING_PATTERN = /\$[({]([A-Za-z_][A-Za-z0-9_]*)[)}]|\$([A-Za-z_][A-Za-z0-9_]*)/g;
32395
+ INVALID_ENTRY = "Invalid entry in .env file. Please verify your .env file is correctly formatted.";
32396
+ }
32397
+ });
32398
+
32280
32399
  // src/flow-timeout-scale.ts
32281
32400
  function flowTimeoutScale() {
32282
32401
  return Math.min(10, Math.max(1, Number(process.env[FLOW_TIMEOUT_SCALE_ENV]) || 1));
@@ -32298,9 +32417,9 @@ function readNativeFirebaseConfig(projectRoot) {
32298
32417
  "app.config.ts",
32299
32418
  "app.config.cjs",
32300
32419
  "app.config.mjs"
32301
- ].some((name2) => import_node_fs19.default.existsSync(import_node_path20.default.join(projectRoot, name2))))
32420
+ ].some((name2) => import_node_fs20.default.existsSync(import_node_path21.default.join(projectRoot, name2))))
32302
32421
  return result;
32303
- const require5 = (0, import_node_module.createRequire)(import_node_path20.default.join(projectRoot, "package.json"));
32422
+ const require5 = (0, import_node_module.createRequire)(import_node_path21.default.join(projectRoot, "package.json"));
32304
32423
  const configModule = require5("@expo/config");
32305
32424
  if (!isRecord(configModule) || typeof configModule.getConfig !== "function") {
32306
32425
  throw new Error("Expo native configuration is unavailable.");
@@ -32314,8 +32433,8 @@ function readNativeFirebaseConfig(projectRoot) {
32314
32433
  const native = config[platform];
32315
32434
  if (!isRecord(native) || typeof native.googleServicesFile !== "string") continue;
32316
32435
  try {
32317
- const source = import_node_fs19.default.readFileSync(
32318
- import_node_path20.default.resolve(projectRoot, native.googleServicesFile),
32436
+ const source = import_node_fs20.default.readFileSync(
32437
+ import_node_path21.default.resolve(projectRoot, native.googleServicesFile),
32319
32438
  "utf8"
32320
32439
  );
32321
32440
  const parsed = platform === "ios" ? parsePlistSource(source) : JSON.parse(source);
@@ -32367,13 +32486,13 @@ function readNativeFirebaseConfig(projectRoot) {
32367
32486
  }
32368
32487
  return result;
32369
32488
  }
32370
- var import_node_fs19, import_node_module, import_node_path20;
32489
+ var import_node_fs20, import_node_module, import_node_path21;
32371
32490
  var init_native_firebase_config = __esm({
32372
32491
  "src/native-firebase-config.ts"() {
32373
32492
  "use strict";
32374
- import_node_fs19 = __toESM(require("node:fs"), 1);
32493
+ import_node_fs20 = __toESM(require("node:fs"), 1);
32375
32494
  import_node_module = require("node:module");
32376
- import_node_path20 = __toESM(require("node:path"), 1);
32495
+ import_node_path21 = __toESM(require("node:path"), 1);
32377
32496
  init_is_record();
32378
32497
  init_plist();
32379
32498
  }
@@ -32537,7 +32656,7 @@ function colorsetValue(color) {
32537
32656
  }
32538
32657
  function enumerateBundleColors(paths, readText2) {
32539
32658
  const table = {};
32540
- for (const contentsPath of paths.filter((path22) => baseOf(path22) === "Contents.json")) {
32659
+ for (const contentsPath of paths.filter((path23) => baseOf(path23) === "Contents.json")) {
32541
32660
  const name2 = catalogEntryName(contentsPath, ".colorset", readText2);
32542
32661
  if (name2 === null || name2 in table) continue;
32543
32662
  let colors;
@@ -32585,59 +32704,59 @@ var init_bundleAssets = __esm({
32585
32704
  // cli/app-catalog.ts
32586
32705
  function listDir(dir) {
32587
32706
  try {
32588
- return import_node_fs20.default.readdirSync(dir, { withFileTypes: true });
32707
+ return import_node_fs21.default.readdirSync(dir, { withFileTypes: true });
32589
32708
  } catch {
32590
32709
  return [];
32591
32710
  }
32592
32711
  }
32593
32712
  function readText(file) {
32594
32713
  try {
32595
- return import_node_fs20.default.readFileSync(file, "utf8");
32714
+ return import_node_fs21.default.readFileSync(file, "utf8");
32596
32715
  } catch {
32597
32716
  return null;
32598
32717
  }
32599
32718
  }
32600
32719
  function catalogFiles(dir, found) {
32601
32720
  for (const entry of listDir(dir)) {
32602
- const full = import_node_path21.default.join(dir, entry.name);
32721
+ const full = import_node_path22.default.join(dir, entry.name);
32603
32722
  if (entry.isDirectory()) catalogFiles(full, found);
32604
32723
  else if (entry.name === "Contents.json") found.push(full);
32605
32724
  }
32606
32725
  }
32607
32726
  function discoverAppCatalog(appDir) {
32608
- const iosDir = import_node_path21.default.join(appDir, "ios");
32727
+ const iosDir = import_node_path22.default.join(appDir, "ios");
32609
32728
  const target = listDir(iosDir).find(
32610
- (entry) => entry.isDirectory() && entry.name !== "Pods" && listDir(import_node_path21.default.join(iosDir, entry.name)).some(
32729
+ (entry) => entry.isDirectory() && entry.name !== "Pods" && listDir(import_node_path22.default.join(iosDir, entry.name)).some(
32611
32730
  (file) => /^AppDelegate\.(swift|mm|m)$/.test(file.name)
32612
32731
  )
32613
32732
  );
32614
32733
  if (!target) return null;
32615
- const targetDir = import_node_path21.default.join(iosDir, target.name);
32734
+ const targetDir = import_node_path22.default.join(iosDir, target.name);
32616
32735
  const files = [];
32617
32736
  for (const entry of listDir(targetDir)) {
32618
32737
  if (entry.isDirectory() && entry.name.endsWith(".xcassets"))
32619
- catalogFiles(import_node_path21.default.join(targetDir, entry.name), files);
32738
+ catalogFiles(import_node_path22.default.join(targetDir, entry.name), files);
32620
32739
  }
32621
32740
  const relative2 = files.map(
32622
- (file) => import_node_path21.default.relative(targetDir, file).split(import_node_path21.default.sep).join(import_node_path21.default.posix.sep)
32741
+ (file) => import_node_path22.default.relative(targetDir, file).split(import_node_path22.default.sep).join(import_node_path22.default.posix.sep)
32623
32742
  );
32624
32743
  const colors = enumerateBundleColors(
32625
32744
  relative2,
32626
- (candidate) => candidate.endsWith("Contents.json") ? readText(import_node_path21.default.join(targetDir, candidate)) : null
32745
+ (candidate) => candidate.endsWith("Contents.json") ? readText(import_node_path22.default.join(targetDir, candidate)) : null
32627
32746
  );
32628
32747
  const pbxproj = listDir(iosDir).find((entry) => entry.name.endsWith(".xcodeproj"));
32629
- const accentName = readText(import_node_path21.default.join(targetDir, "Info.plist"))?.match(PLIST_ACCENT)?.[1] ?? (pbxproj ? readText(import_node_path21.default.join(iosDir, pbxproj.name, "project.pbxproj"))?.match(
32748
+ const accentName = readText(import_node_path22.default.join(targetDir, "Info.plist"))?.match(PLIST_ACCENT)?.[1] ?? (pbxproj ? readText(import_node_path22.default.join(iosDir, pbxproj.name, "project.pbxproj"))?.match(
32630
32749
  ACCENT_BUILD_SETTING
32631
32750
  )?.[1] : void 0) ?? null;
32632
32751
  if (accentName === null && Object.keys(colors).length === 0) return null;
32633
32752
  return { colors, accentName };
32634
32753
  }
32635
- var import_node_fs20, import_node_path21, ACCENT_BUILD_SETTING, PLIST_ACCENT;
32754
+ var import_node_fs21, import_node_path22, ACCENT_BUILD_SETTING, PLIST_ACCENT;
32636
32755
  var init_app_catalog = __esm({
32637
32756
  "cli/app-catalog.ts"() {
32638
32757
  "use strict";
32639
- import_node_fs20 = __toESM(require("node:fs"), 1);
32640
- import_node_path21 = __toESM(require("node:path"), 1);
32758
+ import_node_fs21 = __toESM(require("node:fs"), 1);
32759
+ import_node_path22 = __toESM(require("node:path"), 1);
32641
32760
  init_bundleAssets();
32642
32761
  ACCENT_BUILD_SETTING = /ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "?([^";]+)"?;/;
32643
32762
  PLIST_ACCENT = /<key>NSAccentColorName<\/key>\s*<string>([^<]+)<\/string>/;
@@ -32647,9 +32766,9 @@ var init_app_catalog = __esm({
32647
32766
  // cli/app-project.ts
32648
32767
  function firstNamedFile(dir, names) {
32649
32768
  for (const name2 of names) {
32650
- const candidate = import_node_path22.default.join(dir, name2);
32769
+ const candidate = import_node_path23.default.join(dir, name2);
32651
32770
  try {
32652
- if (import_node_fs21.default.statSync(candidate).isFile()) return candidate;
32771
+ if (import_node_fs22.default.statSync(candidate).isFile()) return candidate;
32653
32772
  } catch {
32654
32773
  }
32655
32774
  }
@@ -32662,24 +32781,24 @@ function findRNXAppConfig(dir) {
32662
32781
  return firstNamedFile(dir, RNX_APP_CONFIG_NAMES);
32663
32782
  }
32664
32783
  function resolveAppProject(projectRoot) {
32665
- const appDir = import_node_path22.default.resolve(projectRoot);
32784
+ const appDir = import_node_path23.default.resolve(projectRoot);
32666
32785
  try {
32667
- if (!import_node_fs21.default.statSync(appDir).isDirectory()) return null;
32786
+ if (!import_node_fs22.default.statSync(appDir).isDirectory()) return null;
32668
32787
  } catch {
32669
32788
  return null;
32670
32789
  }
32671
32790
  const configPath = findRNXAppConfig(appDir);
32672
- if (!configPath && !findExpoAppConfig(appDir) && !import_node_fs21.default.existsSync(import_node_path22.default.join(appDir, "package.json"))) {
32791
+ if (!configPath && !findExpoAppConfig(appDir) && !import_node_fs22.default.existsSync(import_node_path23.default.join(appDir, "package.json"))) {
32673
32792
  return null;
32674
32793
  }
32675
32794
  return { appDir, configPath };
32676
32795
  }
32677
- var import_node_fs21, import_node_path22, EXPO_APP_CONFIG_NAMES, RNX_APP_CONFIG_NAMES;
32796
+ var import_node_fs22, import_node_path23, EXPO_APP_CONFIG_NAMES, RNX_APP_CONFIG_NAMES;
32678
32797
  var init_app_project = __esm({
32679
32798
  "cli/app-project.ts"() {
32680
32799
  "use strict";
32681
- import_node_fs21 = __toESM(require("node:fs"), 1);
32682
- import_node_path22 = __toESM(require("node:path"), 1);
32800
+ import_node_fs22 = __toESM(require("node:fs"), 1);
32801
+ import_node_path23 = __toESM(require("node:path"), 1);
32683
32802
  EXPO_APP_CONFIG_NAMES = [
32684
32803
  "app.config.js",
32685
32804
  "app.config.ts",
@@ -32708,13 +32827,13 @@ function isRNXConfig(value) {
32708
32827
  }
32709
32828
  function resolveConfigReplacementFiles(config, configPath) {
32710
32829
  if (!config.modules) return config;
32711
- const configDir = import_node_path23.default.dirname(configPath);
32830
+ const configDir = import_node_path24.default.dirname(configPath);
32712
32831
  return {
32713
32832
  ...config,
32714
32833
  modules: Object.fromEntries(
32715
32834
  Object.entries(config.modules).map(([name2, resolution]) => [
32716
32835
  name2,
32717
- resolution && typeof resolution === "object" && "file" in resolution ? { ...resolution, file: import_node_path23.default.resolve(configDir, resolution.file) } : resolution
32836
+ resolution && typeof resolution === "object" && "file" in resolution ? { ...resolution, file: import_node_path24.default.resolve(configDir, resolution.file) } : resolution
32718
32837
  ])
32719
32838
  )
32720
32839
  };
@@ -32744,12 +32863,12 @@ async function resolveRNXAppConfig(startDir = process.cwd()) {
32744
32863
  const project = resolveAppProject(startDir);
32745
32864
  return { project, config: await loadRNXAppConfig(project) };
32746
32865
  }
32747
- var import_node_module2, import_node_path23, import_jiti, require2;
32866
+ var import_node_module2, import_node_path24, import_jiti, require2;
32748
32867
  var init_app_config = __esm({
32749
32868
  "cli/app-config.ts"() {
32750
32869
  "use strict";
32751
32870
  import_node_module2 = require("node:module");
32752
- import_node_path23 = __toESM(require("node:path"), 1);
32871
+ import_node_path24 = __toESM(require("node:path"), 1);
32753
32872
  init_src();
32754
32873
  import_jiti = require("jiti");
32755
32874
  init_public_brand();
@@ -32806,13 +32925,13 @@ function discoverNativeLinkedAppFonts(opts) {
32806
32925
  scannedFontDirectories++;
32807
32926
  let entries;
32808
32927
  try {
32809
- entries = import_node_fs22.default.readdirSync(current.dir, { withFileTypes: true });
32928
+ entries = import_node_fs23.default.readdirSync(current.dir, { withFileTypes: true });
32810
32929
  } catch {
32811
32930
  continue;
32812
32931
  }
32813
32932
  for (const entry of entries) {
32814
32933
  if (entry.isSymbolicLink()) continue;
32815
- const fullPath = import_node_path24.default.join(current.dir, entry.name);
32934
+ const fullPath = import_node_path25.default.join(current.dir, entry.name);
32816
32935
  if (entry.isDirectory()) {
32817
32936
  if (current.depth < 4 && pending.length < 64 && !entry.name.startsWith(".")) {
32818
32937
  pending.push({ dir: fullPath, depth: current.depth + 1 });
@@ -32820,15 +32939,15 @@ function discoverNativeLinkedAppFonts(opts) {
32820
32939
  continue;
32821
32940
  }
32822
32941
  if (!entry.isFile() || !/\.(ttf|otf|woff|woff2)$/i.test(entry.name)) continue;
32823
- const relative2 = import_node_path24.default.relative(root, fullPath).split(import_node_path24.default.sep).join("/");
32824
- fontPaths.push(import_node_path24.default.posix.join(metroPathPrefix, relative2));
32942
+ const relative2 = import_node_path25.default.relative(root, fullPath).split(import_node_path25.default.sep).join("/");
32943
+ fontPaths.push(import_node_path25.default.posix.join(metroPathPrefix, relative2));
32825
32944
  if (fontPaths.length >= 256) break;
32826
32945
  }
32827
32946
  }
32828
32947
  };
32829
32948
  try {
32830
32949
  const packageJson = JSON.parse(
32831
- import_node_fs22.default.readFileSync(import_node_path24.default.join(selectedAppDir, "package.json"), "utf8")
32950
+ import_node_fs23.default.readFileSync(import_node_path25.default.join(selectedAppDir, "package.json"), "utf8")
32832
32951
  );
32833
32952
  const dependencyNames = /* @__PURE__ */ new Set();
32834
32953
  for (const field of ["dependencies", "devDependencies", "optionalDependencies"]) {
@@ -32843,32 +32962,32 @@ function discoverNativeLinkedAppFonts(opts) {
32843
32962
  const config = Reflect.get(packageJson, "reactNativeVectorIcons");
32844
32963
  const configuredFontDir = config && typeof config === "object" ? Reflect.get(config, "fontDir") : null;
32845
32964
  const configuredDir = typeof configuredFontDir === "string" ? configuredFontDir : "rnvi-fonts";
32846
- const root = import_node_path24.default.resolve(selectedAppDir, configuredDir);
32847
- const relativeRoot = import_node_path24.default.relative(selectedAppDir, root);
32848
- if (!relativeRoot.startsWith("..") && !import_node_path24.default.isAbsolute(relativeRoot)) {
32849
- collectFontFiles(root, relativeRoot.split(import_node_path24.default.sep).join("/"));
32965
+ const root = import_node_path25.default.resolve(selectedAppDir, configuredDir);
32966
+ const relativeRoot = import_node_path25.default.relative(selectedAppDir, root);
32967
+ if (!relativeRoot.startsWith("..") && !import_node_path25.default.isAbsolute(relativeRoot)) {
32968
+ collectFontFiles(root, relativeRoot.split(import_node_path25.default.sep).join("/"));
32850
32969
  }
32851
- const bundleDir = import_node_path24.default.posix.dirname(new URL(opts.bundleUrl).pathname).replace(/^\/+/, "");
32852
- const appRelativeDir = bundleDir.split("/").join(import_node_path24.default.sep);
32970
+ const bundleDir = import_node_path25.default.posix.dirname(new URL(opts.bundleUrl).pathname).replace(/^\/+/, "");
32971
+ const appRelativeDir = bundleDir.split("/").join(import_node_path25.default.sep);
32853
32972
  const metroRootCandidates = [selectedAppDir];
32854
- if (bundleDir && selectedAppDir.endsWith(import_node_path24.default.sep + appRelativeDir)) {
32973
+ if (bundleDir && selectedAppDir.endsWith(import_node_path25.default.sep + appRelativeDir)) {
32855
32974
  metroRootCandidates.push(selectedAppDir.slice(0, -appRelativeDir.length - 1));
32856
32975
  }
32857
- const vectorIconRequire = (0, import_node_module3.createRequire)(import_node_path24.default.join(selectedAppDir, "package.json"));
32976
+ const vectorIconRequire = (0, import_node_module3.createRequire)(import_node_path25.default.join(selectedAppDir, "package.json"));
32858
32977
  for (const dependencyName of vectorIconDependencies) {
32859
32978
  try {
32860
32979
  const entryPath = vectorIconRequire.resolve(dependencyName);
32861
- const dependencyPath = dependencyName.split("/").join(import_node_path24.default.sep);
32862
- const marker = `${import_node_path24.default.sep}node_modules${import_node_path24.default.sep}${dependencyPath}${import_node_path24.default.sep}`;
32980
+ const dependencyPath = dependencyName.split("/").join(import_node_path25.default.sep);
32981
+ const marker = `${import_node_path25.default.sep}node_modules${import_node_path25.default.sep}${dependencyPath}${import_node_path25.default.sep}`;
32863
32982
  const markerIndex = entryPath.lastIndexOf(marker);
32864
32983
  if (markerIndex === -1) continue;
32865
32984
  const packageRoot = entryPath.slice(0, markerIndex + marker.length - 1);
32866
32985
  const fontsDir = dependencyName === "react-native-vector-icons" ? "Fonts" : "fonts";
32867
- const fontsRoot = import_node_path24.default.join(packageRoot, fontsDir);
32986
+ const fontsRoot = import_node_path25.default.join(packageRoot, fontsDir);
32868
32987
  for (const metroRoot of metroRootCandidates) {
32869
32988
  collectFontFiles(
32870
32989
  fontsRoot,
32871
- import_node_path24.default.relative(metroRoot, fontsRoot).split(import_node_path24.default.sep).join("/")
32990
+ import_node_path25.default.relative(metroRoot, fontsRoot).split(import_node_path25.default.sep).join("/")
32872
32991
  );
32873
32992
  }
32874
32993
  } catch {
@@ -32878,37 +32997,37 @@ function discoverNativeLinkedAppFonts(opts) {
32878
32997
  } catch {
32879
32998
  }
32880
32999
  try {
32881
- const configPath = import_node_path24.default.join(selectedAppDir, "react-native.config.js");
32882
- if (import_node_fs22.default.statSync(configPath).isFile()) {
32883
- const appConfigRequire = (0, import_node_module3.createRequire)(import_node_path24.default.join(selectedAppDir, "package.json"));
33000
+ const configPath = import_node_path25.default.join(selectedAppDir, "react-native.config.js");
33001
+ if (import_node_fs23.default.statSync(configPath).isFile()) {
33002
+ const appConfigRequire = (0, import_node_module3.createRequire)(import_node_path25.default.join(selectedAppDir, "package.json"));
32884
33003
  const rnConfig = appConfigRequire(configPath);
32885
33004
  const assets = rnConfig && typeof rnConfig === "object" ? Reflect.get(rnConfig, "assets") : null;
32886
33005
  if (Array.isArray(assets)) {
32887
33006
  for (const assetDir of assets) {
32888
33007
  if (typeof assetDir !== "string") continue;
32889
- const root = import_node_path24.default.resolve(selectedAppDir, assetDir);
32890
- const relativeRoot = import_node_path24.default.relative(selectedAppDir, root);
32891
- if (relativeRoot.startsWith("..") || import_node_path24.default.isAbsolute(relativeRoot)) continue;
32892
- collectFontFiles(root, relativeRoot.split(import_node_path24.default.sep).join("/"));
33008
+ const root = import_node_path25.default.resolve(selectedAppDir, assetDir);
33009
+ const relativeRoot = import_node_path25.default.relative(selectedAppDir, root);
33010
+ if (relativeRoot.startsWith("..") || import_node_path25.default.isAbsolute(relativeRoot)) continue;
33011
+ collectFontFiles(root, relativeRoot.split(import_node_path25.default.sep).join("/"));
32893
33012
  }
32894
33013
  }
32895
33014
  }
32896
33015
  } catch {
32897
33016
  }
32898
33017
  if (platform === "ios") {
32899
- const iosDir = import_node_path24.default.join(selectedAppDir, "ios");
33018
+ const iosDir = import_node_path25.default.join(selectedAppDir, "ios");
32900
33019
  try {
32901
- const targetDirs = import_node_fs22.default.readdirSync(iosDir, { withFileTypes: true }).filter(
33020
+ const targetDirs = import_node_fs23.default.readdirSync(iosDir, { withFileTypes: true }).filter(
32902
33021
  (entry) => entry.isDirectory() && !entry.isSymbolicLink() && entry.name !== "Pods" && entry.name !== "build" && !entry.name.startsWith(".")
32903
33022
  ).slice(0, 64);
32904
- const plistPaths = [import_node_path24.default.join(iosDir, "Info.plist")];
33023
+ const plistPaths = [import_node_path25.default.join(iosDir, "Info.plist")];
32905
33024
  for (const entry of targetDirs) {
32906
- plistPaths.push(import_node_path24.default.join(iosDir, entry.name, "Info.plist"));
33025
+ plistPaths.push(import_node_path25.default.join(iosDir, entry.name, "Info.plist"));
32907
33026
  }
32908
33027
  for (const plistPath of plistPaths) {
32909
33028
  let parsed;
32910
33029
  try {
32911
- parsed = parsePlistSource(import_node_fs22.default.readFileSync(plistPath, "utf8"));
33030
+ parsed = parsePlistSource(import_node_fs23.default.readFileSync(plistPath, "utf8"));
32912
33031
  } catch {
32913
33032
  continue;
32914
33033
  }
@@ -32918,21 +33037,21 @@ function discoverNativeLinkedAppFonts(opts) {
32918
33037
  for (const declaredFont of declaredFonts) {
32919
33038
  if (typeof declaredFont !== "string") continue;
32920
33039
  const candidates = [
32921
- import_node_path24.default.resolve(import_node_path24.default.dirname(plistPath), declaredFont),
32922
- import_node_path24.default.resolve(iosDir, declaredFont)
33040
+ import_node_path25.default.resolve(import_node_path25.default.dirname(plistPath), declaredFont),
33041
+ import_node_path25.default.resolve(iosDir, declaredFont)
32923
33042
  ];
32924
33043
  const fontPath = candidates.find((candidate) => {
32925
- const relative2 = import_node_path24.default.relative(selectedAppDir, candidate);
32926
- if (relative2.startsWith("..") || import_node_path24.default.isAbsolute(relative2)) return false;
33044
+ const relative2 = import_node_path25.default.relative(selectedAppDir, candidate);
33045
+ if (relative2.startsWith("..") || import_node_path25.default.isAbsolute(relative2)) return false;
32927
33046
  try {
32928
- return import_node_fs22.default.statSync(candidate).isFile();
33047
+ return import_node_fs23.default.statSync(candidate).isFile();
32929
33048
  } catch {
32930
33049
  return false;
32931
33050
  }
32932
33051
  });
32933
33052
  if (!fontPath) continue;
32934
33053
  fontPaths.push(
32935
- import_node_path24.default.relative(selectedAppDir, fontPath).split(import_node_path24.default.sep).join("/")
33054
+ import_node_path25.default.relative(selectedAppDir, fontPath).split(import_node_path25.default.sep).join("/")
32936
33055
  );
32937
33056
  }
32938
33057
  }
@@ -32971,13 +33090,13 @@ async function resolveMetroProjectRoot(bundleUrl, opts) {
32971
33090
  function encodeAppFontsWire(specs) {
32972
33091
  return specs.map((spec) => `${encodeURIComponent(spec.url)}::${encodeURIComponent(spec.family)}`).join(",");
32973
33092
  }
32974
- var import_node_fs22, import_node_module3, import_node_path24, import_config_plugin_fonts, require3;
33093
+ var import_node_fs23, import_node_module3, import_node_path25, import_config_plugin_fonts, require3;
32975
33094
  var init_app_fonts = __esm({
32976
33095
  "cli/app-fonts.ts"() {
32977
33096
  "use strict";
32978
- import_node_fs22 = __toESM(require("node:fs"), 1);
33097
+ import_node_fs23 = __toESM(require("node:fs"), 1);
32979
33098
  import_node_module3 = require("node:module");
32980
- import_node_path24 = __toESM(require("node:path"), 1);
33099
+ import_node_path25 = __toESM(require("node:path"), 1);
32981
33100
  import_config_plugin_fonts = require("peach-engine/engine/config-plugin-fonts");
32982
33101
  init_dev_server_scanner();
32983
33102
  init_backend_origin();
@@ -34229,13 +34348,13 @@ function resolvePlaywright() {
34229
34348
  try {
34230
34349
  const modulePath = requireFromRoot.resolve(spec);
34231
34350
  const packageJsonPath = requireFromRoot.resolve(`${spec}/package.json`);
34232
- const parsed = JSON.parse((0, import_node_fs23.readFileSync)(packageJsonPath, "utf8"));
34351
+ const parsed = JSON.parse((0, import_node_fs24.readFileSync)(packageJsonPath, "utf8"));
34233
34352
  if (!isRecord(parsed) || typeof parsed.version !== "string") continue;
34234
34353
  const corePackagePath = (0, import_node_module5.createRequire)(modulePath).resolve(
34235
34354
  "playwright-core/package.json"
34236
34355
  );
34237
- const cliPath = (0, import_node_path25.join)((0, import_node_path25.dirname)(corePackagePath), "cli.js");
34238
- if (!(0, import_node_fs23.existsSync)(cliPath)) continue;
34356
+ const cliPath = (0, import_node_path26.join)((0, import_node_path26.dirname)(corePackagePath), "cli.js");
34357
+ if (!(0, import_node_fs24.existsSync)(cliPath)) continue;
34239
34358
  return {
34240
34359
  spec,
34241
34360
  modulePath,
@@ -34263,7 +34382,7 @@ async function provisionPlaywright() {
34263
34382
  await installVerifiedTarball({
34264
34383
  url: `https://registry.npmjs.org/playwright-core/-/playwright-core-${version}.tgz`,
34265
34384
  digest: { algorithm, encoding: "base64", value: digest },
34266
- destDir: (0, import_node_path25.join)(playwrightCoreDir(version), "node_modules", "playwright-core"),
34385
+ destDir: (0, import_node_path26.join)(playwrightCoreDir(version), "node_modules", "playwright-core"),
34267
34386
  installedMarker: "package.json",
34268
34387
  // npm tarballs hold the package under a leading `package/`
34269
34388
  stripComponents: 1,
@@ -34306,7 +34425,7 @@ function probeBrowser(resolved, env) {
34306
34425
  return {
34307
34426
  ok: true,
34308
34427
  executablePath: parsed.executablePath,
34309
- exists: parsed.exists && (0, import_node_fs23.existsSync)(parsed.executablePath)
34428
+ exists: parsed.exists && (0, import_node_fs24.existsSync)(parsed.executablePath)
34310
34429
  };
34311
34430
  } catch (error) {
34312
34431
  return {
@@ -34357,14 +34476,14 @@ ${detail}` : ""}`
34357
34476
  }
34358
34477
  return { ok: true, executablePath: after.executablePath, installed: true };
34359
34478
  }
34360
- var import_node_child_process6, import_node_fs23, import_node_module5, import_node_path25;
34479
+ var import_node_child_process6, import_node_fs24, import_node_module5, import_node_path26;
34361
34480
  var init_playwright_provisioning = __esm({
34362
34481
  "cli/drivers/playwright-provisioning.ts"() {
34363
34482
  "use strict";
34364
34483
  import_node_child_process6 = require("node:child_process");
34365
- import_node_fs23 = require("node:fs");
34484
+ import_node_fs24 = require("node:fs");
34366
34485
  import_node_module5 = require("node:module");
34367
- import_node_path25 = require("node:path");
34486
+ import_node_path26 = require("node:path");
34368
34487
  init_src();
34369
34488
  init_home_paths();
34370
34489
  init_is_record();
@@ -35301,7 +35420,7 @@ function assertExplicitBridgeLock(preferredPort, explicitPort, lock) {
35301
35420
  async function ensureRuntimeForOpen() {
35302
35421
  if (resolveDevCheckoutRuntimeRoot()) return;
35303
35422
  const active = readActiveRuntime();
35304
- if (active && import_node_fs24.default.existsSync(runtimeDir(active))) return;
35423
+ if (active && import_node_fs25.default.existsSync(runtimeDir(active))) return;
35305
35424
  console.error(" installing peach engine runtime...");
35306
35425
  const { runRuntime: runRuntime2 } = await Promise.resolve().then(() => (init_runtime(), runtime_exports));
35307
35426
  await runRuntime2(["install"], {});
@@ -35455,10 +35574,10 @@ async function buildResolvedBundleOpenUrl(target, baseUrl, opts = {}) {
35455
35574
  }
35456
35575
  function normalizeReplacementPath(filePath) {
35457
35576
  if (filePath.startsWith("~/")) {
35458
- return import_node_path26.default.join(import_node_os4.default.homedir(), filePath.slice(2));
35577
+ return import_node_path27.default.join(import_node_os4.default.homedir(), filePath.slice(2));
35459
35578
  }
35460
- if (import_node_path26.default.isAbsolute(filePath)) return filePath;
35461
- return import_node_path26.default.resolve(process.cwd(), filePath);
35579
+ if (import_node_path27.default.isAbsolute(filePath)) return filePath;
35580
+ return import_node_path27.default.resolve(process.cwd(), filePath);
35462
35581
  }
35463
35582
  function parseOpenRuntimeConfig(args) {
35464
35583
  const modules = {};
@@ -35477,7 +35596,7 @@ function parseOpenRuntimeConfig(args) {
35477
35596
  }
35478
35597
  const moduleName = raw.slice(0, eqIndex).trim();
35479
35598
  const filePath = normalizeReplacementPath(raw.slice(eqIndex + 1).trim());
35480
- if (!import_node_fs24.default.existsSync(filePath)) {
35599
+ if (!import_node_fs25.default.existsSync(filePath)) {
35481
35600
  console.error(` peach open: replacement file not found: ${filePath}`);
35482
35601
  rnxExit(1);
35483
35602
  }
@@ -35508,7 +35627,7 @@ async function resolveAppProjectForBundleUrl(bundleUrl) {
35508
35627
  return advertisedRoot ? resolveAppProject(advertisedRoot) : null;
35509
35628
  }
35510
35629
  async function ensureConfiguredRuntime(version) {
35511
- if (import_node_fs24.default.existsSync(import_node_path26.default.join(runtimeDir(version), "index.html"))) return;
35630
+ if (import_node_fs25.default.existsSync(import_node_path27.default.join(runtimeDir(version), "index.html"))) return;
35512
35631
  console.error(` installing configured engine runtime ${version}...`);
35513
35632
  const result = await rnxRuntime.install({
35514
35633
  version,
@@ -35683,9 +35802,10 @@ async function buildShellUrl(target, baseUrl = resolveDefaultShellBaseUrl(), opt
35683
35802
  ),
35684
35803
  project
35685
35804
  );
35686
- if (!opts.device && !opts.proof && !opts.posture && !opts.osVersion && !opts.env?.length)
35805
+ if (!opts.device && !opts.proof && !opts.posture && !opts.osVersion && !opts.env?.length && !opts.dotEnv)
35687
35806
  return stamped;
35688
35807
  const url = new URL(stamped);
35808
+ if (opts.dotEnv) url.searchParams.set("dotEnv", JSON.stringify(opts.dotEnv));
35689
35809
  if (opts.device) url.searchParams.set("device", opts.device);
35690
35810
  if (opts.posture) url.searchParams.set("posture", opts.posture);
35691
35811
  if (opts.osVersion) url.searchParams.set("osVersion", opts.osVersion);
@@ -35823,7 +35943,7 @@ function playwrightHostPidForSim(sim) {
35823
35943
  function signalDriverLaunchConnected(result) {
35824
35944
  if (!result.connectAckFile) return false;
35825
35945
  try {
35826
- import_node_fs24.default.writeFileSync(
35946
+ import_node_fs25.default.writeFileSync(
35827
35947
  result.connectAckFile,
35828
35948
  `${JSON.stringify({ connectedAt: Date.now(), pid: result.pid ?? null })}
35829
35949
  `,
@@ -35837,19 +35957,19 @@ function signalDriverLaunchConnected(result) {
35837
35957
  function printDriverDiagnosticLogTail(result) {
35838
35958
  if (!result.diagnosticLogPath) return;
35839
35959
  try {
35840
- const detail = import_node_fs24.default.readFileSync(result.diagnosticLogPath, "utf8").trim();
35960
+ const detail = import_node_fs25.default.readFileSync(result.diagnosticLogPath, "utf8").trim();
35841
35961
  if (!detail) {
35842
- console.error(` ${import_node_path26.default.basename(result.diagnosticLogPath)} was empty`);
35962
+ console.error(` ${import_node_path27.default.basename(result.diagnosticLogPath)} was empty`);
35843
35963
  return;
35844
35964
  }
35845
35965
  const shown = detail.length > 4e3 ? `\u2026
35846
35966
  ${detail.slice(-4e3)}` : detail;
35847
- console.error(` ${import_node_path26.default.basename(result.diagnosticLogPath)}:`);
35967
+ console.error(` ${import_node_path27.default.basename(result.diagnosticLogPath)}:`);
35848
35968
  console.error(shown);
35849
35969
  } catch (err) {
35850
35970
  const message = err instanceof Error ? err.message : String(err);
35851
35971
  console.error(
35852
- ` failed to read ${import_node_path26.default.basename(result.diagnosticLogPath)}: ${message}`
35972
+ ` failed to read ${import_node_path27.default.basename(result.diagnosticLogPath)}: ${message}`
35853
35973
  );
35854
35974
  }
35855
35975
  }
@@ -36092,7 +36212,8 @@ async function runOpenCommand(args, opts = {}) {
36092
36212
  "--no-hmr",
36093
36213
  "--no-describe",
36094
36214
  "--quiet",
36095
- "--proof"
36215
+ "--proof",
36216
+ "--load-env"
36096
36217
  ],
36097
36218
  stripValueFlags: [
36098
36219
  "--base-url",
@@ -36275,6 +36396,25 @@ async function runOpenCommand(args, opts = {}) {
36275
36396
  rnxExit(1);
36276
36397
  }
36277
36398
  const explicitViewport = viewportMatch ? { width: Number(viewportMatch[1]), height: Number(viewportMatch[2]) } : void 0;
36399
+ let dotEnv;
36400
+ if (args.includes("--load-env")) {
36401
+ if (!project) {
36402
+ console.error(
36403
+ " peach open: --load-env needs a local app project to read the env file from"
36404
+ );
36405
+ rnxExit(1);
36406
+ }
36407
+ try {
36408
+ const result2 = readProjectDotEnv(project.appDir);
36409
+ if (!quiet) for (const notice of result2.notices) console.log(` ${notice}`);
36410
+ dotEnv = result2.config;
36411
+ } catch (error) {
36412
+ console.error(
36413
+ ` peach open: ${error instanceof Error ? error.message : String(error)}`
36414
+ );
36415
+ rnxExit(1);
36416
+ }
36417
+ }
36278
36418
  const buildShellUrlOpts = {
36279
36419
  hot: hotMode,
36280
36420
  device: deviceArg,
@@ -36283,7 +36423,8 @@ async function runOpenCommand(args, opts = {}) {
36283
36423
  resolvedBundle,
36284
36424
  project,
36285
36425
  proof: args.includes("--proof"),
36286
- env: envArgs.length ? envArgs : void 0
36426
+ env: envArgs.length ? envArgs : void 0,
36427
+ dotEnv
36287
36428
  };
36288
36429
  const selectedShellBaseUrl = configuredRuntimeVersion ? `http://localhost:${parsed.wsPort}/` : explicitBaseUrl || resolveShellBaseUrlForBridgePort(parsed.wsPort);
36289
36430
  const baseUrl = applyRuntimeGenerationOrigin(
@@ -36797,14 +36938,14 @@ async function runCloseCommand(args, opts = {}) {
36797
36938
  bridge.close();
36798
36939
  }
36799
36940
  }
36800
- var import_node_child_process7, import_node_fs24, import_node_os4, import_node_path26, import_app_catalog_wire, import_devices2, import_ws4, DEFAULT_DRIVER_CONNECT_TIMEOUT_MS, DRIVER_CONNECT_INTERVAL_MS, DRIVER_CONNECT_HOST_GRACE_MS, OPEN_BRIDGE_SPAWN_TIMEOUT_MS, SHELL_APPS, DEV_BUNDLE_RESOLVE_ATTEMPTS, DEV_BUNDLE_RESOLVE_INTERVAL_MS;
36941
+ var import_node_child_process7, import_node_fs25, import_node_os4, import_node_path27, import_app_catalog_wire, import_devices2, import_ws4, DEFAULT_DRIVER_CONNECT_TIMEOUT_MS, DRIVER_CONNECT_INTERVAL_MS, DRIVER_CONNECT_HOST_GRACE_MS, OPEN_BRIDGE_SPAWN_TIMEOUT_MS, SHELL_APPS, DEV_BUNDLE_RESOLVE_ATTEMPTS, DEV_BUNDLE_RESOLVE_INTERVAL_MS;
36801
36942
  var init_control = __esm({
36802
36943
  "cli/commands/control.ts"() {
36803
36944
  "use strict";
36804
36945
  import_node_child_process7 = require("node:child_process");
36805
- import_node_fs24 = __toESM(require("node:fs"), 1);
36946
+ import_node_fs25 = __toESM(require("node:fs"), 1);
36806
36947
  import_node_os4 = __toESM(require("node:os"), 1);
36807
- import_node_path26 = __toESM(require("node:path"), 1);
36948
+ import_node_path27 = __toESM(require("node:path"), 1);
36808
36949
  import_app_catalog_wire = require("peach-engine/engine/app-catalog-wire");
36809
36950
  import_devices2 = require("peach-engine/settings/devices");
36810
36951
  import_ws4 = require("ws");
@@ -36814,6 +36955,7 @@ var init_control = __esm({
36814
36955
  init_bridge_constants();
36815
36956
  init_config();
36816
36957
  init_dev_bundle_resolution();
36958
+ init_dot_env();
36817
36959
  init_flow_timeout_scale();
36818
36960
  init_home_paths();
36819
36961
  init_native_dev_bundle_url();
@@ -38149,16 +38291,16 @@ function readRecentShellAppId(state) {
38149
38291
  }
38150
38292
  function resolveProjectRelativeFlowBase(flowDir) {
38151
38293
  if (!flowDir) return process.cwd();
38152
- return path20.basename(flowDir) === ".maestro" ? path20.dirname(flowDir) : flowDir;
38294
+ return path21.basename(flowDir) === ".maestro" ? path21.dirname(flowDir) : flowDir;
38153
38295
  }
38154
38296
  function resolveFlowScreenshotPathWithMode(screenshotDir, name2, opts) {
38155
38297
  const normalizedName = name2.endsWith(".png") ? name2 : `${name2}.png`;
38156
- if (path20.isAbsolute(normalizedName)) return normalizedName;
38298
+ if (path21.isAbsolute(normalizedName)) return normalizedName;
38157
38299
  if (opts.mode === "flow" && /[\\/]/.test(normalizedName)) {
38158
38300
  const baseDir = normalizedName.startsWith("./") || normalizedName.startsWith("../") ? opts.flowDir ?? process.cwd() : resolveProjectRelativeFlowBase(opts.flowDir);
38159
- return path20.resolve(baseDir, normalizedName);
38301
+ return path21.resolve(baseDir, normalizedName);
38160
38302
  }
38161
- return path20.join(screenshotDir, normalizedName);
38303
+ return path21.join(screenshotDir, normalizedName);
38162
38304
  }
38163
38305
  function normalizeFlowScreenshotSpec(step) {
38164
38306
  if (typeof step === "string") {
@@ -38215,12 +38357,12 @@ function parseFlowSteps(content) {
38215
38357
  const parsed = import_yaml2.default.parse(candidate);
38216
38358
  return Array.isArray(parsed) ? parsed : [];
38217
38359
  }
38218
- var fs20, path20, import_devices4, import_yaml2, import_proof_frame, DEFAULT_TIMEOUT, ASSERTION_LOOKUP_MS, FLOW_TIMEOUT_SCALE, scaledTimeout, MAESTRO_SELECTOR_KEYS, SELECTOR_FILTER_KEYS, UNSUPPORTED_SELECTOR_KEYS, ACCESSIBILITY_SELECTOR_KEYS, ACCESSIBILITY_TRAIT_FILTERS, MAESTRO_PERMISSION_KINDS, MAESTRO_PERMISSION_STATUS, SootSimBridgeFlowRunner;
38360
+ var fs21, path21, import_devices4, import_yaml2, import_proof_frame, DEFAULT_TIMEOUT, ASSERTION_LOOKUP_MS, FLOW_TIMEOUT_SCALE, scaledTimeout, MAESTRO_SELECTOR_KEYS, SELECTOR_FILTER_KEYS, UNSUPPORTED_SELECTOR_KEYS, ACCESSIBILITY_SELECTOR_KEYS, ACCESSIBILITY_TRAIT_FILTERS, MAESTRO_PERMISSION_KINDS, MAESTRO_PERMISSION_STATUS, SootSimBridgeFlowRunner;
38219
38361
  var init_bridge_flow_runner = __esm({
38220
38362
  "cli/bridge-flow-runner.ts"() {
38221
38363
  "use strict";
38222
- fs20 = __toESM(require("fs"), 1);
38223
- path20 = __toESM(require("path"), 1);
38364
+ fs21 = __toESM(require("fs"), 1);
38365
+ path21 = __toESM(require("path"), 1);
38224
38366
  import_devices4 = require("peach-engine/settings/devices");
38225
38367
  import_yaml2 = __toESM(require("yaml"), 1);
38226
38368
  import_proof_frame = __toESM(require_proof_frame(), 1);
@@ -38546,14 +38688,14 @@ var init_bridge_flow_runner = __esm({
38546
38688
  if (chunks.length === 0) {
38547
38689
  throw new Error("recording requested but no video buffer was produced");
38548
38690
  }
38549
- fs20.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
38691
+ fs21.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
38550
38692
  const videoMime = stopped.mime || this.opts.recordingFormat || "video/webm";
38551
38693
  const extension = videoMime.includes("mp4") ? "mp4" : "webm";
38552
- const outputPath = path20.join(
38694
+ const outputPath = path21.join(
38553
38695
  this.opts.recordingOutputDir,
38554
38696
  `peach-${Date.now()}.${extension}`
38555
38697
  );
38556
- fs20.writeFileSync(outputPath, Buffer.concat(chunks));
38698
+ fs21.writeFileSync(outputPath, Buffer.concat(chunks));
38557
38699
  return outputPath;
38558
38700
  }
38559
38701
  async waitForRecordingTail(opts) {
@@ -39229,7 +39371,7 @@ var init_bridge_flow_runner = __esm({
39229
39371
  flowDir: this.opts.flowDir
39230
39372
  }
39231
39373
  );
39232
- fs20.mkdirSync(path20.dirname(outputPath), { recursive: true });
39374
+ fs21.mkdirSync(path21.dirname(outputPath), { recursive: true });
39233
39375
  const layers = spec.layers ?? this.opts.screenshotLayers;
39234
39376
  const screenshotRequest = {
39235
39377
  type: "screenshot",
@@ -39264,11 +39406,11 @@ var init_bridge_flow_runner = __esm({
39264
39406
  throw new Error("could not read current device model for framed screenshot");
39265
39407
  }
39266
39408
  const framed = await composeFramedScreenshot(rawBuffer, model);
39267
- fs20.writeFileSync(outputPath, framed);
39409
+ fs21.writeFileSync(outputPath, framed);
39268
39410
  console.log(`[flow] screenshot: ${outputPath} (frame: ${model})`);
39269
39411
  return outputPath;
39270
39412
  }
39271
- fs20.writeFileSync(outputPath, rawBuffer);
39413
+ fs21.writeFileSync(outputPath, rawBuffer);
39272
39414
  console.log(`[flow] screenshot: ${outputPath}`);
39273
39415
  return outputPath;
39274
39416
  }
@@ -39290,10 +39432,10 @@ var init_bridge_flow_runner = __esm({
39290
39432
  // + a11y tree + console errors/warnings + failed network requests +
39291
39433
  // shell state, all under one directory so post-mortem is one grep away.
39292
39434
  async captureFailureBundle(outputDir, context) {
39293
- fs20.mkdirSync(outputDir, { recursive: true });
39435
+ fs21.mkdirSync(outputDir, { recursive: true });
39294
39436
  const write = (name2, content) => {
39295
39437
  try {
39296
- fs20.writeFileSync(path20.join(outputDir, name2), content);
39438
+ fs21.writeFileSync(path21.join(outputDir, name2), content);
39297
39439
  } catch {
39298
39440
  }
39299
39441
  };
@@ -39891,8 +40033,8 @@ var init_bridge_flow_runner = __esm({
39891
40033
  runScript(target) {
39892
40034
  const spec = typeof target === "string" ? { file: target } : target;
39893
40035
  if (!spec.file) throw new Error("runScript requires a file");
39894
- const scriptPath = path20.resolve(this.opts.flowDir, spec.file);
39895
- const source = fs20.readFileSync(scriptPath, "utf8");
40036
+ const scriptPath = path21.resolve(this.opts.flowDir, spec.file);
40037
+ const source = fs21.readFileSync(scriptPath, "utf8");
39896
40038
  this.js.evaluate(source, { env: spec.env });
39897
40039
  console.log(`[flow] runScript: ${spec.file} done`);
39898
40040
  }
@@ -40252,10 +40394,10 @@ var init_bridge_flow_runner = __esm({
40252
40394
  for (const [k, v] of Object.entries(env)) this.js.putEnv(k, v);
40253
40395
  }
40254
40396
  if (file) {
40255
- const flowPath = path20.resolve(this.opts.flowDir, file);
40256
- const flowContent = fs20.readFileSync(flowPath, "utf8");
40397
+ const flowPath = path21.resolve(this.opts.flowDir, file);
40398
+ const flowContent = fs21.readFileSync(flowPath, "utf8");
40257
40399
  const previousDir = this.opts.flowDir;
40258
- this.opts.flowDir = path20.dirname(flowPath);
40400
+ this.opts.flowDir = path21.dirname(flowPath);
40259
40401
  try {
40260
40402
  await this.runFlow(parseFlowSteps(flowContent));
40261
40403
  } finally {
@@ -40426,8 +40568,8 @@ __export(registry_exports, {
40426
40568
  skillRegistry: () => skillRegistry
40427
40569
  });
40428
40570
  module.exports = __toCommonJS(registry_exports);
40429
- var fs21 = __toESM(require("fs"), 1);
40430
- var path21 = __toESM(require("path"), 1);
40571
+ var fs22 = __toESM(require("fs"), 1);
40572
+ var path22 = __toESM(require("path"), 1);
40431
40573
 
40432
40574
  // src/skills/builtin/a11y-review.ts
40433
40575
  init_reap_browser();
@@ -40446,8 +40588,8 @@ var skill = {
40446
40588
  },
40447
40589
  async execute(params, context) {
40448
40590
  const { chromium } = await import("playwright");
40449
- const path22 = await import("path");
40450
- const fs22 = await import("fs");
40591
+ const path23 = await import("path");
40592
+ const fs23 = await import("fs");
40451
40593
  const browser = await launchReapedChrome((options) => chromium.launch(options), {
40452
40594
  headless: true
40453
40595
  });
@@ -40502,9 +40644,9 @@ var skill = {
40502
40644
  warnings: issues.filter((i) => i.severity === "warning").length,
40503
40645
  tree: typeof tree === "string" ? tree : JSON.stringify(tree)
40504
40646
  };
40505
- const reportPath = path22.join(context.outputDir, "a11y-report.json");
40506
- fs22.mkdirSync(path22.dirname(reportPath), { recursive: true });
40507
- fs22.writeFileSync(reportPath, JSON.stringify(report, null, 2));
40647
+ const reportPath = path23.join(context.outputDir, "a11y-report.json");
40648
+ fs23.mkdirSync(path23.dirname(reportPath), { recursive: true });
40649
+ fs23.writeFileSync(reportPath, JSON.stringify(report, null, 2));
40508
40650
  return {
40509
40651
  success: issues.filter((i) => i.severity === "error").length === 0,
40510
40652
  message: `${report.errors} errors, ${report.warnings} warnings across ${report.nodeCount} nodes`,
@@ -40537,14 +40679,14 @@ var skill2 = {
40537
40679
  }
40538
40680
  },
40539
40681
  async execute(params, context) {
40540
- const fs22 = await import("node:fs");
40541
- const path22 = await import("node:path");
40682
+ const fs23 = await import("node:fs");
40683
+ const path23 = await import("node:path");
40542
40684
  const { COMPAT_RESULT_CAVEAT: COMPAT_RESULT_CAVEAT2, formatPackageStatus: formatPackageStatus2, formatScanCounts: formatScanCounts2, scanDeps: scanDeps2 } = await Promise.resolve().then(() => (init_web(), web_exports));
40543
- const packagePath = path22.join(context.projectDir, "package.json");
40544
- if (!fs22.existsSync(packagePath)) {
40685
+ const packagePath = path23.join(context.projectDir, "package.json");
40686
+ if (!fs23.existsSync(packagePath)) {
40545
40687
  return { success: false, message: "No package.json found" };
40546
40688
  }
40547
- const parsed = JSON.parse(fs22.readFileSync(packagePath, "utf8"));
40689
+ const parsed = JSON.parse(fs23.readFileSync(packagePath, "utf8"));
40548
40690
  if (!parsed || typeof parsed !== "object") {
40549
40691
  return { success: false, message: "package.json is not an object" };
40550
40692
  }
@@ -40556,9 +40698,9 @@ var skill2 = {
40556
40698
  }) : scanDeps2(parsed);
40557
40699
  const packageResult = params.packageName ? scan.packages[0] : void 0;
40558
40700
  const message = packageResult ? `${params.packageName}: ${formatPackageStatus2(packageResult)}. ${COMPAT_RESULT_CAVEAT2}` : `${formatScanCounts2(scan)}. ${COMPAT_RESULT_CAVEAT2}`;
40559
- const reportPath = path22.join(context.outputDir, "compat-report.json");
40560
- fs22.mkdirSync(path22.dirname(reportPath), { recursive: true });
40561
- fs22.writeFileSync(reportPath, `${JSON.stringify(scan, null, 2)}
40701
+ const reportPath = path23.join(context.outputDir, "compat-report.json");
40702
+ fs23.mkdirSync(path23.dirname(reportPath), { recursive: true });
40703
+ fs23.writeFileSync(reportPath, `${JSON.stringify(scan, null, 2)}
40562
40704
  `);
40563
40705
  return {
40564
40706
  success: true,
@@ -40600,8 +40742,8 @@ var skill3 = {
40600
40742
  record: { type: "boolean", description: "Record video of the flow" }
40601
40743
  },
40602
40744
  async execute(params, context) {
40603
- const fs22 = await import("fs");
40604
- const path22 = await import("path");
40745
+ const fs23 = await import("fs");
40746
+ const path23 = await import("path");
40605
40747
  const yaml2 = await import("yaml");
40606
40748
  const { DEFAULT_SOOTSIM_BRIDGE_PORT: DEFAULT_SOOTSIM_BRIDGE_PORT3 } = await Promise.resolve().then(() => (init_bridge_constants(), bridge_constants_exports));
40607
40749
  const { SootSimBridgeHost: SootSimBridgeHost2 } = await Promise.resolve().then(() => (init_bridge_host(), bridge_host_exports));
@@ -40611,7 +40753,7 @@ var skill3 = {
40611
40753
  const host = new SootSimBridgeHost2({ port: DEFAULT_SOOTSIM_BRIDGE_PORT3 });
40612
40754
  host.start({ silent: true });
40613
40755
  try {
40614
- const flowContent = fs22.readFileSync(params.flowPath, "utf8");
40756
+ const flowContent = fs23.readFileSync(params.flowPath, "utf8");
40615
40757
  const fmMatch = flowContent.match(/^---\n([\s\S]*?)\n---\n?/);
40616
40758
  const stepsBody = fmMatch ? flowContent.slice(fmMatch[0].length) : flowContent;
40617
40759
  const steps = yaml2.parse(stepsBody);
@@ -40638,7 +40780,7 @@ var skill3 = {
40638
40780
  });
40639
40781
  const driver = new SootSimBridgeFlowRunner2(bridge, {
40640
40782
  screenshotDir: context.outputDir,
40641
- flowDir: path22.dirname(path22.resolve(params.flowPath)),
40783
+ flowDir: path23.dirname(path23.resolve(params.flowPath)),
40642
40784
  simId,
40643
40785
  recordingOutputDir: params.record ? context.outputDir : void 0
40644
40786
  });
@@ -40660,7 +40802,7 @@ var skill3 = {
40660
40802
  simId,
40661
40803
  videoPath: videoPath || void 0
40662
40804
  },
40663
- artifacts: videoPath ? [{ type: "video", name: path22.basename(videoPath), path: videoPath }] : void 0
40805
+ artifacts: videoPath ? [{ type: "video", name: path23.basename(videoPath), path: videoPath }] : void 0
40664
40806
  };
40665
40807
  } finally {
40666
40808
  try {
@@ -40707,8 +40849,8 @@ var skill4 = {
40707
40849
  },
40708
40850
  async execute(params, context) {
40709
40851
  const { chromium } = await import("playwright");
40710
- const path22 = await import("path");
40711
- const fs22 = await import("fs");
40852
+ const path23 = await import("path");
40853
+ const fs23 = await import("fs");
40712
40854
  const browser = await launchReapedChrome((options) => chromium.launch(options), {
40713
40855
  headless: true
40714
40856
  });
@@ -40734,9 +40876,9 @@ var skill4 = {
40734
40876
  ...profile,
40735
40877
  fps: syncCount > 0 ? (syncCount / (duration / 1e3)).toFixed(1) : "0"
40736
40878
  };
40737
- const reportPath = path22.join(context.outputDir, "perf-report.json");
40738
- fs22.mkdirSync(path22.dirname(reportPath), { recursive: true });
40739
- fs22.writeFileSync(reportPath, JSON.stringify(report, null, 2));
40879
+ const reportPath = path23.join(context.outputDir, "perf-report.json");
40880
+ fs23.mkdirSync(path23.dirname(reportPath), { recursive: true });
40881
+ fs23.writeFileSync(reportPath, JSON.stringify(report, null, 2));
40740
40882
  return {
40741
40883
  success: true,
40742
40884
  message: `${report.fps} fps, ${profile.avgSyncMs?.toFixed(1)}ms avg sync, ${nodeCount} nodes`,
@@ -40769,8 +40911,8 @@ var skill5 = {
40769
40911
  },
40770
40912
  async execute(params, context) {
40771
40913
  const { chromium } = await import("playwright");
40772
- const path22 = await import("path");
40773
- const fs22 = await import("fs");
40914
+ const path23 = await import("path");
40915
+ const fs23 = await import("fs");
40774
40916
  const browser = await launchReapedChrome((options) => chromium.launch(options), {
40775
40917
  headless: true
40776
40918
  });
@@ -40778,8 +40920,8 @@ var skill5 = {
40778
40920
  try {
40779
40921
  await page.goto(context.url, { waitUntil: "networkidle" });
40780
40922
  await page.waitForTimeout(2e3);
40781
- const outputPath = path22.join(context.outputDir, `${params.name}.png`);
40782
- fs22.mkdirSync(path22.dirname(outputPath), { recursive: true });
40923
+ const outputPath = path23.join(context.outputDir, `${params.name}.png`);
40924
+ fs23.mkdirSync(path23.dirname(outputPath), { recursive: true });
40783
40925
  await page.screenshot({ path: outputPath });
40784
40926
  return {
40785
40927
  success: true,
@@ -40820,8 +40962,8 @@ var skill6 = {
40820
40962
  },
40821
40963
  async execute(params, context) {
40822
40964
  const { chromium } = await import("playwright");
40823
- const path22 = await import("path");
40824
- const fs22 = await import("fs");
40965
+ const path23 = await import("path");
40966
+ const fs23 = await import("fs");
40825
40967
  const browser = await launchReapedChrome((options) => chromium.launch(options), {
40826
40968
  headless: true
40827
40969
  });
@@ -40829,14 +40971,14 @@ var skill6 = {
40829
40971
  try {
40830
40972
  await page.goto(context.url, { waitUntil: "networkidle" });
40831
40973
  await page.waitForTimeout(2e3);
40832
- const currentPath = path22.join(context.outputDir, `${params.name}-current.png`);
40833
- fs22.mkdirSync(path22.dirname(currentPath), { recursive: true });
40974
+ const currentPath = path23.join(context.outputDir, `${params.name}-current.png`);
40975
+ fs23.mkdirSync(path23.dirname(currentPath), { recursive: true });
40834
40976
  await page.screenshot({ path: currentPath });
40835
40977
  try {
40836
40978
  const { PNG } = await import("pngjs");
40837
40979
  const pixelmatch = (await import("pixelmatch")).default;
40838
- const baseline = PNG.sync.read(fs22.readFileSync(params.baseline));
40839
- const current = PNG.sync.read(fs22.readFileSync(currentPath));
40980
+ const baseline = PNG.sync.read(fs23.readFileSync(params.baseline));
40981
+ const current = PNG.sync.read(fs23.readFileSync(currentPath));
40840
40982
  const { width, height } = baseline;
40841
40983
  const diff = new PNG({ width, height });
40842
40984
  const numDiffPixels = pixelmatch(
@@ -40847,8 +40989,8 @@ var skill6 = {
40847
40989
  height,
40848
40990
  { threshold: params.threshold || 0.1 }
40849
40991
  );
40850
- const diffPath = path22.join(context.outputDir, `${params.name}-diff.png`);
40851
- fs22.writeFileSync(diffPath, PNG.sync.write(diff));
40992
+ const diffPath = path23.join(context.outputDir, `${params.name}-diff.png`);
40993
+ fs23.writeFileSync(diffPath, PNG.sync.write(diff));
40852
40994
  const totalPixels = width * height;
40853
40995
  const diffPercent = (numDiffPixels / totalPixels * 100).toFixed(2);
40854
40996
  return {
@@ -40912,10 +41054,10 @@ var skillRegistry = {
40912
41054
  },
40913
41055
  // load skills from a project manifest (rnx-skills.json)
40914
41056
  async loadFromManifest(projectDir) {
40915
- const manifestPath = path21.join(projectDir, "rnx-skills.json");
40916
- if (!fs21.existsSync(manifestPath)) return;
41057
+ const manifestPath = path22.join(projectDir, "rnx-skills.json");
41058
+ if (!fs22.existsSync(manifestPath)) return;
40917
41059
  try {
40918
- const manifest = JSON.parse(fs21.readFileSync(manifestPath, "utf8"));
41060
+ const manifest = JSON.parse(fs22.readFileSync(manifestPath, "utf8"));
40919
41061
  if (Array.isArray(manifest.skills)) {
40920
41062
  for (const entry of manifest.skills) {
40921
41063
  if (typeof entry === "string") {
@@ -40926,7 +41068,7 @@ var skillRegistry = {
40926
41068
  }
40927
41069
  } else if (entry.file) {
40928
41070
  try {
40929
- const mod = await import(path21.resolve(projectDir, entry.file));
41071
+ const mod = await import(path22.resolve(projectDir, entry.file));
40930
41072
  if (mod.skill) this.register(mod.skill);
40931
41073
  } catch {
40932
41074
  }
@@ -40939,10 +41081,10 @@ var skillRegistry = {
40939
41081
  // auto-discover skills based on project dependencies
40940
41082
  suggestSkills(projectDir) {
40941
41083
  const suggestions = [];
40942
- const pkgPath = path21.join(projectDir, "package.json");
40943
- if (!fs21.existsSync(pkgPath)) return suggestions;
41084
+ const pkgPath = path22.join(projectDir, "package.json");
41085
+ if (!fs22.existsSync(pkgPath)) return suggestions;
40944
41086
  try {
40945
- const pkg = JSON.parse(fs21.readFileSync(pkgPath, "utf8"));
41087
+ const pkg = JSON.parse(fs22.readFileSync(pkgPath, "utf8"));
40946
41088
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
40947
41089
  if (deps["detox"] || deps["maestro"]) {
40948
41090
  suggestions.push("maestro-test");