@solidrt/cli 0.0.50 → 0.0.52
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/AGENTS.md +79 -36
- package/README.md +86 -15
- package/agents/assets.md +46 -0
- package/agents/debugging.md +294 -0
- package/dist/console.srtapp +94123 -73
- package/dist/server.js +3936 -0
- package/package.json +11 -10
- package/src/android/docs.md +21 -0
- package/src/android/main.ts +286 -0
- package/src/{bundler.ts → bundle/bundler.ts} +163 -76
- package/src/bundle/docs.md +12 -0
- package/src/bundle/main.ts +203 -0
- package/src/check/docs.md +10 -0
- package/src/check/main.ts +85 -0
- package/src/{commands/check.ts → check/typecheck.ts} +11 -34
- package/src/client/docs.md +9 -0
- package/src/client/main.ts +33 -0
- package/src/console/docs.md +14 -0
- package/src/console/main.ts +21 -0
- package/src/demo/docs.md +27 -0
- package/src/demo/main.ts +67 -0
- package/src/init/docs.md +11 -0
- package/src/{commands/init.ts → init/main.ts} +31 -25
- package/src/init/scaffold/AGENTS.md +98 -0
- package/src/init/scaffold/package.json +23 -0
- package/{scaffold → src/init/scaffold}/templates/components/index.tsx +2 -3
- package/{scaffold → src/init/scaffold}/templates/default/index.tsx +2 -3
- package/src/lib/args.ts +194 -0
- package/src/{artifacts.ts → lib/artifacts.ts} +41 -1
- package/src/{dev-dir.ts → lib/dev-dir.ts} +10 -8
- package/src/{fonts.ts → lib/fonts.ts} +12 -26
- package/src/lib/mode.ts +77 -0
- package/src/{project.ts → lib/project.ts} +109 -61
- package/src/lib/registry.ts +120 -0
- package/src/lib/server-bundle.ts +24 -0
- package/src/lib/usage.ts +117 -0
- package/src/lib/util.ts +36 -0
- package/src/main.ts +109 -31
- package/src/mcp/docs.md +22 -0
- package/src/mcp/main.ts +719 -0
- package/src/pack/docs.md +18 -0
- package/src/{pack-folder.ts → pack/layout.ts} +13 -22
- package/src/pack/main.ts +86 -0
- package/src/pack/trailer.ts +97 -0
- package/src/render/docs.md +19 -0
- package/src/render/main.ts +49 -0
- package/src/server/args.ts +126 -0
- package/src/server/binaries.ts +47 -0
- package/src/server/config.ts +54 -0
- package/{server → src/server}/control.ts +246 -78
- package/src/server/docs.md +51 -0
- package/src/server/line-editor.ts +200 -0
- package/src/server/main.ts +473 -0
- package/src/server/mode.ts +92 -0
- package/src/server/rebuild.ts +90 -0
- package/src/server/registry.ts +138 -0
- package/src/server/remap.ts +60 -0
- package/src/server/repl.ts +223 -0
- package/src/server/state.ts +54 -0
- package/{server → src/server}/tsconfig.json +1 -1
- package/{server → src/server}/tunnel.ts +6 -6
- package/src/server/watcher.ts +121 -0
- package/src/tool/main.ts +70 -0
- package/src/types/bundle.d.ts +24 -0
- package/src/types/control.d.ts +90 -0
- package/src/types/registry.d.ts +16 -0
- package/scaffold/AGENTS.md +0 -630
- package/scaffold/package.json +0 -22
- package/scaffold/templates/components/icon.tsx +0 -48
- package/scaffold/templates/default/icon.tsx +0 -48
- package/server/main.ts +0 -308
- package/server/rebuild.ts +0 -68
- package/server/remap.ts +0 -47
- package/server/state.ts +0 -93
- package/src/args.ts +0 -212
- package/src/bundle-cli.ts +0 -13
- package/src/commands/bundle.ts +0 -76
- package/src/commands/client.ts +0 -34
- package/src/commands/mcp.ts +0 -603
- package/src/commands/pack.ts +0 -65
- package/src/commands/render.ts +0 -24
- package/src/commands/server.ts +0 -73
- package/src/dev-android.ts +0 -176
- package/src/dev-client.ts +0 -29
- package/src/dev-server.ts +0 -302
- package/src/packer.ts +0 -103
- package/src/repl.ts +0 -233
- package/src/util.ts +0 -121
- package/src/watcher.ts +0 -69
- /package/src/{untyped-deps.d.ts → bundle/untyped-deps.d.ts} +0 -0
- /package/src/{prompt.ts → init/prompt.ts} +0 -0
- /package/{scaffold → src/init/scaffold}/gitignore +0 -0
- /package/{scaffold → src/init/scaffold}/icon.svg +0 -0
- /package/{scaffold → src/init/scaffold}/mcp.json +0 -0
- /package/{scaffold → src/init/scaffold}/tsconfig.json +0 -0
- /package/{server → src/server}/cache.ts +0 -0
- /package/{server → src/server}/proxy.ts +0 -0
- /package/{server → src/server}/qr.ts +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidrt/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.52",
|
|
4
4
|
"license": "MIT",
|
|
5
|
+
"funding": "https://github.com/sponsors/wellawaretech",
|
|
5
6
|
"author": "Antoine van Wel",
|
|
6
7
|
"type": "module",
|
|
7
8
|
"bin": {
|
|
@@ -10,10 +11,10 @@
|
|
|
10
11
|
"files": [
|
|
11
12
|
"bin/",
|
|
12
13
|
"src/",
|
|
13
|
-
"
|
|
14
|
-
"scaffold/",
|
|
14
|
+
"dist/",
|
|
15
15
|
"fonts/",
|
|
16
|
-
"AGENTS.md"
|
|
16
|
+
"AGENTS.md",
|
|
17
|
+
"agents/"
|
|
17
18
|
],
|
|
18
19
|
"dependencies": {
|
|
19
20
|
"@babel/core": "^7.0.0",
|
|
@@ -23,22 +24,22 @@
|
|
|
23
24
|
"@jridgewell/remapping": "^2.3.0",
|
|
24
25
|
"@jridgewell/trace-mapping": "^0.3.25",
|
|
25
26
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
26
|
-
"babel-preset-solid": "2.0.0-rc.
|
|
27
|
+
"babel-preset-solid": "2.0.0-rc.1",
|
|
27
28
|
"bonjour-service": "^1.4.0",
|
|
28
29
|
"qrcode-generator": "^2.0.4",
|
|
29
30
|
"zod": "^4.4.3"
|
|
30
31
|
},
|
|
31
32
|
"optionalDependencies": {
|
|
32
|
-
"@solidrt/darwin-arm64": "0.0.
|
|
33
|
-
"@solidrt/linux-arm64-gnu": "0.0.
|
|
34
|
-
"@solidrt/linux-x64-gnu": "0.0.
|
|
35
|
-
"@solidrt/win32-x64-msvc": "0.0.
|
|
33
|
+
"@solidrt/darwin-arm64": "0.0.52",
|
|
34
|
+
"@solidrt/linux-arm64-gnu": "0.0.52",
|
|
35
|
+
"@solidrt/linux-x64-gnu": "0.0.52",
|
|
36
|
+
"@solidrt/win32-x64-msvc": "0.0.52"
|
|
36
37
|
},
|
|
37
38
|
"peerDependencies": {
|
|
38
39
|
"typescript": "^7"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
|
-
"@solidrt/flux-types": "0.0.
|
|
42
|
+
"@solidrt/flux-types": "0.0.52",
|
|
42
43
|
"@types/babel__core": "^7.20.5",
|
|
43
44
|
"@types/bun": "latest"
|
|
44
45
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# srt android
|
|
2
|
+
|
|
3
|
+
{{ usage android }}
|
|
4
|
+
|
|
5
|
+
Launches the SolidRT client installed on a connected Android device (or
|
|
6
|
+
emulator) over adb against the dev server: the one serving the project (or
|
|
7
|
+
file) in the current directory, or `--port`. A running instance is restarted
|
|
8
|
+
so it picks the server up. The command then waits a few seconds for the
|
|
9
|
+
client to appear on the server and reports its client id. The server must
|
|
10
|
+
run with `--lan` so the device can reach it; an emulator reaches a loopback
|
|
11
|
+
server through its host alias. `--device` picks one of several connected
|
|
12
|
+
devices by serial or unique prefix.
|
|
13
|
+
|
|
14
|
+
`--install` installs (or updates) the client first, from the
|
|
15
|
+
`@solidrt/android-<abi>` dev dependency matching the device's ABI; the
|
|
16
|
+
command says which package to add when it is missing. Without `--install`
|
|
17
|
+
the installed client is left as it is, and a note says when its version is
|
|
18
|
+
not the one that package carries - a client you built and installed
|
|
19
|
+
yourself is never replaced unless you ask.
|
|
20
|
+
|
|
21
|
+
adb is a system tool (Android Platform Tools) and is never bundled.
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { existsSync } from "node:fs"
|
|
2
|
+
import { networkInterfaces } from "node:os"
|
|
3
|
+
import { resolve } from "node:path"
|
|
4
|
+
import { androidPackageVersion, resolveApk, ANDROID_PKG_MAP } from "../lib/artifacts"
|
|
5
|
+
import { values, port } from "../lib/args"
|
|
6
|
+
import { resolveByPort, resolveFromCwd } from "../lib/registry"
|
|
7
|
+
import type { LiveRecord } from "../types/registry"
|
|
8
|
+
|
|
9
|
+
// `srt android`: the Android client flow, decoupled from `srt client` (a
|
|
10
|
+
// local process) because a device is a different thing: find it over adb and
|
|
11
|
+
// launch the client installed there pointed at the dev server, which is
|
|
12
|
+
// resolved like `srt client` does (the project at the cwd, or --port). The
|
|
13
|
+
// APK is only touched on --install (from the @solidrt/android-<abi> package
|
|
14
|
+
// matching the device's ABI), so a client built and installed by hand stays;
|
|
15
|
+
// without --install the command just notes when the installed version is not
|
|
16
|
+
// the one the project's package carries.
|
|
17
|
+
|
|
18
|
+
// Launch component of the "go" dev-client flavor (see lattice/Makefile.android).
|
|
19
|
+
let PACKAGE_ACTIVITY = "com.solidrt.go/com.solidrt.app.MainActivity"
|
|
20
|
+
let PACKAGE = "com.solidrt.go"
|
|
21
|
+
|
|
22
|
+
let sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
23
|
+
|
|
24
|
+
// adb is a system tool (Android Platform Tools), never bundled. Look on PATH
|
|
25
|
+
// first, then the standard SDK location.
|
|
26
|
+
function resolveAdb() {
|
|
27
|
+
let exe = process.platform === "win32" ? "adb.exe" : "adb"
|
|
28
|
+
let onPath = Bun.which(exe)
|
|
29
|
+
if (onPath) return onPath
|
|
30
|
+
for (let root of [process.env.ANDROID_HOME, process.env.ANDROID_SDK_ROOT]) {
|
|
31
|
+
if (!root) continue
|
|
32
|
+
let candidate = resolve(root, "platform-tools", exe)
|
|
33
|
+
if (existsSync(candidate)) return candidate
|
|
34
|
+
}
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function requireAdb() {
|
|
39
|
+
let path = resolveAdb()
|
|
40
|
+
if (path) return path
|
|
41
|
+
console.error("Could not find adb (Android Platform Tools).")
|
|
42
|
+
console.error("Install it:")
|
|
43
|
+
console.error(" Windows: winget install Google.PlatformTools")
|
|
44
|
+
console.error(" macOS: brew install android-platform-tools")
|
|
45
|
+
console.error(" Linux: install your distro's android-tools / adb package")
|
|
46
|
+
process.exit(1)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let ipToInt = (ip: string) => ip.split(".").reduce((acc, o) => (acc << 8) + (parseInt(o, 10) & 255), 0) >>> 0
|
|
50
|
+
|
|
51
|
+
// This host's IPv4 on the same subnet as `deviceIp`: the interface whose
|
|
52
|
+
// (address & netmask) matches the device's. Pure computation over what the OS
|
|
53
|
+
// reports (cross-platform, no routing socket, no hardcoded ranges).
|
|
54
|
+
function hostIpFor(deviceIp: string): string | null {
|
|
55
|
+
let d = ipToInt(deviceIp)
|
|
56
|
+
for (let addrs of Object.values(networkInterfaces())) {
|
|
57
|
+
for (let a of addrs ?? []) {
|
|
58
|
+
if (a.family === "IPv4" && !a.internal && (ipToInt(a.address) & ipToInt(a.netmask)) === (d & ipToInt(a.netmask))) {
|
|
59
|
+
return a.address
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// The device's own IPv4 on its primary network: from the serial for wireless adb
|
|
67
|
+
// (ip:port), else queried over adb. `ip route get` reports the source IP of the
|
|
68
|
+
// route to a public address, i.e. the device's main interface IP.
|
|
69
|
+
function deviceIp(adb: string, target: string): string | null {
|
|
70
|
+
let m = target.match(/^(\d+\.\d+\.\d+\.\d+):\d+$/)
|
|
71
|
+
if (m) return m[1] ?? null
|
|
72
|
+
let res = Bun.spawnSync([adb, "-s", target, "shell", "ip", "route", "get", "1.1.1.1"], {
|
|
73
|
+
stdout: "pipe",
|
|
74
|
+
stderr: "pipe",
|
|
75
|
+
})
|
|
76
|
+
return res.stdout.toString().match(/src (\d+\.\d+\.\d+\.\d+)/)?.[1] ?? null
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// The host:port the client on `target` should dial to reach this machine's dev
|
|
80
|
+
// server, by adb transport: the emulator reaches the host through its NAT alias
|
|
81
|
+
// 10.0.2.2; every other transport shares a LAN with the host, so match the
|
|
82
|
+
// device's IP to the host interface on its subnet. Replaces the old adb-reverse
|
|
83
|
+
// loopback tunnel, which never worked over wireless adb. Returns null when the
|
|
84
|
+
// address cannot be resolved (the client then falls back to QR/recents).
|
|
85
|
+
function devServerAddress(adb: string, target: string, server: LiveRecord): string | null {
|
|
86
|
+
// The emulator's host alias reaches the host's loopback, so a loopback-only
|
|
87
|
+
// server is fine there; a real device needs a server started with --lan.
|
|
88
|
+
if (target.startsWith("emulator-")) return `10.0.2.2:${server.port}`
|
|
89
|
+
if (server.address === "127.0.0.1") {
|
|
90
|
+
console.log("[cli] The dev server is loopback-only; restart it with --lan so the device can reach it")
|
|
91
|
+
return null
|
|
92
|
+
}
|
|
93
|
+
let dip = deviceIp(adb, target)
|
|
94
|
+
if (!dip) return null
|
|
95
|
+
let host = hostIpFor(dip)
|
|
96
|
+
return host ? `${host}:${server.port}` : null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// The dev server the device should dial: --port picks a local server by
|
|
100
|
+
// port, otherwise the project (or file) in the current directory.
|
|
101
|
+
async function resolveServer(): Promise<LiveRecord> {
|
|
102
|
+
let resolved = port !== undefined ? await resolveByPort(port) : await resolveFromCwd(process.cwd())
|
|
103
|
+
if (!resolved.ok) {
|
|
104
|
+
console.error(resolved.message)
|
|
105
|
+
process.exit(1)
|
|
106
|
+
}
|
|
107
|
+
return resolved.record
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Serials of connected, authorized devices (excludes offline/unauthorized).
|
|
111
|
+
function listDevices(adb: string): string[] {
|
|
112
|
+
let listed = Bun.spawnSync([adb, "devices"], { stdout: "pipe", stderr: "pipe" })
|
|
113
|
+
return listed.stdout
|
|
114
|
+
.toString()
|
|
115
|
+
.split("\n")
|
|
116
|
+
.slice(1)
|
|
117
|
+
.map((l) => l.trim())
|
|
118
|
+
.filter(Boolean)
|
|
119
|
+
.filter((l) => l.endsWith("\tdevice"))
|
|
120
|
+
.map((l) => l.split("\t")[0])
|
|
121
|
+
.filter((s): s is string => Boolean(s))
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Primary ABI of the connected device (e.g. "arm64-v8a", "armeabi-v7a"), used
|
|
125
|
+
// to pick the matching APK -- a fat (multi-ABI) APK reports its 64-bit ABI
|
|
126
|
+
// here and still installs fine, so this only matters for single-ABI builds.
|
|
127
|
+
function deviceAbi(adb: string, target: string): string {
|
|
128
|
+
let res = Bun.spawnSync([adb, "-s", target, "shell", "getprop", "ro.product.cpu.abi"], {
|
|
129
|
+
stdout: "pipe",
|
|
130
|
+
stderr: "pipe",
|
|
131
|
+
})
|
|
132
|
+
return res.stdout.toString().trim()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Always shown up front, regardless of how many devices are connected or
|
|
136
|
+
// whether --device narrows it down: one line per device with the ABI its APK
|
|
137
|
+
// build would target, then (with --install) a dev-dependency hint for each
|
|
138
|
+
// ABI that isn't resolvable locally yet. Returns the device->abi map so
|
|
139
|
+
// callers don't have to re-query it.
|
|
140
|
+
function printDeviceStatus(adb: string, devices: string[]): Map<string, string> {
|
|
141
|
+
let abiByDevice = new Map<string, string>()
|
|
142
|
+
let missingAbis = new Set<string>()
|
|
143
|
+
for (let d of devices) {
|
|
144
|
+
let abi = deviceAbi(adb, d)
|
|
145
|
+
abiByDevice.set(d, abi)
|
|
146
|
+
console.log(`${d} - ${abi}`)
|
|
147
|
+
if (!resolveApk(abi)) missingAbis.add(abi)
|
|
148
|
+
}
|
|
149
|
+
let missingPkgs = [...missingAbis].map((abi) => ANDROID_PKG_MAP[abi]).filter((pkg): pkg is string => Boolean(pkg))
|
|
150
|
+
if (values.install && missingPkgs.length > 0) {
|
|
151
|
+
console.log(`Add dev dependencies with: bun add -d ${missingPkgs.join(" ")}`)
|
|
152
|
+
}
|
|
153
|
+
return abiByDevice
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// The versionName of the client installed on `target`, null when none is.
|
|
157
|
+
function installedVersion(adb: string, target: string): string | null {
|
|
158
|
+
let res = Bun.spawnSync([adb, "-s", target, "shell", "dumpsys", "package", PACKAGE], { stdout: "pipe", stderr: "pipe" })
|
|
159
|
+
return res.stdout.toString().match(/versionName=(\S+)/)?.[1] ?? null
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
type Client = { id: number; platform: string; version: string }
|
|
163
|
+
|
|
164
|
+
// The clients the dev server currently lists (empty when it cannot be asked).
|
|
165
|
+
async function connectedClients(server: LiveRecord): Promise<Client[]> {
|
|
166
|
+
try {
|
|
167
|
+
let resp = await fetch(`http://127.0.0.1:${server.port}/__control__/clients`, { signal: AbortSignal.timeout(1000) })
|
|
168
|
+
return ((await resp.json()) as { clients?: Client[] }).clients ?? []
|
|
169
|
+
} catch {
|
|
170
|
+
return []
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// The first Android client that appears beyond `before`, or null after ~10 s.
|
|
175
|
+
async function waitForClient(server: LiveRecord, before: Set<number>): Promise<Client | null> {
|
|
176
|
+
for (let attempt = 0; attempt < 20; attempt++) {
|
|
177
|
+
await sleep(500)
|
|
178
|
+
let fresh = (await connectedClients(server)).find((c) => c.platform === "android" && !before.has(c.id))
|
|
179
|
+
if (fresh) return fresh
|
|
180
|
+
}
|
|
181
|
+
return null
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Resolve the target device serial (and its ABI). With --device, treat the
|
|
185
|
+
// value as a serial prefix and require it to match exactly one connected
|
|
186
|
+
// device; without it, use the sole connected device. Exits with a clear
|
|
187
|
+
// message on any ambiguity.
|
|
188
|
+
function resolveTarget(adb: string): { target: string; abi: string } {
|
|
189
|
+
let devices = listDevices(adb)
|
|
190
|
+
let abiByDevice = printDeviceStatus(adb, devices)
|
|
191
|
+
|
|
192
|
+
if (values.device) {
|
|
193
|
+
let prefix = values.device
|
|
194
|
+
let matches = devices.filter((d) => d.startsWith(prefix))
|
|
195
|
+
if (matches.length > 1) {
|
|
196
|
+
console.error(`--device "${prefix}" is ambiguous; matches: ${matches.join(", ")}`)
|
|
197
|
+
process.exit(1)
|
|
198
|
+
}
|
|
199
|
+
let [match] = matches
|
|
200
|
+
if (!match) {
|
|
201
|
+
console.error(`No connected device matches --device "${prefix}".`)
|
|
202
|
+
process.exit(1)
|
|
203
|
+
}
|
|
204
|
+
return { target: match, abi: abiByDevice.get(match)! }
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (devices.length > 1) {
|
|
208
|
+
console.error("Pick one with --device <serial or prefix>.")
|
|
209
|
+
process.exit(1)
|
|
210
|
+
}
|
|
211
|
+
let [only] = devices
|
|
212
|
+
if (!only) {
|
|
213
|
+
console.error("No authorized Android device found. Enable USB debugging and check `adb devices`.")
|
|
214
|
+
process.exit(1)
|
|
215
|
+
}
|
|
216
|
+
return { target: only, abi: abiByDevice.get(only)! }
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Launch the Android client on a connected device over adb (installing it
|
|
220
|
+
// first on --install), passing it the dev-server address to dial as a
|
|
221
|
+
// launch-intent extra (see devServerAddress), then wait briefly for it to show
|
|
222
|
+
// up on the dev server. The client is not a child process here: its lifecycle
|
|
223
|
+
// is the WS connect/disconnect the server sees.
|
|
224
|
+
export async function main() {
|
|
225
|
+
let server = await resolveServer()
|
|
226
|
+
let adb = requireAdb()
|
|
227
|
+
|
|
228
|
+
let { target, abi } = resolveTarget(adb)
|
|
229
|
+
|
|
230
|
+
if (values.install) {
|
|
231
|
+
let apk = resolveApk(abi)
|
|
232
|
+
if (!apk) {
|
|
233
|
+
console.error(`Could not find a SolidRT-Go APK for ABI "${abi}".`)
|
|
234
|
+
let pkg = ANDROID_PKG_MAP[abi]
|
|
235
|
+
if (pkg) console.error(`Add it with: bun add -d ${pkg}`)
|
|
236
|
+
process.exit(1)
|
|
237
|
+
}
|
|
238
|
+
console.log(`[cli] Installing SolidRT-Go on ${target}`)
|
|
239
|
+
let install = Bun.spawn([adb, "-s", target, "install", "-r", apk], { stdout: "pipe", stderr: "pipe" })
|
|
240
|
+
if ((await install.exited) !== 0) {
|
|
241
|
+
console.error("adb install failed:\n" + (await new Response(install.stderr).text()))
|
|
242
|
+
process.exit(1)
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
let installed = installedVersion(adb, target)
|
|
246
|
+
if (installed === null) {
|
|
247
|
+
console.error(`No SolidRT-Go client on ${target}; install one with srt android --install`)
|
|
248
|
+
process.exit(1)
|
|
249
|
+
}
|
|
250
|
+
let expected = androidPackageVersion(abi)
|
|
251
|
+
if (expected !== null && expected !== installed) {
|
|
252
|
+
console.log(
|
|
253
|
+
`[cli] Installed client is ${installed}; the project's ${ANDROID_PKG_MAP[abi]} is ${expected} (srt android --install updates it)`,
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Hand the client the dev-server address to dial, as a launch-intent extra that
|
|
259
|
+
// MainActivity forwards to native argv (--dev-server); the client auto-connects
|
|
260
|
+
// to it. Replaces adb reverse, which never worked over wireless adb. -S stops
|
|
261
|
+
// a running instance first: a delivered intent does not reach one, so without
|
|
262
|
+
// it the client would keep whatever server it had.
|
|
263
|
+
let before = new Set((await connectedClients(server)).map((c) => c.id))
|
|
264
|
+
let devServer = devServerAddress(adb, target, server)
|
|
265
|
+
let launchArgs = [adb, "-s", target, "shell", "am", "start", "-S", "-n", PACKAGE_ACTIVITY]
|
|
266
|
+
if (devServer) {
|
|
267
|
+
console.log(`[cli] Client will dial dev server at ${devServer}`)
|
|
268
|
+
launchArgs.push("--es", "srt_dev_server", devServer)
|
|
269
|
+
} else {
|
|
270
|
+
console.log("[cli] Could not resolve a host address for the device; client will need a manual/QR connect")
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
let start = Bun.spawn(launchArgs, { stdout: "pipe", stderr: "pipe" })
|
|
274
|
+
if ((await start.exited) !== 0) {
|
|
275
|
+
console.error("adb start failed:\n" + (await new Response(start.stderr).text()))
|
|
276
|
+
process.exit(1)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
console.log(`[cli] Launched SolidRT-Go on ${target}; waiting for it to connect to the dev server...`)
|
|
280
|
+
let client = await waitForClient(server, before)
|
|
281
|
+
if (client) {
|
|
282
|
+
console.log(`[cli] Client ${client.id} connected (${client.platform}, ${client.version})`)
|
|
283
|
+
} else {
|
|
284
|
+
console.log(`[cli] No connection after 10 s. The server must run with --lan and the device must reach this machine.`)
|
|
285
|
+
}
|
|
286
|
+
}
|