@solidrt/cli 0.0.53 → 0.0.55

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/dist/server.js CHANGED
@@ -705,7 +705,7 @@ ${stderr.trim()}`;
705
705
  return null;
706
706
  }
707
707
 
708
- // ../../node_modules/.bun/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
708
+ // ../../node_modules/.bun/@jridgewell+sourcemap-codec@1.6.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
709
709
  var comma = 44;
710
710
  var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
711
711
  var intToChar = new Uint8Array(64);
@@ -715,7 +715,7 @@ for (let i = 0;i < chars.length; i++) {
715
715
  intToChar[i] = c;
716
716
  charToInt[c] = i;
717
717
  }
718
- function decodeInteger(reader, relative) {
718
+ function decodeInteger(reader) {
719
719
  let value = 0;
720
720
  let shift = 0;
721
721
  let integer2 = 0;
@@ -725,12 +725,10 @@ function decodeInteger(reader, relative) {
725
725
  value |= (integer2 & 31) << shift;
726
726
  shift += 5;
727
727
  } while (integer2 & 32);
728
- const shouldNegate = value & 1;
729
- value >>>= 1;
730
- if (shouldNegate) {
731
- value = -2147483648 | -value;
732
- }
733
- return relative + value;
728
+ return value;
729
+ }
730
+ function decodeSign(num) {
731
+ return num & 1 ? -2147483648 | -(num >>> 1) : num >>> 1;
734
732
  }
735
733
  function hasMoreVlq(reader, max) {
736
734
  if (reader.pos >= max)
@@ -772,16 +770,16 @@ function decode(mappings) {
772
770
  genColumn = 0;
773
771
  while (reader.pos < semi) {
774
772
  let seg;
775
- genColumn = decodeInteger(reader, genColumn);
773
+ genColumn += decodeSign(decodeInteger(reader));
776
774
  if (genColumn < lastCol)
777
775
  sorted = false;
778
776
  lastCol = genColumn;
779
777
  if (hasMoreVlq(reader, semi)) {
780
- sourcesIndex = decodeInteger(reader, sourcesIndex);
781
- sourceLine = decodeInteger(reader, sourceLine);
782
- sourceColumn = decodeInteger(reader, sourceColumn);
778
+ sourcesIndex += decodeSign(decodeInteger(reader));
779
+ sourceLine += decodeSign(decodeInteger(reader));
780
+ sourceColumn += decodeSign(decodeInteger(reader));
783
781
  if (hasMoreVlq(reader, semi)) {
784
- namesIndex = decodeInteger(reader, namesIndex);
782
+ namesIndex += decodeSign(decodeInteger(reader));
785
783
  seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
786
784
  } else {
787
785
  seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
@@ -1083,6 +1081,7 @@ function clientList(withAddress = false) {
1083
1081
  os: info.os,
1084
1082
  kernel: info.kernel,
1085
1083
  videoDriver: info.videoDriver,
1084
+ refreshRate: info.refreshRate,
1086
1085
  gpu: info.gpu,
1087
1086
  ...withAddress ? { address: ws.remoteAddr ?? null } : {}
1088
1087
  }));
@@ -1335,8 +1334,14 @@ async function handleControl(req, path, query) {
1335
1334
  return handleQuery(query, "snapshot", extra);
1336
1335
  }
1337
1336
  case "/__control__/gpu": {
1337
+ let extra = {};
1338
1338
  let label = query.get("label");
1339
- return handleQuery(query, "gpu", label === undefined ? undefined : { label });
1339
+ if (label !== undefined)
1340
+ extra.label = label;
1341
+ let draw = parseInt(query.get("draw") ?? "", 10);
1342
+ if (Number.isFinite(draw))
1343
+ extra.draw = draw;
1344
+ return handleQuery(query, "gpu", extra);
1340
1345
  }
1341
1346
  case "/__control__/debug": {
1342
1347
  if (req.method !== "POST")
@@ -3765,6 +3770,7 @@ function onOpen(ws) {
3765
3770
  os: null,
3766
3771
  kernel: null,
3767
3772
  videoDriver: null,
3773
+ refreshRate: null,
3768
3774
  gpu: null
3769
3775
  });
3770
3776
  console.log(`[cli] Client connected ${ws.remoteAddr ?? "unknown"}`);
@@ -3777,8 +3783,6 @@ function onClose(ws) {
3777
3783
  let info = state.clients.get(ws);
3778
3784
  state.clients.delete(ws);
3779
3785
  console.log(`[cli] Client disconnected: ${info?.platform ?? "unknown"}`);
3780
- if (config.client && localClientExited && state.clients.size === 0)
3781
- shutdown();
3782
3786
  }
3783
3787
  function onMessage(ws, msg) {
3784
3788
  try {
@@ -3801,6 +3805,7 @@ function onMessage(ws, msg) {
3801
3805
  os: text(data.os),
3802
3806
  kernel: text(data.kernel),
3803
3807
  videoDriver: text(data.videoDriver),
3808
+ refreshRate: typeof data.refreshRate === "number" ? data.refreshRate : null,
3804
3809
  gpu: data.gpu && typeof data.gpu === "object" ? { vendor: text(data.gpu.vendor) ?? "", renderer: text(data.gpu.renderer) ?? "", version: text(data.gpu.version) ?? "" } : null
3805
3810
  });
3806
3811
  console.log(`[cli] Client info ${ws.remoteAddr ?? "unknown"} ${data.platform} (${data.version})`);
@@ -3870,7 +3875,6 @@ var keepalive = setInterval(() => {
3870
3875
  var shuttingDown = false;
3871
3876
  var stopRepl = () => {};
3872
3877
  var localClient = null;
3873
- var localClientExited = false;
3874
3878
  var signalOffs = ["SIGINT", "SIGTERM"].map((signal) => onSignal(signal, () => {
3875
3879
  shutdown();
3876
3880
  }));
@@ -3924,13 +3928,7 @@ if (config.client) {
3924
3928
  pump(child.stderr, (line) => console.error(line));
3925
3929
  child.status().then(() => {
3926
3930
  localClient = null;
3927
- localClientExited = true;
3928
- if (shuttingDown)
3929
- return;
3930
- if (state.clients.size === 0) {
3931
- shutdown();
3932
- } else {
3933
- console.log(`[cli] Local client exited, ${state.clients.size} remote client(s) still connected`);
3934
- }
3931
+ if (!shuttingDown)
3932
+ console.log("[cli] Local client exited; the server keeps running (srt client reattaches)");
3935
3933
  });
3936
3934
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidrt/cli",
3
- "version": "0.0.53",
3
+ "version": "0.0.55",
4
4
  "license": "MIT",
5
5
  "funding": "https://github.com/sponsors/wellawaretech",
6
6
  "author": "Antoine van Wel",
@@ -24,22 +24,22 @@
24
24
  "@jridgewell/remapping": "^2.3.0",
25
25
  "@jridgewell/trace-mapping": "^0.3.25",
26
26
  "@modelcontextprotocol/sdk": "^1.29.0",
27
- "@solidjs/babel-plugin": "2.0.0-rc.3",
27
+ "@solidjs/babel-plugin": "2.0.0-rc.4",
28
28
  "bonjour-service": "^1.4.0",
29
29
  "qrcode-generator": "^2.0.4",
30
30
  "zod": "^4.4.3"
31
31
  },
32
32
  "optionalDependencies": {
33
- "@solidrt/darwin-arm64": "0.0.53",
34
- "@solidrt/linux-arm64-gnu": "0.0.53",
35
- "@solidrt/linux-x64-gnu": "0.0.53",
36
- "@solidrt/win32-x64-msvc": "0.0.53"
33
+ "@solidrt/darwin-arm64": "0.0.55",
34
+ "@solidrt/linux-arm64-gnu": "0.0.55",
35
+ "@solidrt/linux-x64-gnu": "0.0.55",
36
+ "@solidrt/win32-x64-msvc": "0.0.55"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "typescript": "^7"
40
40
  },
41
41
  "devDependencies": {
42
- "@solidrt/flux-types": "0.0.53",
42
+ "@solidrt/flux-types": "0.0.55",
43
43
  "@types/babel__core": "^7.20.5",
44
44
  "@types/bun": "latest"
45
45
  }
@@ -8,8 +8,11 @@ file) in the current directory, or `--port`. A running instance is restarted
8
8
  so it picks the server up. The command then waits a few seconds for the
9
9
  client to appear on the server and reports its client id. The server must
10
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.
11
+ server through its host alias. Without a running server the client starts
12
+ on its own, into the launcher (`--port` must name a live server). With several
13
+ devices connected a terminal asks which ones (all preselected, so enter
14
+ launches on every device); `--device` picks one by serial or unique prefix
15
+ (a script must).
13
16
 
14
17
  `--install` installs (or updates) the client first, from the
15
18
  `@solidrt/android-<abi>` dev dependency matching the device's ABI; the
@@ -3,6 +3,8 @@ import { networkInterfaces } from "node:os"
3
3
  import { resolve } from "node:path"
4
4
  import { androidPackageVersion, resolveApk, ANDROID_PKG_MAP } from "../lib/artifacts"
5
5
  import { values, port } from "../lib/args"
6
+ import { CLI_VERSION } from "../lib/project"
7
+ import { multiselect } from "../lib/prompt"
6
8
  import { resolveByPort, resolveFromCwd } from "../lib/registry"
7
9
  import type { LiveRecord } from "../types/registry"
8
10
 
@@ -97,14 +99,19 @@ function devServerAddress(adb: string, target: string, server: LiveRecord): stri
97
99
  }
98
100
 
99
101
  // 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)
102
+ // port (and must exist), otherwise the project (or file) in the current
103
+ // directory, or none: the client then starts on its own, into the launcher.
104
+ async function resolveServer(): Promise<LiveRecord | null> {
105
+ if (port !== undefined) {
106
+ let resolved = await resolveByPort(port)
107
+ if (!resolved.ok) {
108
+ console.error(resolved.message)
109
+ process.exit(1)
110
+ }
111
+ return resolved.record
106
112
  }
107
- return resolved.record
113
+ let resolved = await resolveFromCwd(process.cwd())
114
+ return resolved.ok ? resolved.record : null
108
115
  }
109
116
 
110
117
  // Serials of connected, authorized devices (excludes offline/unauthorized).
@@ -132,25 +139,39 @@ function deviceAbi(adb: string, target: string): string {
132
139
  return res.stdout.toString().trim()
133
140
  }
134
141
 
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)
142
+ // One line per connected device with the ABI its APK build would target;
143
+ // the picker shows the same lines, so this is for the cases without one.
144
+ function printDeviceStatus(devices: string[], abiByDevice: Map<string, string>) {
145
+ for (let d of devices) console.log(`${d} - ${abiByDevice.get(d)}`)
146
+ }
147
+
148
+ // A published CLI version (x.y.z): the release action publishes the CLI and
149
+ // the android packages at one version, so that is the one to pin. A checkout
150
+ // reports a git describe (or the 0.0.0 placeholder), which npm does not have.
151
+ let RELEASE_VERSION = /^\d+\.\d+\.\d+$/
152
+
153
+ // The APK for `abi`, adding the project's @solidrt/android-<abi> dev
154
+ // dependency in the cwd first when it is not installed. ABIs without a
155
+ // published package (e.g. x86) only resolve through SRT_HOME.
156
+ function ensureApk(abi: string): string {
157
+ let apk = resolveApk(abi)
158
+ if (apk) return apk
159
+ let pkg = ANDROID_PKG_MAP[abi]
160
+ if (!pkg) {
161
+ console.error(`Could not find a SolidRT-Go APK for ABI "${abi}".`)
162
+ process.exit(1)
148
163
  }
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(" ")}`)
164
+ let spec = RELEASE_VERSION.test(CLI_VERSION) && CLI_VERSION !== "0.0.0" ? `${pkg}@${CLI_VERSION}` : pkg
165
+ console.log(`[cli] Adding dev dependency ${spec}`)
166
+ let add = Bun.spawnSync(["bun", "add", "-d", spec], { cwd: process.cwd(), stdout: "inherit", stderr: "inherit" })
167
+ if (add.exitCode !== 0) {
168
+ console.error(`Could not add ${spec}; retry with bun add -d ${spec}`)
169
+ process.exit(1)
152
170
  }
153
- return abiByDevice
171
+ apk = resolveApk(abi)
172
+ if (apk) return apk
173
+ console.error(`${pkg} is installed but carries no solidrt-go.apk for ABI "${abi}".`)
174
+ process.exit(1)
154
175
  }
155
176
 
156
177
  // The versionName of the client installed on `target`, null when none is.
@@ -171,25 +192,31 @@ async function connectedClients(server: LiveRecord): Promise<Client[]> {
171
192
  }
172
193
  }
173
194
 
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++) {
195
+ // The Android clients that appear beyond `before`: all of them once `count`
196
+ // have, else whatever showed up within ~10 s.
197
+ async function waitForClients(server: LiveRecord, before: Set<number>, count: number): Promise<Client[]> {
198
+ let fresh: Client[] = []
199
+ for (let attempt = 0; attempt < 20 && fresh.length < count; attempt++) {
177
200
  await sleep(500)
178
- let fresh = (await connectedClients(server)).find((c) => c.platform === "android" && !before.has(c.id))
179
- if (fresh) return fresh
201
+ fresh = (await connectedClients(server)).filter((c) => c.platform === "android" && !before.has(c.id))
180
202
  }
181
- return null
203
+ return fresh
182
204
  }
183
205
 
184
- // Resolve the target device serial (and its ABI). With --device, treat the
206
+ type Device = { target: string; abi: string }
207
+
208
+ // Resolve the target devices (serial and ABI). With --device, treat the
185
209
  // 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 } {
210
+ // device; without it, use the sole connected device, or pick any number of
211
+ // several on a terminal (all preselected: enter means every device). Exits
212
+ // with a clear message on any ambiguity.
213
+ async function resolveTargets(adb: string): Promise<Device[]> {
189
214
  let devices = listDevices(adb)
190
- let abiByDevice = printDeviceStatus(adb, devices)
215
+ let abiByDevice = new Map(devices.map((d) => [d, deviceAbi(adb, d)]))
216
+ let device = (target: string): Device => ({ target, abi: abiByDevice.get(target)! })
191
217
 
192
218
  if (values.device) {
219
+ printDeviceStatus(devices, abiByDevice)
193
220
  let prefix = values.device
194
221
  let matches = devices.filter((d) => d.startsWith(prefix))
195
222
  if (matches.length > 1) {
@@ -201,86 +228,108 @@ function resolveTarget(adb: string): { target: string; abi: string } {
201
228
  console.error(`No connected device matches --device "${prefix}".`)
202
229
  process.exit(1)
203
230
  }
204
- return { target: match, abi: abiByDevice.get(match)! }
231
+ return [device(match)]
205
232
  }
206
233
 
207
234
  if (devices.length > 1) {
208
- console.error("Pick one with --device <serial or prefix>.")
209
- process.exit(1)
235
+ // The prompt's non-TTY default is no way to pick devices, so a script has
236
+ // to say which.
237
+ if (!process.stdin.isTTY) {
238
+ printDeviceStatus(devices, abiByDevice)
239
+ console.error("Pick one with --device <serial or prefix>.")
240
+ process.exit(1)
241
+ }
242
+ let picked = await multiselect(
243
+ "Pick devices",
244
+ devices.map((d) => ({ label: `${d} - ${abiByDevice.get(d)}`, value: d, checked: true })),
245
+ )
246
+ if (picked.length === 0) {
247
+ console.error("No device picked.")
248
+ process.exit(1)
249
+ }
250
+ return picked.map(device)
210
251
  }
252
+ printDeviceStatus(devices, abiByDevice)
211
253
  let [only] = devices
212
254
  if (!only) {
213
255
  console.error("No authorized Android device found. Enable USB debugging and check `adb devices`.")
214
256
  process.exit(1)
215
257
  }
216
- return { target: only, abi: abiByDevice.get(only)! }
258
+ return [device(only)]
217
259
  }
218
260
 
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
-
261
+ // Install the client on `target` (on --install), else check that one is there
262
+ // and note when its version is not the one the project's package carries.
263
+ async function prepare(adb: string, { target, abi }: Device) {
230
264
  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
- }
265
+ let apk = ensureApk(abi)
238
266
  console.log(`[cli] Installing SolidRT-Go on ${target}`)
239
267
  let install = Bun.spawn([adb, "-s", target, "install", "-r", apk], { stdout: "pipe", stderr: "pipe" })
240
268
  if ((await install.exited) !== 0) {
241
269
  console.error("adb install failed:\n" + (await new Response(install.stderr).text()))
242
270
  process.exit(1)
243
271
  }
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
- }
272
+ return
273
+ }
274
+ let installed = installedVersion(adb, target)
275
+ if (installed === null) {
276
+ console.error(`No SolidRT-Go client on ${target}; install one with srt android --install`)
277
+ process.exit(1)
256
278
  }
279
+ let expected = androidPackageVersion(abi)
280
+ if (expected !== null && expected !== installed) {
281
+ console.log(
282
+ `[cli] Installed client is ${installed}; the project's ${ANDROID_PKG_MAP[abi]} is ${expected} (srt android --install updates it)`,
283
+ )
284
+ }
285
+ }
257
286
 
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)
287
+ // Launch the client on `target`, handing it the dev-server address to dial as
288
+ // a launch-intent extra that MainActivity forwards to native argv
289
+ // (--dev-server); the client auto-connects to it. Replaces adb reverse, which
290
+ // never worked over wireless adb. -S stops a running instance first: a
291
+ // delivered intent does not reach one, so without it the client would keep
292
+ // whatever server it had. With no server there is no extra to pass.
293
+ async function launch(adb: string, { target }: Device, server: LiveRecord | null) {
294
+ let devServer = server ? devServerAddress(adb, target, server) : null
265
295
  let launchArgs = [adb, "-s", target, "shell", "am", "start", "-S", "-n", PACKAGE_ACTIVITY]
266
296
  if (devServer) {
267
- console.log(`[cli] Client will dial dev server at ${devServer}`)
297
+ console.log(`[cli] Client on ${target} will dial dev server at ${devServer}`)
268
298
  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")
299
+ } else if (server) {
300
+ console.log(`[cli] Could not resolve a host address for ${target}; client will need a manual/QR connect`)
271
301
  }
272
-
273
302
  let start = Bun.spawn(launchArgs, { stdout: "pipe", stderr: "pipe" })
274
303
  if ((await start.exited) !== 0) {
275
304
  console.error("adb start failed:\n" + (await new Response(start.stderr).text()))
276
305
  process.exit(1)
277
306
  }
307
+ console.log(`[cli] Launched SolidRT-Go on ${target}`)
308
+ }
309
+
310
+ // Launch the Android client on the connected devices over adb (installing it
311
+ // first on --install), then wait briefly for them to show up on the dev
312
+ // server. The clients are not child processes here: their lifecycle is the
313
+ // WS connect/disconnect the server sees.
314
+ export async function main() {
315
+ let server = await resolveServer()
316
+ let adb = requireAdb()
317
+
318
+ let devices = await resolveTargets(adb)
319
+ for (let device of devices) await prepare(adb, device)
320
+
321
+ let before = new Set(server ? (await connectedClients(server)).map((c) => c.id) : [])
322
+ for (let device of devices) await launch(adb, device, server)
323
+ if (!server) return
278
324
 
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) {
325
+ console.log("[cli] Waiting for the client(s) to connect to the dev server...")
326
+ let clients = await waitForClients(server, before, devices.length)
327
+ for (let client of clients) {
282
328
  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
329
  }
286
- }
330
+ if (clients.length < devices.length) {
331
+ console.log(
332
+ `[cli] ${devices.length - clients.length} of ${devices.length} not connected after 10 s. The server must run with --lan and the device must reach this machine.`,
333
+ )
334
+ }
335
+ }
@@ -6,4 +6,6 @@ The client half of [srt run](../server/docs.md), on its own. Without flags
6
6
  it attaches to the dev server of the project (or file) in the current
7
7
  directory; `--port` picks a local server by port and `--server` names any
8
8
  address, which is how a second machine joins a server started with `--lan`.
9
- A phone or tablet is [srt android](../android/docs.md).
9
+ Without a running server the client starts on its own, into the launcher
10
+ (`--port` and `--server` must name a live server). A phone or tablet is
11
+ [srt android](../android/docs.md).
@@ -4,13 +4,14 @@ import { resolveFromCwd } from "../lib/registry"
4
4
 
5
5
  // Standalone solidrt-go client (no dev server of its own). Without flags it
6
6
  // attaches to the dev server of the project (or file) in the current
7
- // directory, resolved from the registry; --port picks a local server by port
8
- // and --server names any address. A device is `srt android`.
7
+ // directory, resolved from the registry, and starts on its own (into the
8
+ // launcher) when there is none; --port picks a local server by port and
9
+ // --server names any address, and those must exist. A device is `srt android`.
9
10
  export async function main() {
10
11
  let runner = requireBinary("solidrt-go")
11
12
  let args: string[] = [...clientStorageArgs()]
12
13
  if (values.size) args.push("--size", values.size)
13
- let address: string
14
+ let address: string | null
14
15
  if (values.server) {
15
16
  if (!values.server.includes(":")) {
16
17
  console.error(`--server needs host:port (got "${values.server}"); dev servers have no fixed port`)
@@ -21,13 +22,9 @@ export async function main() {
21
22
  address = `127.0.0.1:${port}`
22
23
  } else {
23
24
  let resolved = await resolveFromCwd(process.cwd())
24
- if (!resolved.ok) {
25
- console.error(resolved.message)
26
- process.exit(1)
27
- }
28
- address = `127.0.0.1:${resolved.record.port}`
25
+ address = resolved.ok ? `127.0.0.1:${resolved.record.port}` : null
29
26
  }
30
- args.push("--dev-server", address)
27
+ if (address) args.push("--dev-server", address)
31
28
  let exit = await run(runner, args)
32
29
  process.exit(exit)
33
30
  }
package/src/init/main.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { cp, mkdir, readFile, readdir, writeFile } from "node:fs/promises"
2
2
  import { basename, dirname, join, resolve } from "node:path"
3
3
  import { source, values } from "../lib/args"
4
- import { multiselect, note, text } from "./prompt"
4
+ import { multiselect, note, text } from "../lib/prompt"
5
5
 
6
6
  const DEFAULT_NAME = "solidrt-app"
7
7
 
@@ -90,8 +90,10 @@ platform-wide and bite in every app:
90
90
 
91
91
  ## Run / verify
92
92
 
93
- - FIRST check whether a dev server and a client are already running and
94
- build against those; do not start a second `srt run` when one is up.
93
+ - FIRST check whether a dev server and its clients (possibly several) are
94
+ already running and build against those; do not start a second `srt run`
95
+ when one is up. `reload` reaches every connected client; the per-client
96
+ tools are listed in debugging.md.
95
97
  - The dev loop (reload, logs, snapshots, the holds on reload-on-save and on
96
98
  the user's input), typechecking, headless rendering and the MCP tools:
97
99
  node_modules/@solidrt/cli/AGENTS.md and its agents/debugging.md. Read it
@@ -10,14 +10,14 @@
10
10
  "android": "srt android"
11
11
  },
12
12
  "dependencies": {
13
- "@solidrt/core": "0.0.53",
14
- "@solidrt/components": "0.0.53",
15
- "@solidrt/2d": "0.0.53",
16
- "@solidrt/3d": "0.0.53"
13
+ "@solidrt/core": "0.0.55",
14
+ "@solidrt/components": "0.0.55",
15
+ "@solidrt/2d": "0.0.55",
16
+ "@solidrt/3d": "0.0.55"
17
17
  },
18
18
  "devDependencies": {
19
- "@solidrt/cli": "0.0.53",
20
- "@solidrt/flux-types": "0.0.53",
19
+ "@solidrt/cli": "0.0.55",
20
+ "@solidrt/flux-types": "0.0.55",
21
21
  "typescript": "^7"
22
22
  }
23
23
  }