rnxsim 0.1.446 → 0.1.448
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 +3 -0
- package/cli/bridge-flow-runner.ts +43 -59
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +1 -1
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +49 -51
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/src/shell-bridge-identity.ts +15 -0
- package/src/vite-plugin.ts +85 -52
package/README.md
CHANGED
|
@@ -174,6 +174,9 @@ During source development, each Vite bridge owns one
|
|
|
174
174
|
`~/.rnx/dev-bridges/<port>.json` heartbeat record. CLI defaults select the
|
|
175
175
|
current `PORT_OFFSET`, then the current checkout, then the canonical `:7668`
|
|
176
176
|
bridge, so concurrent worktrees cannot replace or delete one another's address.
|
|
177
|
+
Each Vite shell also publishes its exact bridge at `/__sootsim/bridge`, so a
|
|
178
|
+
launcher that reuses a shell from another isolated `RNX_HOME` stays in that
|
|
179
|
+
shell's bridge world without reading the other process's lockfile directory.
|
|
177
180
|
|
|
178
181
|
**The sim** is a browser/Electron *page* launched by a CLI driver. Inside that
|
|
179
182
|
page run three workers: the **shell worker** owns device and native state, the
|
|
@@ -719,25 +719,17 @@ export class SootSimBridgeFlowRunner {
|
|
|
719
719
|
)
|
|
720
720
|
}
|
|
721
721
|
|
|
722
|
-
private async findElement(opts: {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
// the childOf container's bounds (geometric containment mirrors "the X
|
|
732
|
-
// inside post Y" for vertically-stacked lists), then pick the nth.
|
|
733
|
-
if (opts.childOf != null || typeof opts.index === 'number') {
|
|
722
|
+
private async findElement(opts: FlowTargetSelector) {
|
|
723
|
+
// patterns and combined selectors need the full candidate set so id and
|
|
724
|
+
// text constrain the same node. literal single selectors keep the direct lookup.
|
|
725
|
+
if (
|
|
726
|
+
opts.childOf != null ||
|
|
727
|
+
typeof opts.index === 'number' ||
|
|
728
|
+
(opts.id && opts.text) ||
|
|
729
|
+
[opts.id, opts.text].some((value) => value && /[.*+?^$()[\]{}|\\]/.test(value))
|
|
730
|
+
) {
|
|
734
731
|
return this.findElementScoped(opts)
|
|
735
732
|
}
|
|
736
|
-
// maestro text selectors are REGEXPs (e.g. "users[,]? or feeds",
|
|
737
|
-
// ".*Reply 1.*"). only treat a selector as a pattern when it carries regex
|
|
738
|
-
// metacharacters AND the literal/a11y-label lookups miss, so ordinary copy
|
|
739
|
-
// ("Repost") never accidentally over-matches via regex.
|
|
740
|
-
const wantRegex = !!opts.text && /[.*+?^$()[\]{}|\\]/.test(opts.text)
|
|
741
733
|
return this.evaluate<any>(`(async () => {
|
|
742
734
|
const test = window.__sootsimTest
|
|
743
735
|
if (!test) return null
|
|
@@ -762,23 +754,6 @@ export class SootSimBridgeFlowRunner {
|
|
|
762
754
|
labelled
|
|
763
755
|
}
|
|
764
756
|
}
|
|
765
|
-
if (!node && ${JSON.stringify(wantRegex)} && test.queryAll) {
|
|
766
|
-
// regex selector fallback: match the pattern against each visible
|
|
767
|
-
// node's text; prefer the narrowest matching node so a tight <text>
|
|
768
|
-
// wins over a wide container that merely contains it.
|
|
769
|
-
let re = null
|
|
770
|
-
try { re = new RegExp(${JSON.stringify(opts.text || '')}) } catch (e) { re = null }
|
|
771
|
-
if (re) {
|
|
772
|
-
const all = (await test.queryAll({ pruneHidden: true })) || []
|
|
773
|
-
const hits = all.filter(
|
|
774
|
-
(n) =>
|
|
775
|
-
n && n.absolutePosition && n.layout &&
|
|
776
|
-
typeof n.text === 'string' && re.test(n.text),
|
|
777
|
-
)
|
|
778
|
-
hits.sort((a, b) => (a.text || '').length - (b.text || '').length)
|
|
779
|
-
if (hits[0]) node = hits[0]
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
757
|
}
|
|
783
758
|
if (!node && ${JSON.stringify(!!opts.id)}) {
|
|
784
759
|
node = (await test.findByTestId(${JSON.stringify(opts.id || '')})) || (await test.findById(${JSON.stringify(opts.id || '')}))
|
|
@@ -799,30 +774,32 @@ export class SootSimBridgeFlowRunner {
|
|
|
799
774
|
// maestro `index:` (nth match) and `childOf:` (match scoped to a container)
|
|
800
775
|
// resolver. queryAll returns every matching node in tree order; childOf keeps
|
|
801
776
|
// only candidates whose center sits inside the container's bounds.
|
|
802
|
-
private async findElementScoped(opts: {
|
|
803
|
-
text?: string
|
|
804
|
-
id?: string
|
|
805
|
-
index?: number
|
|
806
|
-
childOf?: { id?: string; text?: string }
|
|
807
|
-
}) {
|
|
777
|
+
private async findElementScoped(opts: FlowTargetSelector) {
|
|
808
778
|
const index = typeof opts.index === 'number' ? opts.index : 0
|
|
809
779
|
return this.evaluate<any>(`(async () => {
|
|
810
780
|
const test = window.__sootsimTest
|
|
811
781
|
if (!test || !test.queryAll) return null
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
782
|
+
const compile = (value) => {
|
|
783
|
+
if (!value) return null
|
|
784
|
+
let pattern = null
|
|
785
|
+
try { pattern = new RegExp(value) } catch {}
|
|
786
|
+
return (candidate) => typeof candidate === 'string' &&
|
|
787
|
+
(candidate === value || !!pattern?.test(candidate))
|
|
788
|
+
}
|
|
789
|
+
const matchesId = compile(${JSON.stringify(opts.id)})
|
|
790
|
+
const matchesText = compile(${JSON.stringify(opts.text)})
|
|
791
|
+
const all = ((await test.queryAll({})) || []).filter(
|
|
792
|
+
(n) => n && n.absolutePosition && n.layout,
|
|
793
|
+
)
|
|
794
|
+
let candidates = all.filter((n) =>
|
|
795
|
+
(!matchesId || matchesId(n.testID) || matchesId(n.id)) &&
|
|
796
|
+
(!matchesText || matchesText(n.text) || matchesText(n.accessibilityLabel)),
|
|
797
|
+
)
|
|
798
|
+
const literalText = candidates.filter((n) =>
|
|
799
|
+
n.text === ${JSON.stringify(opts.text)} ||
|
|
800
|
+
n.accessibilityLabel === ${JSON.stringify(opts.text)},
|
|
801
|
+
)
|
|
802
|
+
if (matchesText && literalText.length > 0) candidates = literalText
|
|
826
803
|
// prefer on-screen matches (findByTestId's visible-first behavior); only
|
|
827
804
|
// fall back to off-screen ones when nothing is on-screen, so index: still
|
|
828
805
|
// resolves a target that needs scrolling into view.
|
|
@@ -834,11 +811,12 @@ export class SootSimBridgeFlowRunner {
|
|
|
834
811
|
${
|
|
835
812
|
opts.childOf
|
|
836
813
|
? `
|
|
837
|
-
const
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
814
|
+
const matchesContainerId = compile(${JSON.stringify(opts.childOf.id)})
|
|
815
|
+
const matchesContainerText = compile(${JSON.stringify(opts.childOf.text)})
|
|
816
|
+
const container = all.find((n) =>
|
|
817
|
+
(!matchesContainerId || matchesContainerId(n.testID) || matchesContainerId(n.id)) &&
|
|
818
|
+
(!matchesContainerText || matchesContainerText(n.text) || matchesContainerText(n.accessibilityLabel)),
|
|
819
|
+
)
|
|
842
820
|
if (!container || !container.absolutePosition || !container.layout) return null
|
|
843
821
|
const x0 = container.absolutePosition.x
|
|
844
822
|
const y0 = container.absolutePosition.y
|
|
@@ -851,6 +829,9 @@ export class SootSimBridgeFlowRunner {
|
|
|
851
829
|
})`
|
|
852
830
|
: ''
|
|
853
831
|
}
|
|
832
|
+
if (${JSON.stringify(opts.index === undefined && !!opts.text && !opts.id)}) {
|
|
833
|
+
candidates.sort((a, b) => (a.text || '').length - (b.text || '').length)
|
|
834
|
+
}
|
|
854
835
|
const node = candidates[${index}]
|
|
855
836
|
if (!node) return null
|
|
856
837
|
return {
|
|
@@ -1922,6 +1903,9 @@ export class SootSimBridgeFlowRunner {
|
|
|
1922
1903
|
if (!this.firstLaunchDone) {
|
|
1923
1904
|
this.firstLaunchDone = true
|
|
1924
1905
|
if (wantsClear) {
|
|
1906
|
+
// bundle evaluation temporarily installs a reload bridge without the
|
|
1907
|
+
// storage contract. wait for the app before its first data reset.
|
|
1908
|
+
if (!this.appStopped) await this.waitForTree(120000)
|
|
1925
1909
|
await this.resetGuestAppData({
|
|
1926
1910
|
launchArguments: hasLaunchArguments ? launchArguments : null,
|
|
1927
1911
|
initialUrl: null,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/beta.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/beta.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/cloud.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/cloud.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
package/dist-lib/config.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/detox/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/home-paths.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
|
|
3
3
|
// src/host/fetch-proxy-overrides.ts
|
|
4
4
|
var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/menu.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/menu.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/metro.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
package/dist-lib/profiles.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/render-mode.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
package/dist-lib/sdk.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/sdk.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
|
@@ -693,25 +693,25 @@ var init_capability_inventory_coverage = __esm({
|
|
|
693
693
|
ios: {
|
|
694
694
|
combined: {
|
|
695
695
|
raw: {
|
|
696
|
-
covered:
|
|
697
|
-
ratio: 0.
|
|
696
|
+
covered: 233,
|
|
697
|
+
ratio: 0.167505391804,
|
|
698
698
|
total: 1391
|
|
699
699
|
},
|
|
700
700
|
weighted: {
|
|
701
|
-
covered: 1.
|
|
702
|
-
ratio: 0.
|
|
701
|
+
covered: 1.63749741651,
|
|
702
|
+
ratio: 0.34247124121,
|
|
703
703
|
total: 4.78141583721
|
|
704
704
|
}
|
|
705
705
|
},
|
|
706
706
|
semantic: {
|
|
707
707
|
raw: {
|
|
708
|
-
covered:
|
|
709
|
-
ratio: 0.
|
|
708
|
+
covered: 233,
|
|
709
|
+
ratio: 0.233935742972,
|
|
710
710
|
total: 996
|
|
711
711
|
},
|
|
712
712
|
weighted: {
|
|
713
|
-
covered: 1.
|
|
714
|
-
ratio: 0.
|
|
713
|
+
covered: 1.63749741651,
|
|
714
|
+
ratio: 0.683483499504,
|
|
715
715
|
total: 2.39581119032
|
|
716
716
|
}
|
|
717
717
|
},
|
|
@@ -1334,13 +1334,13 @@ var init_capability_outcomes2 = __esm({
|
|
|
1334
1334
|
assessed: 0
|
|
1335
1335
|
},
|
|
1336
1336
|
ios: {
|
|
1337
|
-
passedWeight: 0,
|
|
1338
|
-
failedWeight:
|
|
1339
|
-
unassessedWeight: 0.
|
|
1340
|
-
totalWeight: 0.
|
|
1341
|
-
assessedWeight: 0,
|
|
1342
|
-
compatibility:
|
|
1343
|
-
assessed: 0
|
|
1337
|
+
passedWeight: 0.32201435438317577,
|
|
1338
|
+
failedWeight: 22084925244e-15,
|
|
1339
|
+
unassessedWeight: 0.6351092493870464,
|
|
1340
|
+
totalWeight: 0.9571456886954661,
|
|
1341
|
+
assessedWeight: 0.3220364393084198,
|
|
1342
|
+
compatibility: 0.9999314210364161,
|
|
1343
|
+
assessed: 0.3364549860192514
|
|
1344
1344
|
}
|
|
1345
1345
|
}
|
|
1346
1346
|
},
|
|
@@ -1749,7 +1749,7 @@ var init_supported_native_packages = __esm({
|
|
|
1749
1749
|
"posthog-react-native-session-replay",
|
|
1750
1750
|
// preset+coverage
|
|
1751
1751
|
"react-native",
|
|
1752
|
-
// preset+visual-proof
|
|
1752
|
+
// preset+visual-proof
|
|
1753
1753
|
"react-native-actions-shortcuts",
|
|
1754
1754
|
// coverage
|
|
1755
1755
|
"react-native-adjust",
|
|
@@ -32174,10 +32174,9 @@ var init_bridge_flow_runner = __esm({
|
|
|
32174
32174
|
);
|
|
32175
32175
|
}
|
|
32176
32176
|
async findElement(opts) {
|
|
32177
|
-
if (opts.childOf != null || typeof opts.index === "number") {
|
|
32177
|
+
if (opts.childOf != null || typeof opts.index === "number" || opts.id && opts.text || [opts.id, opts.text].some((value) => value && /[.*+?^$()[\]{}|\\]/.test(value))) {
|
|
32178
32178
|
return this.findElementScoped(opts);
|
|
32179
32179
|
}
|
|
32180
|
-
const wantRegex = !!opts.text && /[.*+?^$()[\]{}|\\]/.test(opts.text);
|
|
32181
32180
|
return this.evaluate(`(async () => {
|
|
32182
32181
|
const test = window.__sootsimTest
|
|
32183
32182
|
if (!test) return null
|
|
@@ -32202,23 +32201,6 @@ var init_bridge_flow_runner = __esm({
|
|
|
32202
32201
|
labelled
|
|
32203
32202
|
}
|
|
32204
32203
|
}
|
|
32205
|
-
if (!node && ${JSON.stringify(wantRegex)} && test.queryAll) {
|
|
32206
|
-
// regex selector fallback: match the pattern against each visible
|
|
32207
|
-
// node's text; prefer the narrowest matching node so a tight <text>
|
|
32208
|
-
// wins over a wide container that merely contains it.
|
|
32209
|
-
let re = null
|
|
32210
|
-
try { re = new RegExp(${JSON.stringify(opts.text || "")}) } catch (e) { re = null }
|
|
32211
|
-
if (re) {
|
|
32212
|
-
const all = (await test.queryAll({ pruneHidden: true })) || []
|
|
32213
|
-
const hits = all.filter(
|
|
32214
|
-
(n) =>
|
|
32215
|
-
n && n.absolutePosition && n.layout &&
|
|
32216
|
-
typeof n.text === 'string' && re.test(n.text),
|
|
32217
|
-
)
|
|
32218
|
-
hits.sort((a, b) => (a.text || '').length - (b.text || '').length)
|
|
32219
|
-
if (hits[0]) node = hits[0]
|
|
32220
|
-
}
|
|
32221
|
-
}
|
|
32222
32204
|
}
|
|
32223
32205
|
if (!node && ${JSON.stringify(!!opts.id)}) {
|
|
32224
32206
|
node = (await test.findByTestId(${JSON.stringify(opts.id || "")})) || (await test.findById(${JSON.stringify(opts.id || "")}))
|
|
@@ -32243,20 +32225,27 @@ var init_bridge_flow_runner = __esm({
|
|
|
32243
32225
|
return this.evaluate(`(async () => {
|
|
32244
32226
|
const test = window.__sootsimTest
|
|
32245
32227
|
if (!test || !test.queryAll) return null
|
|
32246
|
-
|
|
32247
|
-
|
|
32248
|
-
|
|
32249
|
-
|
|
32250
|
-
|
|
32251
|
-
|
|
32252
|
-
|
|
32253
|
-
|
|
32254
|
-
|
|
32255
|
-
|
|
32256
|
-
|
|
32257
|
-
|
|
32258
|
-
|
|
32259
|
-
|
|
32228
|
+
const compile = (value) => {
|
|
32229
|
+
if (!value) return null
|
|
32230
|
+
let pattern = null
|
|
32231
|
+
try { pattern = new RegExp(value) } catch {}
|
|
32232
|
+
return (candidate) => typeof candidate === 'string' &&
|
|
32233
|
+
(candidate === value || !!pattern?.test(candidate))
|
|
32234
|
+
}
|
|
32235
|
+
const matchesId = compile(${JSON.stringify(opts.id)})
|
|
32236
|
+
const matchesText = compile(${JSON.stringify(opts.text)})
|
|
32237
|
+
const all = ((await test.queryAll({})) || []).filter(
|
|
32238
|
+
(n) => n && n.absolutePosition && n.layout,
|
|
32239
|
+
)
|
|
32240
|
+
let candidates = all.filter((n) =>
|
|
32241
|
+
(!matchesId || matchesId(n.testID) || matchesId(n.id)) &&
|
|
32242
|
+
(!matchesText || matchesText(n.text) || matchesText(n.accessibilityLabel)),
|
|
32243
|
+
)
|
|
32244
|
+
const literalText = candidates.filter((n) =>
|
|
32245
|
+
n.text === ${JSON.stringify(opts.text)} ||
|
|
32246
|
+
n.accessibilityLabel === ${JSON.stringify(opts.text)},
|
|
32247
|
+
)
|
|
32248
|
+
if (matchesText && literalText.length > 0) candidates = literalText
|
|
32260
32249
|
// prefer on-screen matches (findByTestId's visible-first behavior); only
|
|
32261
32250
|
// fall back to off-screen ones when nothing is on-screen, so index: still
|
|
32262
32251
|
// resolves a target that needs scrolling into view.
|
|
@@ -32266,7 +32255,12 @@ var init_bridge_flow_runner = __esm({
|
|
|
32266
32255
|
})
|
|
32267
32256
|
if (onScreen.length > 0) candidates = onScreen
|
|
32268
32257
|
${opts.childOf ? `
|
|
32269
|
-
const
|
|
32258
|
+
const matchesContainerId = compile(${JSON.stringify(opts.childOf.id)})
|
|
32259
|
+
const matchesContainerText = compile(${JSON.stringify(opts.childOf.text)})
|
|
32260
|
+
const container = all.find((n) =>
|
|
32261
|
+
(!matchesContainerId || matchesContainerId(n.testID) || matchesContainerId(n.id)) &&
|
|
32262
|
+
(!matchesContainerText || matchesContainerText(n.text) || matchesContainerText(n.accessibilityLabel)),
|
|
32263
|
+
)
|
|
32270
32264
|
if (!container || !container.absolutePosition || !container.layout) return null
|
|
32271
32265
|
const x0 = container.absolutePosition.x
|
|
32272
32266
|
const y0 = container.absolutePosition.y
|
|
@@ -32277,6 +32271,9 @@ var init_bridge_flow_runner = __esm({
|
|
|
32277
32271
|
const cy = n.absolutePosition.y + n.layout.height / 2
|
|
32278
32272
|
return cx >= x0 && cx <= x1 && cy >= y0 && cy <= y1
|
|
32279
32273
|
})` : ""}
|
|
32274
|
+
if (${JSON.stringify(opts.index === void 0 && !!opts.text && !opts.id)}) {
|
|
32275
|
+
candidates.sort((a, b) => (a.text || '').length - (b.text || '').length)
|
|
32276
|
+
}
|
|
32280
32277
|
const node = candidates[${index}]
|
|
32281
32278
|
if (!node) return null
|
|
32282
32279
|
return {
|
|
@@ -33071,6 +33068,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
33071
33068
|
if (!this.firstLaunchDone) {
|
|
33072
33069
|
this.firstLaunchDone = true;
|
|
33073
33070
|
if (wantsClear) {
|
|
33071
|
+
if (!this.appStopped) await this.waitForTree(12e4);
|
|
33074
33072
|
await this.resetGuestAppData({
|
|
33075
33073
|
launchArguments: hasLaunchArguments ? launchArguments : null,
|
|
33076
33074
|
initialUrl: null
|
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.448 | (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;
|
package/package.json
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const SHELL_BRIDGE_IDENTITY_PATH = '/__sootsim/bridge'
|
|
2
|
+
|
|
3
|
+
export interface ShellBridgeIdentity {
|
|
4
|
+
schema: 1
|
|
5
|
+
bridgePort: number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function isShellBridgeIdentity(value: unknown): value is ShellBridgeIdentity {
|
|
9
|
+
if (typeof value !== 'object' || value === null) return false
|
|
10
|
+
return (
|
|
11
|
+
Reflect.get(value, 'schema') === 1 &&
|
|
12
|
+
Number.isInteger(Reflect.get(value, 'bridgePort')) &&
|
|
13
|
+
Reflect.get(value, 'bridgePort') > 0
|
|
14
|
+
)
|
|
15
|
+
}
|
package/src/vite-plugin.ts
CHANGED
|
@@ -23,6 +23,10 @@ import {
|
|
|
23
23
|
reactNativeDeepStubsForBuildResolver,
|
|
24
24
|
} from '../../compat/src/stub-manifest.ts'
|
|
25
25
|
import { resolveSootsimBridgePort } from './bridge-constants.ts'
|
|
26
|
+
import {
|
|
27
|
+
SHELL_BRIDGE_IDENTITY_PATH,
|
|
28
|
+
type ShellBridgeIdentity,
|
|
29
|
+
} from './shell-bridge-identity.ts'
|
|
26
30
|
import {
|
|
27
31
|
REANIMATED_WORKLETIZATION_REGEX,
|
|
28
32
|
shouldApplyWorkletsPlugin,
|
|
@@ -842,63 +846,92 @@ export function wsBridgePlugin(options: { ownedBridgePort?: number } = {}): Plug
|
|
|
842
846
|
name: 'sootsim-ws-bridge',
|
|
843
847
|
apply: 'serve',
|
|
844
848
|
configureServer(server) {
|
|
845
|
-
if (boundPort)
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
})
|
|
850
|
-
const readShellPort = () => {
|
|
851
|
-
const addr = server.httpServer?.address()
|
|
852
|
-
if (addr && typeof addr === 'object') return addr.port
|
|
853
|
-
return server.config.server.port || null
|
|
854
|
-
}
|
|
855
|
-
const existing = viteBridgeProcesses.get(preferredPort)
|
|
856
|
-
if (existing) {
|
|
857
|
-
existing.owners.add(owner)
|
|
858
|
-
existing.shellPort.read = readShellPort
|
|
859
|
-
boundPort = existing.boundPort
|
|
860
|
-
} else {
|
|
861
|
-
// lazy import to avoid pulling ws into the main bundle.
|
|
862
|
-
// note: the .ts extension is required on vite 8 / node ESM — without
|
|
863
|
-
// it, import() throws "Cannot find module" and the bridge silently
|
|
864
|
-
// never starts.
|
|
865
|
-
const shellPort = { read: readShellPort }
|
|
866
|
-
const host = import('./host/bridge-host.ts').then(({ SootSimBridgeHost }) => {
|
|
867
|
-
return new SootSimBridgeHost({
|
|
868
|
-
port: preferredPort,
|
|
869
|
-
writeDevLockfile: true,
|
|
870
|
-
getShellPort: () => shellPort.read(),
|
|
871
|
-
})
|
|
849
|
+
if (!boundPort) {
|
|
850
|
+
const preferredPort = resolveSootsimBridgePort({
|
|
851
|
+
explicitPort: process.env.SOOTSIM_BRIDGE_PORT,
|
|
852
|
+
portOffset: process.env.PORT_OFFSET,
|
|
872
853
|
})
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
.
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
854
|
+
const readShellPort = () => {
|
|
855
|
+
const addr = server.httpServer?.address()
|
|
856
|
+
if (addr && typeof addr === 'object') return addr.port
|
|
857
|
+
return server.config.server.port || null
|
|
858
|
+
}
|
|
859
|
+
const existing = viteBridgeProcesses.get(preferredPort)
|
|
860
|
+
if (existing) {
|
|
861
|
+
existing.owners.add(owner)
|
|
862
|
+
existing.shellPort.read = readShellPort
|
|
863
|
+
boundPort = existing.boundPort
|
|
864
|
+
} else {
|
|
865
|
+
// lazy import to avoid pulling ws into the main bundle.
|
|
866
|
+
// note: the .ts extension is required on vite 8 / node ESM — without
|
|
867
|
+
// it, import() throws "Cannot find module" and the bridge silently
|
|
868
|
+
// never starts.
|
|
869
|
+
const shellPort = { read: readShellPort }
|
|
870
|
+
const host = import('./host/bridge-host.ts').then(({ SootSimBridgeHost }) => {
|
|
871
|
+
return new SootSimBridgeHost({
|
|
872
|
+
port: preferredPort,
|
|
873
|
+
writeDevLockfile: true,
|
|
874
|
+
getShellPort: () => shellPort.read(),
|
|
875
|
+
})
|
|
883
876
|
})
|
|
884
|
-
|
|
885
|
-
boundPort
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
877
|
+
let entry: ViteBridgeProcessEntry
|
|
878
|
+
boundPort = host
|
|
879
|
+
.then((bridgeHost) => bridgeHost.startAsync({ silent: true }))
|
|
880
|
+
.catch((err: unknown) => {
|
|
881
|
+
if (viteBridgeProcesses.get(preferredPort) === entry) {
|
|
882
|
+
viteBridgeProcesses.delete(preferredPort)
|
|
883
|
+
}
|
|
884
|
+
const message = err instanceof Error ? err.message : String(err)
|
|
885
|
+
console.warn('[rnx] ws bridge failed to start:', message)
|
|
886
|
+
return null
|
|
887
|
+
})
|
|
888
|
+
entry = {
|
|
889
|
+
boundPort,
|
|
890
|
+
close: async () => {
|
|
891
|
+
try {
|
|
892
|
+
await (await host).close()
|
|
893
|
+
} catch {}
|
|
894
|
+
},
|
|
895
|
+
owners: new Set([owner]),
|
|
896
|
+
shellPort,
|
|
897
|
+
}
|
|
898
|
+
viteBridgeProcesses.set(preferredPort, entry)
|
|
893
899
|
}
|
|
894
|
-
|
|
900
|
+
|
|
901
|
+
server.httpServer?.once('close', () => {
|
|
902
|
+
const entry = viteBridgeProcesses.get(preferredPort)
|
|
903
|
+
if (!entry || !entry.owners.delete(owner) || entry.owners.size > 0) return
|
|
904
|
+
viteBridgeProcesses.delete(preferredPort)
|
|
905
|
+
void entry.close()
|
|
906
|
+
})
|
|
895
907
|
}
|
|
896
908
|
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
909
|
+
if (!boundPort) throw new Error('rnx bridge identity was not initialized')
|
|
910
|
+
const identityPort = boundPort
|
|
911
|
+
server.middlewares.use((req, res, next) => {
|
|
912
|
+
if (req.url?.split('?')[0] !== SHELL_BRIDGE_IDENTITY_PATH) {
|
|
913
|
+
next()
|
|
914
|
+
return
|
|
915
|
+
}
|
|
916
|
+
void identityPort
|
|
917
|
+
.then((bridgePort) => {
|
|
918
|
+
if (bridgePort === null) {
|
|
919
|
+
res.statusCode = 503
|
|
920
|
+
res.end('rnx bridge unavailable')
|
|
921
|
+
return
|
|
922
|
+
}
|
|
923
|
+
const identity = {
|
|
924
|
+
schema: 1,
|
|
925
|
+
bridgePort,
|
|
926
|
+
} satisfies ShellBridgeIdentity
|
|
927
|
+
res.setHeader('Content-Type', 'application/json')
|
|
928
|
+
res.setHeader('Cache-Control', 'no-store')
|
|
929
|
+
res.end(JSON.stringify(identity))
|
|
930
|
+
})
|
|
931
|
+
.catch(() => {
|
|
932
|
+
res.statusCode = 503
|
|
933
|
+
res.end('rnx bridge unavailable')
|
|
934
|
+
})
|
|
902
935
|
})
|
|
903
936
|
},
|
|
904
937
|
// publish the bound port to the page. head-prepend so it lands before the
|