rnxsim 0.1.313 → 0.1.315
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-CBU2WDKV.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-JJYYW2WH.js → agent-wrapper-UNB4R27L.js} +2 -2
- package/dist-cli/chunks/{app-fonts-IXRNQG6B.js → app-fonts-YMLRF3JD.js} +2 -2
- package/dist-cli/chunks/{assert-54T5SK5F.js → assert-5N6HUCL5.js} +2 -2
- package/dist-cli/chunks/{auth-FI5UDI45.js → auth-BHDR3A6G.js} +2 -2
- package/dist-cli/chunks/{beta-JV6UKADW.js → beta-LWUVCPYK.js} +2 -2
- package/dist-cli/chunks/camera-CNO6B2JZ.js +33 -0
- package/dist-cli/chunks/{chunk-ZMJD5GEC.js → chunk-25VCR44B.js} +1 -1
- package/dist-cli/chunks/{chunk-WUSWBCWA.js → chunk-26CSIR76.js} +8 -9
- package/dist-cli/chunks/{chunk-WINYQ44O.js → chunk-26WMWUH4.js} +1 -1
- package/dist-cli/chunks/{chunk-BTWORNNG.js → chunk-2JZ53D4A.js} +1 -1
- package/dist-cli/chunks/{chunk-DCEMHR2Y.js → chunk-2POODCTW.js} +2 -2
- package/dist-cli/chunks/{chunk-5TEF3ET3.js → chunk-4LTBK3ZN.js} +2 -2
- package/dist-cli/chunks/{chunk-NMF2ZMZQ.js → chunk-54MIRTFE.js} +4 -4
- package/dist-cli/chunks/{chunk-WEXDAC74.js → chunk-56H6EVO4.js} +2 -2
- package/dist-cli/chunks/{chunk-F5ZRSS3C.js → chunk-657SQG4D.js} +1 -1
- package/dist-cli/chunks/{chunk-IJ5CAZZC.js → chunk-6ZMRJPKI.js} +1 -1
- package/dist-cli/chunks/{chunk-W6K4EFPH.js → chunk-AOGGOC4V.js} +2 -2
- package/dist-cli/chunks/chunk-BPCDO7ST.js +15 -0
- package/dist-cli/chunks/{chunk-D4FFVGI5.js → chunk-C5O5CTXJ.js} +1 -1
- package/dist-cli/chunks/{chunk-RTN5C5RL.js → chunk-CMM64PPR.js} +1 -1
- package/dist-cli/chunks/{chunk-BBULZ7CG.js → chunk-D3M36D7O.js} +62 -87
- package/dist-cli/chunks/{chunk-5DHC6KHQ.js → chunk-DNCNFZ7V.js} +1 -1
- package/dist-cli/chunks/{chunk-YIFT42WN.js → chunk-FNTTIR2P.js} +2 -2
- package/dist-cli/chunks/chunk-H362IX2I.js +4 -0
- package/dist-cli/chunks/{chunk-IJO63TDP.js → chunk-J6HMTUZH.js} +2 -2
- package/dist-cli/chunks/{chunk-RSZWCKNT.js → chunk-JZ6VTZ5B.js} +3 -3
- package/dist-cli/chunks/{chunk-MJRLLB4R.js → chunk-KQSJVNFE.js} +4 -4
- package/dist-cli/chunks/chunk-L4JZKVCC.js +6 -0
- package/dist-cli/chunks/{chunk-VFCMSYZK.js → chunk-LP2BTEJ6.js} +2 -2
- package/dist-cli/chunks/{chunk-2YR5BGA5.js → chunk-LT6UC7I3.js} +2 -2
- package/dist-cli/chunks/{chunk-OVFJFXUD.js → chunk-MCKQH4AM.js} +2 -2
- package/dist-cli/chunks/{chunk-TZFFR3SD.js → chunk-MF7WUHQ3.js} +2 -2
- package/dist-cli/chunks/{chunk-46EUUFJ5.js → chunk-MSSY4EEZ.js} +1 -1
- package/dist-cli/chunks/{chunk-WMIIKMGK.js → chunk-N5ZCYP5F.js} +2 -2
- package/dist-cli/chunks/{chunk-3NV2NCNX.js → chunk-NCKAD3V7.js} +2 -2
- package/dist-cli/chunks/{chunk-VNQEB4L7.js → chunk-O2KRHVTU.js} +2 -2
- package/dist-cli/chunks/{chunk-OZSSI4WN.js → chunk-OF2HTH25.js} +2 -2
- package/dist-cli/chunks/{chunk-GGRX24GF.js → chunk-OXS2IWO2.js} +2 -2
- package/dist-cli/chunks/{chunk-WWZIXIRD.js → chunk-PVL7XSPN.js} +1 -1
- package/dist-cli/chunks/{chunk-DZS6WPUI.js → chunk-PVPAP3TV.js} +1 -1
- package/dist-cli/chunks/{chunk-5YJCOWCH.js → chunk-PXNAZYGV.js} +1 -1
- package/dist-cli/chunks/chunk-QR3HTFRB.js +5 -0
- package/dist-cli/chunks/{chunk-5TPRP5QT.js → chunk-QR7MWAWE.js} +1 -1
- package/dist-cli/chunks/chunk-RJIEZ2NY.js +4 -0
- package/dist-cli/chunks/{chunk-UC6U3MML.js → chunk-RVM4EZ4E.js} +2 -2
- package/dist-cli/chunks/{chunk-2D2UPBBR.js → chunk-SZKSFMWS.js} +1 -1
- package/dist-cli/chunks/{chunk-7GN3LVWB.js → chunk-TEL7G234.js} +2 -2
- package/dist-cli/chunks/{chunk-GASE6UBA.js → chunk-U2HNIHBY.js} +1 -1
- package/dist-cli/chunks/chunk-UROXJVY3.js +27 -0
- package/dist-cli/chunks/{chunk-HI5TFJWN.js → chunk-WM32MGTJ.js} +2 -2
- package/dist-cli/chunks/{chunk-VZXWHRUZ.js → chunk-WMZ7NJAO.js} +89 -133
- package/dist-cli/chunks/{chunk-XEVZYVIW.js → chunk-WUXCH6WN.js} +10 -9
- package/dist-cli/chunks/chunk-XOXGC3EH.js +9 -0
- package/dist-cli/chunks/chunk-XSSHENNY.js +4 -0
- package/dist-cli/chunks/{chunk-OHAZNXLK.js → chunk-XZ6O67AR.js} +1 -1
- package/dist-cli/chunks/{chunk-QKDWYITG.js → chunk-Y2MWQKOS.js} +3 -3
- package/dist-cli/chunks/{chunk-YDGQTMQL.js → chunk-YY24QI25.js} +1 -1
- package/dist-cli/chunks/{chunk-WF3T4SVI.js → chunk-ZWX6DDIS.js} +2 -2
- package/dist-cli/chunks/{cleanup-P27PA6JI.js → cleanup-F3NUJ3SL.js} +2 -2
- package/dist-cli/chunks/cli-version-XIW6O3FG.js +4 -0
- package/dist-cli/chunks/{compat-ZD65FED3.js → compat-AX2SEPTH.js} +2 -2
- package/dist-cli/chunks/{config-XMJRNM2A.js → config-4QQO5JVU.js} +2 -2
- package/dist-cli/chunks/{control-KMIQT3QP.js → control-OCKKSOWA.js} +2 -2
- package/dist-cli/chunks/daemon-N5VLMYKQ.js +4 -0
- package/dist-cli/chunks/{debug-PT4HOP7N.js → debug-T6MWVEVX.js} +5 -5
- package/dist-cli/chunks/{desktop-S3FG72AK.js → desktop-NCW7R7CB.js} +3 -3
- package/dist-cli/chunks/{detox-B3D4IFCN.js → detox-G6GITO2X.js} +2 -2
- package/dist-cli/chunks/{device-XBNDSB2R.js → device-7BTEJCTH.js} +2 -2
- package/dist-cli/chunks/{diagnose-HMQXJE5N.js → diagnose-SC5LACE3.js} +2 -2
- package/dist-cli/chunks/{disk-cleanup-BLCZ5BSZ.js → disk-cleanup-KK56QQZA.js} +2 -2
- package/dist-cli/chunks/drivers-NPGVBWMG.js +4 -0
- package/dist-cli/chunks/{film-BJGTBYZB.js → film-WGYEHGIA.js} +3 -3
- package/dist-cli/chunks/flow-KQBIBM3N.js +4 -0
- package/dist-cli/chunks/help-G7CAKI65.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-ANOYADHM.js → hidden-runtime-alias-CWTZWH3L.js} +2 -2
- package/dist-cli/chunks/home-paths-EBT4XHAS.js +4 -0
- package/dist-cli/chunks/inspect-CCPZXVDU.js +4 -0
- package/dist-cli/chunks/install-desktop-NZ3VGTQZ.js +4 -0
- package/dist-cli/chunks/{login-FJ737MWG.js → login-GSYOTGVQ.js} +4 -4
- package/dist-cli/chunks/{logout-ZCNMMHMY.js → logout-JPRIR7YK.js} +2 -2
- package/dist-cli/chunks/{maestro-SZTNKLDF.js → maestro-LXKDNO5M.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-DCFAIZ4H.js → maestro-generate-5ZIKOU53.js} +3 -3
- package/dist-cli/chunks/{mode-GRMQCRXR.js → mode-N3QHXCES.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-W36EWFFB.js → optional-demo-registry-XDH6X24N.js} +2 -2
- package/dist-cli/chunks/{perf-QYBAAUZG.js → perf-VOPL26FM.js} +2 -2
- package/dist-cli/chunks/{permissions-3QCQ6VF4.js → permissions-CZFKM4UD.js} +2 -2
- package/dist-cli/chunks/{record-QPPC2S4E.js → record-FODSOGMA.js} +3 -3
- package/dist-cli/chunks/{report-issue-7NMFP4HK.js → report-issue-FBPCZKOV.js} +2 -2
- package/dist-cli/chunks/reset-3H35GFO3.js +4 -0
- package/dist-cli/chunks/runtime-4OVFRXV5.js +4 -0
- package/dist-cli/chunks/{screenshot-command-67AECJFB.js → screenshot-command-7S3FYVO7.js} +7 -7
- package/dist-cli/chunks/{screenshot-layers-ASWBYPJL.js → screenshot-layers-CDYHPNC3.js} +3 -3
- package/dist-cli/chunks/{screenshots-capture-PXA3HFQK.js → screenshots-capture-EBIIY2YU.js} +2 -2
- package/dist-cli/chunks/serve-NELNSCZP.js +44 -0
- package/dist-cli/chunks/{setup-7DWPMRSB.js → setup-DF5ZDDIV.js} +2 -2
- package/dist-cli/chunks/{skills-S3Y22TUA.js → skills-E2QZF6WZ.js} +2 -2
- package/dist-cli/chunks/state-MBZDKZ7U.js +14 -0
- package/dist-cli/chunks/{storage-XUIMJWAJ.js → storage-J5BMNVXM.js} +6 -6
- package/dist-cli/chunks/store-U3DXC7HH.js +4 -0
- package/dist-cli/chunks/telemetry-XIPJVT5E.js +4 -0
- package/dist-cli/chunks/{timeline-TMPLQPSP.js → timeline-MC6N5BHY.js} +2 -2
- package/dist-cli/chunks/{upgrade-7HDSIM7K.js → upgrade-7UTU53DH.js} +2 -2
- package/dist-cli/chunks/upload-2M2KOTYI.js +4 -0
- package/dist-cli/chunks/version-VNACNYQK.js +6 -0
- package/dist-cli/chunks/{web-DG3WBYD3.js → web-MGJ2TUKR.js} +2 -2
- package/dist-cli/chunks/{what-happened-XFVUTZR7.js → what-happened-7DLKH3OD.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,361 @@
|
|
|
1
|
+
// sootsim screenshot slides — drive the live screenshot-mode composition from the
|
|
2
|
+
// terminal. same pipeline as the in-shell UI (rail/strip): every mutation
|
|
3
|
+
// goes through the shell's screenshotControl bridge so the browser UI
|
|
4
|
+
// reflects each step live, captures auto-upload, and exports are the
|
|
5
|
+
// composed App-Store canvases (bg + copy + posed device at export size).
|
|
6
|
+
|
|
7
|
+
import { mkdirSync, writeFileSync } from 'node:fs'
|
|
8
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path'
|
|
9
|
+
import {
|
|
10
|
+
callInBridge,
|
|
11
|
+
callInBridgeWrite,
|
|
12
|
+
createBridgeFromParsed,
|
|
13
|
+
evalInBridge,
|
|
14
|
+
parseBridgeCliArgs,
|
|
15
|
+
type WsBridge,
|
|
16
|
+
} from '../ws-bridge'
|
|
17
|
+
|
|
18
|
+
const HELP = `
|
|
19
|
+
rnxsim screenshot slides — compose App Store screenshots in the live sim
|
|
20
|
+
|
|
21
|
+
usage:
|
|
22
|
+
rnxsim screenshot slides list slides (alias: slides list)
|
|
23
|
+
rnxsim screenshot slides set <n> [fields] patch a slide's copy/colors
|
|
24
|
+
rnxsim screenshot slides add append a blank slide (focuses it)
|
|
25
|
+
rnxsim screenshot slides remove <n> delete a slide
|
|
26
|
+
rnxsim screenshot slides move <n> <position> reorder a slide
|
|
27
|
+
rnxsim screenshot slides focus <n> open a slide (device flips into it)
|
|
28
|
+
rnxsim screenshot slides overview back to the gallery
|
|
29
|
+
rnxsim screenshot slides capture [<n>] capture the live frame into a slide
|
|
30
|
+
rnxsim screenshot slides export [<n>] [--out <dir>]
|
|
31
|
+
write composed App-Store PNG(s)
|
|
32
|
+
|
|
33
|
+
set fields:
|
|
34
|
+
--title <text> headline
|
|
35
|
+
--subtitle <text> subheadline
|
|
36
|
+
--bg-top <color> gradient top (white gray slate black cyan blue
|
|
37
|
+
--bg-bottom <color> gradient bottom teal green lime gold orange coral
|
|
38
|
+
--title-color <color> copy color override, or "auto" red berry magenta
|
|
39
|
+
--title-size <s> sm | md | lg | none gray-light
|
|
40
|
+
--underlay <s> black | white | none gray-dark …)
|
|
41
|
+
--shadow <s> light | medium | strong | none
|
|
42
|
+
|
|
43
|
+
notes:
|
|
44
|
+
slides are addressed by 1-based index. screenshot mode is auto-enabled.
|
|
45
|
+
capture shoots whatever the sim currently shows — navigate the app first
|
|
46
|
+
(rnxsim do tap-id …), then capture.
|
|
47
|
+
|
|
48
|
+
examples:
|
|
49
|
+
rnxsim screenshot slides set 1 --title "The ultimate MMA community." --bg-top cyan --bg-bottom black
|
|
50
|
+
rnxsim screenshot slides capture 1
|
|
51
|
+
rnxsim screenshot slides export --out ./exports
|
|
52
|
+
`
|
|
53
|
+
|
|
54
|
+
interface SlideRow {
|
|
55
|
+
index: number
|
|
56
|
+
id: string
|
|
57
|
+
title: string
|
|
58
|
+
subtitle: string
|
|
59
|
+
bgTop: string
|
|
60
|
+
bgBottom: string
|
|
61
|
+
titleColor: string | null
|
|
62
|
+
titleSize: string | null
|
|
63
|
+
titleUnderlay: string | null
|
|
64
|
+
titleShadow: string | null
|
|
65
|
+
captured: boolean
|
|
66
|
+
captureMode: string | null
|
|
67
|
+
focused: boolean
|
|
68
|
+
active: boolean
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface ControlState {
|
|
72
|
+
projectName: string
|
|
73
|
+
canvas: string
|
|
74
|
+
exportSize: { width: number; height: number }
|
|
75
|
+
deviceModel: string
|
|
76
|
+
slides: SlideRow[]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// my value flags, extracted before bridge-arg parsing.
|
|
80
|
+
const VALUE_FLAGS: Record<string, string> = {
|
|
81
|
+
'--title': 'title',
|
|
82
|
+
'--subtitle': 'subtitle',
|
|
83
|
+
'--bg-top': 'bgTop',
|
|
84
|
+
'--bg-bottom': 'bgBottom',
|
|
85
|
+
'--title-color': 'titleColor',
|
|
86
|
+
'--title-size': 'titleSize',
|
|
87
|
+
'--underlay': 'titleUnderlay',
|
|
88
|
+
'--shadow': 'titleShadow',
|
|
89
|
+
'--out': 'out',
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function extractFlags(args: string[]): {
|
|
93
|
+
rest: string[]
|
|
94
|
+
values: Record<string, string>
|
|
95
|
+
json: boolean
|
|
96
|
+
} {
|
|
97
|
+
const rest: string[] = []
|
|
98
|
+
const values: Record<string, string> = {}
|
|
99
|
+
let json = false
|
|
100
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
101
|
+
const arg = args[i]
|
|
102
|
+
if (arg === '--json') {
|
|
103
|
+
json = true
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
const eq = arg.indexOf('=')
|
|
107
|
+
const flagName = eq > 0 ? arg.slice(0, eq) : arg
|
|
108
|
+
const key = VALUE_FLAGS[flagName]
|
|
109
|
+
if (key) {
|
|
110
|
+
if (eq > 0) {
|
|
111
|
+
values[key] = arg.slice(eq + 1)
|
|
112
|
+
} else {
|
|
113
|
+
values[key] = args[i + 1] ?? ''
|
|
114
|
+
i += 1
|
|
115
|
+
}
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
rest.push(arg)
|
|
119
|
+
}
|
|
120
|
+
return { rest, values, json }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function parseSlideRef(raw: string | undefined): number | string | undefined {
|
|
124
|
+
if (!raw) return undefined
|
|
125
|
+
const n = Number(raw)
|
|
126
|
+
return Number.isInteger(n) && n > 0 ? n : raw
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function ensureScreenshotMode(bridge: WsBridge): Promise<void> {
|
|
130
|
+
const on = await evalInBridge<boolean>(
|
|
131
|
+
bridge,
|
|
132
|
+
`(async () => {
|
|
133
|
+
if (window.SootSim?.bridges?.settings?.get?.()?.screenshotMode) return true
|
|
134
|
+
window.dispatchEvent(new CustomEvent('sootsim:shell-command', {
|
|
135
|
+
detail: { type: 'fire-action', id: 'toggle-screenshot-mode' },
|
|
136
|
+
}))
|
|
137
|
+
const deadline = Date.now() + 2000
|
|
138
|
+
while (Date.now() < deadline) {
|
|
139
|
+
if (window.SootSim?.bridges?.settings?.get?.()?.screenshotMode) return true
|
|
140
|
+
await new Promise((r) => setTimeout(r, 40))
|
|
141
|
+
}
|
|
142
|
+
return false
|
|
143
|
+
})()`,
|
|
144
|
+
{ acquireLock: true },
|
|
145
|
+
)
|
|
146
|
+
if (!on) {
|
|
147
|
+
throw new Error(
|
|
148
|
+
'could not enable screenshot mode — is this a browser sim with the screenshot plugin? (electron has no screenshot mode)',
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function printState(state: ControlState) {
|
|
154
|
+
console.log(
|
|
155
|
+
` ${state.projectName} — canvas ${state.canvas} (${state.exportSize.width}×${state.exportSize.height}), device ${state.deviceModel}`,
|
|
156
|
+
)
|
|
157
|
+
for (const s of state.slides) {
|
|
158
|
+
const marks = [
|
|
159
|
+
s.focused ? 'focused' : s.active ? 'active' : null,
|
|
160
|
+
s.captured ? `captured${s.captureMode === '3d' ? ' 3d' : ''}` : 'no capture',
|
|
161
|
+
]
|
|
162
|
+
.filter(Boolean)
|
|
163
|
+
.join(', ')
|
|
164
|
+
const copy = s.title ? `"${s.title}"` : '(no title)'
|
|
165
|
+
const style = [
|
|
166
|
+
`bg ${s.bgTop}→${s.bgBottom}`,
|
|
167
|
+
s.titleColor ? `color ${s.titleColor}` : null,
|
|
168
|
+
s.titleSize ? `size ${s.titleSize}` : null,
|
|
169
|
+
s.titleUnderlay ? `underlay ${s.titleUnderlay}` : null,
|
|
170
|
+
s.titleShadow ? `shadow ${s.titleShadow}` : null,
|
|
171
|
+
]
|
|
172
|
+
.filter(Boolean)
|
|
173
|
+
.join(', ')
|
|
174
|
+
console.log(` ${s.index}. ${copy} — ${style} [${marks}]`)
|
|
175
|
+
if (s.subtitle) console.log(` ${s.subtitle}`)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function dataUrlToBytes(dataUrl: string): Buffer {
|
|
180
|
+
const m = dataUrl.match(/^data:[^;]+;base64,(.+)$/)
|
|
181
|
+
if (!m) throw new Error('export returned an unexpected payload')
|
|
182
|
+
return Buffer.from(m[1], 'base64')
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export async function runSlides(
|
|
186
|
+
args: string[],
|
|
187
|
+
opts: { port?: number; verbose?: boolean },
|
|
188
|
+
): Promise<void> {
|
|
189
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
190
|
+
console.log(HELP)
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
const { rest, values, json } = extractFlags(args)
|
|
194
|
+
const parsed = parseBridgeCliArgs(rest, {
|
|
195
|
+
port: opts.port,
|
|
196
|
+
// capture waits on focus animation + frame bake; export composes at
|
|
197
|
+
// full App-Store resolution — both can exceed the default 15s.
|
|
198
|
+
commandTimeoutMs: 45_000,
|
|
199
|
+
})
|
|
200
|
+
const sub = parsed.positional[0] ?? 'list'
|
|
201
|
+
const refArg = parseSlideRef(parsed.positional[1])
|
|
202
|
+
const positionArg = Number(parsed.positional[2])
|
|
203
|
+
const bridge = createBridgeFromParsed(parsed)
|
|
204
|
+
const emit = (state: ControlState) => {
|
|
205
|
+
if (json) console.log(JSON.stringify(state, null, 2))
|
|
206
|
+
else printState(state)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
await ensureScreenshotMode(bridge)
|
|
211
|
+
switch (sub) {
|
|
212
|
+
case 'list': {
|
|
213
|
+
emit(
|
|
214
|
+
await callInBridge<ControlState>(
|
|
215
|
+
bridge,
|
|
216
|
+
'SootSim.bridges.screenshotControl.getState',
|
|
217
|
+
),
|
|
218
|
+
)
|
|
219
|
+
break
|
|
220
|
+
}
|
|
221
|
+
case 'set': {
|
|
222
|
+
if (refArg == null)
|
|
223
|
+
throw new Error(
|
|
224
|
+
'usage: rnxsim screenshot slides set <n> --title … (see --help)',
|
|
225
|
+
)
|
|
226
|
+
const patch: Record<string, string> = {}
|
|
227
|
+
for (const key of [
|
|
228
|
+
'title',
|
|
229
|
+
'subtitle',
|
|
230
|
+
'bgTop',
|
|
231
|
+
'bgBottom',
|
|
232
|
+
'titleColor',
|
|
233
|
+
'titleSize',
|
|
234
|
+
'titleUnderlay',
|
|
235
|
+
'titleShadow',
|
|
236
|
+
]) {
|
|
237
|
+
if (values[key] != null) patch[key] = values[key]
|
|
238
|
+
}
|
|
239
|
+
if (Object.keys(patch).length === 0) {
|
|
240
|
+
throw new Error('nothing to set — pass at least one field (see --help)')
|
|
241
|
+
}
|
|
242
|
+
emit(
|
|
243
|
+
await callInBridgeWrite<ControlState>(
|
|
244
|
+
bridge,
|
|
245
|
+
'SootSim.bridges.screenshotControl.setSlide',
|
|
246
|
+
refArg,
|
|
247
|
+
patch,
|
|
248
|
+
),
|
|
249
|
+
)
|
|
250
|
+
break
|
|
251
|
+
}
|
|
252
|
+
case 'add': {
|
|
253
|
+
emit(
|
|
254
|
+
await callInBridgeWrite<ControlState>(
|
|
255
|
+
bridge,
|
|
256
|
+
'SootSim.bridges.screenshotControl.addSlide',
|
|
257
|
+
),
|
|
258
|
+
)
|
|
259
|
+
break
|
|
260
|
+
}
|
|
261
|
+
case 'remove': {
|
|
262
|
+
if (refArg == null) throw new Error('usage: rnxsim screenshot slides remove <n>')
|
|
263
|
+
emit(
|
|
264
|
+
await callInBridgeWrite<ControlState>(
|
|
265
|
+
bridge,
|
|
266
|
+
'SootSim.bridges.screenshotControl.removeSlide',
|
|
267
|
+
refArg,
|
|
268
|
+
),
|
|
269
|
+
)
|
|
270
|
+
break
|
|
271
|
+
}
|
|
272
|
+
case 'move': {
|
|
273
|
+
if (refArg == null || !Number.isInteger(positionArg) || positionArg < 1) {
|
|
274
|
+
throw new Error('usage: rnxsim screenshot slides move <n> <position>')
|
|
275
|
+
}
|
|
276
|
+
emit(
|
|
277
|
+
await callInBridgeWrite<ControlState>(
|
|
278
|
+
bridge,
|
|
279
|
+
'SootSim.bridges.screenshotControl.moveSlide',
|
|
280
|
+
refArg,
|
|
281
|
+
positionArg,
|
|
282
|
+
),
|
|
283
|
+
)
|
|
284
|
+
break
|
|
285
|
+
}
|
|
286
|
+
case 'focus': {
|
|
287
|
+
if (refArg == null) throw new Error('usage: rnxsim screenshot slides focus <n>')
|
|
288
|
+
emit(
|
|
289
|
+
await callInBridgeWrite<ControlState>(
|
|
290
|
+
bridge,
|
|
291
|
+
'SootSim.bridges.screenshotControl.focusSlide',
|
|
292
|
+
refArg,
|
|
293
|
+
),
|
|
294
|
+
)
|
|
295
|
+
break
|
|
296
|
+
}
|
|
297
|
+
case 'overview': {
|
|
298
|
+
emit(
|
|
299
|
+
await callInBridgeWrite<ControlState>(
|
|
300
|
+
bridge,
|
|
301
|
+
'SootSim.bridges.screenshotControl.overview',
|
|
302
|
+
),
|
|
303
|
+
)
|
|
304
|
+
break
|
|
305
|
+
}
|
|
306
|
+
case 'capture': {
|
|
307
|
+
const state = await callInBridgeWrite<ControlState>(
|
|
308
|
+
bridge,
|
|
309
|
+
'SootSim.bridges.screenshotControl.capture',
|
|
310
|
+
...(refArg != null ? [refArg] : []),
|
|
311
|
+
)
|
|
312
|
+
emit(state)
|
|
313
|
+
break
|
|
314
|
+
}
|
|
315
|
+
case 'export': {
|
|
316
|
+
const outDir = values.out
|
|
317
|
+
? isAbsolute(values.out)
|
|
318
|
+
? values.out
|
|
319
|
+
: resolve(process.cwd(), values.out)
|
|
320
|
+
: join(process.cwd(), 'screenshots')
|
|
321
|
+
const state = await callInBridge<ControlState>(
|
|
322
|
+
bridge,
|
|
323
|
+
'SootSim.bridges.screenshotControl.getState',
|
|
324
|
+
)
|
|
325
|
+
const targets =
|
|
326
|
+
refArg != null
|
|
327
|
+
? state.slides.filter((s) => s.index === refArg || s.id === refArg)
|
|
328
|
+
: state.slides.filter((s) => s.captured)
|
|
329
|
+
if (targets.length === 0) {
|
|
330
|
+
throw new Error(
|
|
331
|
+
refArg != null
|
|
332
|
+
? `no slide ${refArg}`
|
|
333
|
+
: 'no captured slides to export — capture first',
|
|
334
|
+
)
|
|
335
|
+
}
|
|
336
|
+
const written: string[] = []
|
|
337
|
+
for (const slide of targets) {
|
|
338
|
+
const result = await callInBridge<{
|
|
339
|
+
name: string
|
|
340
|
+
width: number
|
|
341
|
+
height: number
|
|
342
|
+
dataUrl: string
|
|
343
|
+
}>(bridge, 'SootSim.bridges.screenshotControl.exportSlide', slide.index)
|
|
344
|
+
const path = join(outDir, result.name)
|
|
345
|
+
mkdirSync(dirname(path), { recursive: true })
|
|
346
|
+
writeFileSync(path, dataUrlToBytes(result.dataUrl))
|
|
347
|
+
written.push(path)
|
|
348
|
+
console.log(` saved: ${path} (${result.width}×${result.height})`)
|
|
349
|
+
}
|
|
350
|
+
if (json) console.log(JSON.stringify({ written }, null, 2))
|
|
351
|
+
break
|
|
352
|
+
}
|
|
353
|
+
default:
|
|
354
|
+
throw new Error(
|
|
355
|
+
`unknown subcommand "${sub}" — see rnxsim screenshot slides --help`,
|
|
356
|
+
)
|
|
357
|
+
}
|
|
358
|
+
} finally {
|
|
359
|
+
bridge.close()
|
|
360
|
+
}
|
|
361
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { printBridgeFailureDiagnostics } from '../bridge-diagnostics'
|
|
2
|
+
import { createBridgeFromParsed, parseBridgeCliArgs } from '../ws-bridge'
|
|
3
|
+
import type { SimStateResult } from '../../src/bridge-contract'
|
|
4
|
+
|
|
5
|
+
function isSimStateResult(value: unknown): value is SimStateResult {
|
|
6
|
+
return (
|
|
7
|
+
!!value &&
|
|
8
|
+
typeof value === 'object' &&
|
|
9
|
+
typeof Reflect.get(value, 'capturedAt') === 'number'
|
|
10
|
+
)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function printHelp(): void {
|
|
14
|
+
console.log(`
|
|
15
|
+
rnxsim state - capture the current app state in one call
|
|
16
|
+
|
|
17
|
+
usage:
|
|
18
|
+
rnxsim state [--json] [--sim <id>]
|
|
19
|
+
|
|
20
|
+
options:
|
|
21
|
+
--json print the complete structured result, including the screenshot
|
|
22
|
+
--sim <id> target a specific sim
|
|
23
|
+
--port <p> WS bridge port
|
|
24
|
+
`)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function runState(
|
|
28
|
+
args: string[],
|
|
29
|
+
opts: { port?: number } = {},
|
|
30
|
+
): Promise<number> {
|
|
31
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
32
|
+
printHelp()
|
|
33
|
+
return 0
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const parsed = parseBridgeCliArgs(args, {
|
|
37
|
+
port: opts.port,
|
|
38
|
+
stripBooleanFlags: ['--json'],
|
|
39
|
+
})
|
|
40
|
+
if (parsed.positional.length > 0) {
|
|
41
|
+
console.error(` unexpected state argument: ${parsed.positional[0]}`)
|
|
42
|
+
return 1
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const bridge = createBridgeFromParsed(parsed)
|
|
46
|
+
try {
|
|
47
|
+
const value: unknown = await bridge.send({ type: 'state' })
|
|
48
|
+
if (!isSimStateResult(value)) {
|
|
49
|
+
throw new Error('state bridge returned an invalid result')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (args.includes('--json')) {
|
|
53
|
+
console.log(JSON.stringify(value))
|
|
54
|
+
return 0
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const route = value.route
|
|
58
|
+
console.log(` route: ${route?.screen ?? route?.url ?? '(unknown)'}`)
|
|
59
|
+
if (route?.stack?.length) console.log(` stack: ${route.stack.join(' > ')}`)
|
|
60
|
+
console.log(` keyboard: ${value.keyboard?.visible ? 'visible' : 'hidden'}`)
|
|
61
|
+
console.log('')
|
|
62
|
+
console.log(typeof value.tree === 'string' ? value.tree : JSON.stringify(value.tree))
|
|
63
|
+
console.log('')
|
|
64
|
+
if (value.recentErrors?.length) {
|
|
65
|
+
console.log(` recent errors (${value.recentErrors.length}):`)
|
|
66
|
+
for (const error of value.recentErrors) {
|
|
67
|
+
console.log(` [${error.level}] ${error.text}`)
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
console.log(' recent errors: none')
|
|
71
|
+
}
|
|
72
|
+
const screenshotLength =
|
|
73
|
+
typeof value.screenshot === 'string' ? value.screenshot.length : 0
|
|
74
|
+
console.log(
|
|
75
|
+
screenshotLength > 0
|
|
76
|
+
? ` screenshot: captured (${screenshotLength} characters; use --json to read it)`
|
|
77
|
+
: ' screenshot: unavailable',
|
|
78
|
+
)
|
|
79
|
+
return 0
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error(` state failed: ${error instanceof Error ? error.message : error}`)
|
|
82
|
+
await printBridgeFailureDiagnostics(bridge)
|
|
83
|
+
return 1
|
|
84
|
+
} finally {
|
|
85
|
+
bridge.close()
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { runProfile } from './profile'
|
|
2
|
+
import { runReset } from './reset'
|
|
3
|
+
|
|
4
|
+
interface StorageOptions {
|
|
5
|
+
port?: number
|
|
6
|
+
verbose?: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const VALUE_FLAGS = new Set(['--sim', '--port', '-p'])
|
|
10
|
+
const SUBCOMMANDS = new Set(['profile', 'clear'])
|
|
11
|
+
|
|
12
|
+
function findSubcommand(args: string[]): { name: string; index: number } | null {
|
|
13
|
+
for (let i = 0; i < args.length; i++) {
|
|
14
|
+
const arg = args[i]
|
|
15
|
+
if (arg.startsWith('-')) {
|
|
16
|
+
if (VALUE_FLAGS.has(arg)) i++
|
|
17
|
+
continue
|
|
18
|
+
}
|
|
19
|
+
return SUBCOMMANDS.has(arg) ? { name: arg, index: i } : null
|
|
20
|
+
}
|
|
21
|
+
return null
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function printHelp(): void {
|
|
25
|
+
console.log(`
|
|
26
|
+
rnxsim storage — manage sim and app storage
|
|
27
|
+
|
|
28
|
+
usage:
|
|
29
|
+
rnxsim storage profile <subcommand>
|
|
30
|
+
rnxsim storage clear [--full] [--sim <id>] [--json]
|
|
31
|
+
|
|
32
|
+
subcommands:
|
|
33
|
+
profile ls
|
|
34
|
+
profile create <id>
|
|
35
|
+
profile clear <id>
|
|
36
|
+
profile delete <id>
|
|
37
|
+
clear clear the current guest app data and relaunch it
|
|
38
|
+
`)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function runStorage(args: string[], opts: StorageOptions): Promise<number> {
|
|
42
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
43
|
+
printHelp()
|
|
44
|
+
return 0
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const sub = findSubcommand(args)
|
|
48
|
+
if (sub?.name === 'profile') {
|
|
49
|
+
return runProfile([...args.slice(0, sub.index), ...args.slice(sub.index + 1)], opts)
|
|
50
|
+
}
|
|
51
|
+
if (sub?.name === 'clear') {
|
|
52
|
+
return runReset([...args.slice(0, sub.index), ...args.slice(sub.index + 1)], opts)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
console.error(` unknown storage command: ${sub?.name ?? '(missing)'}`)
|
|
56
|
+
printHelp()
|
|
57
|
+
return 1
|
|
58
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// `sootsim config telemetry on|off` — retained as the command spelling for the
|
|
2
|
+
// product analytics preference shown by guided setup and Settings.
|
|
3
|
+
//
|
|
4
|
+
// this is the process-wide preference; `DO_NOT_TRACK=1` still forces opt-out
|
|
5
|
+
// for a single run regardless of what's stored (honored by isOptedOut in
|
|
6
|
+
// telemetry.ts, the same cross-tool signal npm/turbo/supabase use).
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
configFilePath,
|
|
10
|
+
readPrivacyPreferences,
|
|
11
|
+
writePrivacyPreferences,
|
|
12
|
+
} from '../../src/home-paths'
|
|
13
|
+
|
|
14
|
+
function printStatus(): void {
|
|
15
|
+
const preferences = readPrivacyPreferences()
|
|
16
|
+
console.log(` product analytics are ${preferences.productAnalytics ? 'ON' : 'OFF'}`)
|
|
17
|
+
console.log(` config: ${configFilePath()}`)
|
|
18
|
+
const doNotTrack = process.env.DO_NOT_TRACK
|
|
19
|
+
if (doNotTrack === '1' || doNotTrack === 'true') {
|
|
20
|
+
console.log(
|
|
21
|
+
` note: DO_NOT_TRACK=${doNotTrack} is set — telemetry is off for this run`,
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function runTelemetry(args: string[]): Promise<void> {
|
|
27
|
+
const sub = args.find((a) => !a.startsWith('-'))?.toLowerCase()
|
|
28
|
+
|
|
29
|
+
switch (sub) {
|
|
30
|
+
case undefined:
|
|
31
|
+
case 'status':
|
|
32
|
+
printStatus()
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
case 'on':
|
|
36
|
+
case 'enable':
|
|
37
|
+
writePrivacyPreferences({ ...readPrivacyPreferences(), productAnalytics: true })
|
|
38
|
+
console.log(' product analytics ON')
|
|
39
|
+
console.log(` config: ${configFilePath()}`)
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
case 'off':
|
|
43
|
+
case 'disable':
|
|
44
|
+
writePrivacyPreferences({ ...readPrivacyPreferences(), productAnalytics: false })
|
|
45
|
+
console.log(' product analytics OFF')
|
|
46
|
+
console.log(` config: ${configFilePath()}`)
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
default:
|
|
50
|
+
console.error(` unknown telemetry action: ${sub}`)
|
|
51
|
+
console.error(' usage: rnxsim config telemetry [on|off|status]')
|
|
52
|
+
process.exit(1)
|
|
53
|
+
}
|
|
54
|
+
}
|