rnxsim 0.1.516 → 0.1.518
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/detox/index.ts +56 -31
- 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 +29 -1
- package/dist-lib/cloud-contract.mjs +23 -1
- package/dist-lib/cloud.cjs +114 -16
- package/dist-lib/cloud.mjs +111 -16
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +30 -14
- 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/jump-to-source-native.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 +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/src/cloud-contract.ts +37 -1
- package/src/cloud.ts +178 -21
package/detox/index.ts
CHANGED
|
@@ -1772,8 +1772,15 @@ export const device = {
|
|
|
1772
1772
|
// once durationMs of lockstep time has elapsed, so held states (a lifted
|
|
1773
1773
|
// control thumb, a pressed row) are painted mid-hold. an external trigger
|
|
1774
1774
|
// that holds and releases before returning never paints a frame in
|
|
1775
|
-
// between, because no lockstep frame steps while it runs.
|
|
1776
|
-
|
|
1775
|
+
// between, because no lockstep frame steps while it runs. moves drag the
|
|
1776
|
+
// held pointer to each point once afterMs of lockstep time has elapsed
|
|
1777
|
+
// since the press, and the release lands at the last point reached.
|
|
1778
|
+
hold?: {
|
|
1779
|
+
durationMs: number
|
|
1780
|
+
moves?: Array<{ afterMs: number; x: number; y: number }>
|
|
1781
|
+
x: number
|
|
1782
|
+
y: number
|
|
1783
|
+
} | null
|
|
1777
1784
|
rootFrame?: { height: number; width: number; x: number; y: number } | null
|
|
1778
1785
|
settleMs?: number
|
|
1779
1786
|
trigger?: () => unknown
|
|
@@ -1851,6 +1858,7 @@ export const device = {
|
|
|
1851
1858
|
bridges?: {
|
|
1852
1859
|
interact?: {
|
|
1853
1860
|
touchDown: (x: number, y: number) => Promise<boolean>
|
|
1861
|
+
touchMove: (x: number, y: number) => Promise<boolean>
|
|
1854
1862
|
touchUp: (x: number, y: number) => Promise<boolean>
|
|
1855
1863
|
}
|
|
1856
1864
|
liveComposite?: {
|
|
@@ -1982,23 +1990,45 @@ export const device = {
|
|
|
1982
1990
|
const frameMs = 1000 / 60
|
|
1983
1991
|
const controller = await lockstep.begin(60)
|
|
1984
1992
|
// the hold's pointer goes down before the first stepped frame, so its
|
|
1985
|
-
// start is one frame before the first receipt;
|
|
1986
|
-
// first stepped frame at or past
|
|
1987
|
-
//
|
|
1988
|
-
// duration lets rounding push
|
|
1989
|
-
const
|
|
1993
|
+
// start is one frame before the first receipt; each move and the release
|
|
1994
|
+
// land on the first stepped frame at or past their time from there. the
|
|
1995
|
+
// deadlines are frame indexes: comparing summed virtual timestamps
|
|
1996
|
+
// against a duration lets rounding push an event past its frame.
|
|
1997
|
+
const moves = input.hold?.moves ?? []
|
|
1998
|
+
const holdState = {
|
|
1999
|
+
nextMove: 0,
|
|
2000
|
+
pressFrameIndex: null as number | null,
|
|
1990
2001
|
released: false,
|
|
1991
|
-
|
|
2002
|
+
x: input.hold?.x ?? 0,
|
|
2003
|
+
y: input.hold?.y ?? 0,
|
|
1992
2004
|
}
|
|
1993
|
-
const
|
|
2005
|
+
const holdEventFrameIndex = (afterMs: number) =>
|
|
2006
|
+
(holdState.pressFrameIndex ?? 0) + Math.ceil(afterMs / frameMs)
|
|
2007
|
+
const nextHoldEventFrameIndex = () => {
|
|
2008
|
+
if (!input.hold || holdState.released || holdState.pressFrameIndex === null) {
|
|
2009
|
+
return null
|
|
2010
|
+
}
|
|
2011
|
+
const move = moves[holdState.nextMove]
|
|
2012
|
+
return holdEventFrameIndex(move ? move.afterMs : input.hold.durationMs)
|
|
2013
|
+
}
|
|
2014
|
+
const advanceHold = async (receipt: FrameReceipt) => {
|
|
1994
2015
|
if (!input.hold || !interact || holdState.released) return
|
|
1995
|
-
if (holdState.
|
|
1996
|
-
holdState.
|
|
1997
|
-
|
|
2016
|
+
if (holdState.pressFrameIndex === null) {
|
|
2017
|
+
holdState.pressFrameIndex = receipt.frameIndex - 1
|
|
2018
|
+
}
|
|
2019
|
+
for (
|
|
2020
|
+
let move = moves[holdState.nextMove];
|
|
2021
|
+
move && receipt.frameIndex >= holdEventFrameIndex(move.afterMs);
|
|
2022
|
+
move = moves[holdState.nextMove]
|
|
2023
|
+
) {
|
|
2024
|
+
holdState.nextMove++
|
|
2025
|
+
holdState.x = move.x
|
|
2026
|
+
holdState.y = move.y
|
|
2027
|
+
await interact.touchMove(move.x, move.y)
|
|
1998
2028
|
}
|
|
1999
|
-
if (receipt.frameIndex <
|
|
2029
|
+
if (receipt.frameIndex < holdEventFrameIndex(input.hold.durationMs)) return
|
|
2000
2030
|
holdState.released = true
|
|
2001
|
-
await interact.touchUp(
|
|
2031
|
+
await interact.touchUp(holdState.x, holdState.y)
|
|
2002
2032
|
}
|
|
2003
2033
|
try {
|
|
2004
2034
|
const baselineBitmap = await captureBitmap()
|
|
@@ -2023,7 +2053,7 @@ export const device = {
|
|
|
2023
2053
|
for (let frame = 0; frame < detectionFrameLimit; frame++) {
|
|
2024
2054
|
if (state.cancelled) throw new Error('rnx motion capture was cancelled')
|
|
2025
2055
|
const receipt = await controller.stepFrame()
|
|
2026
|
-
await
|
|
2056
|
+
await advanceHold(receipt)
|
|
2027
2057
|
const candidateBitmap = await captureBitmap()
|
|
2028
2058
|
const bounds = boundsFor(candidateBitmap)
|
|
2029
2059
|
const measurement = measureChange({
|
|
@@ -2050,25 +2080,20 @@ export const device = {
|
|
|
2050
2080
|
const snapshots: Snapshot[] = []
|
|
2051
2081
|
for (const stage of input.stages) {
|
|
2052
2082
|
if (state.cancelled) throw new Error('rnx motion capture was cancelled')
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2083
|
+
// step through every hold move and the release that fall before
|
|
2084
|
+
// this stage one frame at a time, so the stage paints the pointer
|
|
2085
|
+
// where it belongs rather than a hold the jump skipped past.
|
|
2086
|
+
const stageFrameIndex =
|
|
2087
|
+
visibleStart.frameIndex + Math.ceil(stage.offsetMs / frameMs)
|
|
2088
|
+
for (
|
|
2089
|
+
let eventFrameIndex = nextHoldEventFrameIndex();
|
|
2090
|
+
eventFrameIndex !== null && stageFrameIndex > eventFrameIndex;
|
|
2091
|
+
eventFrameIndex = nextHoldEventFrameIndex()
|
|
2057
2092
|
) {
|
|
2058
|
-
|
|
2059
|
-
// so the stage paints the released state rather than a hold
|
|
2060
|
-
// that overran because the jump skipped its deadline.
|
|
2061
|
-
const stageFrameIndex =
|
|
2062
|
-
visibleStart.frameIndex + Math.ceil(stage.offsetMs / frameMs)
|
|
2063
|
-
while (
|
|
2064
|
-
!holdState.released &&
|
|
2065
|
-
stageFrameIndex > holdState.releaseFrameIndex
|
|
2066
|
-
) {
|
|
2067
|
-
await releaseHoldIfDue(await controller.stepFrame())
|
|
2068
|
-
}
|
|
2093
|
+
await advanceHold(await controller.stepFrame())
|
|
2069
2094
|
}
|
|
2070
2095
|
const receipt = await controller.stepToOffset(visibleStart, stage.offsetMs)
|
|
2071
|
-
await
|
|
2096
|
+
await advanceHold(receipt)
|
|
2072
2097
|
snapshots.push({
|
|
2073
2098
|
actualMs: receipt.virtualTimestampMs - visibleStart.virtualTimestampMs,
|
|
2074
2099
|
bitmap: await captureBitmap(),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.518 | (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.518 | (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.518 | (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.518 | (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.518 | (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.518 | (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.518 | (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.518 | (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.518 | (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.518 | (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.518 | (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.518 | (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.518 | (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.518 | (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;
|
|
@@ -30,9 +30,15 @@ __export(cloud_contract_exports, {
|
|
|
30
30
|
RNX_CLOUD_LABELS_MAX_COUNT: () => RNX_CLOUD_LABELS_MAX_COUNT,
|
|
31
31
|
RNX_CLOUD_LABEL_MAX_LENGTH: () => RNX_CLOUD_LABEL_MAX_LENGTH,
|
|
32
32
|
RNX_CLOUD_MAX_ARTIFACT_BYTES: () => RNX_CLOUD_MAX_ARTIFACT_BYTES,
|
|
33
|
+
RNX_CLOUD_SCOPED_TOKEN_DEFAULT_TTL_SECONDS: () => RNX_CLOUD_SCOPED_TOKEN_DEFAULT_TTL_SECONDS,
|
|
34
|
+
RNX_CLOUD_SCOPED_TOKEN_MAX_ORIGINS: () => RNX_CLOUD_SCOPED_TOKEN_MAX_ORIGINS,
|
|
35
|
+
RNX_CLOUD_SCOPED_TOKEN_MAX_TTL_SECONDS: () => RNX_CLOUD_SCOPED_TOKEN_MAX_TTL_SECONDS,
|
|
36
|
+
RNX_CLOUD_SCOPED_TOKEN_MIN_TTL_SECONDS: () => RNX_CLOUD_SCOPED_TOKEN_MIN_TTL_SECONDS,
|
|
37
|
+
RNX_CLOUD_SCOPED_TOKEN_PREFIX: () => RNX_CLOUD_SCOPED_TOKEN_PREFIX,
|
|
33
38
|
RNX_CLOUD_TEST_FILES_MAX_BYTES: () => RNX_CLOUD_TEST_FILES_MAX_BYTES,
|
|
34
39
|
RNX_CLOUD_TEST_FILES_MAX_COUNT: () => RNX_CLOUD_TEST_FILES_MAX_COUNT,
|
|
35
40
|
RNX_CLOUD_TOKEN_SCOPES: () => RNX_CLOUD_TOKEN_SCOPES,
|
|
41
|
+
isRnxCloudCommandScope: () => isRnxCloudCommandScope,
|
|
36
42
|
isRnxCloudCommandType: () => isRnxCloudCommandType,
|
|
37
43
|
isRnxCloudSimStatus: () => isRnxCloudSimStatus,
|
|
38
44
|
isValidRnxCloudLabel: () => isValidRnxCloudLabel,
|
|
@@ -48,6 +54,22 @@ var RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES = 256;
|
|
|
48
54
|
var RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024;
|
|
49
55
|
var RNX_CLOUD_TEST_FILES_MAX_COUNT = 256;
|
|
50
56
|
var RNX_CLOUD_TEST_FILES_MAX_BYTES = 5e5;
|
|
57
|
+
var RNX_CLOUD_COMMAND_SCOPE_SET = /* @__PURE__ */ new Set([
|
|
58
|
+
"read",
|
|
59
|
+
"drive",
|
|
60
|
+
"reset",
|
|
61
|
+
"media",
|
|
62
|
+
"debug",
|
|
63
|
+
"watch"
|
|
64
|
+
]);
|
|
65
|
+
function isRnxCloudCommandScope(value) {
|
|
66
|
+
return RNX_CLOUD_COMMAND_SCOPE_SET.has(value);
|
|
67
|
+
}
|
|
68
|
+
var RNX_CLOUD_SCOPED_TOKEN_PREFIX = "sk_rnx_sim_";
|
|
69
|
+
var RNX_CLOUD_SCOPED_TOKEN_DEFAULT_TTL_SECONDS = 3600;
|
|
70
|
+
var RNX_CLOUD_SCOPED_TOKEN_MIN_TTL_SECONDS = 1;
|
|
71
|
+
var RNX_CLOUD_SCOPED_TOKEN_MAX_TTL_SECONDS = 14400;
|
|
72
|
+
var RNX_CLOUD_SCOPED_TOKEN_MAX_ORIGINS = 16;
|
|
51
73
|
var RNX_CLOUD_COMMAND_SCOPES = {
|
|
52
74
|
state: "read",
|
|
53
75
|
tree: "read",
|
|
@@ -152,9 +174,15 @@ function isRnxCloudSimStatus(value) {
|
|
|
152
174
|
RNX_CLOUD_LABELS_MAX_COUNT,
|
|
153
175
|
RNX_CLOUD_LABEL_MAX_LENGTH,
|
|
154
176
|
RNX_CLOUD_MAX_ARTIFACT_BYTES,
|
|
177
|
+
RNX_CLOUD_SCOPED_TOKEN_DEFAULT_TTL_SECONDS,
|
|
178
|
+
RNX_CLOUD_SCOPED_TOKEN_MAX_ORIGINS,
|
|
179
|
+
RNX_CLOUD_SCOPED_TOKEN_MAX_TTL_SECONDS,
|
|
180
|
+
RNX_CLOUD_SCOPED_TOKEN_MIN_TTL_SECONDS,
|
|
181
|
+
RNX_CLOUD_SCOPED_TOKEN_PREFIX,
|
|
155
182
|
RNX_CLOUD_TEST_FILES_MAX_BYTES,
|
|
156
183
|
RNX_CLOUD_TEST_FILES_MAX_COUNT,
|
|
157
184
|
RNX_CLOUD_TOKEN_SCOPES,
|
|
185
|
+
isRnxCloudCommandScope,
|
|
158
186
|
isRnxCloudCommandType,
|
|
159
187
|
isRnxCloudSimStatus,
|
|
160
188
|
isValidRnxCloudLabel,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.518 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
|
|
3
3
|
// src/cloud-contract.ts
|
|
4
4
|
var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
|
|
@@ -6,6 +6,22 @@ var RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES = 256;
|
|
|
6
6
|
var RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024;
|
|
7
7
|
var RNX_CLOUD_TEST_FILES_MAX_COUNT = 256;
|
|
8
8
|
var RNX_CLOUD_TEST_FILES_MAX_BYTES = 5e5;
|
|
9
|
+
var RNX_CLOUD_COMMAND_SCOPE_SET = /* @__PURE__ */ new Set([
|
|
10
|
+
"read",
|
|
11
|
+
"drive",
|
|
12
|
+
"reset",
|
|
13
|
+
"media",
|
|
14
|
+
"debug",
|
|
15
|
+
"watch"
|
|
16
|
+
]);
|
|
17
|
+
function isRnxCloudCommandScope(value) {
|
|
18
|
+
return RNX_CLOUD_COMMAND_SCOPE_SET.has(value);
|
|
19
|
+
}
|
|
20
|
+
var RNX_CLOUD_SCOPED_TOKEN_PREFIX = "sk_rnx_sim_";
|
|
21
|
+
var RNX_CLOUD_SCOPED_TOKEN_DEFAULT_TTL_SECONDS = 3600;
|
|
22
|
+
var RNX_CLOUD_SCOPED_TOKEN_MIN_TTL_SECONDS = 1;
|
|
23
|
+
var RNX_CLOUD_SCOPED_TOKEN_MAX_TTL_SECONDS = 14400;
|
|
24
|
+
var RNX_CLOUD_SCOPED_TOKEN_MAX_ORIGINS = 16;
|
|
9
25
|
var RNX_CLOUD_COMMAND_SCOPES = {
|
|
10
26
|
state: "read",
|
|
11
27
|
tree: "read",
|
|
@@ -109,9 +125,15 @@ export {
|
|
|
109
125
|
RNX_CLOUD_LABELS_MAX_COUNT,
|
|
110
126
|
RNX_CLOUD_LABEL_MAX_LENGTH,
|
|
111
127
|
RNX_CLOUD_MAX_ARTIFACT_BYTES,
|
|
128
|
+
RNX_CLOUD_SCOPED_TOKEN_DEFAULT_TTL_SECONDS,
|
|
129
|
+
RNX_CLOUD_SCOPED_TOKEN_MAX_ORIGINS,
|
|
130
|
+
RNX_CLOUD_SCOPED_TOKEN_MAX_TTL_SECONDS,
|
|
131
|
+
RNX_CLOUD_SCOPED_TOKEN_MIN_TTL_SECONDS,
|
|
132
|
+
RNX_CLOUD_SCOPED_TOKEN_PREFIX,
|
|
112
133
|
RNX_CLOUD_TEST_FILES_MAX_BYTES,
|
|
113
134
|
RNX_CLOUD_TEST_FILES_MAX_COUNT,
|
|
114
135
|
RNX_CLOUD_TOKEN_SCOPES,
|
|
136
|
+
isRnxCloudCommandScope,
|
|
115
137
|
isRnxCloudCommandType,
|
|
116
138
|
isRnxCloudSimStatus,
|
|
117
139
|
isValidRnxCloudLabel,
|
package/dist-lib/cloud.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.518 | (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;
|
|
@@ -24,8 +24,11 @@ var cloud_exports = {};
|
|
|
24
24
|
__export(cloud_exports, {
|
|
25
25
|
RNX_CLOUD_COMMAND_TYPES: () => RNX_CLOUD_COMMAND_TYPES,
|
|
26
26
|
RNX_CLOUD_MAX_ARTIFACT_BYTES: () => RNX_CLOUD_MAX_ARTIFACT_BYTES,
|
|
27
|
+
RNX_CLOUD_SCOPED_TOKEN_PREFIX: () => RNX_CLOUD_SCOPED_TOKEN_PREFIX,
|
|
27
28
|
RemoteSimulator: () => RemoteSimulator,
|
|
29
|
+
connect: () => connect,
|
|
28
30
|
createRemoteSimulator: () => createRemoteSimulator,
|
|
31
|
+
isRnxCloudCommandScope: () => isRnxCloudCommandScope,
|
|
29
32
|
isRnxCloudCommandType: () => isRnxCloudCommandType
|
|
30
33
|
});
|
|
31
34
|
module.exports = __toCommonJS(cloud_exports);
|
|
@@ -99,6 +102,18 @@ function isRnxScreenCapture(value) {
|
|
|
99
102
|
// src/cloud-contract.ts
|
|
100
103
|
var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
|
|
101
104
|
var RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024;
|
|
105
|
+
var RNX_CLOUD_COMMAND_SCOPE_SET = /* @__PURE__ */ new Set([
|
|
106
|
+
"read",
|
|
107
|
+
"drive",
|
|
108
|
+
"reset",
|
|
109
|
+
"media",
|
|
110
|
+
"debug",
|
|
111
|
+
"watch"
|
|
112
|
+
]);
|
|
113
|
+
function isRnxCloudCommandScope(value) {
|
|
114
|
+
return RNX_CLOUD_COMMAND_SCOPE_SET.has(value);
|
|
115
|
+
}
|
|
116
|
+
var RNX_CLOUD_SCOPED_TOKEN_PREFIX = "sk_rnx_sim_";
|
|
102
117
|
var RNX_CLOUD_COMMAND_SCOPES = {
|
|
103
118
|
state: "read",
|
|
104
119
|
tree: "read",
|
|
@@ -336,7 +351,7 @@ function readBoxCreate(value, expectedBytes, expectedSha256) {
|
|
|
336
351
|
simulatorToken: simulator.token
|
|
337
352
|
};
|
|
338
353
|
}
|
|
339
|
-
function cloudCommand(command) {
|
|
354
|
+
function cloudCommand(command, scopes) {
|
|
340
355
|
const clean = {};
|
|
341
356
|
for (const [key, value] of Object.entries(command)) {
|
|
342
357
|
if (key !== "id" && key !== "simId") clean[key] = value;
|
|
@@ -344,7 +359,7 @@ function cloudCommand(command) {
|
|
|
344
359
|
if (!isRnxCloudCommandType(command.type)) {
|
|
345
360
|
throw new Error(`RNX Cloud does not support bridge command type ${command.type}`);
|
|
346
361
|
}
|
|
347
|
-
if (!rnxCloudScopesAllowCommand(
|
|
362
|
+
if (!rnxCloudScopesAllowCommand(scopes, command.type)) {
|
|
348
363
|
throw new Error(
|
|
349
364
|
`RNX Cloud command ${command.type} requires the ${rnxCloudCommandScope(command.type)} scope`
|
|
350
365
|
);
|
|
@@ -391,7 +406,10 @@ var RemoteSimulator = class {
|
|
|
391
406
|
}
|
|
392
407
|
return result;
|
|
393
408
|
},
|
|
394
|
-
reset: () => this.sendCommand({ type: "reset" })
|
|
409
|
+
reset: () => this.sendCommand({ type: "reset" }),
|
|
410
|
+
state: (options) => this.sendCommand(
|
|
411
|
+
options === void 0 ? { type: "state" } : { type: "state", stateOptions: options }
|
|
412
|
+
)
|
|
395
413
|
};
|
|
396
414
|
}
|
|
397
415
|
get simId() {
|
|
@@ -400,7 +418,13 @@ var RemoteSimulator = class {
|
|
|
400
418
|
get claim() {
|
|
401
419
|
return this.session.claim;
|
|
402
420
|
}
|
|
421
|
+
get scopes() {
|
|
422
|
+
return this.session.scopes;
|
|
423
|
+
}
|
|
403
424
|
get receipt() {
|
|
425
|
+
if (!this.session.claim) {
|
|
426
|
+
throw new Error("this simulator was attached with connect() and holds no claim");
|
|
427
|
+
}
|
|
404
428
|
return {
|
|
405
429
|
simId: this.session.simId,
|
|
406
430
|
artifact: this.session.artifact,
|
|
@@ -410,8 +434,10 @@ var RemoteSimulator = class {
|
|
|
410
434
|
async sendCommand(command, options) {
|
|
411
435
|
const body = {
|
|
412
436
|
id: globalThis.crypto.randomUUID(),
|
|
413
|
-
|
|
414
|
-
|
|
437
|
+
// a scoped token drives without a claim: the service checks the token
|
|
438
|
+
// instead. a full token still joins the claim it names here.
|
|
439
|
+
claimId: this.session.claim?.id ?? "",
|
|
440
|
+
command: cloudCommand(command, this.session.scopes)
|
|
415
441
|
};
|
|
416
442
|
let response;
|
|
417
443
|
try {
|
|
@@ -450,6 +476,10 @@ var RemoteSimulator = class {
|
|
|
450
476
|
return parsed.result;
|
|
451
477
|
}
|
|
452
478
|
async confirm() {
|
|
479
|
+
if (!this.session.claim) {
|
|
480
|
+
throw new Error("this simulator was attached with connect() and holds no claim");
|
|
481
|
+
}
|
|
482
|
+
const claimId = this.session.claim.id;
|
|
453
483
|
const response = await fetchWithCloudRetry(
|
|
454
484
|
`${this.session.origin}/v1/sims/${encodeURIComponent(this.session.simId)}/claim`,
|
|
455
485
|
{
|
|
@@ -458,7 +488,7 @@ var RemoteSimulator = class {
|
|
|
458
488
|
authorization: `Bearer ${this.session.simulatorToken}`,
|
|
459
489
|
"content-type": "application/json"
|
|
460
490
|
},
|
|
461
|
-
body: JSON.stringify({ claimId
|
|
491
|
+
body: JSON.stringify({ claimId })
|
|
462
492
|
}
|
|
463
493
|
);
|
|
464
494
|
const text = await response.text();
|
|
@@ -470,20 +500,24 @@ var RemoteSimulator = class {
|
|
|
470
500
|
throw new Error("RNX Cloud claim returned unreadable JSON");
|
|
471
501
|
}
|
|
472
502
|
const claim = readClaim(isRecord(parsed) ? parsed.claim : null);
|
|
473
|
-
if (claim.id !==
|
|
503
|
+
if (claim.id !== claimId) {
|
|
474
504
|
throw new Error("RNX Cloud confirmation replaced the initial claim");
|
|
475
505
|
}
|
|
476
506
|
this.session = { ...this.session, claim };
|
|
477
507
|
return claim;
|
|
478
508
|
}
|
|
479
509
|
async close() {
|
|
480
|
-
const
|
|
481
|
-
`${this.session.origin}/v1/boxes/${encodeURIComponent(this.session.boxId)}`,
|
|
482
|
-
{
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
|
|
510
|
+
const target = this.session.boxId !== null && this.session.boxToken !== null ? {
|
|
511
|
+
url: `${this.session.origin}/v1/boxes/${encodeURIComponent(this.session.boxId)}`,
|
|
512
|
+
authorization: `Bearer ${this.session.boxToken}`
|
|
513
|
+
} : {
|
|
514
|
+
url: `${this.session.origin}/v1/sims/${encodeURIComponent(this.session.simId)}`,
|
|
515
|
+
authorization: `Bearer ${this.session.simulatorToken}`
|
|
516
|
+
};
|
|
517
|
+
const response = await fetchWithCloudRetry(target.url, {
|
|
518
|
+
method: "DELETE",
|
|
519
|
+
headers: { authorization: target.authorization }
|
|
520
|
+
});
|
|
487
521
|
const text = await response.text();
|
|
488
522
|
if (!response.ok && response.status !== 404) {
|
|
489
523
|
throw responseError(response.status, text);
|
|
@@ -541,16 +575,80 @@ async function createRemoteSimulator(input) {
|
|
|
541
575
|
simId: created.receipt.simulator.simId,
|
|
542
576
|
simulatorToken: created.simulatorToken,
|
|
543
577
|
claim: created.receipt.simulator.claim,
|
|
544
|
-
artifact: created.receipt.artifact
|
|
578
|
+
artifact: created.receipt.artifact,
|
|
579
|
+
scopes: RNX_CLOUD_TOKEN_SCOPES
|
|
545
580
|
});
|
|
546
581
|
await simulator.confirm();
|
|
547
582
|
return simulator;
|
|
548
583
|
}
|
|
584
|
+
function readSimArtifact(value) {
|
|
585
|
+
if (!isRecord(value) || typeof value.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(value.sha256) || typeof value.bytes !== "number" || !Number.isInteger(value.bytes) || value.bytes <= 0) {
|
|
586
|
+
throw new Error("RNX Cloud returned an invalid simulator artifact");
|
|
587
|
+
}
|
|
588
|
+
return { id: `sha256:${value.sha256}`, bytes: value.bytes };
|
|
589
|
+
}
|
|
590
|
+
function readConnectClaim(value) {
|
|
591
|
+
if (value === null) return null;
|
|
592
|
+
return readClaim(value);
|
|
593
|
+
}
|
|
594
|
+
function readConnectScopes(value, token) {
|
|
595
|
+
if (!token.startsWith(RNX_CLOUD_SCOPED_TOKEN_PREFIX)) return RNX_CLOUD_TOKEN_SCOPES;
|
|
596
|
+
if (!isRecord(value) || typeof value.id !== "string" || !value.id || !Array.isArray(value.scopes) || value.scopes.length === 0 || !value.scopes.every(
|
|
597
|
+
(scope) => typeof scope === "string" && isRnxCloudCommandScope(scope)
|
|
598
|
+
) || typeof value.expiresAt !== "number") {
|
|
599
|
+
throw new Error("RNX Cloud returned an invalid scoped token");
|
|
600
|
+
}
|
|
601
|
+
return Object.freeze([...value.scopes]);
|
|
602
|
+
}
|
|
603
|
+
async function connect(input) {
|
|
604
|
+
if (!input.id) throw new Error("RNX Cloud connect needs a simulator id");
|
|
605
|
+
if (!input.token) throw new Error("RNX Cloud connect needs a token");
|
|
606
|
+
const origin = resolveOrigin(input.origin);
|
|
607
|
+
let response;
|
|
608
|
+
try {
|
|
609
|
+
response = await fetchWithCloudRetry(
|
|
610
|
+
`${origin}/v1/sims/${encodeURIComponent(input.id)}`,
|
|
611
|
+
{ headers: { authorization: `Bearer ${input.token}` } }
|
|
612
|
+
);
|
|
613
|
+
} catch (error) {
|
|
614
|
+
throw new Error(
|
|
615
|
+
`could not reach RNX Cloud at ${origin}: ${error instanceof Error ? error.message : String(error)}`
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
const text = await response.text();
|
|
619
|
+
if (!response.ok) throw responseError(response.status, text);
|
|
620
|
+
let parsed;
|
|
621
|
+
try {
|
|
622
|
+
parsed = JSON.parse(text);
|
|
623
|
+
} catch {
|
|
624
|
+
throw new Error("RNX Cloud connect returned unreadable JSON");
|
|
625
|
+
}
|
|
626
|
+
if (!isRecord(parsed) || !isRecord(parsed.sim)) {
|
|
627
|
+
throw new Error("RNX Cloud connect returned an invalid simulator");
|
|
628
|
+
}
|
|
629
|
+
const sim = parsed.sim;
|
|
630
|
+
if (typeof sim.simId !== "string" || !sim.simId) {
|
|
631
|
+
throw new Error("RNX Cloud connect returned an invalid simulator");
|
|
632
|
+
}
|
|
633
|
+
return new RemoteSimulator({
|
|
634
|
+
origin,
|
|
635
|
+
boxId: null,
|
|
636
|
+
boxToken: null,
|
|
637
|
+
simId: sim.simId,
|
|
638
|
+
simulatorToken: input.token,
|
|
639
|
+
claim: readConnectClaim(sim.claim ?? null),
|
|
640
|
+
artifact: readSimArtifact(sim.artifact),
|
|
641
|
+
scopes: readConnectScopes(isRecord(parsed) ? parsed.token : null, input.token)
|
|
642
|
+
});
|
|
643
|
+
}
|
|
549
644
|
// Annotate the CommonJS export names for ESM import in node:
|
|
550
645
|
0 && (module.exports = {
|
|
551
646
|
RNX_CLOUD_COMMAND_TYPES,
|
|
552
647
|
RNX_CLOUD_MAX_ARTIFACT_BYTES,
|
|
648
|
+
RNX_CLOUD_SCOPED_TOKEN_PREFIX,
|
|
553
649
|
RemoteSimulator,
|
|
650
|
+
connect,
|
|
554
651
|
createRemoteSimulator,
|
|
652
|
+
isRnxCloudCommandScope,
|
|
555
653
|
isRnxCloudCommandType
|
|
556
654
|
});
|