rnxsim 0.1.313 → 0.1.314
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 +11 -10
- package/README.md +5 -0
- package/cli/app-config.ts +65 -0
- package/cli/app-fonts.ts +408 -0
- package/cli/app-project.ts +231 -0
- package/cli/app-splash.ts +185 -0
- package/cli/app-state-reset.ts +24 -0
- package/cli/auth.ts +155 -0
- package/cli/bin.ts +594 -0
- package/cli/bridge-diagnostics.ts +226 -0
- package/cli/bridge-flow-runner.ts +2830 -0
- package/cli/browser-evals.ts +96 -0
- package/cli/commands/agent-wrapper.ts +986 -0
- package/cli/commands/agent.ts +423 -0
- package/cli/commands/app-fonts.ts +98 -0
- package/cli/commands/assert.ts +541 -0
- package/cli/commands/auth.ts +59 -0
- package/cli/commands/camera.ts +266 -0
- package/cli/commands/cleanup.ts +169 -0
- package/cli/commands/compat.ts +87 -0
- package/cli/commands/config.ts +32 -0
- package/cli/commands/control.ts +2142 -0
- package/cli/commands/cpu-profile.ts +269 -0
- package/cli/commands/daemon-mac-app.ts +169 -0
- package/cli/commands/daemon.ts +874 -0
- package/cli/commands/debug.ts +719 -0
- package/cli/commands/desktop.ts +39 -0
- package/cli/commands/detect.ts +197 -0
- package/cli/commands/detox.ts +385 -0
- package/cli/commands/device.ts +133 -0
- package/cli/commands/diagnose.ts +589 -0
- package/cli/commands/electron.ts +95 -0
- package/cli/commands/film.ts +379 -0
- package/cli/commands/flow.ts +1124 -0
- package/cli/commands/inspect/actions.ts +622 -0
- package/cli/commands/inspect/core.ts +2405 -0
- package/cli/commands/inspect/count.ts +17 -0
- package/cli/commands/inspect/describe.ts +192 -0
- package/cli/commands/inspect/env.ts +23 -0
- package/cli/commands/inspect/find.ts +171 -0
- package/cli/commands/inspect/get-layout.ts +39 -0
- package/cli/commands/inspect/keyboard.ts +52 -0
- package/cli/commands/inspect/list.ts +58 -0
- package/cli/commands/inspect/memory.ts +215 -0
- package/cli/commands/inspect/redaction.ts +39 -0
- package/cli/commands/inspect/resolve-target.ts +82 -0
- package/cli/commands/inspect/screens.ts +78 -0
- package/cli/commands/inspect/settle.ts +22 -0
- package/cli/commands/inspect/settling.ts +158 -0
- package/cli/commands/inspect/shared.ts +353 -0
- package/cli/commands/inspect/sleep.ts +14 -0
- package/cli/commands/inspect/tree.ts +32 -0
- package/cli/commands/inspect/url.ts +17 -0
- package/cli/commands/inspect/wait-event.ts +210 -0
- package/cli/commands/inspect/wait-idle.ts +24 -0
- package/cli/commands/inspect/wait-ready.ts +74 -0
- package/cli/commands/inspect/wait-selector.ts +54 -0
- package/cli/commands/inspect/wait.ts +31 -0
- package/cli/commands/inspect.ts +4519 -0
- package/cli/commands/install-desktop.ts +351 -0
- package/cli/commands/login.ts +331 -0
- package/cli/commands/logout.ts +31 -0
- package/cli/commands/maestro-generate.ts +361 -0
- package/cli/commands/maestro.ts +453 -0
- package/cli/commands/mode.ts +57 -0
- package/cli/commands/no-bridge-hint.ts +80 -0
- package/cli/commands/perf.ts +66 -0
- package/cli/commands/permissions.ts +203 -0
- package/cli/commands/profile.ts +108 -0
- package/cli/commands/react.ts +353 -0
- package/cli/commands/record.ts +1434 -0
- package/cli/commands/report-issue.ts +305 -0
- package/cli/commands/reset.ts +85 -0
- package/cli/commands/runtime.ts +351 -0
- package/cli/commands/screenshot-command.ts +106 -0
- package/cli/commands/screenshot-layers.ts +143 -0
- package/cli/commands/screenshot-mode.ts +37 -0
- package/cli/commands/screenshot.ts +488 -0
- package/cli/commands/screenshots-capture.ts +607 -0
- package/cli/commands/screenshots.ts +127 -0
- package/cli/commands/serve.ts +168 -0
- package/cli/commands/setup.ts +545 -0
- package/cli/commands/shell-boolean-mode.ts +81 -0
- package/cli/commands/skills.ts +467 -0
- package/cli/commands/slides.ts +361 -0
- package/cli/commands/state.ts +87 -0
- package/cli/commands/storage.ts +58 -0
- package/cli/commands/telemetry.ts +54 -0
- package/cli/commands/three-mode.ts +763 -0
- package/cli/commands/timeline.ts +122 -0
- package/cli/commands/upgrade.ts +208 -0
- package/cli/commands/upload.ts +1225 -0
- package/cli/commands/version.ts +54 -0
- package/cli/commands/what-happened.ts +327 -0
- package/cli/current-sim.ts +204 -0
- package/cli/desktop-companion.ts +300 -0
- package/cli/drivers/electron.ts +70 -0
- package/cli/drivers/index.ts +20 -0
- package/cli/drivers/playwright-provisioning.ts +180 -0
- package/cli/drivers/playwright.ts +698 -0
- package/cli/drivers/registry.ts +65 -0
- package/cli/drivers/types.ts +102 -0
- package/cli/flow-file.ts +142 -0
- package/cli/flow-live-status.ts +120 -0
- package/cli/flow-session.ts +187 -0
- package/cli/help.ts +80 -0
- package/cli/hidden-runtime-alias.ts +19 -0
- package/cli/hints.ts +216 -0
- package/cli/inspect-notice-state.ts +114 -0
- package/cli/maestro-js.ts +334 -0
- package/cli/open-url.ts +8 -0
- package/cli/parent-pid.ts +204 -0
- package/cli/parse-args.ts +211 -0
- package/cli/prompt.ts +51 -0
- package/cli/recording-access.ts +107 -0
- package/cli/registry.ts +1 -0
- package/cli/resolve-assets.ts +63 -0
- package/cli/run-registry.ts +226 -0
- package/cli/runtime-notes.ts +66 -0
- package/cli/runtime-summary.ts +25 -0
- package/cli/setup-repository.ts +187 -0
- package/cli/telemetry.ts +187 -0
- package/cli/ws-bridge.ts +798 -0
- package/dist-cli/bin.js +5 -5
- package/dist-cli/chunks/{agent-XZ2KTPCU.js → agent-7YBDCYMA.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-JJYYW2WH.js → agent-wrapper-2GHFBHCR.js} +2 -2
- package/dist-cli/chunks/{app-fonts-IXRNQG6B.js → app-fonts-RSNVPQSU.js} +2 -2
- package/dist-cli/chunks/{assert-54T5SK5F.js → assert-XCMX3XJX.js} +2 -2
- package/dist-cli/chunks/{auth-FI5UDI45.js → auth-B442HRAX.js} +2 -2
- package/dist-cli/chunks/{beta-JV6UKADW.js → beta-XJ55JK3M.js} +2 -2
- package/dist-cli/chunks/camera-UGYSSLIK.js +33 -0
- package/dist-cli/chunks/{chunk-3NV2NCNX.js → chunk-277AEQZX.js} +2 -2
- package/dist-cli/chunks/{chunk-2YR5BGA5.js → chunk-2JNSK774.js} +2 -2
- package/dist-cli/chunks/{chunk-RSZWCKNT.js → chunk-32WOTSTR.js} +3 -3
- package/dist-cli/chunks/{chunk-WEXDAC74.js → chunk-3S753SNQ.js} +2 -2
- package/dist-cli/chunks/{chunk-IJO63TDP.js → chunk-46ZOLOYA.js} +2 -2
- package/dist-cli/chunks/{chunk-WUSWBCWA.js → chunk-5L7ELDQL.js} +8 -9
- package/dist-cli/chunks/{chunk-WF3T4SVI.js → chunk-7OOPFSQS.js} +2 -2
- package/dist-cli/chunks/{chunk-TZFFR3SD.js → chunk-7SV3RPRW.js} +2 -2
- package/dist-cli/chunks/{chunk-WWZIXIRD.js → chunk-7ZC35MOU.js} +1 -1
- package/dist-cli/chunks/chunk-AMG5E6CC.js +9 -0
- package/dist-cli/chunks/{chunk-WINYQ44O.js → chunk-APWNH3A4.js} +1 -1
- package/dist-cli/chunks/chunk-B57XUKY3.js +4 -0
- package/dist-cli/chunks/{chunk-YDGQTMQL.js → chunk-C2NL26TD.js} +1 -1
- package/dist-cli/chunks/{chunk-NMF2ZMZQ.js → chunk-D2FNUWAB.js} +4 -4
- package/dist-cli/chunks/{chunk-YIFT42WN.js → chunk-E5T4XSJ3.js} +2 -2
- package/dist-cli/chunks/{chunk-46EUUFJ5.js → chunk-EAC34EQS.js} +1 -1
- package/dist-cli/chunks/{chunk-OVFJFXUD.js → chunk-EG32ML36.js} +2 -2
- package/dist-cli/chunks/{chunk-5YJCOWCH.js → chunk-FXUAC6D5.js} +1 -1
- package/dist-cli/chunks/chunk-GQSL4USA.js +6 -0
- package/dist-cli/chunks/{chunk-VFCMSYZK.js → chunk-HAXW27SS.js} +2 -2
- package/dist-cli/chunks/{chunk-2D2UPBBR.js → chunk-IZAHPAN6.js} +1 -1
- package/dist-cli/chunks/{chunk-7GN3LVWB.js → chunk-J62KM5TB.js} +2 -2
- package/dist-cli/chunks/{chunk-BTWORNNG.js → chunk-JEMCD5E4.js} +1 -1
- package/dist-cli/chunks/{chunk-DCEMHR2Y.js → chunk-JZS3Q37N.js} +2 -2
- package/dist-cli/chunks/{chunk-D4FFVGI5.js → chunk-KR4JON7D.js} +1 -1
- package/dist-cli/chunks/chunk-KWCYKQIQ.js +4 -0
- package/dist-cli/chunks/{chunk-VNQEB4L7.js → chunk-MCWPL644.js} +2 -2
- package/dist-cli/chunks/chunk-MJYK3N2I.js +4 -0
- package/dist-cli/chunks/{chunk-5TEF3ET3.js → chunk-O6TRIZNS.js} +2 -2
- package/dist-cli/chunks/{chunk-QKDWYITG.js → chunk-P7XL2E73.js} +3 -3
- package/dist-cli/chunks/{chunk-BBULZ7CG.js → chunk-PFQTUKQ4.js} +62 -87
- package/dist-cli/chunks/{chunk-GGRX24GF.js → chunk-PG5RZCTN.js} +2 -2
- package/dist-cli/chunks/{chunk-W6K4EFPH.js → chunk-QGRI2Z4M.js} +2 -2
- package/dist-cli/chunks/{chunk-ZMJD5GEC.js → chunk-QLXXE7GE.js} +1 -1
- package/dist-cli/chunks/{chunk-VZXWHRUZ.js → chunk-QOJJJWJE.js} +89 -133
- package/dist-cli/chunks/{chunk-OZSSI4WN.js → chunk-RWZY5427.js} +2 -2
- package/dist-cli/chunks/{chunk-UC6U3MML.js → chunk-RZKU2K3J.js} +2 -2
- package/dist-cli/chunks/{chunk-IJ5CAZZC.js → chunk-SBV4IK4H.js} +1 -1
- package/dist-cli/chunks/{chunk-DZS6WPUI.js → chunk-SGMVFFMK.js} +1 -1
- package/dist-cli/chunks/{chunk-OHAZNXLK.js → chunk-TAX4UT2N.js} +1 -1
- package/dist-cli/chunks/{chunk-5DHC6KHQ.js → chunk-TUOFAWXT.js} +1 -1
- package/dist-cli/chunks/{chunk-GASE6UBA.js → chunk-UHZLOHGP.js} +1 -1
- package/dist-cli/chunks/{chunk-F5ZRSS3C.js → chunk-VC7V76U3.js} +1 -1
- package/dist-cli/chunks/{chunk-RTN5C5RL.js → chunk-VQVMLW4U.js} +1 -1
- package/dist-cli/chunks/{chunk-WMIIKMGK.js → chunk-VUKKYPZN.js} +2 -2
- package/dist-cli/chunks/{chunk-5TPRP5QT.js → chunk-WGGRJDRE.js} +1 -1
- package/dist-cli/chunks/chunk-X6H76EKP.js +15 -0
- package/dist-cli/chunks/chunk-XLZ5FNRT.js +27 -0
- package/dist-cli/chunks/{chunk-HI5TFJWN.js → chunk-XULEACM4.js} +2 -2
- package/dist-cli/chunks/{chunk-MJRLLB4R.js → chunk-YFSDM7AX.js} +4 -4
- package/dist-cli/chunks/chunk-YWI3UEVX.js +5 -0
- package/dist-cli/chunks/{chunk-XEVZYVIW.js → chunk-ZBSJO4NB.js} +10 -9
- package/dist-cli/chunks/{cleanup-P27PA6JI.js → cleanup-EYLGCA6Z.js} +2 -2
- package/dist-cli/chunks/cli-version-LL2UGIHE.js +4 -0
- package/dist-cli/chunks/{compat-ZD65FED3.js → compat-TLJYHB4E.js} +2 -2
- package/dist-cli/chunks/{config-XMJRNM2A.js → config-4JWUOEXK.js} +2 -2
- package/dist-cli/chunks/{control-KMIQT3QP.js → control-HPAOYF4N.js} +2 -2
- package/dist-cli/chunks/daemon-OYLASXLE.js +4 -0
- package/dist-cli/chunks/{debug-PT4HOP7N.js → debug-4BKXF6KI.js} +5 -5
- package/dist-cli/chunks/{desktop-S3FG72AK.js → desktop-ZQ6ZD2S6.js} +3 -3
- package/dist-cli/chunks/{detox-B3D4IFCN.js → detox-WNPASSS3.js} +2 -2
- package/dist-cli/chunks/{device-XBNDSB2R.js → device-BXLXVG3V.js} +2 -2
- package/dist-cli/chunks/{diagnose-HMQXJE5N.js → diagnose-3QX7W5RW.js} +2 -2
- package/dist-cli/chunks/{disk-cleanup-BLCZ5BSZ.js → disk-cleanup-KSWKI7WB.js} +2 -2
- package/dist-cli/chunks/drivers-EPIEFF7P.js +4 -0
- package/dist-cli/chunks/{film-BJGTBYZB.js → film-GDMR33VO.js} +3 -3
- package/dist-cli/chunks/flow-NKMPBYCJ.js +4 -0
- package/dist-cli/chunks/help-OGCBHOKA.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-ANOYADHM.js → hidden-runtime-alias-S2GTDX3T.js} +2 -2
- package/dist-cli/chunks/home-paths-QRCDLTTV.js +4 -0
- package/dist-cli/chunks/inspect-FUYMOZPY.js +4 -0
- package/dist-cli/chunks/install-desktop-FR6YKW7Y.js +4 -0
- package/dist-cli/chunks/{login-FJ737MWG.js → login-IJAPUZHI.js} +4 -4
- package/dist-cli/chunks/{logout-ZCNMMHMY.js → logout-QMXDFU2X.js} +2 -2
- package/dist-cli/chunks/{maestro-SZTNKLDF.js → maestro-ZXU3YCVX.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-DCFAIZ4H.js → maestro-generate-PYB5QY7K.js} +3 -3
- package/dist-cli/chunks/{mode-GRMQCRXR.js → mode-WGUCL5FZ.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-W36EWFFB.js → optional-demo-registry-WH2O6H36.js} +2 -2
- package/dist-cli/chunks/{perf-QYBAAUZG.js → perf-TOD3UFAH.js} +2 -2
- package/dist-cli/chunks/{permissions-3QCQ6VF4.js → permissions-I5BRJGTB.js} +2 -2
- package/dist-cli/chunks/{record-QPPC2S4E.js → record-ZYL2FYSK.js} +3 -3
- package/dist-cli/chunks/{report-issue-7NMFP4HK.js → report-issue-TAI6DYZO.js} +2 -2
- package/dist-cli/chunks/reset-7YGYKQPQ.js +4 -0
- package/dist-cli/chunks/runtime-B4JO6QRI.js +4 -0
- package/dist-cli/chunks/{screenshot-command-67AECJFB.js → screenshot-command-7ANLODZY.js} +7 -7
- package/dist-cli/chunks/{screenshot-layers-ASWBYPJL.js → screenshot-layers-A7FYXSVU.js} +3 -3
- package/dist-cli/chunks/{screenshots-capture-PXA3HFQK.js → screenshots-capture-WT2ZY6CB.js} +2 -2
- package/dist-cli/chunks/serve-TG5WKA4V.js +44 -0
- package/dist-cli/chunks/{setup-7DWPMRSB.js → setup-PCWLD22V.js} +2 -2
- package/dist-cli/chunks/{skills-S3Y22TUA.js → skills-27ZHWCQS.js} +2 -2
- package/dist-cli/chunks/state-ZQVY46ZO.js +14 -0
- package/dist-cli/chunks/{storage-XUIMJWAJ.js → storage-OYC57C4X.js} +6 -6
- package/dist-cli/chunks/store-32HSPZHI.js +4 -0
- package/dist-cli/chunks/telemetry-PBJR7XHR.js +4 -0
- package/dist-cli/chunks/{timeline-TMPLQPSP.js → timeline-RAJJFQT6.js} +2 -2
- package/dist-cli/chunks/{upgrade-7HDSIM7K.js → upgrade-OEFNZRIP.js} +2 -2
- package/dist-cli/chunks/upload-LQJITLKK.js +4 -0
- package/dist-cli/chunks/version-NIXTY6PL.js +6 -0
- package/dist-cli/chunks/{web-DG3WBYD3.js → web-XBUTBVGR.js} +2 -2
- package/dist-cli/chunks/{what-happened-XFVUTZR7.js → what-happened-YNHRFUDX.js} +3 -3
- 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.cjs +20 -0
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +67 -28
- package/dist-lib/host/bridge-host.cjs +140 -12
- 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/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +2815 -40
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +2549 -2061
- package/dist-lib/sdk.mjs +2543 -2061
- package/dist-lib/skills.cjs +480 -280
- package/dist-lib/vite.cjs +1 -1
- package/package.json +8 -2
- package/src/bridge-constants.ts +3 -4
- package/src/bridge-contract.ts +251 -0
- package/src/connect.ts +83 -0
- package/src/disk-cleanup.ts +30 -0
- package/src/home-paths.ts +81 -38
- package/src/host/bridge-host.ts +134 -6
- package/src/index.ts +27 -1
- package/src/sdk.ts +8 -0
- package/src/sim-client.ts +660 -0
- package/dist-cli/chunks/camera-VL73YIKP.js +0 -22
- package/dist-cli/chunks/chunk-4NPPOV2N.js +0 -5
- package/dist-cli/chunks/chunk-FSUYIVJ6.js +0 -9
- package/dist-cli/chunks/chunk-G2WW6L2C.js +0 -23
- package/dist-cli/chunks/chunk-KTHV3RUS.js +0 -26
- package/dist-cli/chunks/chunk-LF2ZVT7O.js +0 -6
- package/dist-cli/chunks/chunk-NFK7T35W.js +0 -4
- package/dist-cli/chunks/chunk-TIVZIMMW.js +0 -4
- package/dist-cli/chunks/cli-version-WWLPBDQ7.js +0 -4
- package/dist-cli/chunks/daemon-G2ME7NLB.js +0 -4
- package/dist-cli/chunks/drivers-LDECZGP2.js +0 -4
- package/dist-cli/chunks/flow-UEQNVTU7.js +0 -4
- package/dist-cli/chunks/help-T5FYSVGB.js +0 -4
- package/dist-cli/chunks/home-paths-GT3LFNOR.js +0 -4
- package/dist-cli/chunks/inspect-ZA6XF5LD.js +0 -4
- package/dist-cli/chunks/install-desktop-TIMUDHPL.js +0 -4
- package/dist-cli/chunks/runtime-XOAXMSTU.js +0 -4
- package/dist-cli/chunks/serve-BI2NBAXG.js +0 -44
- package/dist-cli/chunks/store-JTHEJLAZ.js +0 -4
- package/dist-cli/chunks/telemetry-ZYJGD2DB.js +0 -4
- package/dist-cli/chunks/upload-GMSZPWM6.js +0 -4
- package/dist-cli/chunks/version-HOCHZ37L.js +0 -6
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// rnxsim camera drives the host-owned camera source. fixture video uses the
|
|
2
|
+
// same hidden video, canvas frame pump, ImageBitmap transfer, and
|
|
3
|
+
// BarcodeDetector loop as a real device camera. `do scan` remains the narrow
|
|
4
|
+
// synthetic special case for callers that have a payload string but no media.
|
|
5
|
+
|
|
6
|
+
import { createHash, randomUUID } from 'node:crypto'
|
|
7
|
+
import { createReadStream } from 'node:fs'
|
|
8
|
+
import fs from 'node:fs/promises'
|
|
9
|
+
import path from 'node:path'
|
|
10
|
+
import { cameraFixturesDir } from '../../src/home-paths'
|
|
11
|
+
import { printBridgeFailureDiagnostics } from '../bridge-diagnostics'
|
|
12
|
+
import {
|
|
13
|
+
createBridgeFromParsed,
|
|
14
|
+
evalInBridge,
|
|
15
|
+
parseBridgeCliArgs,
|
|
16
|
+
type WsBridge,
|
|
17
|
+
} from '../ws-bridge'
|
|
18
|
+
import type { CameraCommand, CameraResult } from '../../src/bridge-contract'
|
|
19
|
+
|
|
20
|
+
const CAMERA_FIXTURE_ROUTE = '/__camera-fixtures/'
|
|
21
|
+
const VIDEO_EXTENSIONS = new Set(['.m4v', '.mov', '.mp4', '.webm'])
|
|
22
|
+
|
|
23
|
+
function printHelp() {
|
|
24
|
+
console.log(`
|
|
25
|
+
rnxsim camera — control the simulator camera source
|
|
26
|
+
|
|
27
|
+
usage:
|
|
28
|
+
rnxsim camera play <file> [--loop] [--rate <number>]
|
|
29
|
+
rnxsim camera stop
|
|
30
|
+
rnxsim camera status [--json]
|
|
31
|
+
rnxsim do scan <text> [--format <web-format>]
|
|
32
|
+
|
|
33
|
+
subcommands:
|
|
34
|
+
play <file> replace the active camera source with a local video fixture
|
|
35
|
+
stop clear fixture mode and restore the live camera source
|
|
36
|
+
status report live, fixture, or idle source state
|
|
37
|
+
scan <text> inject a synthetic barcode result into an active scan session
|
|
38
|
+
|
|
39
|
+
options:
|
|
40
|
+
--loop loop fixture playback
|
|
41
|
+
--rate <n> fixture playback rate (default: 1)
|
|
42
|
+
--format <f> synthetic BarcodeDetector format (default: qr_code)
|
|
43
|
+
--json print status/result as JSON
|
|
44
|
+
--sim <id> target a specific sim
|
|
45
|
+
--port <p> WS bridge port (default: 7668)
|
|
46
|
+
|
|
47
|
+
examples:
|
|
48
|
+
rnxsim camera play ./fixtures/qr.mp4 --loop
|
|
49
|
+
rnxsim camera play ./fixtures/document.webm --rate 2
|
|
50
|
+
rnxsim camera status
|
|
51
|
+
rnxsim camera stop
|
|
52
|
+
rnxsim do scan "https://example.com" --format qr_code
|
|
53
|
+
`)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function isCameraResult(value: unknown): value is CameraResult {
|
|
57
|
+
if (!value || typeof value !== 'object') return false
|
|
58
|
+
const ok = Reflect.get(value, 'ok')
|
|
59
|
+
const source = Reflect.get(value, 'source')
|
|
60
|
+
return (
|
|
61
|
+
typeof ok === 'boolean' &&
|
|
62
|
+
(source === 'live' || source === 'fixture' || source === 'idle')
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function sendCameraCommand(
|
|
67
|
+
bridge: WsBridge,
|
|
68
|
+
camera: CameraCommand,
|
|
69
|
+
): Promise<CameraResult> {
|
|
70
|
+
const result: unknown = await bridge.send({ type: 'camera', camera })
|
|
71
|
+
if (!isCameraResult(result)) {
|
|
72
|
+
throw new Error('camera bridge returned an invalid result')
|
|
73
|
+
}
|
|
74
|
+
return result
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function printCameraResult(result: CameraResult, json: boolean): void {
|
|
78
|
+
if (json) {
|
|
79
|
+
console.log(JSON.stringify(result))
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
if (result.source === 'fixture') {
|
|
83
|
+
console.log(
|
|
84
|
+
` camera source: fixture (${result.url ?? 'unknown url'}, ${
|
|
85
|
+
result.loop ? 'looping' : 'once'
|
|
86
|
+
}, ${result.rate ?? 1}x)`,
|
|
87
|
+
)
|
|
88
|
+
} else if (result.source === 'live') {
|
|
89
|
+
console.log(' camera source: live')
|
|
90
|
+
} else if (result.url) {
|
|
91
|
+
console.log(
|
|
92
|
+
` camera source: idle (fixture queued: ${result.url}, ${
|
|
93
|
+
result.loop ? 'looping' : 'once'
|
|
94
|
+
}, ${result.rate ?? 1}x)`,
|
|
95
|
+
)
|
|
96
|
+
} else {
|
|
97
|
+
console.log(' camera source: idle')
|
|
98
|
+
}
|
|
99
|
+
if (!result.ok && result.error) console.error(` camera failed: ${result.error}`)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export async function runCamera(
|
|
103
|
+
args: string[],
|
|
104
|
+
opts: { port?: number } = {},
|
|
105
|
+
): Promise<number> {
|
|
106
|
+
const parsed = parseBridgeCliArgs(args, {
|
|
107
|
+
port: opts.port,
|
|
108
|
+
stripBooleanFlags: ['--help', '-h', '--json', '--loop'],
|
|
109
|
+
stripValueFlags: ['--format', '--rate'],
|
|
110
|
+
})
|
|
111
|
+
const positional = parsed.positional
|
|
112
|
+
const subcommand = positional[0]
|
|
113
|
+
if (
|
|
114
|
+
!subcommand ||
|
|
115
|
+
subcommand === 'help' ||
|
|
116
|
+
args.includes('--help') ||
|
|
117
|
+
args.includes('-h')
|
|
118
|
+
) {
|
|
119
|
+
printHelp()
|
|
120
|
+
return subcommand ? 0 : 1
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const bridge = createBridgeFromParsed(parsed)
|
|
124
|
+
const json = args.includes('--json')
|
|
125
|
+
try {
|
|
126
|
+
if (subcommand === 'scan') {
|
|
127
|
+
const text = positional[1]
|
|
128
|
+
if (!text) {
|
|
129
|
+
console.error(' usage: rnxsim do scan <text>')
|
|
130
|
+
return 1
|
|
131
|
+
}
|
|
132
|
+
const formatFlag = args.indexOf('--format')
|
|
133
|
+
const format = formatFlag >= 0 ? args[formatFlag + 1] : 'qr_code'
|
|
134
|
+
if (!format) {
|
|
135
|
+
console.error(' --format requires a value')
|
|
136
|
+
return 1
|
|
137
|
+
}
|
|
138
|
+
const injected = await evalInBridge<boolean>(
|
|
139
|
+
bridge,
|
|
140
|
+
`globalThis.__sootsimCameraInjectScan?.(${JSON.stringify(text)}, ${JSON.stringify(format)}) ?? false`,
|
|
141
|
+
)
|
|
142
|
+
if (!injected) {
|
|
143
|
+
console.error(
|
|
144
|
+
' no active barcode scan session. open a scanning <CameraView> first',
|
|
145
|
+
)
|
|
146
|
+
return 1
|
|
147
|
+
}
|
|
148
|
+
console.log(` injected ${format} scan: ${text}`)
|
|
149
|
+
return 0
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (subcommand === 'status') {
|
|
153
|
+
const result = await sendCameraCommand(bridge, { action: 'status' })
|
|
154
|
+
printCameraResult(result, json)
|
|
155
|
+
return result.ok ? 0 : 1
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (subcommand === 'stop') {
|
|
159
|
+
const result = await sendCameraCommand(bridge, { action: 'stop' })
|
|
160
|
+
printCameraResult(result, json)
|
|
161
|
+
return result.ok ? 0 : 1
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (subcommand === 'play') {
|
|
165
|
+
const input = positional[1]
|
|
166
|
+
if (!input) {
|
|
167
|
+
console.error(' usage: rnxsim camera play <file> [--loop] [--rate <number>]')
|
|
168
|
+
return 1
|
|
169
|
+
}
|
|
170
|
+
const sourcePath = path.resolve(input)
|
|
171
|
+
const extension = path.extname(sourcePath).toLowerCase()
|
|
172
|
+
if (!VIDEO_EXTENSIONS.has(extension)) {
|
|
173
|
+
console.error(
|
|
174
|
+
` unsupported camera fixture extension ${extension || '(none)'}. use mp4, webm, mov, or m4v`,
|
|
175
|
+
)
|
|
176
|
+
return 1
|
|
177
|
+
}
|
|
178
|
+
let sourceStat
|
|
179
|
+
try {
|
|
180
|
+
sourceStat = await fs.stat(sourcePath)
|
|
181
|
+
} catch {
|
|
182
|
+
console.error(` camera fixture not found: ${sourcePath}`)
|
|
183
|
+
return 1
|
|
184
|
+
}
|
|
185
|
+
if (!sourceStat.isFile() || sourceStat.size === 0) {
|
|
186
|
+
console.error(` camera fixture must be a non-empty file: ${sourcePath}`)
|
|
187
|
+
return 1
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const rateFlag = args.indexOf('--rate')
|
|
191
|
+
const rawRate = rateFlag >= 0 ? args[rateFlag + 1] : undefined
|
|
192
|
+
const rate = rawRate === undefined ? 1 : Number(rawRate)
|
|
193
|
+
if (!Number.isFinite(rate) || rate <= 0) {
|
|
194
|
+
console.error(' --rate must be a positive finite number')
|
|
195
|
+
return 1
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const fixtureDirectory = cameraFixturesDir()
|
|
199
|
+
await fs.mkdir(fixtureDirectory, { recursive: true })
|
|
200
|
+
const digest = createHash('sha256')
|
|
201
|
+
await new Promise<void>((resolve, reject) => {
|
|
202
|
+
const input = createReadStream(sourcePath)
|
|
203
|
+
input.on('data', (chunk) => digest.update(chunk))
|
|
204
|
+
input.once('error', reject)
|
|
205
|
+
input.once('end', resolve)
|
|
206
|
+
})
|
|
207
|
+
const filename = `${digest.digest('hex')}${extension}`
|
|
208
|
+
const servedPath = path.join(fixtureDirectory, filename)
|
|
209
|
+
let staged = false
|
|
210
|
+
try {
|
|
211
|
+
const servedStat = await fs.lstat(servedPath)
|
|
212
|
+
if (!servedStat.isFile()) {
|
|
213
|
+
throw new Error(`camera fixture cache entry is not a file: ${servedPath}`)
|
|
214
|
+
}
|
|
215
|
+
staged = true
|
|
216
|
+
} catch (error) {
|
|
217
|
+
if (
|
|
218
|
+
!error ||
|
|
219
|
+
typeof error !== 'object' ||
|
|
220
|
+
Reflect.get(error, 'code') !== 'ENOENT'
|
|
221
|
+
) {
|
|
222
|
+
throw error
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (!staged) {
|
|
226
|
+
const temporaryPath = path.join(
|
|
227
|
+
fixtureDirectory,
|
|
228
|
+
`.${filename}.${process.pid}-${randomUUID()}.tmp`,
|
|
229
|
+
)
|
|
230
|
+
await fs.copyFile(sourcePath, temporaryPath)
|
|
231
|
+
try {
|
|
232
|
+
await fs.link(temporaryPath, servedPath)
|
|
233
|
+
} catch (error) {
|
|
234
|
+
if (
|
|
235
|
+
!error ||
|
|
236
|
+
typeof error !== 'object' ||
|
|
237
|
+
Reflect.get(error, 'code') !== 'EEXIST'
|
|
238
|
+
) {
|
|
239
|
+
throw error
|
|
240
|
+
}
|
|
241
|
+
} finally {
|
|
242
|
+
await fs.unlink(temporaryPath).catch(() => {})
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const url = `http://127.0.0.1:${parsed.wsPort}${CAMERA_FIXTURE_ROUTE}${filename}`
|
|
246
|
+
const result = await sendCameraCommand(bridge, {
|
|
247
|
+
action: 'play',
|
|
248
|
+
url,
|
|
249
|
+
loop: args.includes('--loop'),
|
|
250
|
+
rate,
|
|
251
|
+
})
|
|
252
|
+
printCameraResult(result, json)
|
|
253
|
+
return result.ok ? 0 : 1
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
console.error(` unknown camera subcommand: ${subcommand}`)
|
|
257
|
+
printHelp()
|
|
258
|
+
return 1
|
|
259
|
+
} catch (error) {
|
|
260
|
+
console.error(` camera failed: ${error instanceof Error ? error.message : error}`)
|
|
261
|
+
await printBridgeFailureDiagnostics(bridge)
|
|
262
|
+
return 1
|
|
263
|
+
} finally {
|
|
264
|
+
bridge.close()
|
|
265
|
+
}
|
|
266
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyAutomaticSootsimCleanup,
|
|
3
|
+
applySootsimCleanup,
|
|
4
|
+
formatSootsimBytes,
|
|
5
|
+
planSootsimCleanup,
|
|
6
|
+
type SootsimCleanupEntry,
|
|
7
|
+
type SootsimCleanupKind,
|
|
8
|
+
} from '../../src/disk-cleanup'
|
|
9
|
+
|
|
10
|
+
const KIND_LABELS: Record<SootsimCleanupKind, string> = {
|
|
11
|
+
'browser-cache': 'browser caches',
|
|
12
|
+
'camera-fixture': 'staged camera fixture videos',
|
|
13
|
+
recording: 'recordings and captured frames',
|
|
14
|
+
'runtime-archive': 'downloaded runtime archives',
|
|
15
|
+
'runtime-version': 'inactive runtime versions',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function summarize(entries: SootsimCleanupEntry[]): string[] {
|
|
19
|
+
const byKind = new Map<SootsimCleanupKind, { bytes: number; count: number }>()
|
|
20
|
+
for (const entry of entries) {
|
|
21
|
+
const current = byKind.get(entry.kind) ?? { bytes: 0, count: 0 }
|
|
22
|
+
current.bytes += entry.bytes
|
|
23
|
+
current.count++
|
|
24
|
+
byKind.set(entry.kind, current)
|
|
25
|
+
}
|
|
26
|
+
return [...byKind]
|
|
27
|
+
.sort((left, right) => right[1].bytes - left[1].bytes)
|
|
28
|
+
.map(
|
|
29
|
+
([kind, summary]) =>
|
|
30
|
+
` ${KIND_LABELS[kind]}: ${formatSootsimBytes(summary.bytes)} (${summary.count} ${
|
|
31
|
+
summary.count === 1 ? 'item' : 'items'
|
|
32
|
+
})`,
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function printHelp(): void {
|
|
37
|
+
console.log(`
|
|
38
|
+
rnxsim cleanup — inspect and reclaim local rnx disk usage
|
|
39
|
+
|
|
40
|
+
usage:
|
|
41
|
+
rnxsim cleanup
|
|
42
|
+
rnxsim cleanup --apply
|
|
43
|
+
rnxsim cleanup --aggressive
|
|
44
|
+
rnxsim cleanup --apply --aggressive
|
|
45
|
+
|
|
46
|
+
The default is a read-only preview. --apply removes downloaded runtime archives,
|
|
47
|
+
old runtimes outside a two-version rollback window, and disposable browser
|
|
48
|
+
caches. It never removes the active runtime, a runtime serving a connected
|
|
49
|
+
simulator, cookies, localStorage, IndexedDB, service workers, or other persistent
|
|
50
|
+
app storage.
|
|
51
|
+
|
|
52
|
+
--aggressive additionally removes the rollback runtime plus user-created
|
|
53
|
+
recordings and captured frames. It still preserves the active runtime and app storage.
|
|
54
|
+
`)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function runCleanup(args: string[]): Promise<number> {
|
|
58
|
+
if (args.length === 1 && args[0] === '--automatic-worker') {
|
|
59
|
+
try {
|
|
60
|
+
const result = applyAutomaticSootsimCleanup()
|
|
61
|
+
if (result.status === 'complete') {
|
|
62
|
+
process.stderr.write(
|
|
63
|
+
result.reclaimedBytes > 0
|
|
64
|
+
? ` rnx automatic cleanup reclaimed ${formatSootsimBytes(
|
|
65
|
+
result.reclaimedBytes,
|
|
66
|
+
)}; active runtimes and app data were kept.\n`
|
|
67
|
+
: ' rnx automatic cleanup found no obsolete local data.\n',
|
|
68
|
+
)
|
|
69
|
+
} else if (result.status === 'deferred') {
|
|
70
|
+
process.stderr.write(
|
|
71
|
+
` rnx automatic cleanup reclaimed ${formatSootsimBytes(
|
|
72
|
+
result.reclaimedBytes,
|
|
73
|
+
)}; ${formatSootsimBytes(
|
|
74
|
+
result.deferredInUseBytes,
|
|
75
|
+
)} is in use and will be retried on a later run.\n`,
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
return 0
|
|
79
|
+
} catch (error) {
|
|
80
|
+
process.stderr.write(
|
|
81
|
+
` rnx automatic cleanup will retry on the next run: ${
|
|
82
|
+
error instanceof Error ? error.message : String(error)
|
|
83
|
+
}\n`,
|
|
84
|
+
)
|
|
85
|
+
return 0
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
89
|
+
printHelp()
|
|
90
|
+
return 0
|
|
91
|
+
}
|
|
92
|
+
const known = new Set(['--aggressive', '--apply'])
|
|
93
|
+
const unknown = args.find((arg) => !known.has(arg))
|
|
94
|
+
if (unknown) {
|
|
95
|
+
console.error(` cleanup: unknown option ${unknown}`)
|
|
96
|
+
printHelp()
|
|
97
|
+
return 1
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const aggressive = args.includes('--aggressive')
|
|
101
|
+
const apply = args.includes('--apply')
|
|
102
|
+
const plan = planSootsimCleanup({ aggressive })
|
|
103
|
+
const selected = plan.entries.filter((entry) => entry.selected)
|
|
104
|
+
const safe = selected.filter((entry) => entry.state === 'safe')
|
|
105
|
+
const aggressiveOnly = plan.entries.filter(
|
|
106
|
+
(entry) => entry.state === 'aggressive' && entry.selected,
|
|
107
|
+
)
|
|
108
|
+
const inUse = plan.entries.filter((entry) => entry.state === 'in-use')
|
|
109
|
+
const inUseBrowserCaches = inUse.filter((entry) => entry.kind === 'browser-cache')
|
|
110
|
+
const inUseRuntimes = inUse.filter((entry) => entry.kind === 'runtime-version')
|
|
111
|
+
const rollback = plan.entries.find(
|
|
112
|
+
(entry) => entry.kind === 'runtime-version' && entry.state === 'aggressive',
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
console.log(` rnx data home: ${plan.home}`)
|
|
116
|
+
console.log(` current size: ${formatSootsimBytes(plan.totalBytes)}`)
|
|
117
|
+
console.log(` active runtime: ${plan.activeRuntime ?? '(none installed)'}`)
|
|
118
|
+
console.log('')
|
|
119
|
+
console.log(apply ? ' safe items selected for removal:' : ' safe to reclaim:')
|
|
120
|
+
for (const line of summarize(safe)) console.log(line)
|
|
121
|
+
if (safe.length === 0) console.log(' nothing')
|
|
122
|
+
|
|
123
|
+
if (aggressiveOnly.length > 0) {
|
|
124
|
+
console.log('')
|
|
125
|
+
console.log(' aggressive additions:')
|
|
126
|
+
for (const line of summarize(aggressiveOnly)) console.log(line)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log('')
|
|
130
|
+
console.log(' protected:')
|
|
131
|
+
if (plan.activeRuntime) console.log(` active runtime ${plan.activeRuntime} (in use)`)
|
|
132
|
+
for (const entry of inUseRuntimes) {
|
|
133
|
+
console.log(` running daemon runtime ${entry.path}`)
|
|
134
|
+
}
|
|
135
|
+
if (rollback && !aggressive) {
|
|
136
|
+
console.log(` rollback runtime ${rollback.path}`)
|
|
137
|
+
}
|
|
138
|
+
console.log(' cookies, localStorage, IndexedDB, service workers, and profile data')
|
|
139
|
+
if (!aggressive) {
|
|
140
|
+
console.log(' recordings and captured frames (use --aggressive to remove)')
|
|
141
|
+
}
|
|
142
|
+
if (inUseBrowserCaches.length > 0) {
|
|
143
|
+
console.log(
|
|
144
|
+
` ${formatSootsimBytes(
|
|
145
|
+
inUseBrowserCaches.reduce((total, entry) => total + entry.bytes, 0),
|
|
146
|
+
)} ` + `of browser cache is open; close rnx and rerun cleanup`,
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
console.log('')
|
|
151
|
+
console.log(` reclaimable now: ${formatSootsimBytes(plan.reclaimableBytes)}`)
|
|
152
|
+
if (!apply) {
|
|
153
|
+
console.log(
|
|
154
|
+
` preview only — run \`rnxsim cleanup --apply${
|
|
155
|
+
aggressive ? ' --aggressive' : ''
|
|
156
|
+
}\` to remove these items`,
|
|
157
|
+
)
|
|
158
|
+
return 0
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const result = applySootsimCleanup({ aggressive })
|
|
162
|
+
console.log(
|
|
163
|
+
` removed ${result.removedPaths.length} ${
|
|
164
|
+
result.removedPaths.length === 1 ? 'item' : 'items'
|
|
165
|
+
}; reclaimed ${formatSootsimBytes(result.reclaimedBytes)}`,
|
|
166
|
+
)
|
|
167
|
+
console.log(` remaining rnx data: ${formatSootsimBytes(result.remainingBytes)}`)
|
|
168
|
+
return 0
|
|
169
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// sootsim compat — scan dependencies with the shared compatibility engine.
|
|
2
|
+
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
4
|
+
import { resolve } from 'node:path'
|
|
5
|
+
import {
|
|
6
|
+
COMPAT_RESULT_CAVEAT,
|
|
7
|
+
formatDetailedScanLines,
|
|
8
|
+
formatScanCounts,
|
|
9
|
+
scanDeps,
|
|
10
|
+
type ScanResult,
|
|
11
|
+
} from '@sootsim/compat/web'
|
|
12
|
+
|
|
13
|
+
interface PackageManifest {
|
|
14
|
+
name?: string
|
|
15
|
+
dependencies?: Record<string, string>
|
|
16
|
+
devDependencies?: Record<string, string>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function runCompat(args: string[]): Promise<void> {
|
|
20
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
21
|
+
console.log(`
|
|
22
|
+
rnxsim compat — check package compatibility
|
|
23
|
+
|
|
24
|
+
usage:
|
|
25
|
+
rnxsim compat [package-name]
|
|
26
|
+
rnxsim compat --json
|
|
27
|
+
rnxsim compat --brief
|
|
28
|
+
|
|
29
|
+
flags:
|
|
30
|
+
--json machine-readable output
|
|
31
|
+
--brief one-line summary
|
|
32
|
+
--app <dir> target directory (default: cwd)
|
|
33
|
+
`)
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const appIndex = args.indexOf('--app')
|
|
38
|
+
const appDir =
|
|
39
|
+
appIndex >= 0 && args[appIndex + 1] ? resolve(args[appIndex + 1]) : process.cwd()
|
|
40
|
+
const packageName = args.find(
|
|
41
|
+
(arg, index) => !arg.startsWith('-') && (appIndex < 0 || index !== appIndex + 1),
|
|
42
|
+
)
|
|
43
|
+
const pkg = readPackageJson(appDir)
|
|
44
|
+
if (!pkg) {
|
|
45
|
+
console.error(` no package.json found in ${appDir}`)
|
|
46
|
+
process.exitCode = 1
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const result = packageName ? scanOnePackage(pkg, packageName) : scanDeps(pkg)
|
|
51
|
+
if (args.includes('--json')) {
|
|
52
|
+
console.log(JSON.stringify(result, null, 2))
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
if (args.includes('--brief')) {
|
|
56
|
+
console.log(` ${formatScanCounts(result)}`)
|
|
57
|
+
console.log(` ${COMPAT_RESULT_CAVEAT}`)
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log(`\n rnx compatibility report`)
|
|
62
|
+
console.log(` ${formatScanCounts(result)}\n`)
|
|
63
|
+
for (const line of formatDetailedScanLines(result)) console.log(` ${line}`)
|
|
64
|
+
const supported = result.packages.filter((item) => item.status === 'full').length
|
|
65
|
+
if (supported > 0) console.log(` supported: ${supported} packages`)
|
|
66
|
+
const notRelevant = result.packages.filter(
|
|
67
|
+
(item) => item.status === 'not-relevant',
|
|
68
|
+
).length
|
|
69
|
+
if (notRelevant > 0) console.log(` not relevant at runtime: ${notRelevant} packages`)
|
|
70
|
+
if (result.packages.length === 0) {
|
|
71
|
+
console.log(` no React Native ecosystem packages detected`)
|
|
72
|
+
}
|
|
73
|
+
console.log(`\n ${COMPAT_RESULT_CAVEAT}\n`)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function readPackageJson(appDir: string): PackageManifest | null {
|
|
77
|
+
const packagePath = resolve(appDir, 'package.json')
|
|
78
|
+
if (!existsSync(packagePath)) return null
|
|
79
|
+
const parsed: unknown = JSON.parse(readFileSync(packagePath, 'utf8'))
|
|
80
|
+
return parsed && typeof parsed === 'object' ? parsed : null
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function scanOnePackage(pkg: PackageManifest, packageName: string): ScanResult {
|
|
84
|
+
const version =
|
|
85
|
+
pkg.dependencies?.[packageName] ?? pkg.devDependencies?.[packageName] ?? '*'
|
|
86
|
+
return scanDeps({ dependencies: { [packageName]: version } })
|
|
87
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { runTelemetry } from './telemetry'
|
|
2
|
+
|
|
3
|
+
function printHelp(): void {
|
|
4
|
+
console.log(`
|
|
5
|
+
rnxsim config — manage local CLI preferences
|
|
6
|
+
|
|
7
|
+
usage:
|
|
8
|
+
rnxsim config telemetry [on|off|status]
|
|
9
|
+
|
|
10
|
+
environment:
|
|
11
|
+
SOOTSIM_HINTS=off suppress CLI hints
|
|
12
|
+
SOOTSIM_HINTS=always show every CLI hint every time
|
|
13
|
+
`)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function runConfig(args: string[]): Promise<void> {
|
|
17
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
18
|
+
printHelp()
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const sub = args.find((arg) => !arg.startsWith('-'))
|
|
23
|
+
if (sub === 'telemetry') {
|
|
24
|
+
const index = args.indexOf(sub)
|
|
25
|
+
await runTelemetry([...args.slice(0, index), ...args.slice(index + 1)])
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
console.error(` unknown config command: ${sub ?? '(missing)'}`)
|
|
30
|
+
printHelp()
|
|
31
|
+
process.exit(1)
|
|
32
|
+
}
|