peachsim 0.1.527 → 0.1.571
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 +28 -28
- package/cli/app-fonts.ts +1 -1
- package/cli/app-splash.ts +1 -1
- package/cli/bin.ts +1 -1
- package/cli/bridge-diagnostics.ts +1 -1
- package/cli/bridge-flow-runner.ts +72 -12
- package/cli/cloud-client.ts +273 -6
- package/cli/cloud-dispatch.ts +23 -2
- package/cli/cloud-session.ts +60 -4
- package/cli/cloud-test-result-files.ts +97 -0
- package/cli/cloud-test-tunnel.ts +354 -0
- package/cli/commands/box/bundle-plane.ts +2 -2
- package/cli/commands/box/checkout-plane.ts +1 -1
- package/cli/commands/box/rnx-command.ts +2 -2
- package/cli/commands/box/search-command.ts +2 -2
- package/cli/commands/box.ts +8 -8
- package/cli/commands/compat.ts +1 -1
- package/cli/commands/control.ts +22 -3
- package/cli/commands/detox.ts +1 -1
- package/cli/commands/device.ts +1 -1
- package/cli/commands/diagnose.ts +1 -1
- package/cli/commands/film.ts +1 -1
- package/cli/commands/flow.ts +60 -3
- package/cli/commands/inspect/actions.ts +1 -1
- package/cli/commands/inspect/core.ts +6 -7
- package/cli/commands/inspect/find.ts +2 -1
- package/cli/commands/inspect/resolve-target.ts +5 -3
- package/cli/commands/inspect/shared.ts +1 -1
- package/cli/commands/inspect/wait-event.ts +1 -1
- package/cli/commands/inspect/wait-selector.ts +15 -4
- package/cli/commands/inspect.ts +19 -14
- package/cli/commands/maestro.ts +582 -69
- package/cli/commands/permissions.ts +1 -1
- package/cli/commands/platform.ts +205 -8
- package/cli/commands/preview.ts +2 -2
- package/cli/commands/record.ts +2 -2
- package/cli/commands/report-issue.ts +2 -2
- package/cli/commands/screenshot-layers.ts +1 -1
- package/cli/commands/screenshot.ts +1 -1
- package/cli/commands/setup.ts +2 -2
- package/cli/commands/test.ts +600 -117
- package/cli/commands/three-mode.ts +1 -1
- package/cli/commands/upload.ts +5 -5
- package/cli/commands/what-happened.ts +1 -1
- package/cli/desktop-companion.ts +3 -3
- package/cli/drivers/playwright-sim-host.ts +2 -2
- package/cli/flow-file.ts +7 -0
- package/cli/flow-live-status.ts +65 -8
- package/cli/help-core.ts +3 -3
- package/cli/hidden-runtime-alias.ts +1 -1
- package/cli/maestro-report.ts +180 -0
- package/cli/main.ts +1 -1
- package/cli/outbound-endpoints.ts +187 -136
- package/cli/parse-args.ts +1 -1
- package/cli/registry.ts +1 -1
- package/cli/resolve-assets.ts +1 -1
- package/cli/run-registry.ts +10 -1
- package/cli/send-to-box.ts +4 -4
- package/cli/ws-bridge.ts +3 -5
- package/detox/expectations.ts +1 -1
- package/detox/gestures.ts +2 -2
- package/detox/index.ts +71 -29
- package/detox/jest-preset.cjs +5 -5
- package/detox/jest-setup-after-env.cjs +1 -1
- package/dist-lib/agent-daemon-client.cjs +2 -2
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +2 -2
- package/dist-lib/attached-projects.cjs +2 -2
- 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 +94 -3
- package/dist-lib/capture-contract.mjs +93 -3
- 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-test-args.cjs +116 -0
- package/dist-lib/cloud-test-args.mjs +86 -0
- package/dist-lib/cloud.cjs +2 -2
- package/dist-lib/cloud.mjs +2 -2
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +106 -25
- package/dist-lib/detox/jest-preset.cjs +5 -5
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +150 -65
- package/dist-lib/host/fetch-proxy-handler.cjs +28 -2
- package/dist-lib/host/fetch-proxy-overrides.cjs +33 -3
- package/dist-lib/host/fetch-proxy-overrides.mjs +30 -2
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +224 -41
- 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 +2 -2
- package/dist-lib/menu.mjs +2 -2
- 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 +3 -3
- package/dist-lib/metro-production-bundle.mjs +3 -3
- package/dist-lib/metro.cjs +8 -8
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +2 -2
- 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 +31 -15
- package/dist-lib/sdk.cjs +3 -2
- package/dist-lib/sdk.mjs +3 -2
- package/dist-lib/skills.cjs +478 -266
- package/dist-lib/swift-compile.cjs +372 -0
- package/dist-lib/swift-compile.mjs +339 -0
- package/dist-lib/swift-package.cjs +78 -0
- package/dist-lib/swift-package.mjs +52 -0
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift.cjs +583 -16
- package/dist-lib/vite.cjs +483 -150
- package/package.json +30 -9
- package/scripts/dev-server-scanner.ts +41 -14
- package/scripts/optional-demo-registry.ts +3 -3
- package/skills/contrast/SKILL.md +9 -9
- package/skills/rnx-debug/SKILL.md +14 -4
- package/skills/rnx-perf/SKILL.md +5 -5
- package/skills/rnx-setup/SKILL.md +11 -11
- package/skills/rnx-test/SKILL.md +14 -14
- package/skills/rnx-visual/SKILL.md +6 -6
- package/src/agent-sessions.ts +3 -3
- package/src/attached-projects.ts +1 -1
- package/src/bridge-contract-input.ts +1 -1
- package/src/bridge-contract.ts +23 -5
- package/src/capture-contract.ts +145 -3
- package/src/cloud-test-args.ts +100 -0
- package/src/config.ts +2 -2
- package/src/connect.ts +2 -2
- package/src/home-paths.ts +3 -3
- package/src/host/bridge-host.ts +2 -2
- package/src/host/fetch-proxy-handler.ts +4 -3
- package/src/host/fetch-proxy-overrides.ts +41 -0
- package/src/host/plane-host.ts +2 -2
- package/src/index.ts +3 -0
- package/src/metro-plugin.ts +4 -4
- package/src/metro-production-bundle.ts +2 -2
- package/src/native-seam-manifest.ts +6 -6
- package/src/public-brand.ts +1 -1
- package/src/rolldown-plugin-swift.ts +16 -12
- package/src/runtime-assets.ts +8 -6
- package/src/screenshots/frame-compose.ts +24 -56
- package/src/screenshots/org-deck.ts +1 -1
- package/src/screenshots/registry.ts +4 -4
- package/src/screenshots/schema.ts +1 -1
- package/src/sdk.ts +2 -2
- package/src/settings-bundle.ts +1 -1
- package/src/sim-client.ts +2 -4
- package/src/skills/builtin/compat-check.ts +1 -1
- package/src/swift-compile.ts +359 -0
- package/src/swift-package.ts +69 -0
- package/src/swift-submit.ts +3 -2
- package/src/vite-plugin-one.ts +1 -1
- package/src/vite-plugin-swift.ts +114 -113
- package/src/vite-plugin.ts +30 -17
- package/src/worklets-babel.ts +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.571 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
|
|
3
3
|
// src/capture-contract.ts
|
|
4
4
|
var RNX_SCREEN_CAPTURE_VERSION = 1;
|
|
@@ -10,7 +10,7 @@ function selectRnxRasterNodeIds(tree) {
|
|
|
10
10
|
if (!visibleFrame || visibleFrame.width <= 0 || visibleFrame.height <= 0) continue;
|
|
11
11
|
if (node.type === "masked-view" || node.type === "text" && typeof node.text === "string" && (/\p{Emoji_Presentation}/u.test(node.text) || /\uFE0F|\u200D|\u20E3|\p{Emoji_Modifier}|\p{Regional_Indicator}/u.test(
|
|
12
12
|
node.text
|
|
13
|
-
)) || node.style._liquidGlass !== void 0 || node.style._liquidGlassEdge !== void 0) {
|
|
13
|
+
)) || node.style._liquidGlass !== void 0 || node.style._liquidGlassEdge !== void 0 || node.style._liquidGlassMaterialTint !== void 0) {
|
|
14
14
|
unsupported.add(node.nodeId);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -109,6 +109,95 @@ function rnxCaptureRasterRegions(capture) {
|
|
|
109
109
|
return frame ? [{ key: String(nodeId), nodeId, frame }] : [];
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
|
+
function packRnxCaptureRegions(regions, pixelRatio, surface) {
|
|
113
|
+
const physical = regions.map((region) => {
|
|
114
|
+
const left = Math.floor(region.frame.x * pixelRatio);
|
|
115
|
+
const top = Math.floor(region.frame.y * pixelRatio);
|
|
116
|
+
const right = Math.ceil((region.frame.x + region.frame.width) * pixelRatio);
|
|
117
|
+
const bottom = Math.ceil((region.frame.y + region.frame.height) * pixelRatio);
|
|
118
|
+
if (left < 0 || top < 0 || right > surface.pixelWidth || bottom > surface.pixelHeight || right <= left || bottom <= top) {
|
|
119
|
+
throw new Error(`capture region ${region.key} is outside the app surface`);
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
key: region.key,
|
|
123
|
+
nodeId: region.nodeId,
|
|
124
|
+
frame: {
|
|
125
|
+
x: left / pixelRatio,
|
|
126
|
+
y: top / pixelRatio,
|
|
127
|
+
width: (right - left) / pixelRatio,
|
|
128
|
+
height: (bottom - top) / pixelRatio
|
|
129
|
+
},
|
|
130
|
+
sourceX: left,
|
|
131
|
+
sourceY: top,
|
|
132
|
+
pixelWidth: right - left,
|
|
133
|
+
pixelHeight: bottom - top
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
const largestWidth = Math.max(...physical.map((region) => region.pixelWidth));
|
|
137
|
+
const totalArea = physical.reduce(
|
|
138
|
+
(area, region) => area + region.pixelWidth * region.pixelHeight,
|
|
139
|
+
0
|
|
140
|
+
);
|
|
141
|
+
if (totalArea > 4194304) {
|
|
142
|
+
throw new Error("capture region pixels exceed the atlas budget");
|
|
143
|
+
}
|
|
144
|
+
const candidates = [
|
|
145
|
+
largestWidth,
|
|
146
|
+
Math.max(largestWidth, Math.ceil(Math.sqrt(totalArea))),
|
|
147
|
+
Math.max(largestWidth, surface.pixelWidth),
|
|
148
|
+
4096
|
|
149
|
+
];
|
|
150
|
+
const ordered = [...physical].sort(
|
|
151
|
+
(left, right) => right.pixelHeight - left.pixelHeight || right.pixelWidth - left.pixelWidth || left.key.localeCompare(right.key)
|
|
152
|
+
);
|
|
153
|
+
let best = null;
|
|
154
|
+
for (const candidate of [...new Set(candidates)]) {
|
|
155
|
+
if (candidate > 4096) continue;
|
|
156
|
+
let x = 0;
|
|
157
|
+
let y = 0;
|
|
158
|
+
let rowHeight = 0;
|
|
159
|
+
let usedWidth = 0;
|
|
160
|
+
const packed = [];
|
|
161
|
+
for (const region of ordered) {
|
|
162
|
+
if (x > 0 && x + region.pixelWidth > candidate) {
|
|
163
|
+
y += rowHeight;
|
|
164
|
+
x = 0;
|
|
165
|
+
rowHeight = 0;
|
|
166
|
+
}
|
|
167
|
+
packed.push({ ...region, atlasX: x, atlasY: y });
|
|
168
|
+
x += region.pixelWidth;
|
|
169
|
+
rowHeight = Math.max(rowHeight, region.pixelHeight);
|
|
170
|
+
usedWidth = Math.max(usedWidth, x);
|
|
171
|
+
}
|
|
172
|
+
const height2 = y + rowHeight;
|
|
173
|
+
if (height2 > 4096 || usedWidth * height2 > 4194304) continue;
|
|
174
|
+
const result = { width: usedWidth, height: height2, regions: packed };
|
|
175
|
+
if (!best || result.width * result.height < best.width * best.height) best = result;
|
|
176
|
+
}
|
|
177
|
+
if (!best) throw new Error("capture regions cannot fit in one bounded atlas");
|
|
178
|
+
const width = best.width / pixelRatio;
|
|
179
|
+
const height = best.height / pixelRatio;
|
|
180
|
+
return {
|
|
181
|
+
width,
|
|
182
|
+
height,
|
|
183
|
+
pixelWidth: best.width,
|
|
184
|
+
pixelHeight: best.height,
|
|
185
|
+
regions: best.regions,
|
|
186
|
+
atlasRegions: best.regions.map((region) => ({
|
|
187
|
+
key: region.key,
|
|
188
|
+
nodeId: region.nodeId,
|
|
189
|
+
frame: region.frame,
|
|
190
|
+
// a region flush with the far edge is anchored to the logical edge so
|
|
191
|
+
// its source never runs past the atlas by a rounding hair
|
|
192
|
+
source: {
|
|
193
|
+
x: region.atlasX + region.pixelWidth === best.width ? width - region.frame.width : region.atlasX / pixelRatio,
|
|
194
|
+
y: region.atlasY + region.pixelHeight === best.height ? height - region.frame.height : region.atlasY / pixelRatio,
|
|
195
|
+
width: region.frame.width,
|
|
196
|
+
height: region.frame.height
|
|
197
|
+
}
|
|
198
|
+
}))
|
|
199
|
+
};
|
|
200
|
+
}
|
|
112
201
|
function captureRecord(value) {
|
|
113
202
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
114
203
|
}
|
|
@@ -164,7 +253,7 @@ function isRnxScreenCapture(value) {
|
|
|
164
253
|
return captureRecord(tree.viewport) && captureInteger(tree.viewport.width) && tree.viewport.width > 0 && captureInteger(tree.viewport.height) && tree.viewport.height > 0 && captureInteger(tree.rootNodeId) && (tree.commitRevision === void 0 || captureInteger(tree.commitRevision)) && Array.isArray(tree.nodes) && tree.nodes.every(captureNode) && (visual === void 0 || visual.kind === "png" && (visual.producer === "headless-cpu-app-surface" || visual.producer === "browser-compositor-app-surface") && typeof visual.dataUri === "string" && visual.dataUri.startsWith("data:image/png;base64,") && captureInteger(visual.pixelWidth) && visual.pixelWidth > 0 && captureInteger(visual.pixelHeight) && visual.pixelHeight > 0);
|
|
165
254
|
}
|
|
166
255
|
function isRnxCaptureRegionAtlas(value) {
|
|
167
|
-
if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
|
|
256
|
+
if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" && value.producer !== "browser-compositor-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
|
|
168
257
|
return false;
|
|
169
258
|
}
|
|
170
259
|
const scale = value.pixelWidth / value.width;
|
|
@@ -184,6 +273,7 @@ export {
|
|
|
184
273
|
RNX_SCREEN_CAPTURE_VERSION,
|
|
185
274
|
isRnxCaptureRegionAtlas,
|
|
186
275
|
isRnxScreenCapture,
|
|
276
|
+
packRnxCaptureRegions,
|
|
187
277
|
rnxCaptureRasterRegions,
|
|
188
278
|
rnxRasterFrames,
|
|
189
279
|
selectRnxRasterNodeIds
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.571 | (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.571 | (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;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/*! rnx v0.1.571 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
|
+
"use strict";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/cloud-test-args.ts
|
|
23
|
+
var cloud_test_args_exports = {};
|
|
24
|
+
__export(cloud_test_args_exports, {
|
|
25
|
+
CLOUD_TEST_ARGS_MAX_BYTES: () => CLOUD_TEST_ARGS_MAX_BYTES,
|
|
26
|
+
CLOUD_TEST_ARGS_MAX_COUNT: () => CLOUD_TEST_ARGS_MAX_COUNT,
|
|
27
|
+
CLOUD_TEST_ARG_MAX_LENGTH: () => CLOUD_TEST_ARG_MAX_LENGTH,
|
|
28
|
+
CLOUD_TEST_VALUE_FLAGS: () => CLOUD_TEST_VALUE_FLAGS,
|
|
29
|
+
isCloudTestValueFlag: () => isCloudTestValueFlag,
|
|
30
|
+
parseCloudTestArgs: () => parseCloudTestArgs
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(cloud_test_args_exports);
|
|
33
|
+
var CLOUD_TEST_ARGS_MAX_COUNT = 32;
|
|
34
|
+
var CLOUD_TEST_ARG_MAX_LENGTH = 1e3;
|
|
35
|
+
var CLOUD_TEST_ARGS_MAX_BYTES = 16 * 1024;
|
|
36
|
+
var CLOUD_TEST_VALUE_FLAGS = [
|
|
37
|
+
"-t",
|
|
38
|
+
"--testNamePattern",
|
|
39
|
+
"--testPathPattern",
|
|
40
|
+
"--include-tags",
|
|
41
|
+
"--exclude-tags",
|
|
42
|
+
"--grep"
|
|
43
|
+
];
|
|
44
|
+
var CLOUD_TEST_VALUE_FLAG_SET = new Set(CLOUD_TEST_VALUE_FLAGS);
|
|
45
|
+
function isCloudTestValueFlag(name) {
|
|
46
|
+
return CLOUD_TEST_VALUE_FLAG_SET.has(name);
|
|
47
|
+
}
|
|
48
|
+
function parseCloudTestArgs(value) {
|
|
49
|
+
if (value === void 0 || value === null) return { ok: true, args: [] };
|
|
50
|
+
if (!Array.isArray(value)) {
|
|
51
|
+
return { ok: false, message: "testArgs must be an array of strings" };
|
|
52
|
+
}
|
|
53
|
+
if (value.length > CLOUD_TEST_ARGS_MAX_COUNT) {
|
|
54
|
+
return {
|
|
55
|
+
ok: false,
|
|
56
|
+
message: `testArgs may contain at most ${CLOUD_TEST_ARGS_MAX_COUNT} entries`
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const encoder = new TextEncoder();
|
|
60
|
+
let bytes = 0;
|
|
61
|
+
const entries = [];
|
|
62
|
+
for (const entry of value) {
|
|
63
|
+
if (typeof entry !== "string" || entry.length === 0) {
|
|
64
|
+
return { ok: false, message: "testArgs entries must be non-empty strings" };
|
|
65
|
+
}
|
|
66
|
+
if (entry.length > CLOUD_TEST_ARG_MAX_LENGTH || entry.includes("\0")) {
|
|
67
|
+
return { ok: false, message: `testArgs entry is too long or carries a NUL byte: ${entry.slice(0, 60)}` };
|
|
68
|
+
}
|
|
69
|
+
bytes += encoder.encode(entry).length;
|
|
70
|
+
if (bytes > CLOUD_TEST_ARGS_MAX_BYTES) {
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
message: `testArgs may contain at most ${CLOUD_TEST_ARGS_MAX_BYTES} bytes`
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
entries.push(entry);
|
|
77
|
+
}
|
|
78
|
+
const args = [];
|
|
79
|
+
for (let i = 0; i < entries.length; i++) {
|
|
80
|
+
const entry = entries[i];
|
|
81
|
+
if (!entry.startsWith("-")) {
|
|
82
|
+
return {
|
|
83
|
+
ok: false,
|
|
84
|
+
message: `testArgs carries a positional argument (selection flags only): ${entry.slice(0, 60)}`
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const eq = entry.indexOf("=");
|
|
88
|
+
const head = eq > 0 ? entry.slice(0, eq) : entry;
|
|
89
|
+
if (!isCloudTestValueFlag(head)) {
|
|
90
|
+
return { ok: false, message: `testArgs carries an unknown flag: ${head.slice(0, 60)}` };
|
|
91
|
+
}
|
|
92
|
+
if (eq > 0) {
|
|
93
|
+
if (!entry.slice(eq + 1)) {
|
|
94
|
+
return { ok: false, message: `${head} expects a value` };
|
|
95
|
+
}
|
|
96
|
+
args.push(entry);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const val = entries[i + 1];
|
|
100
|
+
if (val === void 0 || val.startsWith("-")) {
|
|
101
|
+
return { ok: false, message: `${head} expects a value` };
|
|
102
|
+
}
|
|
103
|
+
args.push(entry, val);
|
|
104
|
+
i += 1;
|
|
105
|
+
}
|
|
106
|
+
return { ok: true, args };
|
|
107
|
+
}
|
|
108
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
109
|
+
0 && (module.exports = {
|
|
110
|
+
CLOUD_TEST_ARGS_MAX_BYTES,
|
|
111
|
+
CLOUD_TEST_ARGS_MAX_COUNT,
|
|
112
|
+
CLOUD_TEST_ARG_MAX_LENGTH,
|
|
113
|
+
CLOUD_TEST_VALUE_FLAGS,
|
|
114
|
+
isCloudTestValueFlag,
|
|
115
|
+
parseCloudTestArgs
|
|
116
|
+
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*! rnx v0.1.571 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
|
|
3
|
+
// src/cloud-test-args.ts
|
|
4
|
+
var CLOUD_TEST_ARGS_MAX_COUNT = 32;
|
|
5
|
+
var CLOUD_TEST_ARG_MAX_LENGTH = 1e3;
|
|
6
|
+
var CLOUD_TEST_ARGS_MAX_BYTES = 16 * 1024;
|
|
7
|
+
var CLOUD_TEST_VALUE_FLAGS = [
|
|
8
|
+
"-t",
|
|
9
|
+
"--testNamePattern",
|
|
10
|
+
"--testPathPattern",
|
|
11
|
+
"--include-tags",
|
|
12
|
+
"--exclude-tags",
|
|
13
|
+
"--grep"
|
|
14
|
+
];
|
|
15
|
+
var CLOUD_TEST_VALUE_FLAG_SET = new Set(CLOUD_TEST_VALUE_FLAGS);
|
|
16
|
+
function isCloudTestValueFlag(name) {
|
|
17
|
+
return CLOUD_TEST_VALUE_FLAG_SET.has(name);
|
|
18
|
+
}
|
|
19
|
+
function parseCloudTestArgs(value) {
|
|
20
|
+
if (value === void 0 || value === null) return { ok: true, args: [] };
|
|
21
|
+
if (!Array.isArray(value)) {
|
|
22
|
+
return { ok: false, message: "testArgs must be an array of strings" };
|
|
23
|
+
}
|
|
24
|
+
if (value.length > CLOUD_TEST_ARGS_MAX_COUNT) {
|
|
25
|
+
return {
|
|
26
|
+
ok: false,
|
|
27
|
+
message: `testArgs may contain at most ${CLOUD_TEST_ARGS_MAX_COUNT} entries`
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const encoder = new TextEncoder();
|
|
31
|
+
let bytes = 0;
|
|
32
|
+
const entries = [];
|
|
33
|
+
for (const entry of value) {
|
|
34
|
+
if (typeof entry !== "string" || entry.length === 0) {
|
|
35
|
+
return { ok: false, message: "testArgs entries must be non-empty strings" };
|
|
36
|
+
}
|
|
37
|
+
if (entry.length > CLOUD_TEST_ARG_MAX_LENGTH || entry.includes("\0")) {
|
|
38
|
+
return { ok: false, message: `testArgs entry is too long or carries a NUL byte: ${entry.slice(0, 60)}` };
|
|
39
|
+
}
|
|
40
|
+
bytes += encoder.encode(entry).length;
|
|
41
|
+
if (bytes > CLOUD_TEST_ARGS_MAX_BYTES) {
|
|
42
|
+
return {
|
|
43
|
+
ok: false,
|
|
44
|
+
message: `testArgs may contain at most ${CLOUD_TEST_ARGS_MAX_BYTES} bytes`
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
entries.push(entry);
|
|
48
|
+
}
|
|
49
|
+
const args = [];
|
|
50
|
+
for (let i = 0; i < entries.length; i++) {
|
|
51
|
+
const entry = entries[i];
|
|
52
|
+
if (!entry.startsWith("-")) {
|
|
53
|
+
return {
|
|
54
|
+
ok: false,
|
|
55
|
+
message: `testArgs carries a positional argument (selection flags only): ${entry.slice(0, 60)}`
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const eq = entry.indexOf("=");
|
|
59
|
+
const head = eq > 0 ? entry.slice(0, eq) : entry;
|
|
60
|
+
if (!isCloudTestValueFlag(head)) {
|
|
61
|
+
return { ok: false, message: `testArgs carries an unknown flag: ${head.slice(0, 60)}` };
|
|
62
|
+
}
|
|
63
|
+
if (eq > 0) {
|
|
64
|
+
if (!entry.slice(eq + 1)) {
|
|
65
|
+
return { ok: false, message: `${head} expects a value` };
|
|
66
|
+
}
|
|
67
|
+
args.push(entry);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const val = entries[i + 1];
|
|
71
|
+
if (val === void 0 || val.startsWith("-")) {
|
|
72
|
+
return { ok: false, message: `${head} expects a value` };
|
|
73
|
+
}
|
|
74
|
+
args.push(entry, val);
|
|
75
|
+
i += 1;
|
|
76
|
+
}
|
|
77
|
+
return { ok: true, args };
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
CLOUD_TEST_ARGS_MAX_BYTES,
|
|
81
|
+
CLOUD_TEST_ARGS_MAX_COUNT,
|
|
82
|
+
CLOUD_TEST_ARG_MAX_LENGTH,
|
|
83
|
+
CLOUD_TEST_VALUE_FLAGS,
|
|
84
|
+
isCloudTestValueFlag,
|
|
85
|
+
parseCloudTestArgs
|
|
86
|
+
};
|
package/dist-lib/cloud.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.571 | (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;
|
|
@@ -173,7 +173,7 @@ function rnxCloudScopesAllowCommand(scopes, type) {
|
|
|
173
173
|
var name = "rnx";
|
|
174
174
|
var rnxPublicBrand = Object.freeze({
|
|
175
175
|
name,
|
|
176
|
-
packageName: "
|
|
176
|
+
packageName: "peachsim",
|
|
177
177
|
commandName: "rnx",
|
|
178
178
|
domain: "rnxsim.com",
|
|
179
179
|
origin: "https://rnxsim.com"
|
package/dist-lib/cloud.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.571 | (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);
|
|
@@ -143,7 +143,7 @@ function rnxCloudScopesAllowCommand(scopes, type) {
|
|
|
143
143
|
var name = "rnx";
|
|
144
144
|
var rnxPublicBrand = Object.freeze({
|
|
145
145
|
name,
|
|
146
|
-
packageName: "
|
|
146
|
+
packageName: "peachsim",
|
|
147
147
|
commandName: "rnx",
|
|
148
148
|
domain: "rnxsim.com",
|
|
149
149
|
origin: "https://rnxsim.com"
|
package/dist-lib/config.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.571 | (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.571 | (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;
|
|
@@ -233,7 +233,8 @@ __export(detox_exports, {
|
|
|
233
233
|
element: () => element,
|
|
234
234
|
expect: () => sootsimExpect,
|
|
235
235
|
waitFor: () => sootsimWaitFor,
|
|
236
|
-
waitForSootsimIdle: () => waitForSootsimIdle
|
|
236
|
+
waitForSootsimIdle: () => waitForSootsimIdle,
|
|
237
|
+
waitForSootsimShellReady: () => waitForSootsimShellReady
|
|
237
238
|
});
|
|
238
239
|
module.exports = __toCommonJS(detox_exports);
|
|
239
240
|
var fs = __toESM(require("fs"), 1);
|
|
@@ -758,7 +759,7 @@ async function launchReapedChromeScoped(launch, opts = {}, rendererTarget, polic
|
|
|
758
759
|
);
|
|
759
760
|
}
|
|
760
761
|
|
|
761
|
-
// ../
|
|
762
|
+
// ../peach-engine/src/capture/browser-composite.ts
|
|
762
763
|
function resolveBrowserCompositeCdpClip(request, metrics) {
|
|
763
764
|
if (!metrics || typeof metrics !== "object") {
|
|
764
765
|
throw new Error("browser composite capture requires CDP layout metrics");
|
|
@@ -824,6 +825,65 @@ function readBrowserCompositeCaptureRequest(value) {
|
|
|
824
825
|
return request;
|
|
825
826
|
}
|
|
826
827
|
|
|
828
|
+
// ../peach-engine/src/remote-stream/remoteEngineParam.ts
|
|
829
|
+
function readRemoteEngineParam(search, hash) {
|
|
830
|
+
const fromQuery = new URLSearchParams(search).get("remoteEngine");
|
|
831
|
+
if (fromQuery) return fromQuery;
|
|
832
|
+
const fromFragment = new URLSearchParams(hash.replace(/^#/, "")).get("remoteEngine");
|
|
833
|
+
return fromFragment || null;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
// ../peach-engine/src/render-worker/app-load.ts
|
|
837
|
+
var TEST_FIXTURE_SHELL_APP_ID = "sootsim-test-fixture";
|
|
838
|
+
var KITCHEN_SINK_SHELL_APP_ID = "sootsim-kitchen-sink";
|
|
839
|
+
var REMOTE_DISPLAY_SHELL_APP_ID = "sootsim-remote-display";
|
|
840
|
+
function getVisibleHarnessAppForUrl(initUrl) {
|
|
841
|
+
if (!initUrl) return null;
|
|
842
|
+
try {
|
|
843
|
+
const parsed = new URL(initUrl);
|
|
844
|
+
const testName = parsed.searchParams.get("test");
|
|
845
|
+
if (testName) {
|
|
846
|
+
return {
|
|
847
|
+
id: TEST_FIXTURE_SHELL_APP_ID,
|
|
848
|
+
name: testName,
|
|
849
|
+
color: "#0f172a",
|
|
850
|
+
icon: "T",
|
|
851
|
+
hidden: true
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
if (parsed.searchParams.get("mode") === "kitchen-sink") {
|
|
855
|
+
return {
|
|
856
|
+
id: KITCHEN_SINK_SHELL_APP_ID,
|
|
857
|
+
name: "Kitchen Sink",
|
|
858
|
+
color: "#0f172a",
|
|
859
|
+
icon: "K",
|
|
860
|
+
hidden: true
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
if (readRemoteEngineParam(parsed.search, parsed.hash)) {
|
|
864
|
+
return {
|
|
865
|
+
id: REMOTE_DISPLAY_SHELL_APP_ID,
|
|
866
|
+
name: "Remote",
|
|
867
|
+
color: "#0f172a",
|
|
868
|
+
icon: "R",
|
|
869
|
+
hidden: true
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
} catch {
|
|
873
|
+
}
|
|
874
|
+
return null;
|
|
875
|
+
}
|
|
876
|
+
function isAppBootTargetUrl(initUrl) {
|
|
877
|
+
if (!initUrl) return false;
|
|
878
|
+
if (getVisibleHarnessAppForUrl(initUrl)) return true;
|
|
879
|
+
try {
|
|
880
|
+
const parsed = new URL(initUrl);
|
|
881
|
+
return parsed.searchParams.has("nativePreview") || parsed.searchParams.has("bundle") || parsed.searchParams.has("app") || /\/app\/[^/]+$/i.test(parsed.pathname) || /\/rn(?:\/[^/]+)?$/i.test(parsed.pathname) || /\/dock\/[^/]+$/i.test(parsed.pathname);
|
|
882
|
+
} catch {
|
|
883
|
+
return false;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
827
887
|
// src/poll-until.ts
|
|
828
888
|
async function pollUntil(read, ready, options) {
|
|
829
889
|
if (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0) {
|
|
@@ -1969,8 +2029,9 @@ async function waitForSootsimSurfaceMetrics(page, timeout = 3e4) {
|
|
|
1969
2029
|
);
|
|
1970
2030
|
}
|
|
1971
2031
|
async function waitForSootsimShellReady(page, timeout = 3e4) {
|
|
2032
|
+
const expectsInitialAppPaint = isAppBootTargetUrl(page.url());
|
|
1972
2033
|
try {
|
|
1973
|
-
await page.evaluate(async (timeoutMs) => {
|
|
2034
|
+
await page.evaluate(async ({ timeoutMs, expectsInitialAppPaint: expectsInitialAppPaint2 }) => {
|
|
1974
2035
|
const start = Date.now();
|
|
1975
2036
|
const deadline = start + timeoutMs;
|
|
1976
2037
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -1992,8 +2053,6 @@ async function waitForSootsimShellReady(page, timeout = 3e4) {
|
|
|
1992
2053
|
}
|
|
1993
2054
|
};
|
|
1994
2055
|
const isTenantOnly = new URL(window.location.href).searchParams.get("renderMode") === "tenant-only";
|
|
1995
|
-
const currentUrl = new URL(window.location.href);
|
|
1996
|
-
const expectsInitialAppPaint = currentUrl.searchParams.has("test") || currentUrl.pathname.includes("/app/");
|
|
1997
2056
|
let shellHost = null;
|
|
1998
2057
|
while (Date.now() < deadline) {
|
|
1999
2058
|
const candidate = window.SootSim?.bridges?.shellHost;
|
|
@@ -2010,26 +2069,47 @@ async function waitForSootsimShellReady(page, timeout = 3e4) {
|
|
|
2010
2069
|
if (shellHost.ready && typeof shellHost.ready.then === "function") {
|
|
2011
2070
|
await withTimeout("sootsim shell ready", shellHost.ready);
|
|
2012
2071
|
}
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2072
|
+
const isRenderHostDisposed = (error) => error instanceof Error && error.message.includes("render host disposed");
|
|
2073
|
+
for (; ; ) {
|
|
2074
|
+
try {
|
|
2075
|
+
if (expectsInitialAppPaint2) {
|
|
2076
|
+
while (Date.now() < deadline) {
|
|
2077
|
+
if (document.documentElement.dataset.sootsimBootStage === "painted") {
|
|
2078
|
+
break;
|
|
2079
|
+
}
|
|
2080
|
+
await sleep(50);
|
|
2081
|
+
}
|
|
2082
|
+
if (document.documentElement.dataset.sootsimBootStage !== "painted") {
|
|
2083
|
+
throw new Error(
|
|
2084
|
+
`sootsim app first content paint timed out after ${timeoutMs}ms`
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2087
|
+
} else if (shellHost.firstContentPainted && typeof shellHost.firstContentPainted.then === "function") {
|
|
2088
|
+
await withTimeout(
|
|
2089
|
+
"sootsim shell first content paint",
|
|
2090
|
+
shellHost.firstContentPainted
|
|
2091
|
+
);
|
|
2092
|
+
}
|
|
2093
|
+
const waitForScreenTransitions = window.__sootsimTest?.waitForScreenTransitions;
|
|
2094
|
+
if (typeof waitForScreenTransitions === "function") {
|
|
2095
|
+
const transitionResult = await waitForScreenTransitions({
|
|
2096
|
+
timeoutMs: Math.min(remaining(), 3e3),
|
|
2097
|
+
settleMs: 64,
|
|
2098
|
+
startWindowMs: 700
|
|
2099
|
+
});
|
|
2100
|
+
if (transitionResult?.timedOut === true) {
|
|
2101
|
+
throw new Error(
|
|
2102
|
+
`sootsim app launch transitions timed out: ${JSON.stringify(transitionResult)}`
|
|
2103
|
+
);
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
break;
|
|
2107
|
+
} catch (error) {
|
|
2108
|
+
if (!isRenderHostDisposed(error) || Date.now() >= deadline) throw error;
|
|
2109
|
+
await sleep(100);
|
|
2030
2110
|
}
|
|
2031
2111
|
}
|
|
2032
|
-
}, timeout);
|
|
2112
|
+
}, { timeoutMs: timeout, expectsInitialAppPaint });
|
|
2033
2113
|
} catch (error) {
|
|
2034
2114
|
throw await describeSootsimBridgeFailure(page, error);
|
|
2035
2115
|
}
|
|
@@ -3785,5 +3865,6 @@ async function cleanup() {
|
|
|
3785
3865
|
element,
|
|
3786
3866
|
expect,
|
|
3787
3867
|
waitFor,
|
|
3788
|
-
waitForSootsimIdle
|
|
3868
|
+
waitForSootsimIdle,
|
|
3869
|
+
waitForSootsimShellReady
|
|
3789
3870
|
});
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
// jest preset for running existing detox suites against sootsim.
|
|
2
2
|
//
|
|
3
|
-
// users drop `preset: '
|
|
3
|
+
// users drop `preset: 'peachsim/detox'` into their jest config
|
|
4
4
|
// (or `rnx-detox.config.cjs`) and their `import { by, device, element,
|
|
5
5
|
// expect, waitFor } from 'detox'` calls resolve to the sootsim driver.
|
|
6
6
|
|
|
7
7
|
const path = require('path')
|
|
8
8
|
|
|
9
9
|
// resolve the published driver entry so the mapping works from any cwd.
|
|
10
|
-
// `require.resolve('
|
|
11
|
-
//
|
|
12
|
-
const DRIVER_ENTRY = require.resolve('
|
|
13
|
-
const PACKAGE_ROOT = path.dirname(require.resolve('
|
|
10
|
+
// `require.resolve('peachsim/detox')` honours the subpath export in the
|
|
11
|
+
// peachsim package.json.
|
|
12
|
+
const DRIVER_ENTRY = require.resolve('peachsim/detox')
|
|
13
|
+
const PACKAGE_ROOT = path.dirname(require.resolve('peachsim/package.json'))
|
|
14
14
|
|
|
15
15
|
/** @type {import('@jest/types').Config.InitialOptions} */
|
|
16
16
|
module.exports = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.571 | (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.571 | (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;
|