peachsim 0.1.1625 → 0.1.1640
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/LICENSE +1 -1
- package/README.md +15 -2
- package/cli/app-config.ts +18 -6
- package/cli/app-fonts.ts +37 -17
- package/cli/app-stubs.ts +284 -20
- package/cli/bridge-flow-runner.ts +66 -45
- package/cli/cloud-client.ts +60 -40
- package/cli/command-registry.ts +1 -0
- package/cli/commands/control.ts +283 -49
- package/cli/commands/doctor.ts +30 -189
- package/cli/commands/flow.ts +79 -11
- package/cli/commands/inspect/core.ts +10 -5
- package/cli/commands/inspect/settling.ts +14 -2
- package/cli/commands/inspect/shared.ts +9 -4
- package/cli/commands/inspect/wait-ready.ts +12 -0
- package/cli/commands/inspect.ts +91 -50
- package/cli/commands/install-desktop.ts +1 -0
- package/cli/commands/maestro-compare.ts +97 -38
- package/cli/commands/maestro.ts +9 -1
- package/cli/commands/preview.ts +1 -1
- package/cli/commands/record.ts +118 -48
- package/cli/commands/screenshot.ts +23 -1
- package/cli/commands/serve.ts +7 -2
- package/cli/commands/setup.ts +19 -42
- package/cli/commands/swift.ts +14 -3
- package/cli/commands/upload.ts +93 -48
- package/cli/desktop-companion.ts +102 -17
- package/cli/drivers/desktop.ts +14 -1
- package/cli/drivers/playwright-sim-host.ts +103 -45
- package/cli/drivers/playwright.ts +9 -8
- package/cli/drivers/types.ts +5 -0
- package/cli/maestro-accessibility.ts +1 -1
- package/cli/maestro-compare.ts +84 -12
- package/cli/main.ts +3 -2
- package/cli/outbound-endpoints.ts +20 -6
- package/cli/pause-aware-timeout.ts +106 -0
- package/cli/scene-video.ts +89 -0
- package/cli/ws-bridge.ts +37 -19
- package/detox/attempt-events.cjs +66 -5
- package/detox/attempt-events.d.cts +7 -0
- package/detox/expectations.ts +7 -3
- package/detox/index.ts +269 -170
- package/detox/motion-change.cjs +206 -21
- package/detox/motion-change.d.cts +39 -2
- package/detox/navigation-lifecycle.ts +35 -3
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.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 +8 -7
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +13 -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 +14 -8
- package/dist-lib/bridge-contract.mjs +13 -7
- package/dist-lib/bundle-channel.cjs +11887 -7900
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +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 +6 -3
- package/dist-lib/config.mjs +6 -3
- package/dist-lib/detox/index.cjs +1379 -725
- package/dist-lib/dev-bundle-resolution.cjs +14 -2
- package/dist-lib/expo-swift-bundle.cjs +9341 -5462
- package/dist-lib/expo-swift-metadata.cjs +11 -7
- package/dist-lib/expo-swift-metadata.mjs +11 -7
- package/dist-lib/home-paths.cjs +32 -3
- package/dist-lib/host/bridge-host.cjs +50204 -7258
- 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 +3541 -448
- 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 +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 +2931 -104
- package/dist-lib/native-app-identity-project.cjs +289 -49
- package/dist-lib/native-app-identity-project.mjs +289 -49
- package/dist-lib/native-app-identity.cjs +77 -26
- package/dist-lib/native-app-identity.mjs +76 -26
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +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 +6 -2
- package/dist-lib/react-native-host-modules.mjs +6 -2
- package/dist-lib/scripts/dev-server-scanner.cjs +22 -8
- package/dist-lib/sdk.cjs +27 -11
- package/dist-lib/sdk.mjs +27 -10
- package/dist-lib/skills.cjs +72201 -26208
- package/dist-lib/swift-compile.cjs +1007 -140
- package/dist-lib/swift-compile.mjs +1049 -174
- package/dist-lib/swift-package.cjs +12 -3
- package/dist-lib/swift-package.mjs +12 -3
- package/dist-lib/swift-submit.cjs +13 -5
- package/dist-lib/swift-submit.mjs +11 -5
- package/dist-lib/swift-toolchain.cjs +423 -33
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +8628 -5268
- package/dist-lib/vite.cjs +2859 -12
- package/dist-lib/worklet-executable.cjs +14 -2
- package/dist-lib/worklet-executable.mjs +14 -2
- package/kotlin/AppSources/dev/peach/app/PeachDrawable.kt +21 -14
- package/kotlin/Sources/androidx/annotation/DrawableRes.kt +14 -0
- package/package.json +1 -1
- package/scripts/dev-server-scanner.ts +2 -1
- package/skills/peach-perf/SKILL.md +11 -5
- package/skills/peach-setup/SKILL.md +16 -19
- package/src/backend-origin.ts +13 -6
- package/src/bridge-constants.ts +11 -0
- package/src/bridge-contract.ts +22 -34
- package/src/config.ts +15 -0
- package/src/desktop-host-delivery.ts +5 -1
- package/src/dev-bundle-resolution.ts +2 -1
- package/src/expo-manifest-body.ts +13 -0
- package/src/expo-swift-host.ts +196 -49
- package/src/expo-swift-ready.ts +78 -0
- package/src/expoKotlinContract.ts +4 -7
- package/src/expoSwiftContract.ts +17 -6
- package/src/home-paths.ts +48 -2
- package/src/host/bridge-host.ts +5 -2
- package/src/host/staged-host-files.ts +9 -0
- package/src/native-app-identity-project.ts +27 -6
- package/src/native-app-identity.ts +91 -4
- package/src/native-firebase-config.ts +209 -13
- package/src/nativeAppIconContract.ts +1 -4
- package/src/output-lock-stdio.ts +36 -0
- package/src/process-group.ts +25 -2
- package/src/react-native-bridge-modules.ts +431 -0
- package/src/react-native-host-modules.ts +8 -1
- package/src/settings-bundle.ts +1 -4
- package/src/swift-binary-modules.ts +2 -2
- package/src/swift-compile.ts +918 -109
- package/src/swift-compiler-digest.ts +14 -0
- package/src/swift-distribution.lock.json +24 -12
- package/src/swift-distribution.ts +103 -4
- package/src/swift-host.ts +180 -55
- package/src/swift-icu.ts +27 -13
- package/src/swift-objc-compile.ts +355 -0
- package/src/swift-objc-sdk.ts +821 -27
- package/src/swift-objc-standin.ts +148 -14
- package/src/swift-package-manifest.ts +60 -7
- package/src/swift-package.ts +15 -1
- package/src/swift-packages.ts +154 -81
- package/src/swift-standin-emit.ts +96 -15
- package/src/swift-standins.ts +530 -116
- package/src/swift-submit.ts +13 -5
- package/src/swift-toolchain.ts +500 -42
- package/src/vite-plugin.ts +12 -1
- package/src/worker-system-chunks.ts +11 -12
- package/src/worklet-executable.ts +19 -1
- package/src/xcode-project.ts +270 -30
|
@@ -2175,48 +2175,58 @@ export class SootSimBridgeFlowRunner {
|
|
|
2175
2175
|
await sleep(120)
|
|
2176
2176
|
}
|
|
2177
2177
|
|
|
2178
|
+
// maestro's android driver sends Back. its ios driver never presses a key:
|
|
2179
|
+
// while the keyboard shows it swipes from the screen center up 3%, then
|
|
2180
|
+
// left 3%, and the app's own handling of those touches dismisses it, or
|
|
2181
|
+
// presses whatever sits under the center
|
|
2178
2182
|
async hideKeyboard() {
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
await this.callTest<boolean>('blurFocusedTextInput')
|
|
2185
|
-
} catch {
|
|
2186
|
-
// fall through to the shell-level dismiss below; older bridges may not
|
|
2187
|
-
// expose the text-input helper yet.
|
|
2183
|
+
if (this.js.maestro.platform.toLowerCase() === 'android') {
|
|
2184
|
+
await this.back()
|
|
2185
|
+
await sleep(300)
|
|
2186
|
+
await this.waitForAppToSettle()
|
|
2187
|
+
return
|
|
2188
2188
|
}
|
|
2189
|
+
if (!(await this.isKeyboardVisible())) return
|
|
2190
|
+
const screen = await this.screenBounds()
|
|
2191
|
+
const center = parsePoint('50%,50%', screen)
|
|
2192
|
+
await this.xctestSwipe(center, parsePoint('50%,47%', screen), 50)
|
|
2193
|
+
if (!(await this.isKeyboardVisible())) return
|
|
2194
|
+
await this.xctestSwipe(center, parsePoint('47%,50%', screen), 50)
|
|
2195
|
+
await this.waitForAppToSettle()
|
|
2196
|
+
}
|
|
2189
2197
|
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
}
|
|
2198
|
+
// the xctest runner's swipe: press, move to the end over its 100ms tap
|
|
2199
|
+
// duration, rest there for the requested duration, then lift, so the
|
|
2200
|
+
// finger leaves at rest rather than flinging
|
|
2201
|
+
private async xctestSwipe(
|
|
2202
|
+
from: { x: number; y: number },
|
|
2203
|
+
to: { x: number; y: number },
|
|
2204
|
+
durationMs: number,
|
|
2205
|
+
) {
|
|
2206
|
+
const moves = 6
|
|
2207
|
+
const steps: PerformStep[] = [{ type: 'touchDown', x: from.x, y: from.y }]
|
|
2208
|
+
for (let i = 1; i <= moves; i++) {
|
|
2209
|
+
steps.push({ type: 'wait', ms: 100 / moves })
|
|
2210
|
+
steps.push({
|
|
2211
|
+
type: 'touchMove',
|
|
2212
|
+
x: from.x + ((to.x - from.x) * i) / moves,
|
|
2213
|
+
y: from.y + ((to.y - from.y) * i) / moves,
|
|
2214
|
+
})
|
|
2215
|
+
}
|
|
2216
|
+
steps.push({ type: 'wait', ms: durationMs })
|
|
2217
|
+
steps.push({ type: 'touchUp', x: to.x, y: to.y })
|
|
2218
|
+
const result = await this.perform(steps)
|
|
2219
|
+
if (!result?.ok) throw new Error(`swipe failed: ${result?.error ?? 'swipe missed'}`)
|
|
2220
|
+
await this.waitForAppToSettle()
|
|
2221
|
+
}
|
|
2195
2222
|
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
}>(`(async () => {
|
|
2204
|
-
const keyboard =
|
|
2205
|
-
window.__sootsimKeyboard ??
|
|
2206
|
-
window.SootSim?.bridges?.keyboard ??
|
|
2207
|
-
null
|
|
2208
|
-
const test = window.__sootsimTest
|
|
2209
|
-
return {
|
|
2210
|
-
visible: !!keyboard?.isVisible?.(),
|
|
2211
|
-
focused: !!(await test?.isTextInputFocused?.()),
|
|
2212
|
-
}
|
|
2213
|
-
})()`)
|
|
2214
|
-
if (!state?.visible && !state?.focused) {
|
|
2215
|
-
await sleep(80)
|
|
2216
|
-
return
|
|
2217
|
-
}
|
|
2218
|
-
await sleep(80)
|
|
2219
|
-
} while (Date.now() < deadline)
|
|
2223
|
+
private async isKeyboardVisible(): Promise<boolean> {
|
|
2224
|
+
const visible = await this.evaluate<boolean>(`(() => {
|
|
2225
|
+
const keyboard =
|
|
2226
|
+
window.__sootsimKeyboard ?? window.SootSim?.bridges?.keyboard ?? null
|
|
2227
|
+
return !!keyboard?.isVisible?.()
|
|
2228
|
+
})()`)
|
|
2229
|
+
return visible === true
|
|
2220
2230
|
}
|
|
2221
2231
|
|
|
2222
2232
|
async eraseText(count: number) {
|
|
@@ -2765,8 +2775,15 @@ export class SootSimBridgeFlowRunner {
|
|
|
2765
2775
|
: { x: centerX, y: screen.height * 0.1 }
|
|
2766
2776
|
const element = await this.findElement(target)
|
|
2767
2777
|
if (element) {
|
|
2768
|
-
|
|
2769
|
-
const { width, height } =
|
|
2778
|
+
// maestro computes visibility from integer edges, as it does selection.
|
|
2779
|
+
const { x, y, width, height } = accessibilityBounds({
|
|
2780
|
+
frame: {
|
|
2781
|
+
x: element.absolutePosition.x,
|
|
2782
|
+
y: element.absolutePosition.y,
|
|
2783
|
+
width: element.layout.width,
|
|
2784
|
+
height: element.layout.height,
|
|
2785
|
+
},
|
|
2786
|
+
})
|
|
2770
2787
|
const shownX = Math.max(0, Math.min(x + width, screen.width) - Math.max(x, 0))
|
|
2771
2788
|
const shownY = Math.max(0, Math.min(y + height, screen.height) - Math.max(y, 0))
|
|
2772
2789
|
const share = width * height > 0 ? (shownX * shownY) / (width * height) : 0
|
|
@@ -2892,6 +2909,12 @@ export class SootSimBridgeFlowRunner {
|
|
|
2892
2909
|
const wantsClear = !!(opts && typeof opts === 'object' && opts.clearState)
|
|
2893
2910
|
const wantsResetRuntime = readBooleanKey(opts, 'resetRuntime')
|
|
2894
2911
|
const wantsForeground = isObjectRecord(opts) && opts.stopApp === false
|
|
2912
|
+
// maestro's launchApp clears the keychain, then app state, then sets
|
|
2913
|
+
// permissions and launches
|
|
2914
|
+
if (readBooleanKey(opts, 'clearKeychain')) {
|
|
2915
|
+
if (!this.firstLaunchDone && !this.appStopped) await this.waitForTree(120000)
|
|
2916
|
+
await this.clearKeychain()
|
|
2917
|
+
}
|
|
2895
2918
|
await this.setLaunchPermissions(isObjectRecord(opts) ? opts.permissions : undefined)
|
|
2896
2919
|
|
|
2897
2920
|
if (!this.firstLaunchDone) {
|
|
@@ -2982,9 +3005,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
2982
3005
|
|
|
2983
3006
|
private async setLaunchPermissions(permissions: unknown) {
|
|
2984
3007
|
const statuses = maestroLaunchPermissions(permissions)
|
|
2985
|
-
const
|
|
2986
|
-
const appId = readStringKey(state, 'activeApp') || readRecentShellAppId(state)
|
|
2987
|
-
if (!appId) throw new Error('launchApp: no simulator app to set permissions for')
|
|
3008
|
+
const appId = await this.callTest<string>('permissionGuestAppId')
|
|
2988
3009
|
for (const [kind, status] of statuses) {
|
|
2989
3010
|
await this.callTest('permissionSetAppPermission', appId, kind, {
|
|
2990
3011
|
status,
|
|
@@ -3082,11 +3103,11 @@ export class SootSimBridgeFlowRunner {
|
|
|
3082
3103
|
}
|
|
3083
3104
|
|
|
3084
3105
|
async startProfile() {
|
|
3085
|
-
const result = await this.evaluate<any>(`(() => {
|
|
3106
|
+
const result = await this.evaluate<any>(`(async () => {
|
|
3086
3107
|
if (!window.__sootsimShellPerf) {
|
|
3087
3108
|
return { error: "shell frame profile unavailable (__sootsimShellPerf missing on the page)" }
|
|
3088
3109
|
}
|
|
3089
|
-
window.__sootsimShellPerf.start()
|
|
3110
|
+
await window.__sootsimShellPerf.start()
|
|
3090
3111
|
return { started: true }
|
|
3091
3112
|
})()`)
|
|
3092
3113
|
if (result?.error) {
|
package/cli/cloud-client.ts
CHANGED
|
@@ -27,6 +27,10 @@ import {
|
|
|
27
27
|
import { rewriteGuestImportMeta } from '../../peach-engine/src/guest-import-meta.ts'
|
|
28
28
|
import { loadMetroFingerprintRegistry } from '../../peach-engine/src/metro-fingerprint-registry-client.ts'
|
|
29
29
|
import { inferMetroModuleIdentity } from '../../peach-engine/src/metro-fingerprint.ts'
|
|
30
|
+
import {
|
|
31
|
+
isNativeJavaScriptBundle,
|
|
32
|
+
isRolldownBundle,
|
|
33
|
+
} from '../../peach-engine/src/preview/bundle-layout'
|
|
30
34
|
import { isLoopbackHost } from '../src/backend-origin.ts'
|
|
31
35
|
import {
|
|
32
36
|
isRnxCloudCommandType,
|
|
@@ -172,7 +176,7 @@ function resolveCloudOrigin(value?: string): string {
|
|
|
172
176
|
function readImmutableBundleSource(bundlePath: string, command: string): string {
|
|
173
177
|
const filepath = resolve(bundlePath)
|
|
174
178
|
if (extname(filepath) !== '.js') {
|
|
175
|
-
throw new Error(`${command} requires one local
|
|
179
|
+
throw new Error(`${command} requires one local .js bundle`)
|
|
176
180
|
}
|
|
177
181
|
const descriptor = openSync(filepath, 'r')
|
|
178
182
|
try {
|
|
@@ -200,9 +204,6 @@ function readImmutableBundleSource(bundlePath: string, command: string): string
|
|
|
200
204
|
} catch {
|
|
201
205
|
throw new Error(`${command} bundle must be valid UTF-8 JavaScript`)
|
|
202
206
|
}
|
|
203
|
-
if (source.includes('\0') || !source.includes('__d(') || !source.includes('__r(')) {
|
|
204
|
-
throw new Error(`${command} requires a Metro JavaScript bundle`)
|
|
205
|
-
}
|
|
206
207
|
return source
|
|
207
208
|
} finally {
|
|
208
209
|
closeSync(descriptor)
|
|
@@ -231,9 +232,6 @@ async function fetchBundleSource(bundleUrl: string, command: string): Promise<st
|
|
|
231
232
|
if (text.length === 0) {
|
|
232
233
|
throw new Error(`${command} bundle is empty`)
|
|
233
234
|
}
|
|
234
|
-
if (text.includes('\0') || !text.includes('__d(') || !text.includes('__r(')) {
|
|
235
|
-
throw new Error(`${command} requires a Metro JavaScript bundle`)
|
|
236
|
-
}
|
|
237
235
|
return text
|
|
238
236
|
}
|
|
239
237
|
|
|
@@ -260,6 +258,9 @@ async function loadBundleSource(bundleInput: string, command: string): Promise<s
|
|
|
260
258
|
const source = isRemoteBundleInput(bundleInput)
|
|
261
259
|
? await fetchBundleSource(bundleInput, command)
|
|
262
260
|
: readImmutableBundleSource(bundleInput, command)
|
|
261
|
+
if (!isNativeJavaScriptBundle(source)) {
|
|
262
|
+
throw new Error(`${command} requires a supported React Native JavaScript bundle`)
|
|
263
|
+
}
|
|
263
264
|
// validate the actual runtime script form without executing guest code or
|
|
264
265
|
// allocating a host.
|
|
265
266
|
try {
|
|
@@ -728,25 +729,44 @@ export async function produceCloudArtifact(
|
|
|
728
729
|
maxBytes: number = MAX_RNX_CLOUD_BUNDLE_BYTES,
|
|
729
730
|
assetsDirectory?: string,
|
|
730
731
|
): Promise<CloudArtifactProduction> {
|
|
731
|
-
|
|
732
|
+
const prepared = await embedBundleAssets(
|
|
732
733
|
bundlePath,
|
|
733
|
-
maxBytes,
|
|
734
734
|
REMOTE_COMMAND,
|
|
735
735
|
assetsDirectory ? 'require-assets' : 'allow-placeholders',
|
|
736
736
|
assetsDirectory,
|
|
737
737
|
)
|
|
738
|
+
return produceArtifact(prepared, maxBytes, REMOTE_COMMAND)
|
|
738
739
|
}
|
|
739
740
|
|
|
740
741
|
/** prepares a standalone preview whose bytes must represent every Metro asset. */
|
|
741
|
-
export async function producePreviewArtifact(
|
|
742
|
-
bundlePath
|
|
743
|
-
)
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
)
|
|
742
|
+
export async function producePreviewArtifact(bundlePath: string) {
|
|
743
|
+
const prepared = await embedBundleAssets(bundlePath, PREVIEW_COMMAND, 'require-assets')
|
|
744
|
+
if (!isRolldownBundle(prepared.source)) {
|
|
745
|
+
return {
|
|
746
|
+
...(await produceArtifact(prepared, Number.POSITIVE_INFINITY, PREVIEW_COMMAND)),
|
|
747
|
+
minified: true,
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
const bytes = Buffer.from(prepared.code, 'utf8')
|
|
751
|
+
const sha256 = createHash('sha256').update(bytes).digest('hex')
|
|
752
|
+
return {
|
|
753
|
+
bytes,
|
|
754
|
+
sha256,
|
|
755
|
+
minified: false,
|
|
756
|
+
receipt: {
|
|
757
|
+
source: {
|
|
758
|
+
sha256: createHash('sha256').update(prepared.source).digest('hex'),
|
|
759
|
+
bytes: Buffer.byteLength(prepared.source, 'utf8'),
|
|
760
|
+
},
|
|
761
|
+
artifact: { sha256, bytes: bytes.byteLength },
|
|
762
|
+
},
|
|
763
|
+
warnings:
|
|
764
|
+
prepared.search.unconfirmed && prepared.dest
|
|
765
|
+
? [
|
|
766
|
+
`peach preview could not authenticate asset hashes in ${prepared.dest.directory}; confirm these are the assets this bundle was built against.`,
|
|
767
|
+
]
|
|
768
|
+
: [],
|
|
769
|
+
}
|
|
750
770
|
}
|
|
751
771
|
|
|
752
772
|
export interface CloudBoxArtifactProduction {
|
|
@@ -890,18 +910,10 @@ async function embedBundleAssets(
|
|
|
890
910
|
}
|
|
891
911
|
|
|
892
912
|
async function produceArtifact(
|
|
893
|
-
|
|
913
|
+
prepared: Awaited<ReturnType<typeof embedBundleAssets>>,
|
|
894
914
|
maxBytes: number,
|
|
895
915
|
command: string,
|
|
896
|
-
assetPolicy: 'allow-placeholders' | 'require-assets',
|
|
897
|
-
assetsDirectory?: string,
|
|
898
916
|
): Promise<CloudArtifactProduction> {
|
|
899
|
-
const prepared = await embedBundleAssets(
|
|
900
|
-
bundlePath,
|
|
901
|
-
command,
|
|
902
|
-
assetPolicy,
|
|
903
|
-
assetsDirectory,
|
|
904
|
-
)
|
|
905
917
|
const artifact = await buildRnxCloudArtifact(prepared.code, {
|
|
906
918
|
inferModuleIdentity: (source) => inferCloudModuleIdentity(source, command),
|
|
907
919
|
})
|
|
@@ -1453,12 +1465,17 @@ function cloudCommand(command: {
|
|
|
1453
1465
|
class CloudBridge implements WsBridge {
|
|
1454
1466
|
readonly plane = 'cloud' as const
|
|
1455
1467
|
|
|
1456
|
-
constructor(
|
|
1468
|
+
constructor(
|
|
1469
|
+
private readonly session: CloudSimSession,
|
|
1470
|
+
private readonly explicitTimeoutMs?: number,
|
|
1471
|
+
) {}
|
|
1457
1472
|
|
|
1458
1473
|
async send(
|
|
1459
1474
|
command: { type: string; [key: string]: unknown },
|
|
1460
|
-
options?: { timeoutMs?: number },
|
|
1475
|
+
options?: { timeoutMs?: number; defaultTimeoutMs?: number },
|
|
1461
1476
|
): Promise<unknown> {
|
|
1477
|
+
const timeoutMs =
|
|
1478
|
+
options?.timeoutMs ?? this.explicitTimeoutMs ?? options?.defaultTimeoutMs
|
|
1462
1479
|
const body: CloudCommandEnvelope = {
|
|
1463
1480
|
id: randomUUID(),
|
|
1464
1481
|
claimId: this.session.claimId,
|
|
@@ -1475,9 +1492,7 @@ class CloudBridge implements WsBridge {
|
|
|
1475
1492
|
'content-type': 'application/json',
|
|
1476
1493
|
},
|
|
1477
1494
|
body: JSON.stringify(body),
|
|
1478
|
-
...(
|
|
1479
|
-
? { signal: AbortSignal.timeout(options.timeoutMs) }
|
|
1480
|
-
: {}),
|
|
1495
|
+
...(timeoutMs ? { signal: AbortSignal.timeout(timeoutMs) } : {}),
|
|
1481
1496
|
},
|
|
1482
1497
|
)
|
|
1483
1498
|
} catch (error) {
|
|
@@ -1538,12 +1553,17 @@ class CloudBridge implements WsBridge {
|
|
|
1538
1553
|
class CloudBoxBridge implements WsBridge {
|
|
1539
1554
|
readonly plane = 'cloud' as const
|
|
1540
1555
|
|
|
1541
|
-
constructor(
|
|
1556
|
+
constructor(
|
|
1557
|
+
private readonly session: CloudBoxSession,
|
|
1558
|
+
private readonly explicitTimeoutMs?: number,
|
|
1559
|
+
) {}
|
|
1542
1560
|
|
|
1543
1561
|
async send(
|
|
1544
1562
|
command: { type: string; [key: string]: unknown },
|
|
1545
|
-
options?: { timeoutMs?: number },
|
|
1563
|
+
options?: { timeoutMs?: number; defaultTimeoutMs?: number },
|
|
1546
1564
|
): Promise<unknown> {
|
|
1565
|
+
const timeoutMs =
|
|
1566
|
+
options?.timeoutMs ?? this.explicitTimeoutMs ?? options?.defaultTimeoutMs
|
|
1547
1567
|
const id = randomUUID()
|
|
1548
1568
|
// the wire id is this request's, so the command carries none. `simId` names
|
|
1549
1569
|
// a local sim among several and a box has exactly one.
|
|
@@ -1562,9 +1582,7 @@ class CloudBoxBridge implements WsBridge {
|
|
|
1562
1582
|
'content-type': 'application/json',
|
|
1563
1583
|
},
|
|
1564
1584
|
body: JSON.stringify({ id, command: payload }),
|
|
1565
|
-
...(
|
|
1566
|
-
? { signal: AbortSignal.timeout(options.timeoutMs) }
|
|
1567
|
-
: {}),
|
|
1585
|
+
...(timeoutMs ? { signal: AbortSignal.timeout(timeoutMs) } : {}),
|
|
1568
1586
|
},
|
|
1569
1587
|
)
|
|
1570
1588
|
} catch (error) {
|
|
@@ -1619,13 +1637,15 @@ class CloudBoxBridge implements WsBridge {
|
|
|
1619
1637
|
}
|
|
1620
1638
|
|
|
1621
1639
|
export function createCloudBridgeForParsed(
|
|
1622
|
-
parsed: Pick<ParsedBridgeCliArgs, 'simId' | 'simIdSource'
|
|
1640
|
+
parsed: Pick<ParsedBridgeCliArgs, 'simId' | 'simIdSource'> &
|
|
1641
|
+
Partial<Pick<ParsedBridgeCliArgs, 'explicitTimeout' | 'commandTimeoutMs'>>,
|
|
1623
1642
|
): WsBridge | null {
|
|
1624
1643
|
const session = resolveCloudSessionForParsed(parsed)
|
|
1625
1644
|
if (!session) return null
|
|
1645
|
+
const timeoutMs = parsed.explicitTimeout ? parsed.commandTimeoutMs : undefined
|
|
1626
1646
|
return session.service === 'box'
|
|
1627
|
-
? new CloudBoxBridge(session)
|
|
1628
|
-
: new CloudBridge(session)
|
|
1647
|
+
? new CloudBoxBridge(session, timeoutMs)
|
|
1648
|
+
: new CloudBridge(session, timeoutMs)
|
|
1629
1649
|
}
|
|
1630
1650
|
|
|
1631
1651
|
// deletes the box, which ends the simulator it holds. a cloud session box is
|