rnxsim 0.1.431 → 0.1.433
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -50
- package/cli/auth.ts +33 -3
- package/cli/cloud-client.ts +524 -88
- package/cli/cloud-dispatch.ts +5 -10
- package/cli/cloud-session.ts +5 -5
- package/cli/commands/auth.ts +13 -2
- package/cli/commands/box.ts +189 -20
- package/cli/commands/control.ts +40 -13
- package/cli/commands/device.ts +1 -1
- package/cli/commands/flow.ts +189 -43
- package/cli/commands/inspect/get-layout.ts +1 -1
- package/cli/commands/inspect.ts +8 -1
- package/cli/commands/login.ts +79 -14
- package/cli/commands/maestro-generate.ts +70 -54
- package/cli/commands/maestro.ts +69 -20
- package/cli/commands/platform.ts +30 -32
- package/cli/commands/screenshot.ts +3 -2
- package/cli/commands/upload.ts +28 -10
- package/cli/help-core.ts +11 -1
- package/cli/outbound-endpoints.ts +27 -5
- package/cli/parse-args.ts +17 -0
- package/cli/shell-init.ts +4 -4
- package/cli/ws-bridge.ts +109 -62
- 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 +17 -4
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud.cjs +108 -93
- package/dist-lib/cloud.mjs +106 -91
- 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 +1 -1
- package/dist-lib/host/bridge-host.cjs +1 -1
- 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 +58 -139
- 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-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 +33 -212
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +436 -351
- package/dist-lib/vite.cjs +1 -1
- package/package.json +2 -1
- package/src/auth/shared-session.ts +31 -0
- package/src/cloud.ts +83 -113
- package/src/metro-plugin.ts +30 -113
- package/src/vite-plugin.ts +11 -2
|
@@ -115,7 +115,7 @@ export const OUTBOUND_ENDPOINTS: Record<string, OutboundEndpointDeclaration> = {
|
|
|
115
115
|
'https://rnxsim.com by default, or the test or disposable origin named by RNX_CLOUD_ORIGIN',
|
|
116
116
|
preConsent: false,
|
|
117
117
|
payload:
|
|
118
|
-
'the Metro JavaScript bundle selected by rnx ios --
|
|
118
|
+
'the Metro JavaScript bundle selected by rnx ios --remote, then structured simulator commands and lifecycle requests',
|
|
119
119
|
},
|
|
120
120
|
}
|
|
121
121
|
|
|
@@ -152,8 +152,6 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
152
152
|
{ category: 'rnx_cloud_sim', count: 1 },
|
|
153
153
|
'packages/sootsim/src/cloud.ts :: fetch :: `${this.session.origin}/v1/sims/${encodeURIComponent(this.session.simId)}/claim`':
|
|
154
154
|
{ category: 'rnx_cloud_sim', count: 1 },
|
|
155
|
-
'packages/sootsim/src/cloud.ts :: fetch :: `${this.session.origin}/v1/boxes/${encodeURIComponent(this.session.boxId)}/simulators`':
|
|
156
|
-
{ category: 'rnx_cloud_sim', count: 1 },
|
|
157
155
|
'packages/sootsim/src/cloud.ts :: fetch :: `${this.session.origin}/v1/boxes/${encodeURIComponent(this.session.boxId)}`':
|
|
158
156
|
{ category: 'rnx_cloud_sim', count: 1 },
|
|
159
157
|
// maestro's flow `http` API. the url is whatever the flow author wrote, and
|
|
@@ -173,17 +171,36 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
173
171
|
category: 'rnx_cloud_box',
|
|
174
172
|
count: 1,
|
|
175
173
|
},
|
|
174
|
+
// a micro box's own Browser Run session, over the worker's BROWSER binding.
|
|
175
|
+
// the binding routes on path alone and ignores the host, so `browser.invalid`
|
|
176
|
+
// is a placeholder that exists only so URL can parse the search parameters.
|
|
177
|
+
// nothing leaves Cloudflare and no project content is sent.
|
|
178
|
+
'packages/rnx-cloud-box/src/browser-run.ts :: fetch :: sessionEndpoint(undefined, { keepAliveMs, includeTargets: true })':
|
|
179
|
+
{ category: 'rnx_cloud_box', count: 1 },
|
|
180
|
+
'packages/rnx-cloud-box/src/browser-run.ts :: fetch :: `https://browser.invalid/v1/devtools/browser/${sessionId}/json/list`':
|
|
181
|
+
{ category: 'rnx_cloud_box', count: 1 },
|
|
182
|
+
// twice: closing the session, and the CDP websocket upgrade that navigates a
|
|
183
|
+
// target. both address the same session over the same binding.
|
|
184
|
+
'packages/rnx-cloud-box/src/browser-run.ts :: fetch :: `https://browser.invalid/v1/devtools/browser/${sessionId}`':
|
|
185
|
+
{ category: 'rnx_cloud_box', count: 2 },
|
|
176
186
|
// the account's own session meter: starting, listing and heartbeating the
|
|
177
187
|
// session a cloud box is billed against. no project content.
|
|
178
|
-
"packages/rnx-cloud-box/src/client.ts :: fetch :: `${options.apiOrigin.replace(/\\/+$/, '')}/api/v1/rnx/sessions`":
|
|
188
|
+
"packages/rnx-cloud-box/src/client.ts :: fetch :: `${options.apiOrigin.replace(/\\/+$/, '')}/api/v1/rnx/sessions${ options.accountId ? `?accountId=${encodeURIComponent(options.accountId)}` : '' }`":
|
|
179
189
|
{ category: 'contrast_user_action', count: 1 },
|
|
180
190
|
'packages/rnx-cloud-box/src/client.ts :: fetch :: url': {
|
|
181
191
|
category: 'contrast_user_action',
|
|
182
192
|
count: 1,
|
|
183
193
|
},
|
|
194
|
+
// `rnx box connect` asks the account service which box that ID or name is
|
|
195
|
+
// and for the box's own token. the account is the only thing that knows, so
|
|
196
|
+
// this is the one call that turns a name into an authorized Box reference.
|
|
197
|
+
'packages/rnx-cloud-box/src/client.ts :: fetch :: connectUrl': {
|
|
198
|
+
category: 'contrast_user_action',
|
|
199
|
+
count: 1,
|
|
200
|
+
},
|
|
184
201
|
"packages/rnx-cloud-box/src/box-do.ts :: fetch :: `${origin}/api/v1/rnx/sessions${serviceAuthorized ? '/internal' : ''}`":
|
|
185
202
|
{ category: 'contrast_user_action', count: 1 },
|
|
186
|
-
"packages/rnx-cloud-box/src/box-do.ts :: fetch :: `${origin}/api/v1/rnx/sessions/${ serviceAuthority ? 'internal/' : '' }${encodeURIComponent(sessionId)}`":
|
|
203
|
+
"packages/rnx-cloud-box/src/box-do.ts :: fetch :: `${origin}/api/v1/rnx/sessions/${ serviceAuthority ? 'internal/' : '' }${encodeURIComponent(sessionId)}${ accountId ? `?accountId=${encodeURIComponent(accountId)}` : '' }`":
|
|
187
204
|
{ category: 'contrast_user_action', count: 1 },
|
|
188
205
|
'packages/rnx-cloud-box/src/box-do.ts :: fetch :: `${origin}/api/v1/rnx/sessions/internal/${encodeURIComponent(sessionId)}`':
|
|
189
206
|
{ category: 'contrast_user_action', count: 1 },
|
|
@@ -324,6 +341,11 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
324
341
|
category: 'same_origin_runtime',
|
|
325
342
|
count: 1,
|
|
326
343
|
},
|
|
344
|
+
// the cpu simulator iframe document's dedicated worker loads the headless
|
|
345
|
+
// canvaskit wasm and the font and asset manifests from the page's own
|
|
346
|
+
// `/deps-native/engine-assets/` directory.
|
|
347
|
+
'packages/sootsim-engine/src/headless/browser-tenant-worker.ts :: fetch :: new URL(name, assetBase).href':
|
|
348
|
+
{ category: 'same_origin_runtime', count: 1 },
|
|
327
349
|
// the tenant build's built-in app chunk prefetch list and the chunk bodies
|
|
328
350
|
// it names, resolved against the worker chunk's own url.
|
|
329
351
|
'packages/sootsim-engine/src/render-worker/app-in-worker.tsx :: fetch :: listUrl': {
|
package/cli/parse-args.ts
CHANGED
|
@@ -31,6 +31,23 @@ const GLOBAL_FLAGS: Record<
|
|
|
31
31
|
'--tab': { type: 'string' },
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// every spelling parseRnxArgs consumes before the command name, mapped to
|
|
35
|
+
// whether it takes a value. a command that rejects unknown flags uses this to
|
|
36
|
+
// tell a genuinely unknown flag apart from a global one typed after the
|
|
37
|
+
// command, where nothing reads it, and to show how to pass that one: telling
|
|
38
|
+
// someone to write `rnx --verbose <value>` earns them a second error.
|
|
39
|
+
export const GLOBAL_FLAG_TAKES_VALUE: ReadonlyMap<string, boolean> = new Map(
|
|
40
|
+
Object.entries(GLOBAL_FLAGS).flatMap(([name, def]): [string, boolean][] => {
|
|
41
|
+
const takesValue = def.type !== 'boolean'
|
|
42
|
+
return def.short
|
|
43
|
+
? [
|
|
44
|
+
[name, takesValue],
|
|
45
|
+
[def.short, takesValue],
|
|
46
|
+
]
|
|
47
|
+
: [[name, takesValue]]
|
|
48
|
+
}),
|
|
49
|
+
)
|
|
50
|
+
|
|
34
51
|
// top-level verbs that route into runInspect. the surface is intentionally
|
|
35
52
|
// tiny — everything else lives under one of the grouping verbs:
|
|
36
53
|
// - `rnx get <noun>` reads
|
package/cli/shell-init.ts
CHANGED
|
@@ -30,7 +30,7 @@ export function renderRnxShellInit(shell: string): string {
|
|
|
30
30
|
claim|close) ;;
|
|
31
31
|
ios)
|
|
32
32
|
for _rnx_shell_session in "$@"; do
|
|
33
|
-
if [ "$_rnx_shell_session" = '--
|
|
33
|
+
if [ "$_rnx_shell_session" = '--remote' ]; then
|
|
34
34
|
_rnx_shell_create=1
|
|
35
35
|
break
|
|
36
36
|
fi
|
|
@@ -48,15 +48,15 @@ export function renderRnxShellInit(shell: string): string {
|
|
|
48
48
|
|
|
49
49
|
if { [ -n "\${BASH_VERSION:-}" ] && [ "\${BASH_SUBSHELL:-0}" -ne 0 ]; } ||
|
|
50
50
|
{ [ -n "\${ZSH_VERSION:-}" ] && [ "\${ZSH_SUBSHELL:-0}" -ne 0 ]; }; then
|
|
51
|
-
printf '%s\\n' 'rnx
|
|
51
|
+
printf '%s\\n' 'rnx remote simulator lifecycle commands must run directly in the current shell, not in a pipeline or command substitution' >&2
|
|
52
52
|
return 1
|
|
53
53
|
fi
|
|
54
54
|
if ( : >&9 ) 2>/dev/null; then
|
|
55
|
-
printf '%s\\n' 'rnx
|
|
55
|
+
printf '%s\\n' 'rnx remote simulator shell integration requires file descriptor 9 to be unused' >&2
|
|
56
56
|
return 1
|
|
57
57
|
fi
|
|
58
58
|
if ! ( export ${RNX_CLOUD_SESSION_ENV}=__rnx_shell_probe && unset ${RNX_CLOUD_SESSION_ENV} ) 2>/dev/null; then
|
|
59
|
-
printf '%s\\n' 'rnx
|
|
59
|
+
printf '%s\\n' 'rnx remote simulator shell integration cannot update RNX_CLOUD_SESSION in this shell' >&2
|
|
60
60
|
return 1
|
|
61
61
|
fi
|
|
62
62
|
|
package/cli/ws-bridge.ts
CHANGED
|
@@ -248,6 +248,35 @@ export function bridgePortForShellBaseUrl(baseUrl: string): number | null {
|
|
|
248
248
|
return null
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
+
/** the bridge a `--base-url` pin implies. one rule for every command that takes
|
|
252
|
+
* the flag, because they used to disagree: flow refused an unserved pin while
|
|
253
|
+
* open kept the discovered default and then started a bridge of its own, so
|
|
254
|
+
* the page rendered in the pinned shell and the polling waited on another
|
|
255
|
+
* world's bridge. that reads as "saved sim <id> is gone" and gets retried
|
|
256
|
+
* rather than fixed. an explicit --port states the world outright and wins;
|
|
257
|
+
* otherwise the pin has to name a world something serves. */
|
|
258
|
+
export function resolveBridgePortForPin(pin: {
|
|
259
|
+
baseUrl: string
|
|
260
|
+
wsPort: number
|
|
261
|
+
explicitPort: boolean
|
|
262
|
+
}): { port: number; error?: undefined } | { port?: undefined; error: string } {
|
|
263
|
+
const served = bridgePortForShellBaseUrl(pin.baseUrl)
|
|
264
|
+
if (served === null) {
|
|
265
|
+
if (pin.explicitPort) return { port: pin.wsPort }
|
|
266
|
+
return {
|
|
267
|
+
error:
|
|
268
|
+
`no live rnx world serves ${pin.baseUrl} — start that shell first, ` +
|
|
269
|
+
'or name its bridge with --port <port>',
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (pin.explicitPort && pin.wsPort !== served) {
|
|
273
|
+
return {
|
|
274
|
+
error: `--base-url ${pin.baseUrl} belongs to bridge port ${served}, but --port ${pin.wsPort} names another world`,
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return { port: served }
|
|
278
|
+
}
|
|
279
|
+
|
|
251
280
|
/** default ws bridge port for CLI commands: the fresh dev bridge when a vite
|
|
252
281
|
* shell is live, else the fresh daemon, else the hardcoded default. one
|
|
253
282
|
* deterministic answer regardless of how the CLI was invoked (global binary
|
|
@@ -390,76 +419,94 @@ export interface ParsedBridgeCliArgs {
|
|
|
390
419
|
commandTimeoutMs: number
|
|
391
420
|
}
|
|
392
421
|
|
|
422
|
+
interface BridgeFlagState {
|
|
423
|
+
wsPort: number
|
|
424
|
+
explicitPort: boolean
|
|
425
|
+
commandTimeoutMs: number
|
|
426
|
+
simId: string | undefined
|
|
427
|
+
simIdSource: ParsedBridgeCliArgs['simIdSource']
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// every flag parseBridgeCliArgs consumes a value for on its own, without being
|
|
431
|
+
// listed in a caller's stripValueFlags. the parser iterates this table, so the
|
|
432
|
+
// exported name list below cannot drift from what is actually parsed. a name
|
|
433
|
+
// missing from that list is not a parse failure, it is a command that hunts a
|
|
434
|
+
// positional in raw argv and takes the flag's value instead: `maestro test
|
|
435
|
+
// --newflag value login.yaml` would run `value` as the flow.
|
|
436
|
+
const BRIDGE_VALUE_FLAGS_TABLE: readonly {
|
|
437
|
+
names: readonly string[]
|
|
438
|
+
apply: (state: BridgeFlagState, value: string | undefined) => void
|
|
439
|
+
}[] = [
|
|
440
|
+
{
|
|
441
|
+
names: ['--port', '-p'],
|
|
442
|
+
// naming the flag pins the world even when the value is missing or junk,
|
|
443
|
+
// so a later --base-url cannot quietly retarget the run to another shell.
|
|
444
|
+
apply: (state, value) => {
|
|
445
|
+
state.explicitPort = true
|
|
446
|
+
if (value !== undefined) state.wsPort = Number(value)
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
names: ['--timeout'],
|
|
451
|
+
apply: (state, value) => {
|
|
452
|
+
if (value !== undefined) state.commandTimeoutMs = Number(value)
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
// `--sim` is the canonical target flag; `--session` / `--tab` are
|
|
457
|
+
// documented aliases (CLAUDE.md, the rnx agent skills, and engine docs all
|
|
458
|
+
// say `--session <id>`). without these aliases an agent following the docs
|
|
459
|
+
// would have `--session ef` silently ignored and get the *currently
|
|
460
|
+
// pinned* sim's tree instead — wrong-app data with no error.
|
|
461
|
+
names: ['--sim', '--session', '--tab'],
|
|
462
|
+
apply: (state, value) => {
|
|
463
|
+
if (value === undefined) return
|
|
464
|
+
state.simId = value.trim() || undefined
|
|
465
|
+
state.simIdSource = 'flag'
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
]
|
|
469
|
+
|
|
470
|
+
export const BRIDGE_VALUE_FLAGS: readonly string[] = BRIDGE_VALUE_FLAGS_TABLE.flatMap(
|
|
471
|
+
(flag) => [...flag.names],
|
|
472
|
+
)
|
|
473
|
+
|
|
393
474
|
export function parseBridgeCliArgs(
|
|
394
475
|
args: string[],
|
|
395
476
|
opts: ParseBridgeCliArgsOptions = {},
|
|
396
477
|
): ParsedBridgeCliArgs {
|
|
397
478
|
const flagIndices = new Set<number>()
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
479
|
+
const state: BridgeFlagState = {
|
|
480
|
+
wsPort: opts.port ?? resolveDefaultBridgePort(),
|
|
481
|
+
explicitPort: opts.port !== undefined,
|
|
482
|
+
commandTimeoutMs: opts.commandTimeoutMs ?? 15000,
|
|
483
|
+
simId: undefined,
|
|
484
|
+
simIdSource: 'none',
|
|
485
|
+
}
|
|
403
486
|
|
|
404
487
|
const stripBooleanFlags = new Set(opts.stripBooleanFlags ?? [])
|
|
405
488
|
const stripValueFlags = new Set(opts.stripValueFlags ?? [])
|
|
406
489
|
|
|
407
490
|
for (let i = 0; i < args.length; i++) {
|
|
408
491
|
const arg = args[i]
|
|
409
|
-
|
|
492
|
+
// both spellings for every flag in the table: `--flag value` and
|
|
493
|
+
// `--flag=value`.
|
|
494
|
+
const valueFlag = BRIDGE_VALUE_FLAGS_TABLE.find((flag) =>
|
|
495
|
+
flag.names.some((name) => arg === name || arg.startsWith(`${name}=`)),
|
|
496
|
+
)
|
|
497
|
+
if (valueFlag) {
|
|
410
498
|
flagIndices.add(i)
|
|
411
|
-
|
|
412
|
-
if (
|
|
413
|
-
|
|
414
|
-
|
|
499
|
+
const inline = valueFlag.names.find((name) => arg.startsWith(`${name}=`))
|
|
500
|
+
if (inline) {
|
|
501
|
+
valueFlag.apply(state, arg.slice(inline.length + 1))
|
|
502
|
+
continue
|
|
415
503
|
}
|
|
504
|
+
const value = i + 1 < args.length ? args[i + 1] : undefined
|
|
505
|
+
if (value !== undefined) flagIndices.add(i + 1)
|
|
506
|
+
valueFlag.apply(state, value)
|
|
416
507
|
i++
|
|
417
508
|
continue
|
|
418
509
|
}
|
|
419
|
-
if (arg.startsWith('--port=')) {
|
|
420
|
-
flagIndices.add(i)
|
|
421
|
-
explicitPort = true
|
|
422
|
-
wsPort = Number(arg.slice('--port='.length))
|
|
423
|
-
continue
|
|
424
|
-
}
|
|
425
|
-
if (arg === '--timeout') {
|
|
426
|
-
flagIndices.add(i)
|
|
427
|
-
if (i + 1 < args.length) {
|
|
428
|
-
flagIndices.add(i + 1)
|
|
429
|
-
commandTimeoutMs = Number(args[i + 1])
|
|
430
|
-
}
|
|
431
|
-
i++
|
|
432
|
-
continue
|
|
433
|
-
}
|
|
434
|
-
// `--sim` is the canonical target flag; `--session` / `--tab` are
|
|
435
|
-
// documented aliases (CLAUDE.md, the rnx agent skills, and engine docs all
|
|
436
|
-
// say `--session <id>`). without these aliases an agent following the docs
|
|
437
|
-
// would have `--session ef` silently ignored and get the *currently
|
|
438
|
-
// pinned* sim's tree instead — wrong-app data with no error. accept the
|
|
439
|
-
// `--flag value` and `--flag=value` forms for all three spellings.
|
|
440
|
-
if (arg === '--sim' || arg === '--session' || arg === '--tab') {
|
|
441
|
-
flagIndices.add(i)
|
|
442
|
-
if (i + 1 < args.length) {
|
|
443
|
-
flagIndices.add(i + 1)
|
|
444
|
-
simId = args[i + 1]?.trim() || undefined
|
|
445
|
-
simIdSource = 'flag'
|
|
446
|
-
}
|
|
447
|
-
i++
|
|
448
|
-
continue
|
|
449
|
-
}
|
|
450
|
-
const simEq = arg.startsWith('--sim=')
|
|
451
|
-
? arg.slice('--sim='.length)
|
|
452
|
-
: arg.startsWith('--session=')
|
|
453
|
-
? arg.slice('--session='.length)
|
|
454
|
-
: arg.startsWith('--tab=')
|
|
455
|
-
? arg.slice('--tab='.length)
|
|
456
|
-
: undefined
|
|
457
|
-
if (simEq !== undefined) {
|
|
458
|
-
flagIndices.add(i)
|
|
459
|
-
simId = simEq.trim() || undefined
|
|
460
|
-
simIdSource = 'flag'
|
|
461
|
-
continue
|
|
462
|
-
}
|
|
463
510
|
if (stripBooleanFlags.has(arg)) {
|
|
464
511
|
flagIndices.add(i)
|
|
465
512
|
continue
|
|
@@ -473,21 +520,21 @@ export function parseBridgeCliArgs(
|
|
|
473
520
|
}
|
|
474
521
|
}
|
|
475
522
|
|
|
476
|
-
if (!simId) {
|
|
523
|
+
if (!state.simId) {
|
|
477
524
|
const savedSim = readCurrentSim()
|
|
478
525
|
if (savedSim) {
|
|
479
|
-
simId = savedSim.simId.trim() || undefined
|
|
480
|
-
simIdSource = 'saved'
|
|
526
|
+
state.simId = savedSim.simId.trim() || undefined
|
|
527
|
+
state.simIdSource = 'saved'
|
|
481
528
|
}
|
|
482
529
|
}
|
|
483
530
|
|
|
484
531
|
return {
|
|
485
532
|
positional: args.filter((_, i) => !flagIndices.has(i)),
|
|
486
|
-
wsPort,
|
|
487
|
-
explicitPort,
|
|
488
|
-
simId,
|
|
489
|
-
simIdSource,
|
|
490
|
-
commandTimeoutMs,
|
|
533
|
+
wsPort: state.wsPort,
|
|
534
|
+
explicitPort: state.explicitPort,
|
|
535
|
+
simId: state.simId,
|
|
536
|
+
simIdSource: state.simIdSource,
|
|
537
|
+
commandTimeoutMs: state.commandTimeoutMs,
|
|
491
538
|
}
|
|
492
539
|
}
|
|
493
540
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -36,6 +36,7 @@ __export(shared_session_exports, {
|
|
|
36
36
|
getSharedDesktopAuthFilePath: () => getSharedDesktopAuthFilePath,
|
|
37
37
|
readSharedDesktopAuthSession: () => readSharedDesktopAuthSession,
|
|
38
38
|
refreshSharedDesktopAuthSession: () => refreshSharedDesktopAuthSession,
|
|
39
|
+
sharedDesktopAuthAccounts: () => sharedDesktopAuthAccounts,
|
|
39
40
|
writeSharedDesktopAuthSession: () => writeSharedDesktopAuthSession
|
|
40
41
|
});
|
|
41
42
|
module.exports = __toCommonJS(shared_session_exports);
|
|
@@ -60,6 +61,12 @@ function electronUserDataDir() {
|
|
|
60
61
|
var DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
|
|
61
62
|
|
|
62
63
|
// src/auth/shared-session.ts
|
|
64
|
+
function sharedDesktopAuthAccounts(user) {
|
|
65
|
+
return [
|
|
66
|
+
...user?.personalAccountId ? [{ id: user.personalAccountId, name: "Personal" }] : [],
|
|
67
|
+
...(user?.teams ?? []).map((team) => ({ id: team.id, name: team.name }))
|
|
68
|
+
];
|
|
69
|
+
}
|
|
63
70
|
var SESSION_VERSION = 1;
|
|
64
71
|
var SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
|
|
65
72
|
var DEFAULT_ORIGIN = "https://contrast.dev";
|
|
@@ -85,6 +92,7 @@ function normalizeUser(input) {
|
|
|
85
92
|
email: typeof value.email === "string" ? value.email : void 0,
|
|
86
93
|
image: typeof value.image === "string" ? value.image : void 0,
|
|
87
94
|
githubUsername: typeof value.githubUsername === "string" ? value.githubUsername : void 0,
|
|
95
|
+
personalAccountId: typeof value.personalAccountId === "string" && value.personalAccountId.trim() ? value.personalAccountId.trim() : void 0,
|
|
88
96
|
isAdmin: value.isAdmin === true,
|
|
89
97
|
teams: Array.isArray(value.teams) ? value.teams.map((team) => {
|
|
90
98
|
if (!team || typeof team !== "object") return null;
|
|
@@ -108,6 +116,7 @@ function normalizeSession(input) {
|
|
|
108
116
|
const source = value.source === "cli" || value.source === "electron" || value.source === "browser" || value.source === "unknown" ? value.source : "unknown";
|
|
109
117
|
const updatedAt = typeof value.updatedAt === "string" && value.updatedAt ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
110
118
|
const validatedAt = typeof value.validatedAt === "string" && value.validatedAt ? value.validatedAt : void 0;
|
|
119
|
+
const accountId = typeof value.accountId === "string" && value.accountId.trim() ? value.accountId.trim() : void 0;
|
|
111
120
|
return {
|
|
112
121
|
version: SESSION_VERSION,
|
|
113
122
|
token: value.token.trim(),
|
|
@@ -115,7 +124,8 @@ function normalizeSession(input) {
|
|
|
115
124
|
origin,
|
|
116
125
|
source,
|
|
117
126
|
updatedAt,
|
|
118
|
-
validatedAt
|
|
127
|
+
validatedAt,
|
|
128
|
+
accountId
|
|
119
129
|
};
|
|
120
130
|
}
|
|
121
131
|
function readSharedDesktopAuthSession() {
|
|
@@ -144,7 +154,8 @@ function writeSharedDesktopAuthSession(session) {
|
|
|
144
154
|
origin: session.origin?.trim() || DEFAULT_ORIGIN,
|
|
145
155
|
source: session.source,
|
|
146
156
|
updatedAt: session.updatedAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
147
|
-
validatedAt: session.validatedAt
|
|
157
|
+
validatedAt: session.validatedAt,
|
|
158
|
+
accountId: session.accountId?.trim() || void 0
|
|
148
159
|
};
|
|
149
160
|
(0, import_node_fs.writeFileSync)(filepath, JSON.stringify(normalized, null, 2) + "\n");
|
|
150
161
|
try {
|
|
@@ -179,7 +190,8 @@ async function refreshSharedDesktopAuthSession(originOverride) {
|
|
|
179
190
|
user: data.user,
|
|
180
191
|
origin,
|
|
181
192
|
source: current.source,
|
|
182
|
-
validatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
193
|
+
validatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
194
|
+
accountId: current.accountId
|
|
183
195
|
});
|
|
184
196
|
} catch {
|
|
185
197
|
return current;
|
|
@@ -191,5 +203,6 @@ async function refreshSharedDesktopAuthSession(originOverride) {
|
|
|
191
203
|
getSharedDesktopAuthFilePath,
|
|
192
204
|
readSharedDesktopAuthSession,
|
|
193
205
|
refreshSharedDesktopAuthSession,
|
|
206
|
+
sharedDesktopAuthAccounts,
|
|
194
207
|
writeSharedDesktopAuthSession
|
|
195
208
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/beta.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/beta.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|