peachsim 0.1.657 → 0.1.659
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 +21 -2
- package/cli/app-config.ts +25 -9
- package/cli/bridge-flow-runner.ts +10 -23
- package/cli/commands/compat.ts +234 -10
- package/cli/commands/do-chain.ts +5 -1
- package/cli/commands/inspect/actions.ts +33 -76
- package/cli/commands/inspect/resolve-target.ts +67 -2
- package/cli/commands/inspect.ts +16 -1
- package/cli/drivers/playwright-provisioning.ts +95 -0
- package/cli/ws-bridge.ts +7 -7
- 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 +9 -1
- package/dist-lib/bridge-contract-input.mjs +9 -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-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +3 -2
- package/dist-lib/detox/index.cjs +2 -2
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +78 -35
- 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 +51 -8
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +317 -70
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +14 -4
- 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 +300 -29
- package/dist-lib/native-app-identity.cjs +58 -25
- package/dist-lib/native-app-identity.mjs +57 -25
- package/dist-lib/plist.cjs +64 -0
- package/dist-lib/plist.mjs +29 -0
- 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 +2 -2
- package/dist-lib/sdk.cjs +36 -49
- package/dist-lib/sdk.mjs +36 -49
- package/dist-lib/skills.cjs +257 -138
- package/dist-lib/swift-compile.cjs +1 -1
- package/dist-lib/swift-compile.mjs +1 -1
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +1 -1
- package/dist-lib/vite.cjs +51 -8
- package/kotlin/AppSources/android/app/Activity.kt +44 -0
- package/kotlin/AppSources/android/app/UiModeManager.kt +9 -0
- package/kotlin/AppSources/android/content/Context.kt +9 -2
- package/kotlin/AppSources/android/content/res/Configuration.kt +16 -0
- package/kotlin/AppSources/android/content/res/Resources.kt +7 -0
- package/kotlin/AppSources/android/graphics/Color.kt +13 -0
- package/kotlin/AppSources/android/os/Bundle.kt +9 -3
- package/kotlin/AppSources/android/view/View.kt +2 -0
- package/kotlin/AppSources/android/view/Window.kt +99 -8
- package/kotlin/AppSources/android/view/WindowInsetsController.kt +12 -0
- package/kotlin/AppSources/android/view/WindowManager.kt +16 -0
- package/kotlin/AppSources/androidx/activity/BackEventCompat.kt +17 -0
- package/kotlin/AppSources/androidx/activity/Cancellable.kt +5 -0
- package/kotlin/AppSources/androidx/activity/ComponentActivity.kt +22 -3
- package/kotlin/AppSources/androidx/activity/EdgeToEdge.kt +71 -0
- package/kotlin/AppSources/androidx/activity/OnBackPressedCallback.kt +28 -0
- package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +144 -0
- package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcherOwner.kt +7 -0
- package/kotlin/AppSources/androidx/activity/compose/BackHandler.kt +55 -0
- package/kotlin/AppSources/androidx/core/view/WindowCompat.kt +32 -0
- package/kotlin/AppSources/dev/peach/app/PeachApp.kt +67 -12
- package/kotlin/AppSources/dev/peach/app/PeachWindowHost.kt +2 -1
- package/kotlin/AppSources/java/lang/Runnable.kt +6 -0
- package/kotlin/ComposeSources/PeachComposeHost.kt +11 -1
- package/package.json +8 -1
- package/skills/peach-setup/SKILL.md +27 -0
- package/src/android-theme.ts +167 -0
- package/src/android-xml.ts +70 -0
- package/src/bridge-contract-input.ts +10 -1
- package/src/bridge-contract.ts +7 -1
- package/src/config.ts +8 -0
- package/src/generated/android-framework-themes.json +6303 -0
- package/src/host/replacement-module-handler.ts +33 -0
- package/src/index.ts +1 -0
- package/src/kotlin-app.ts +86 -61
- package/src/kotlin-host.ts +13 -3
- package/src/metro-plugin.ts +46 -3
- package/src/native-app-identity.ts +75 -26
- package/src/sim-client.ts +2 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
|
|
3
3
|
// src/native-app-identity.ts
|
|
4
4
|
var NATIVE_APP_IDENTITY_PREFIX = "globalThis.__sootsimNativeAppIdentity=";
|
|
@@ -11,6 +11,8 @@ function nonEmptyString(value) {
|
|
|
11
11
|
}
|
|
12
12
|
function isNativeAppIdentity(value) {
|
|
13
13
|
if (!isRecord(value)) return false;
|
|
14
|
+
const descriptions = value.permissionUsageDescriptions;
|
|
15
|
+
if (descriptions !== void 0 && !isRecord(descriptions)) return false;
|
|
14
16
|
const platform = value.platform;
|
|
15
17
|
if (platform !== "ios" && platform !== "android") return false;
|
|
16
18
|
const applicationName = value.applicationName;
|
|
@@ -32,7 +34,10 @@ function readNativeAppIdentity(value) {
|
|
|
32
34
|
appVersion: value.appVersion,
|
|
33
35
|
buildVersion: value.buildVersion,
|
|
34
36
|
bundleIdentifier: value.bundleIdentifier,
|
|
35
|
-
platform: value.platform
|
|
37
|
+
platform: value.platform,
|
|
38
|
+
...value.permissionUsageDescriptions === void 0 ? {} : {
|
|
39
|
+
permissionUsageDescriptions: { ...value.permissionUsageDescriptions }
|
|
40
|
+
}
|
|
36
41
|
};
|
|
37
42
|
}
|
|
38
43
|
function applyNativeAppIdentity(identity) {
|
|
@@ -137,7 +142,7 @@ function readBuildSettingsBlock(source, start) {
|
|
|
137
142
|
}
|
|
138
143
|
function parseBuildSettings(block) {
|
|
139
144
|
const settings = {};
|
|
140
|
-
const matchPattern = /([A-
|
|
145
|
+
const matchPattern = /([A-Za-z0-9_]+) = ("(?:[^"\\]|\\.)*"|[^;{}]*);/g;
|
|
141
146
|
let match;
|
|
142
147
|
while ((match = matchPattern.exec(block)) !== null) {
|
|
143
148
|
const raw = match[2].trim();
|
|
@@ -173,27 +178,29 @@ function appTargetReleaseSettings(pbxproj, targetName, infoPlistRelativePath) {
|
|
|
173
178
|
(candidate) => candidate.name === "Release" && named(candidate.settings)
|
|
174
179
|
)?.settings ?? null;
|
|
175
180
|
}
|
|
176
|
-
function nativeAppIdentityFromIos(files) {
|
|
181
|
+
function nativeAppIdentityFromIos(files, parseInfoPlist) {
|
|
182
|
+
const pbxprojPath = Object.keys(files).find(
|
|
183
|
+
(path) => /(?:^|\/)ios\/[^/]+\.xcodeproj\/project\.pbxproj$/.test(path)
|
|
184
|
+
);
|
|
185
|
+
if (!pbxprojPath) return null;
|
|
186
|
+
const pbxproj = files[pbxprojPath];
|
|
187
|
+
const applicationTargets = new Set(
|
|
188
|
+
[
|
|
189
|
+
...pbxproj.matchAll(
|
|
190
|
+
/isa = PBXNativeTarget;[^}]*?name = "?([^";]+)"?;[^}]*?productType = "com\.apple\.product-type\.application";/g
|
|
191
|
+
)
|
|
192
|
+
].map((match) => match[1])
|
|
193
|
+
);
|
|
177
194
|
const appDelegatePattern = /(?:^|\/)ios\/([^/]+)\/AppDelegate\.(?:swift|mm|m)$/;
|
|
178
|
-
|
|
179
|
-
for (const path of Object.keys(files)) {
|
|
180
|
-
if (path.includes("/Pods/")) continue;
|
|
181
|
-
const match = path.match(appDelegatePattern);
|
|
182
|
-
if (match) {
|
|
183
|
-
targetName = match[1];
|
|
184
|
-
break;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
195
|
+
const targetName = Object.keys(files).filter((path) => !path.includes("/Pods/")).map((path) => path.match(appDelegatePattern)?.[1]).find((name) => name !== void 0 && applicationTargets.has(name)) ?? null;
|
|
187
196
|
if (!targetName) return null;
|
|
188
|
-
const
|
|
189
|
-
(path) => path === `ios/${targetName}/Info.plist`
|
|
190
|
-
);
|
|
191
|
-
const plist = plistPath ? files[plistPath] : null;
|
|
197
|
+
const plist = files[`ios/${targetName}/Info.plist`];
|
|
192
198
|
if (!plist) return null;
|
|
193
|
-
const
|
|
194
|
-
|
|
199
|
+
const settings = appTargetReleaseSettings(
|
|
200
|
+
pbxproj,
|
|
201
|
+
targetName,
|
|
202
|
+
`${targetName}/Info.plist`
|
|
195
203
|
);
|
|
196
|
-
const settings = pbxprojPath ? appTargetReleaseSettings(files[pbxprojPath], targetName, `${targetName}/Info.plist`) : null;
|
|
197
204
|
if (!settings) return null;
|
|
198
205
|
const bundleIdentifier = identityFieldFrom(
|
|
199
206
|
settings,
|
|
@@ -218,22 +225,47 @@ function nativeAppIdentityFromIos(files) {
|
|
|
218
225
|
settings.PRODUCT_NAME
|
|
219
226
|
) ?? resolvedIdentityField(resolveBuildSetting(settings.PRODUCT_NAME ?? "", settings)) ?? resolvedIdentityField(targetName);
|
|
220
227
|
if (!applicationName) return null;
|
|
228
|
+
const dictionary = parseInfoPlist(plist);
|
|
229
|
+
if (!isRecord(dictionary)) throw new Error("native app Info.plist is not a dictionary");
|
|
230
|
+
const permissionUsageDescriptions = {};
|
|
231
|
+
for (const [key, value] of Object.entries(dictionary)) {
|
|
232
|
+
if (!/^NS.*UsageDescription$/.test(key)) continue;
|
|
233
|
+
if (typeof value !== "string") {
|
|
234
|
+
permissionUsageDescriptions[key] = value;
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
const resolved = resolveBuildSetting(value, settings);
|
|
238
|
+
if (resolved === null) throw new Error(`native app Info.plist ${key} is unresolved`);
|
|
239
|
+
permissionUsageDescriptions[key] = resolved;
|
|
240
|
+
}
|
|
241
|
+
if (settings.GENERATE_INFOPLIST_FILE === "YES") {
|
|
242
|
+
for (const [setting, value] of Object.entries(settings)) {
|
|
243
|
+
if (!/^INFOPLIST_KEY_NS.*UsageDescription$/.test(setting)) continue;
|
|
244
|
+
const key = setting.slice("INFOPLIST_KEY_".length);
|
|
245
|
+
const resolved = resolveBuildSetting(value, settings);
|
|
246
|
+
if (resolved === null)
|
|
247
|
+
throw new Error(`native app build setting ${setting} is unresolved`);
|
|
248
|
+
permissionUsageDescriptions[key] = resolved;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
221
251
|
return {
|
|
222
252
|
applicationName,
|
|
223
253
|
appVersion,
|
|
224
254
|
buildVersion,
|
|
225
255
|
bundleIdentifier,
|
|
226
|
-
platform: "ios"
|
|
256
|
+
platform: "ios",
|
|
257
|
+
permissionUsageDescriptions
|
|
227
258
|
};
|
|
228
259
|
}
|
|
229
|
-
function
|
|
230
|
-
return
|
|
260
|
+
function canExtractNativeAppIdentity(platform) {
|
|
261
|
+
return platform === "ios";
|
|
231
262
|
}
|
|
232
|
-
function extractNativeAppIdentityFromFiles(files, platform) {
|
|
233
|
-
return platform
|
|
263
|
+
function extractNativeAppIdentityFromFiles(files, platform, parseInfoPlist) {
|
|
264
|
+
return canExtractNativeAppIdentity(platform) ? nativeAppIdentityFromIos(files, parseInfoPlist) : null;
|
|
234
265
|
}
|
|
235
266
|
export {
|
|
236
267
|
applyNativeAppIdentity,
|
|
268
|
+
canExtractNativeAppIdentity,
|
|
237
269
|
createNativeAppIdentityFooter,
|
|
238
270
|
detachNativeAppIdentityFooter,
|
|
239
271
|
extractNativeAppIdentityFromFiles,
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/*! rnx v0.1.659 | (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 __create = Object.create;
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __export = (target, all) => {
|
|
11
|
+
for (var name in all)
|
|
12
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
+
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
28
|
+
mod
|
|
29
|
+
));
|
|
30
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
31
|
+
|
|
32
|
+
// src/plist.ts
|
|
33
|
+
var plist_exports = {};
|
|
34
|
+
__export(plist_exports, {
|
|
35
|
+
parsePlistSource: () => parsePlistSource
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(plist_exports);
|
|
38
|
+
var import_plist = __toESM(require("@expo/plist"), 1);
|
|
39
|
+
|
|
40
|
+
// src/is-record.ts
|
|
41
|
+
function isRecord(value) {
|
|
42
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/plist.ts
|
|
46
|
+
function resolvePlistParser(value) {
|
|
47
|
+
if (!isRecord(value)) return null;
|
|
48
|
+
const direct = value.parse;
|
|
49
|
+
if (typeof direct === "function") {
|
|
50
|
+
return (source) => Reflect.apply(direct, value, [source]);
|
|
51
|
+
}
|
|
52
|
+
const nested = value.default;
|
|
53
|
+
if (!isRecord(nested)) return null;
|
|
54
|
+
const nestedParse = nested.parse;
|
|
55
|
+
return typeof nestedParse === "function" ? (source) => Reflect.apply(nestedParse, nested, [source]) : null;
|
|
56
|
+
}
|
|
57
|
+
var parsePlist = resolvePlistParser(import_plist.default);
|
|
58
|
+
function parsePlistSource(source) {
|
|
59
|
+
return parsePlist?.(source) ?? null;
|
|
60
|
+
}
|
|
61
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
62
|
+
0 && (module.exports = {
|
|
63
|
+
parsePlistSource
|
|
64
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
|
|
3
|
+
// src/plist.ts
|
|
4
|
+
import plistModule from "@expo/plist";
|
|
5
|
+
|
|
6
|
+
// src/is-record.ts
|
|
7
|
+
function isRecord(value) {
|
|
8
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/plist.ts
|
|
12
|
+
function resolvePlistParser(value) {
|
|
13
|
+
if (!isRecord(value)) return null;
|
|
14
|
+
const direct = value.parse;
|
|
15
|
+
if (typeof direct === "function") {
|
|
16
|
+
return (source) => Reflect.apply(direct, value, [source]);
|
|
17
|
+
}
|
|
18
|
+
const nested = value.default;
|
|
19
|
+
if (!isRecord(nested)) return null;
|
|
20
|
+
const nestedParse = nested.parse;
|
|
21
|
+
return typeof nestedParse === "function" ? (source) => Reflect.apply(nestedParse, nested, [source]) : null;
|
|
22
|
+
}
|
|
23
|
+
var parsePlist = resolvePlistParser(plistModule);
|
|
24
|
+
function parsePlistSource(source) {
|
|
25
|
+
return parsePlist?.(source) ?? null;
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
parsePlistSource
|
|
29
|
+
};
|
package/dist-lib/profiles.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.659 | (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.659 | (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.659 | (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.659 | (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.659 | (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;
|
|
@@ -228,7 +228,7 @@ function hasOwnKeys(value) {
|
|
|
228
228
|
}
|
|
229
229
|
function hasPeachConfig(config) {
|
|
230
230
|
if (!config) return false;
|
|
231
|
-
return typeof config.runtimeVersion === "string" && config.runtimeVersion.length > 0 || hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.env) || hasOwnKeys(config.network?.remap) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
|
|
231
|
+
return typeof config.runtimeVersion === "string" && config.runtimeVersion.length > 0 || hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.nativeViews) || hasOwnKeys(config.env) || hasOwnKeys(config.network?.remap) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
|
|
232
232
|
}
|
|
233
233
|
function applyPeachConfigToUrl(url, config) {
|
|
234
234
|
const parsed = new URL(url);
|
package/dist-lib/sdk.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.659 | (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;
|
|
@@ -1452,10 +1452,20 @@ function formatTimelineEvents(events) {
|
|
|
1452
1452
|
}
|
|
1453
1453
|
|
|
1454
1454
|
// cli/commands/inspect/resolve-target.ts
|
|
1455
|
+
function isScreenSize(value) {
|
|
1456
|
+
if (value === null || typeof value !== "object") return false;
|
|
1457
|
+
const width = Reflect.get(value, "width");
|
|
1458
|
+
const height = Reflect.get(value, "height");
|
|
1459
|
+
return typeof width === "number" && Number.isFinite(width) && width > 0 && typeof height === "number" && Number.isFinite(height) && height > 0;
|
|
1460
|
+
}
|
|
1461
|
+
function isOffscreen(x, y, screen) {
|
|
1462
|
+
return !(x >= 0 && y >= 0 && x <= screen.width && y <= screen.height);
|
|
1463
|
+
}
|
|
1464
|
+
var UNREPORTED_SCREEN_ERROR = "this runtime does not report the screen size a targeted gesture needs; update it with `peach runtime install`, or use coordinates";
|
|
1455
1465
|
async function resolveTargetCoords(bridge, target) {
|
|
1456
1466
|
const result = await bridge.send({
|
|
1457
1467
|
type: "resolve",
|
|
1458
|
-
selector: target.mode === "testid" ? { testID: target.value } : { text: target.value }
|
|
1468
|
+
selector: target.mode === "node" ? { nodeId: target.nodeId } : target.mode === "testid" ? { testID: target.value } : { text: target.value }
|
|
1459
1469
|
});
|
|
1460
1470
|
if (result === null) return null;
|
|
1461
1471
|
if (typeof result !== "object") throw new Error("resolve returned an invalid result");
|
|
@@ -1463,6 +1473,9 @@ async function resolveTargetCoords(bridge, target) {
|
|
|
1463
1473
|
const resolvedTarget = Reflect.get(result, "target");
|
|
1464
1474
|
const semanticNodes = [match, resolvedTarget];
|
|
1465
1475
|
const point = Reflect.get(result, "point");
|
|
1476
|
+
const viewport = Reflect.get(result, "viewport");
|
|
1477
|
+
const width = viewport !== null && typeof viewport === "object" ? Reflect.get(viewport, "width") : void 0;
|
|
1478
|
+
const height = viewport !== null && typeof viewport === "object" ? Reflect.get(viewport, "height") : void 0;
|
|
1466
1479
|
const x = point !== null && typeof point === "object" ? Reflect.get(point, "x") : void 0;
|
|
1467
1480
|
const y = point !== null && typeof point === "object" ? Reflect.get(point, "y") : void 0;
|
|
1468
1481
|
if (!isSimSemanticTree(semanticNodes) || typeof x !== "number" || !Number.isFinite(x) || typeof y !== "number" || !Number.isFinite(y)) {
|
|
@@ -1476,7 +1489,8 @@ async function resolveTargetCoords(bridge, target) {
|
|
|
1476
1489
|
nodeId: semanticMatch.nodeId,
|
|
1477
1490
|
testID: semanticMatch.testID ?? null,
|
|
1478
1491
|
text: semanticMatch.text ?? (target.mode === "text" ? target.value : semanticMatch.label),
|
|
1479
|
-
type: semanticMatch.type
|
|
1492
|
+
type: semanticMatch.type,
|
|
1493
|
+
...typeof width === "number" && typeof height === "number" ? { viewport: { width, height } } : {}
|
|
1480
1494
|
};
|
|
1481
1495
|
}
|
|
1482
1496
|
|
|
@@ -1671,30 +1685,6 @@ async function waitForSootsimIdle({
|
|
|
1671
1685
|
}
|
|
1672
1686
|
|
|
1673
1687
|
// cli/commands/inspect/actions.ts
|
|
1674
|
-
function isScreenSize(value) {
|
|
1675
|
-
if (value === null || typeof value !== "object") return false;
|
|
1676
|
-
const width = Reflect.get(value, "width");
|
|
1677
|
-
const height = Reflect.get(value, "height");
|
|
1678
|
-
return typeof width === "number" && Number.isFinite(width) && width > 0 && typeof height === "number" && Number.isFinite(height) && height > 0;
|
|
1679
|
-
}
|
|
1680
|
-
function viewportFromCapture(value) {
|
|
1681
|
-
if (value === null || typeof value !== "object") return void 0;
|
|
1682
|
-
const tree = Reflect.get(value, "tree");
|
|
1683
|
-
return tree !== null && typeof tree === "object" ? Reflect.get(tree, "viewport") : void 0;
|
|
1684
|
-
}
|
|
1685
|
-
async function readScreen(bridge) {
|
|
1686
|
-
try {
|
|
1687
|
-
const viewport = viewportFromCapture(
|
|
1688
|
-
await bridge.send({ type: "capture", includeVisual: false })
|
|
1689
|
-
);
|
|
1690
|
-
return isScreenSize(viewport) ? { width: viewport.width, height: viewport.height } : null;
|
|
1691
|
-
} catch {
|
|
1692
|
-
return null;
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1695
|
-
function isOffscreen(cx, cy, screen) {
|
|
1696
|
-
return !(cx >= 0 && cy >= 0 && cx <= screen.width && cy <= screen.height);
|
|
1697
|
-
}
|
|
1698
1688
|
var DEFAULT_AGENT_TIMING = {
|
|
1699
1689
|
initialWaitMs: 3e3,
|
|
1700
1690
|
deadlineMs: 5e3,
|
|
@@ -1756,17 +1746,24 @@ async function tapResolvedTarget(bridge, args) {
|
|
|
1756
1746
|
}
|
|
1757
1747
|
const deadline = Date.now() + timing.deadlineMs;
|
|
1758
1748
|
let lastOffscreenAt = null;
|
|
1759
|
-
const screen = bridge.plane === "cloud" ? null : await readScreen(bridge);
|
|
1760
1749
|
while (Date.now() <= deadline || attempts === 0) {
|
|
1761
1750
|
attempts++;
|
|
1762
|
-
const resolved = await args.resolve();
|
|
1763
|
-
const
|
|
1751
|
+
const { screen, ...resolved } = await args.resolve() ?? {};
|
|
1752
|
+
const checksScreen = bridge.plane !== "cloud" && typeof resolved.cx === "number";
|
|
1753
|
+
if (checksScreen && screen === void 0) {
|
|
1754
|
+
throw new Error(UNREPORTED_SCREEN_ERROR);
|
|
1755
|
+
}
|
|
1756
|
+
const unsized = checksScreen && !isScreenSize(screen);
|
|
1757
|
+
const payload = checksScreen && typeof resolved.cx === "number" && typeof resolved.cy === "number" && isScreenSize(screen) && isOffscreen(resolved.cx, resolved.cy, screen) ? { ...resolved, offscreen: true, screen } : resolved;
|
|
1764
1758
|
lastPayload = payload;
|
|
1765
1759
|
if (payload?.error === "bridge-not-ready" || payload?.ambiguous || payload?.nthOutOfRange) {
|
|
1766
1760
|
return { payload, result: null, attempts, failure: "special" };
|
|
1767
1761
|
}
|
|
1768
1762
|
if (payload && typeof payload.cx === "number" && typeof payload.cy === "number") {
|
|
1769
|
-
if (
|
|
1763
|
+
if (unsized) {
|
|
1764
|
+
lastResult = { hit: false, reason: "screen-not-laid-out" };
|
|
1765
|
+
lastOffscreenAt = null;
|
|
1766
|
+
} else if (payload.offscreen) {
|
|
1770
1767
|
lastResult = {
|
|
1771
1768
|
hit: false,
|
|
1772
1769
|
reason: "offscreen",
|
|
@@ -1839,6 +1836,7 @@ function payloadFromResolved(resolved, match, extra = {}) {
|
|
|
1839
1836
|
return {
|
|
1840
1837
|
cx: resolved.x,
|
|
1841
1838
|
cy: resolved.y,
|
|
1839
|
+
screen: resolved.viewport,
|
|
1842
1840
|
match: {
|
|
1843
1841
|
nodeId: match.nodeId ?? null,
|
|
1844
1842
|
id: match.testID ?? null,
|
|
@@ -1972,24 +1970,12 @@ async function resolveTextTapTarget(bridge, query, options = {}) {
|
|
|
1972
1970
|
const picked = candidates[idx];
|
|
1973
1971
|
if (!picked) return { matched: 0, total };
|
|
1974
1972
|
const node = picked.node;
|
|
1975
|
-
const
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
args: [node.nodeId]
|
|
1973
|
+
const resolved = await resolveTargetCoords(bridge, {
|
|
1974
|
+
mode: "node",
|
|
1975
|
+
nodeId: node.nodeId
|
|
1979
1976
|
});
|
|
1980
|
-
if (!
|
|
1981
|
-
return payloadFromResolved(
|
|
1982
|
-
{
|
|
1983
|
-
x: tap.cx,
|
|
1984
|
-
y: tap.cy,
|
|
1985
|
-
nodeId: tap.target.nodeId,
|
|
1986
|
-
testID: tap.target.testID,
|
|
1987
|
-
text: tap.target.text ?? tap.target.accessibilityLabel,
|
|
1988
|
-
type: tap.target.type
|
|
1989
|
-
},
|
|
1990
|
-
node,
|
|
1991
|
-
{ total, idx }
|
|
1992
|
-
);
|
|
1977
|
+
if (!resolved) return { matched: 0, total };
|
|
1978
|
+
return payloadFromResolved(resolved, node, { total, idx });
|
|
1993
1979
|
}
|
|
1994
1980
|
var TAP_QUERY_FINDERS = {
|
|
1995
1981
|
label: "findByLabel",
|
|
@@ -2021,7 +2007,8 @@ async function tapByQuery(bridge, query, opts = {}) {
|
|
|
2021
2007
|
nodeId: tap.target.nodeId,
|
|
2022
2008
|
testID: tap.target.testID,
|
|
2023
2009
|
text: tap.target.text ?? tap.target.accessibilityLabel,
|
|
2024
|
-
type: tap.target.type
|
|
2010
|
+
type: tap.target.type,
|
|
2011
|
+
viewport: tap.viewport
|
|
2025
2012
|
},
|
|
2026
2013
|
{
|
|
2027
2014
|
nodeId: node.nodeId,
|
package/dist-lib/sdk.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.659 | (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);
|
|
@@ -1352,10 +1352,20 @@ function formatTimelineEvents(events) {
|
|
|
1352
1352
|
}
|
|
1353
1353
|
|
|
1354
1354
|
// cli/commands/inspect/resolve-target.ts
|
|
1355
|
+
function isScreenSize(value) {
|
|
1356
|
+
if (value === null || typeof value !== "object") return false;
|
|
1357
|
+
const width = Reflect.get(value, "width");
|
|
1358
|
+
const height = Reflect.get(value, "height");
|
|
1359
|
+
return typeof width === "number" && Number.isFinite(width) && width > 0 && typeof height === "number" && Number.isFinite(height) && height > 0;
|
|
1360
|
+
}
|
|
1361
|
+
function isOffscreen(x, y, screen) {
|
|
1362
|
+
return !(x >= 0 && y >= 0 && x <= screen.width && y <= screen.height);
|
|
1363
|
+
}
|
|
1364
|
+
var UNREPORTED_SCREEN_ERROR = "this runtime does not report the screen size a targeted gesture needs; update it with `peach runtime install`, or use coordinates";
|
|
1355
1365
|
async function resolveTargetCoords(bridge, target) {
|
|
1356
1366
|
const result = await bridge.send({
|
|
1357
1367
|
type: "resolve",
|
|
1358
|
-
selector: target.mode === "testid" ? { testID: target.value } : { text: target.value }
|
|
1368
|
+
selector: target.mode === "node" ? { nodeId: target.nodeId } : target.mode === "testid" ? { testID: target.value } : { text: target.value }
|
|
1359
1369
|
});
|
|
1360
1370
|
if (result === null) return null;
|
|
1361
1371
|
if (typeof result !== "object") throw new Error("resolve returned an invalid result");
|
|
@@ -1363,6 +1373,9 @@ async function resolveTargetCoords(bridge, target) {
|
|
|
1363
1373
|
const resolvedTarget = Reflect.get(result, "target");
|
|
1364
1374
|
const semanticNodes = [match, resolvedTarget];
|
|
1365
1375
|
const point = Reflect.get(result, "point");
|
|
1376
|
+
const viewport = Reflect.get(result, "viewport");
|
|
1377
|
+
const width = viewport !== null && typeof viewport === "object" ? Reflect.get(viewport, "width") : void 0;
|
|
1378
|
+
const height = viewport !== null && typeof viewport === "object" ? Reflect.get(viewport, "height") : void 0;
|
|
1366
1379
|
const x = point !== null && typeof point === "object" ? Reflect.get(point, "x") : void 0;
|
|
1367
1380
|
const y = point !== null && typeof point === "object" ? Reflect.get(point, "y") : void 0;
|
|
1368
1381
|
if (!isSimSemanticTree(semanticNodes) || typeof x !== "number" || !Number.isFinite(x) || typeof y !== "number" || !Number.isFinite(y)) {
|
|
@@ -1376,7 +1389,8 @@ async function resolveTargetCoords(bridge, target) {
|
|
|
1376
1389
|
nodeId: semanticMatch.nodeId,
|
|
1377
1390
|
testID: semanticMatch.testID ?? null,
|
|
1378
1391
|
text: semanticMatch.text ?? (target.mode === "text" ? target.value : semanticMatch.label),
|
|
1379
|
-
type: semanticMatch.type
|
|
1392
|
+
type: semanticMatch.type,
|
|
1393
|
+
...typeof width === "number" && typeof height === "number" ? { viewport: { width, height } } : {}
|
|
1380
1394
|
};
|
|
1381
1395
|
}
|
|
1382
1396
|
|
|
@@ -1571,30 +1585,6 @@ async function waitForSootsimIdle({
|
|
|
1571
1585
|
}
|
|
1572
1586
|
|
|
1573
1587
|
// cli/commands/inspect/actions.ts
|
|
1574
|
-
function isScreenSize(value) {
|
|
1575
|
-
if (value === null || typeof value !== "object") return false;
|
|
1576
|
-
const width = Reflect.get(value, "width");
|
|
1577
|
-
const height = Reflect.get(value, "height");
|
|
1578
|
-
return typeof width === "number" && Number.isFinite(width) && width > 0 && typeof height === "number" && Number.isFinite(height) && height > 0;
|
|
1579
|
-
}
|
|
1580
|
-
function viewportFromCapture(value) {
|
|
1581
|
-
if (value === null || typeof value !== "object") return void 0;
|
|
1582
|
-
const tree = Reflect.get(value, "tree");
|
|
1583
|
-
return tree !== null && typeof tree === "object" ? Reflect.get(tree, "viewport") : void 0;
|
|
1584
|
-
}
|
|
1585
|
-
async function readScreen(bridge) {
|
|
1586
|
-
try {
|
|
1587
|
-
const viewport = viewportFromCapture(
|
|
1588
|
-
await bridge.send({ type: "capture", includeVisual: false })
|
|
1589
|
-
);
|
|
1590
|
-
return isScreenSize(viewport) ? { width: viewport.width, height: viewport.height } : null;
|
|
1591
|
-
} catch {
|
|
1592
|
-
return null;
|
|
1593
|
-
}
|
|
1594
|
-
}
|
|
1595
|
-
function isOffscreen(cx, cy, screen) {
|
|
1596
|
-
return !(cx >= 0 && cy >= 0 && cx <= screen.width && cy <= screen.height);
|
|
1597
|
-
}
|
|
1598
1588
|
var DEFAULT_AGENT_TIMING = {
|
|
1599
1589
|
initialWaitMs: 3e3,
|
|
1600
1590
|
deadlineMs: 5e3,
|
|
@@ -1656,17 +1646,24 @@ async function tapResolvedTarget(bridge, args) {
|
|
|
1656
1646
|
}
|
|
1657
1647
|
const deadline = Date.now() + timing.deadlineMs;
|
|
1658
1648
|
let lastOffscreenAt = null;
|
|
1659
|
-
const screen = bridge.plane === "cloud" ? null : await readScreen(bridge);
|
|
1660
1649
|
while (Date.now() <= deadline || attempts === 0) {
|
|
1661
1650
|
attempts++;
|
|
1662
|
-
const resolved = await args.resolve();
|
|
1663
|
-
const
|
|
1651
|
+
const { screen, ...resolved } = await args.resolve() ?? {};
|
|
1652
|
+
const checksScreen = bridge.plane !== "cloud" && typeof resolved.cx === "number";
|
|
1653
|
+
if (checksScreen && screen === void 0) {
|
|
1654
|
+
throw new Error(UNREPORTED_SCREEN_ERROR);
|
|
1655
|
+
}
|
|
1656
|
+
const unsized = checksScreen && !isScreenSize(screen);
|
|
1657
|
+
const payload = checksScreen && typeof resolved.cx === "number" && typeof resolved.cy === "number" && isScreenSize(screen) && isOffscreen(resolved.cx, resolved.cy, screen) ? { ...resolved, offscreen: true, screen } : resolved;
|
|
1664
1658
|
lastPayload = payload;
|
|
1665
1659
|
if (payload?.error === "bridge-not-ready" || payload?.ambiguous || payload?.nthOutOfRange) {
|
|
1666
1660
|
return { payload, result: null, attempts, failure: "special" };
|
|
1667
1661
|
}
|
|
1668
1662
|
if (payload && typeof payload.cx === "number" && typeof payload.cy === "number") {
|
|
1669
|
-
if (
|
|
1663
|
+
if (unsized) {
|
|
1664
|
+
lastResult = { hit: false, reason: "screen-not-laid-out" };
|
|
1665
|
+
lastOffscreenAt = null;
|
|
1666
|
+
} else if (payload.offscreen) {
|
|
1670
1667
|
lastResult = {
|
|
1671
1668
|
hit: false,
|
|
1672
1669
|
reason: "offscreen",
|
|
@@ -1739,6 +1736,7 @@ function payloadFromResolved(resolved, match, extra = {}) {
|
|
|
1739
1736
|
return {
|
|
1740
1737
|
cx: resolved.x,
|
|
1741
1738
|
cy: resolved.y,
|
|
1739
|
+
screen: resolved.viewport,
|
|
1742
1740
|
match: {
|
|
1743
1741
|
nodeId: match.nodeId ?? null,
|
|
1744
1742
|
id: match.testID ?? null,
|
|
@@ -1872,24 +1870,12 @@ async function resolveTextTapTarget(bridge, query, options = {}) {
|
|
|
1872
1870
|
const picked = candidates[idx];
|
|
1873
1871
|
if (!picked) return { matched: 0, total };
|
|
1874
1872
|
const node = picked.node;
|
|
1875
|
-
const
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
args: [node.nodeId]
|
|
1873
|
+
const resolved = await resolveTargetCoords(bridge, {
|
|
1874
|
+
mode: "node",
|
|
1875
|
+
nodeId: node.nodeId
|
|
1879
1876
|
});
|
|
1880
|
-
if (!
|
|
1881
|
-
return payloadFromResolved(
|
|
1882
|
-
{
|
|
1883
|
-
x: tap.cx,
|
|
1884
|
-
y: tap.cy,
|
|
1885
|
-
nodeId: tap.target.nodeId,
|
|
1886
|
-
testID: tap.target.testID,
|
|
1887
|
-
text: tap.target.text ?? tap.target.accessibilityLabel,
|
|
1888
|
-
type: tap.target.type
|
|
1889
|
-
},
|
|
1890
|
-
node,
|
|
1891
|
-
{ total, idx }
|
|
1892
|
-
);
|
|
1877
|
+
if (!resolved) return { matched: 0, total };
|
|
1878
|
+
return payloadFromResolved(resolved, node, { total, idx });
|
|
1893
1879
|
}
|
|
1894
1880
|
var TAP_QUERY_FINDERS = {
|
|
1895
1881
|
label: "findByLabel",
|
|
@@ -1921,7 +1907,8 @@ async function tapByQuery(bridge, query, opts = {}) {
|
|
|
1921
1907
|
nodeId: tap.target.nodeId,
|
|
1922
1908
|
testID: tap.target.testID,
|
|
1923
1909
|
text: tap.target.text ?? tap.target.accessibilityLabel,
|
|
1924
|
-
type: tap.target.type
|
|
1910
|
+
type: tap.target.type,
|
|
1911
|
+
viewport: tap.viewport
|
|
1925
1912
|
},
|
|
1926
1913
|
{
|
|
1927
1914
|
nodeId: node.nodeId,
|