@quenty/studio-bridge 0.21.0 → 0.22.0

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.
Files changed (491) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +109 -17
  3. package/build-scripts/transform-add-session-attribute.lua +1 -0
  4. package/deploy.nevermore.json +10 -0
  5. package/dist/src/bridge/bridge-connection.d.ts +26 -2
  6. package/dist/src/bridge/bridge-connection.d.ts.map +1 -1
  7. package/dist/src/bridge/bridge-connection.js +159 -14
  8. package/dist/src/bridge/bridge-connection.js.map +1 -1
  9. package/dist/src/bridge/bridge-connection.test.js +81 -0
  10. package/dist/src/bridge/bridge-connection.test.js.map +1 -1
  11. package/dist/src/bridge/bridge-session.d.ts +35 -2
  12. package/dist/src/bridge/bridge-session.d.ts.map +1 -1
  13. package/dist/src/bridge/bridge-session.js +185 -28
  14. package/dist/src/bridge/bridge-session.js.map +1 -1
  15. package/dist/src/bridge/bridge-session.test.js +6 -4
  16. package/dist/src/bridge/bridge-session.test.js.map +1 -1
  17. package/dist/src/bridge/index.d.ts +1 -1
  18. package/dist/src/bridge/index.d.ts.map +1 -1
  19. package/dist/src/bridge/index.js.map +1 -1
  20. package/dist/src/bridge/internal/bridge-client.d.ts +4 -0
  21. package/dist/src/bridge/internal/bridge-client.d.ts.map +1 -1
  22. package/dist/src/bridge/internal/bridge-client.js +20 -7
  23. package/dist/src/bridge/internal/bridge-client.js.map +1 -1
  24. package/dist/src/bridge/internal/bridge-client.test.js +18 -0
  25. package/dist/src/bridge/internal/bridge-client.test.js.map +1 -1
  26. package/dist/src/bridge/internal/bridge-host.d.ts +13 -1
  27. package/dist/src/bridge/internal/bridge-host.d.ts.map +1 -1
  28. package/dist/src/bridge/internal/bridge-host.js +35 -0
  29. package/dist/src/bridge/internal/bridge-host.js.map +1 -1
  30. package/dist/src/bridge/internal/bridge-host.test.js +31 -0
  31. package/dist/src/bridge/internal/bridge-host.test.js.map +1 -1
  32. package/dist/src/bridge/internal/hand-off.d.ts.map +1 -1
  33. package/dist/src/bridge/internal/hand-off.js +4 -1
  34. package/dist/src/bridge/internal/hand-off.js.map +1 -1
  35. package/dist/src/bridge/internal/host-protocol.d.ts +8 -0
  36. package/dist/src/bridge/internal/host-protocol.d.ts.map +1 -1
  37. package/dist/src/bridge/internal/host-protocol.js +120 -13
  38. package/dist/src/bridge/internal/host-protocol.js.map +1 -1
  39. package/dist/src/bridge/internal/host-protocol.test.js +13 -0
  40. package/dist/src/bridge/internal/host-protocol.test.js.map +1 -1
  41. package/dist/src/bridge/internal/instance-state.d.ts +9 -0
  42. package/dist/src/bridge/internal/instance-state.d.ts.map +1 -0
  43. package/dist/src/bridge/internal/instance-state.js +28 -0
  44. package/dist/src/bridge/internal/instance-state.js.map +1 -0
  45. package/dist/src/bridge/internal/transport-client.d.ts.map +1 -1
  46. package/dist/src/bridge/internal/transport-client.js +2 -1
  47. package/dist/src/bridge/internal/transport-client.js.map +1 -1
  48. package/dist/src/bridge/internal/transport-server.d.ts.map +1 -1
  49. package/dist/src/bridge/internal/transport-server.js +5 -1
  50. package/dist/src/bridge/internal/transport-server.js.map +1 -1
  51. package/dist/src/bridge/types.d.ts +43 -4
  52. package/dist/src/bridge/types.d.ts.map +1 -1
  53. package/dist/src/bridge/types.js.map +1 -1
  54. package/dist/src/cli/adapters/cli-command-adapter-handler.test.js +24 -0
  55. package/dist/src/cli/adapters/cli-command-adapter-handler.test.js.map +1 -1
  56. package/dist/src/cli/adapters/cli-command-adapter.d.ts +6 -0
  57. package/dist/src/cli/adapters/cli-command-adapter.d.ts.map +1 -1
  58. package/dist/src/cli/adapters/cli-command-adapter.js +107 -11
  59. package/dist/src/cli/adapters/cli-command-adapter.js.map +1 -1
  60. package/dist/src/cli/adapters/group-builder.d.ts +3 -0
  61. package/dist/src/cli/adapters/group-builder.d.ts.map +1 -1
  62. package/dist/src/cli/adapters/group-builder.js +34 -15
  63. package/dist/src/cli/adapters/group-builder.js.map +1 -1
  64. package/dist/src/cli/adapters/group-builder.test.js +26 -2
  65. package/dist/src/cli/adapters/group-builder.test.js.map +1 -1
  66. package/dist/src/cli/adapters/help-formatter.d.ts.map +1 -1
  67. package/dist/src/cli/adapters/help-formatter.js +4 -3
  68. package/dist/src/cli/adapters/help-formatter.js.map +1 -1
  69. package/dist/src/cli/adapters/help-formatter.test.js +1 -1
  70. package/dist/src/cli/adapters/help-formatter.test.js.map +1 -1
  71. package/dist/src/cli/adapters/playtest-edit-guard.test.d.ts +2 -0
  72. package/dist/src/cli/adapters/playtest-edit-guard.test.d.ts.map +1 -0
  73. package/dist/src/cli/adapters/playtest-edit-guard.test.js +28 -0
  74. package/dist/src/cli/adapters/playtest-edit-guard.test.js.map +1 -0
  75. package/dist/src/cli/args/global-args.d.ts +1 -1
  76. package/dist/src/cli/args/global-args.d.ts.map +1 -1
  77. package/dist/src/cli/cli-output-context.d.ts +14 -0
  78. package/dist/src/cli/cli-output-context.d.ts.map +1 -0
  79. package/dist/src/cli/cli-output-context.js +39 -0
  80. package/dist/src/cli/cli-output-context.js.map +1 -0
  81. package/dist/src/cli/cli-output-context.test.d.ts +2 -0
  82. package/dist/src/cli/cli-output-context.test.d.ts.map +1 -0
  83. package/dist/src/cli/cli-output-context.test.js +38 -0
  84. package/dist/src/cli/cli-output-context.test.js.map +1 -0
  85. package/dist/src/cli/cli.js +40 -17
  86. package/dist/src/cli/cli.js.map +1 -1
  87. package/dist/src/cli/managed-studio-run.d.ts +21 -0
  88. package/dist/src/cli/managed-studio-run.d.ts.map +1 -0
  89. package/dist/src/cli/managed-studio-run.js +75 -0
  90. package/dist/src/cli/managed-studio-run.js.map +1 -0
  91. package/dist/src/cli/managed-studio-run.test.d.ts +2 -0
  92. package/dist/src/cli/managed-studio-run.test.d.ts.map +1 -0
  93. package/dist/src/cli/managed-studio-run.test.js +52 -0
  94. package/dist/src/cli/managed-studio-run.test.js.map +1 -0
  95. package/dist/src/cli/resolve-session.js +1 -1
  96. package/dist/src/cli/resolve-session.js.map +1 -1
  97. package/dist/src/cli/resolve-session.test.js +1 -1
  98. package/dist/src/cli/resolve-session.test.js.map +1 -1
  99. package/dist/src/cli/script-executor.d.ts +13 -1
  100. package/dist/src/cli/script-executor.d.ts.map +1 -1
  101. package/dist/src/cli/script-executor.js +77 -47
  102. package/dist/src/cli/script-executor.js.map +1 -1
  103. package/dist/src/commands/console/exec/exec.d.ts +17 -0
  104. package/dist/src/commands/console/exec/exec.d.ts.map +1 -1
  105. package/dist/src/commands/console/exec/exec.js +39 -7
  106. package/dist/src/commands/console/exec/exec.js.map +1 -1
  107. package/dist/src/commands/console/exec/exec.test.js +62 -3
  108. package/dist/src/commands/console/exec/exec.test.js.map +1 -1
  109. package/dist/src/commands/console/logs/logs.d.ts +30 -2
  110. package/dist/src/commands/console/logs/logs.d.ts.map +1 -1
  111. package/dist/src/commands/console/logs/logs.js +82 -7
  112. package/dist/src/commands/console/logs/logs.js.map +1 -1
  113. package/dist/src/commands/console/logs/logs.test.js +63 -4
  114. package/dist/src/commands/console/logs/logs.test.js.map +1 -1
  115. package/dist/src/commands/explorer/export/export.d.ts +19 -0
  116. package/dist/src/commands/explorer/export/export.d.ts.map +1 -0
  117. package/dist/src/commands/explorer/export/export.js +37 -0
  118. package/dist/src/commands/explorer/export/export.js.map +1 -0
  119. package/dist/src/commands/explorer/export/export.test.d.ts +2 -0
  120. package/dist/src/commands/explorer/export/export.test.d.ts.map +1 -0
  121. package/dist/src/commands/explorer/export/export.test.js +25 -0
  122. package/dist/src/commands/explorer/export/export.test.js.map +1 -0
  123. package/dist/src/commands/explorer/find/find.d.ts +28 -0
  124. package/dist/src/commands/explorer/find/find.d.ts.map +1 -0
  125. package/dist/src/commands/explorer/find/find.js +75 -0
  126. package/dist/src/commands/explorer/find/find.js.map +1 -0
  127. package/dist/src/commands/explorer/find/find.test.d.ts +2 -0
  128. package/dist/src/commands/explorer/find/find.test.d.ts.map +1 -0
  129. package/dist/src/commands/explorer/find/find.test.js +44 -0
  130. package/dist/src/commands/explorer/find/find.test.js.map +1 -0
  131. package/dist/src/commands/explorer/grep/grep.d.ts +24 -0
  132. package/dist/src/commands/explorer/grep/grep.d.ts.map +1 -0
  133. package/dist/src/commands/explorer/grep/grep.js +63 -0
  134. package/dist/src/commands/explorer/grep/grep.js.map +1 -0
  135. package/dist/src/commands/explorer/grep/grep.test.d.ts +2 -0
  136. package/dist/src/commands/explorer/grep/grep.test.d.ts.map +1 -0
  137. package/dist/src/commands/explorer/grep/grep.test.js +42 -0
  138. package/dist/src/commands/explorer/grep/grep.test.js.map +1 -0
  139. package/dist/src/commands/explorer/import/import.d.ts +21 -0
  140. package/dist/src/commands/explorer/import/import.d.ts.map +1 -0
  141. package/dist/src/commands/explorer/import/import.js +37 -0
  142. package/dist/src/commands/explorer/import/import.js.map +1 -0
  143. package/dist/src/commands/explorer/import/import.test.d.ts +2 -0
  144. package/dist/src/commands/explorer/import/import.test.d.ts.map +1 -0
  145. package/dist/src/commands/explorer/import/import.test.js +45 -0
  146. package/dist/src/commands/explorer/import/import.test.js.map +1 -0
  147. package/dist/src/commands/formatters.test.js +7 -1
  148. package/dist/src/commands/formatters.test.js.map +1 -1
  149. package/dist/src/commands/framework/action-loader.d.ts +5 -1
  150. package/dist/src/commands/framework/action-loader.d.ts.map +1 -1
  151. package/dist/src/commands/framework/action-loader.js +9 -2
  152. package/dist/src/commands/framework/action-loader.js.map +1 -1
  153. package/dist/src/commands/framework/action-loader.test.js +23 -0
  154. package/dist/src/commands/framework/action-loader.test.js.map +1 -1
  155. package/dist/src/commands/framework/arg-builder.d.ts +15 -2
  156. package/dist/src/commands/framework/arg-builder.d.ts.map +1 -1
  157. package/dist/src/commands/framework/arg-builder.js +22 -2
  158. package/dist/src/commands/framework/arg-builder.js.map +1 -1
  159. package/dist/src/commands/framework/define-command.d.ts +19 -3
  160. package/dist/src/commands/framework/define-command.d.ts.map +1 -1
  161. package/dist/src/commands/framework/define-command.js.map +1 -1
  162. package/dist/src/commands/framework/index.d.ts +1 -1
  163. package/dist/src/commands/framework/index.d.ts.map +1 -1
  164. package/dist/src/commands/framework/index.js.map +1 -1
  165. package/dist/src/commands/index.d.ts +11 -0
  166. package/dist/src/commands/index.d.ts.map +1 -1
  167. package/dist/src/commands/index.js +11 -0
  168. package/dist/src/commands/index.js.map +1 -1
  169. package/dist/src/commands/linux/inject-credentials/inject-credentials.d.ts.map +1 -1
  170. package/dist/src/commands/linux/inject-credentials/inject-credentials.js +1 -3
  171. package/dist/src/commands/linux/inject-credentials/inject-credentials.js.map +1 -1
  172. package/dist/src/commands/linux/setup/setup.d.ts.map +1 -1
  173. package/dist/src/commands/linux/setup/setup.js +1 -3
  174. package/dist/src/commands/linux/setup/setup.js.map +1 -1
  175. package/dist/src/commands/linux/status/status.d.ts +9 -1
  176. package/dist/src/commands/linux/status/status.d.ts.map +1 -1
  177. package/dist/src/commands/linux/status/status.js +66 -86
  178. package/dist/src/commands/linux/status/status.js.map +1 -1
  179. package/dist/src/commands/playtest/player/add/add.d.ts +17 -0
  180. package/dist/src/commands/playtest/player/add/add.d.ts.map +1 -0
  181. package/dist/src/commands/playtest/player/add/add.js +45 -0
  182. package/dist/src/commands/playtest/player/add/add.js.map +1 -0
  183. package/dist/src/commands/playtest/player/list/list.d.ts +13 -0
  184. package/dist/src/commands/playtest/player/list/list.d.ts.map +1 -0
  185. package/dist/src/commands/playtest/player/list/list.js +33 -0
  186. package/dist/src/commands/playtest/player/list/list.js.map +1 -0
  187. package/dist/src/commands/playtest/player/playtest-players.d.ts +36 -0
  188. package/dist/src/commands/playtest/player/playtest-players.d.ts.map +1 -0
  189. package/dist/src/commands/playtest/player/playtest-players.js +187 -0
  190. package/dist/src/commands/playtest/player/playtest-players.js.map +1 -0
  191. package/dist/src/commands/playtest/player/playtest-players.test.d.ts +2 -0
  192. package/dist/src/commands/playtest/player/playtest-players.test.d.ts.map +1 -0
  193. package/dist/src/commands/playtest/player/playtest-players.test.js +89 -0
  194. package/dist/src/commands/playtest/player/playtest-players.test.js.map +1 -0
  195. package/dist/src/commands/playtest/player/remove/remove.d.ts +17 -0
  196. package/dist/src/commands/playtest/player/remove/remove.d.ts.map +1 -0
  197. package/dist/src/commands/playtest/player/remove/remove.js +42 -0
  198. package/dist/src/commands/playtest/player/remove/remove.js.map +1 -0
  199. package/dist/src/commands/playtest/playtest-sessions.d.ts +49 -0
  200. package/dist/src/commands/playtest/playtest-sessions.d.ts.map +1 -0
  201. package/dist/src/commands/playtest/playtest-sessions.js +283 -0
  202. package/dist/src/commands/playtest/playtest-sessions.js.map +1 -0
  203. package/dist/src/commands/playtest/playtest-sessions.test.d.ts +2 -0
  204. package/dist/src/commands/playtest/playtest-sessions.test.d.ts.map +1 -0
  205. package/dist/src/commands/playtest/playtest-sessions.test.js +87 -0
  206. package/dist/src/commands/playtest/playtest-sessions.test.js.map +1 -0
  207. package/dist/src/commands/playtest/restart/restart.d.ts +23 -0
  208. package/dist/src/commands/playtest/restart/restart.d.ts.map +1 -0
  209. package/dist/src/commands/playtest/restart/restart.js +105 -0
  210. package/dist/src/commands/playtest/restart/restart.js.map +1 -0
  211. package/dist/src/commands/playtest/run/run.d.ts +47 -0
  212. package/dist/src/commands/playtest/run/run.d.ts.map +1 -0
  213. package/dist/src/commands/playtest/run/run.js +137 -0
  214. package/dist/src/commands/playtest/run/run.js.map +1 -0
  215. package/dist/src/commands/playtest/start/start.d.ts +42 -0
  216. package/dist/src/commands/playtest/start/start.d.ts.map +1 -0
  217. package/dist/src/commands/playtest/start/start.js +70 -0
  218. package/dist/src/commands/playtest/start/start.js.map +1 -0
  219. package/dist/src/commands/playtest/stop/stop.d.ts +15 -0
  220. package/dist/src/commands/playtest/stop/stop.d.ts.map +1 -0
  221. package/dist/src/commands/playtest/stop/stop.js +24 -0
  222. package/dist/src/commands/playtest/stop/stop.js.map +1 -0
  223. package/dist/src/commands/process/close/close.d.ts +19 -10
  224. package/dist/src/commands/process/close/close.d.ts.map +1 -1
  225. package/dist/src/commands/process/close/close.js +118 -15
  226. package/dist/src/commands/process/close/close.js.map +1 -1
  227. package/dist/src/commands/process/close/close.test.d.ts +2 -0
  228. package/dist/src/commands/process/close/close.test.d.ts.map +1 -0
  229. package/dist/src/commands/process/close/close.test.js +190 -0
  230. package/dist/src/commands/process/close/close.test.js.map +1 -0
  231. package/dist/src/commands/process/info/info.d.ts +45 -5
  232. package/dist/src/commands/process/info/info.d.ts.map +1 -1
  233. package/dist/src/commands/process/info/info.js +117 -13
  234. package/dist/src/commands/process/info/info.js.map +1 -1
  235. package/dist/src/commands/process/info/info.test.js +140 -38
  236. package/dist/src/commands/process/info/info.test.js.map +1 -1
  237. package/dist/src/commands/process/launch/launch.d.ts +11 -1
  238. package/dist/src/commands/process/launch/launch.d.ts.map +1 -1
  239. package/dist/src/commands/process/launch/launch.js +37 -7
  240. package/dist/src/commands/process/launch/launch.js.map +1 -1
  241. package/dist/src/commands/process/launch/launch.test.js +99 -20
  242. package/dist/src/commands/process/launch/launch.test.js.map +1 -1
  243. package/dist/src/commands/process/list/list.d.ts +2 -1
  244. package/dist/src/commands/process/list/list.d.ts.map +1 -1
  245. package/dist/src/commands/process/list/list.js +9 -6
  246. package/dist/src/commands/process/list/list.js.map +1 -1
  247. package/dist/src/commands/process/list/list.test.js +1 -0
  248. package/dist/src/commands/process/list/list.test.js.map +1 -1
  249. package/dist/src/commands/process/run/run.d.ts +9 -0
  250. package/dist/src/commands/process/run/run.d.ts.map +1 -1
  251. package/dist/src/commands/process/run/run.js +15 -5
  252. package/dist/src/commands/process/run/run.js.map +1 -1
  253. package/dist/src/commands/serve/serve.d.ts +2 -0
  254. package/dist/src/commands/serve/serve.d.ts.map +1 -1
  255. package/dist/src/commands/serve/serve.js +17 -4
  256. package/dist/src/commands/serve/serve.js.map +1 -1
  257. package/dist/src/commands/serve/serve.test.js +9 -2
  258. package/dist/src/commands/serve/serve.test.js.map +1 -1
  259. package/dist/src/commands/viewport/screenshot/screenshot.d.ts.map +1 -1
  260. package/dist/src/commands/viewport/screenshot/screenshot.js +4 -1
  261. package/dist/src/commands/viewport/screenshot/screenshot.js.map +1 -1
  262. package/dist/src/commands/viewport/screenshot/screenshot.test.js +5 -9
  263. package/dist/src/commands/viewport/screenshot/screenshot.test.js.map +1 -1
  264. package/dist/src/deploy/deploy-places.d.ts +39 -0
  265. package/dist/src/deploy/deploy-places.d.ts.map +1 -0
  266. package/dist/src/deploy/deploy-places.js +162 -0
  267. package/dist/src/deploy/deploy-places.js.map +1 -0
  268. package/dist/src/deploy/deploy-places.test.d.ts +2 -0
  269. package/dist/src/deploy/deploy-places.test.d.ts.map +1 -0
  270. package/dist/src/deploy/deploy-places.test.js +96 -0
  271. package/dist/src/deploy/deploy-places.test.js.map +1 -0
  272. package/dist/src/index.d.ts +2 -2
  273. package/dist/src/index.d.ts.map +1 -1
  274. package/dist/src/index.js +1 -1
  275. package/dist/src/index.js.map +1 -1
  276. package/dist/src/linux/linux-studio-launcher.d.ts.map +1 -1
  277. package/dist/src/linux/linux-studio-launcher.js +10 -0
  278. package/dist/src/linux/linux-studio-launcher.js.map +1 -1
  279. package/dist/src/linux/linux-studio-launcher.test.d.ts +2 -0
  280. package/dist/src/linux/linux-studio-launcher.test.d.ts.map +1 -0
  281. package/dist/src/linux/linux-studio-launcher.test.js +68 -0
  282. package/dist/src/linux/linux-studio-launcher.test.js.map +1 -0
  283. package/dist/src/plugin/persistent-plugin-installer.d.ts.map +1 -1
  284. package/dist/src/plugin/persistent-plugin-installer.js +2 -1
  285. package/dist/src/plugin/persistent-plugin-installer.js.map +1 -1
  286. package/dist/src/plugin/persistent-plugin-installer.test.js +3 -0
  287. package/dist/src/plugin/persistent-plugin-installer.test.js.map +1 -1
  288. package/dist/src/plugin/plugin-build-version.d.ts +7 -0
  289. package/dist/src/plugin/plugin-build-version.d.ts.map +1 -0
  290. package/dist/src/plugin/plugin-build-version.js +42 -0
  291. package/dist/src/plugin/plugin-build-version.js.map +1 -0
  292. package/dist/src/plugin/plugin-build-version.test.d.ts +2 -0
  293. package/dist/src/plugin/plugin-build-version.test.d.ts.map +1 -0
  294. package/dist/src/plugin/plugin-build-version.test.js +41 -0
  295. package/dist/src/plugin/plugin-build-version.test.js.map +1 -0
  296. package/dist/src/plugin/plugin-injector.d.ts.map +1 -1
  297. package/dist/src/plugin/plugin-injector.js +7 -1
  298. package/dist/src/plugin/plugin-injector.js.map +1 -1
  299. package/dist/src/process/studio-process-closer.d.ts +35 -0
  300. package/dist/src/process/studio-process-closer.d.ts.map +1 -0
  301. package/dist/src/process/studio-process-closer.js +129 -0
  302. package/dist/src/process/studio-process-closer.js.map +1 -0
  303. package/dist/src/process/studio-process-closer.test.d.ts +2 -0
  304. package/dist/src/process/studio-process-closer.test.d.ts.map +1 -0
  305. package/dist/src/process/studio-process-closer.test.js +80 -0
  306. package/dist/src/process/studio-process-closer.test.js.map +1 -0
  307. package/dist/src/process/studio-settings.d.ts +14 -0
  308. package/dist/src/process/studio-settings.d.ts.map +1 -0
  309. package/dist/src/process/studio-settings.js +50 -0
  310. package/dist/src/process/studio-settings.js.map +1 -0
  311. package/dist/src/process/studio-settings.test.d.ts +2 -0
  312. package/dist/src/process/studio-settings.test.d.ts.map +1 -0
  313. package/dist/src/process/studio-settings.test.js +16 -0
  314. package/dist/src/process/studio-settings.test.js.map +1 -0
  315. package/dist/src/process/studio-window-state.d.ts +13 -0
  316. package/dist/src/process/studio-window-state.d.ts.map +1 -0
  317. package/dist/src/process/studio-window-state.js +48 -0
  318. package/dist/src/process/studio-window-state.js.map +1 -0
  319. package/dist/src/server/studio-bridge-server.d.ts +3 -1
  320. package/dist/src/server/studio-bridge-server.d.ts.map +1 -1
  321. package/dist/src/server/studio-bridge-server.js +12 -4
  322. package/dist/src/server/studio-bridge-server.js.map +1 -1
  323. package/dist/src/server/web-socket-protocol.d.ts +173 -6
  324. package/dist/src/server/web-socket-protocol.d.ts.map +1 -1
  325. package/dist/src/server/web-socket-protocol.js +244 -1
  326. package/dist/src/server/web-socket-protocol.js.map +1 -1
  327. package/dist/src/server/web-socket-protocol.test.js +48 -0
  328. package/dist/src/server/web-socket-protocol.test.js.map +1 -1
  329. package/dist/src/test/e2e/persistent-session.test.js +121 -0
  330. package/dist/src/test/e2e/persistent-session.test.js.map +1 -1
  331. package/dist/src/test/e2e/split-server.test.d.ts +3 -5
  332. package/dist/src/test/e2e/split-server.test.d.ts.map +1 -1
  333. package/dist/src/test/e2e/split-server.test.js +3 -5
  334. package/dist/src/test/e2e/split-server.test.js.map +1 -1
  335. package/dist/tsconfig.tsbuildinfo +1 -1
  336. package/docker/Dockerfile +3 -0
  337. package/package.json +8 -6
  338. package/src/bridge/bridge-connection.test.ts +126 -0
  339. package/src/bridge/bridge-connection.ts +217 -22
  340. package/src/bridge/bridge-session.test.ts +6 -4
  341. package/src/bridge/bridge-session.ts +273 -28
  342. package/src/bridge/index.ts +3 -0
  343. package/src/bridge/internal/bridge-client.test.ts +23 -0
  344. package/src/bridge/internal/bridge-client.ts +25 -7
  345. package/src/bridge/internal/bridge-host.test.ts +38 -0
  346. package/src/bridge/internal/bridge-host.ts +47 -0
  347. package/src/bridge/internal/hand-off.ts +4 -1
  348. package/src/bridge/internal/host-protocol.test.ts +15 -0
  349. package/src/bridge/internal/host-protocol.ts +148 -37
  350. package/src/bridge/internal/instance-state.ts +34 -0
  351. package/src/bridge/internal/transport-client.ts +2 -1
  352. package/src/bridge/internal/transport-server.ts +5 -1
  353. package/src/bridge/types.ts +47 -2
  354. package/src/cli/adapters/cli-command-adapter-handler.test.ts +28 -0
  355. package/src/cli/adapters/cli-command-adapter.ts +150 -18
  356. package/src/cli/adapters/group-builder.test.ts +34 -2
  357. package/src/cli/adapters/group-builder.ts +52 -20
  358. package/src/cli/adapters/help-formatter.test.ts +1 -1
  359. package/src/cli/adapters/help-formatter.ts +4 -3
  360. package/src/cli/adapters/playtest-edit-guard.test.ts +54 -0
  361. package/src/cli/args/global-args.ts +1 -1
  362. package/src/cli/cli-output-context.test.ts +55 -0
  363. package/src/cli/cli-output-context.ts +50 -0
  364. package/src/cli/cli.ts +49 -17
  365. package/src/cli/managed-studio-run.test.ts +71 -0
  366. package/src/cli/managed-studio-run.ts +135 -0
  367. package/src/cli/resolve-session.test.ts +1 -1
  368. package/src/cli/resolve-session.ts +1 -1
  369. package/src/cli/script-executor.ts +99 -51
  370. package/src/commands/console/exec/exec.test.ts +96 -3
  371. package/src/commands/console/exec/exec.ts +59 -6
  372. package/src/commands/console/exec/execute.lua +356 -240
  373. package/src/commands/console/exec/execute.spec.lua +286 -0
  374. package/src/commands/console/logs/logs.test.ts +76 -4
  375. package/src/commands/console/logs/logs.ts +132 -17
  376. package/src/commands/console/logs/query-logs.lua +85 -52
  377. package/src/commands/console/logs/query-logs.spec.lua +132 -0
  378. package/src/commands/explorer/export/export-instances.lua +108 -0
  379. package/src/commands/explorer/export/export-instances.spec.lua +87 -0
  380. package/src/commands/explorer/export/export.test.ts +27 -0
  381. package/src/commands/explorer/export/export.ts +60 -0
  382. package/src/commands/explorer/find/find-instances.lua +174 -0
  383. package/src/commands/explorer/find/find-instances.spec.lua +122 -0
  384. package/src/commands/explorer/find/find.test.ts +53 -0
  385. package/src/commands/explorer/find/find.ts +113 -0
  386. package/src/commands/explorer/grep/grep-scripts.lua +214 -0
  387. package/src/commands/explorer/grep/grep-scripts.spec.lua +130 -0
  388. package/src/commands/explorer/grep/grep.test.ts +45 -0
  389. package/src/commands/explorer/grep/grep.ts +93 -0
  390. package/src/commands/explorer/import/import-instances.lua +106 -0
  391. package/src/commands/explorer/import/import-instances.spec.lua +84 -0
  392. package/src/commands/explorer/import/import.test.ts +60 -0
  393. package/src/commands/explorer/import/import.ts +66 -0
  394. package/src/commands/explorer/query/query-data-model.lua +124 -152
  395. package/src/commands/explorer/query/query-data-model.spec.lua +150 -0
  396. package/src/commands/formatters.test.ts +7 -1
  397. package/src/commands/framework/action-loader.test.ts +28 -0
  398. package/src/commands/framework/action-loader.ts +10 -2
  399. package/src/commands/framework/arg-builder.ts +26 -3
  400. package/src/commands/framework/define-command.ts +32 -3
  401. package/src/commands/framework/index.ts +1 -0
  402. package/src/commands/index.ts +50 -0
  403. package/src/commands/linux/inject-credentials/inject-credentials.ts +1 -3
  404. package/src/commands/linux/setup/setup.ts +1 -3
  405. package/src/commands/linux/status/status.ts +105 -98
  406. package/src/commands/playtest/player/add/add.ts +85 -0
  407. package/src/commands/playtest/player/list/list.ts +57 -0
  408. package/src/commands/playtest/player/playtest-players.test.ts +146 -0
  409. package/src/commands/playtest/player/playtest-players.ts +270 -0
  410. package/src/commands/playtest/player/remove/remove.ts +78 -0
  411. package/src/commands/playtest/playtest-sessions.test.ts +143 -0
  412. package/src/commands/playtest/playtest-sessions.ts +417 -0
  413. package/src/commands/playtest/restart/restart.ts +199 -0
  414. package/src/commands/playtest/run/playtest-runner.luau +264 -0
  415. package/src/commands/playtest/run/playtest-runner.spec.lua +71 -0
  416. package/src/commands/playtest/run/run-playtest-script.lua +139 -0
  417. package/src/commands/playtest/run/run-playtest-script.spec.lua +43 -0
  418. package/src/commands/playtest/run/run.ts +239 -0
  419. package/src/commands/playtest/start/start-playtest.lua +108 -0
  420. package/src/commands/playtest/start/start.ts +138 -0
  421. package/src/commands/playtest/stop/end-playtest.lua +47 -0
  422. package/src/commands/playtest/stop/stop.ts +51 -0
  423. package/src/commands/process/close/close.test.ts +250 -0
  424. package/src/commands/process/close/close.ts +183 -17
  425. package/src/commands/process/info/info.test.ts +198 -44
  426. package/src/commands/process/info/info.ts +204 -15
  427. package/src/commands/process/info/query-state.lua +42 -29
  428. package/src/commands/process/info/query-state.spec.lua +39 -0
  429. package/src/commands/process/launch/launch.test.ts +138 -21
  430. package/src/commands/process/launch/launch.ts +69 -9
  431. package/src/commands/process/list/list.test.ts +1 -0
  432. package/src/commands/process/list/list.ts +14 -6
  433. package/src/commands/process/run/run.ts +26 -5
  434. package/src/commands/serve/serve.test.ts +17 -2
  435. package/src/commands/serve/serve.ts +25 -6
  436. package/src/commands/viewport/screenshot/capture-screenshot.lua +175 -182
  437. package/src/commands/viewport/screenshot/capture-screenshot.spec.lua +129 -0
  438. package/src/commands/viewport/screenshot/screenshot.test.ts +7 -10
  439. package/src/commands/viewport/screenshot/screenshot.ts +6 -1
  440. package/src/deploy/deploy-places.test.ts +127 -0
  441. package/src/deploy/deploy-places.ts +229 -0
  442. package/src/index.ts +11 -0
  443. package/src/linux/linux-studio-launcher.test.ts +89 -0
  444. package/src/linux/linux-studio-launcher.ts +11 -0
  445. package/src/plugin/persistent-plugin-installer.test.ts +4 -0
  446. package/src/plugin/persistent-plugin-installer.ts +2 -1
  447. package/src/plugin/plugin-build-version.test.ts +55 -0
  448. package/src/plugin/plugin-build-version.ts +53 -0
  449. package/src/plugin/plugin-injector.ts +7 -1
  450. package/src/process/studio-process-closer.test.ts +107 -0
  451. package/src/process/studio-process-closer.ts +187 -0
  452. package/src/process/studio-settings.test.ts +18 -0
  453. package/src/process/studio-settings.ts +61 -0
  454. package/src/process/studio-window-state.ts +65 -0
  455. package/src/server/studio-bridge-server.ts +15 -4
  456. package/src/server/web-socket-protocol.test.ts +55 -0
  457. package/src/server/web-socket-protocol.ts +468 -8
  458. package/src/test/e2e/persistent-session.test.ts +137 -0
  459. package/src/test/e2e/split-server.test.ts +3 -5
  460. package/templates/studio-bridge-plugin/default.project.json +3 -0
  461. package/templates/studio-bridge-plugin/src/Shared/ActionRouter.lua +208 -159
  462. package/templates/studio-bridge-plugin/src/Shared/ActionRouter.spec.lua +418 -0
  463. package/templates/studio-bridge-plugin/src/Shared/BuiltInActions.lua +94 -0
  464. package/templates/studio-bridge-plugin/src/Shared/BuiltInActions.spec.lua +166 -0
  465. package/templates/studio-bridge-plugin/src/Shared/DiscoveryStateMachine.lua +118 -137
  466. package/templates/studio-bridge-plugin/src/Shared/DiscoveryStateMachine.spec.lua +228 -0
  467. package/templates/studio-bridge-plugin/src/Shared/MessageBuffer.lua +80 -109
  468. package/templates/studio-bridge-plugin/src/Shared/MessageBuffer.spec.lua +116 -0
  469. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeConnection.lua +233 -0
  470. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeConnection.spec.lua +239 -0
  471. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeLogUtils.lua +53 -0
  472. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeLogUtils.spec.lua +27 -0
  473. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeSessionUtils.lua +164 -0
  474. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeSessionUtils.spec.lua +159 -0
  475. package/templates/studio-bridge-plugin/src/StudioBridgePlugin.server.lua +266 -368
  476. package/templates/studio-bridge-plugin/src/Vendor/png.lua +8 -2
  477. package/test/default.project.json +41 -0
  478. package/test/jest.config.lua +3 -0
  479. package/test/scripts/Server/ServerMain.server.lua +10 -0
  480. package/tsconfig.json +1 -0
  481. package/templates/studio-bridge-plugin/src/Shared/Protocol.lua +0 -132
  482. package/templates/studio-bridge-plugin-test/test/actions.test.lua +0 -580
  483. package/templates/studio-bridge-plugin-test/test/discovery.test.lua +0 -622
  484. package/templates/studio-bridge-plugin-test/test/execute-handler.test.lua +0 -517
  485. package/templates/studio-bridge-plugin-test/test/hash-lifecycle.test.lua +0 -814
  486. package/templates/studio-bridge-plugin-test/test/integration.test.lua +0 -1020
  487. package/templates/studio-bridge-plugin-test/test/new-actions.test.lua +0 -339
  488. package/templates/studio-bridge-plugin-test/test/plugin-entry.test.lua +0 -493
  489. package/templates/studio-bridge-plugin-test/test/protocol.test.lua +0 -506
  490. package/templates/studio-bridge-plugin-test/test/roblox-mocks.lua +0 -108
  491. package/templates/studio-bridge-plugin-test/test/test-runner.lua +0 -112
@@ -2,7 +2,10 @@
2
2
  * Unit tests for the launch command handler.
3
3
  */
4
4
 
5
- import { describe, it, expect, vi } from 'vitest';
5
+ import * as fs from 'fs/promises';
6
+ import * as os from 'os';
7
+ import * as path from 'path';
8
+ import { afterEach, beforeEach, describe, it, expect, vi } from 'vitest';
6
9
 
7
10
  // Mock the process manager before importing the handler
8
11
  vi.mock('../../../process/studio-process-manager.js', () => ({
@@ -15,11 +18,36 @@ vi.mock('../../../process/studio-process-manager.js', () => ({
15
18
  import { launchHandlerAsync } from './launch.js';
16
19
  import { launchStudioAsync } from '../../../process/studio-process-manager.js';
17
20
 
21
+ let tempDir: string;
22
+
23
+ beforeEach(async () => {
24
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'launch-test-'));
25
+ vi.mocked(launchStudioAsync).mockClear();
26
+ });
27
+
28
+ afterEach(async () => {
29
+ await fs.rm(tempDir, { recursive: true, force: true });
30
+ });
31
+
32
+ async function writeDeployConfigAsync(dir: string, config: unknown) {
33
+ await fs.writeFile(
34
+ path.join(dir, 'deploy.nevermore.json'),
35
+ JSON.stringify(config)
36
+ );
37
+ }
38
+
39
+ const place = (placeId: number, name?: string) => ({
40
+ name,
41
+ universeId: 900,
42
+ placeId,
43
+ project: 'default.project.json',
44
+ });
45
+
18
46
  describe('launchHandlerAsync', () => {
19
- it('calls launchStudioAsync and returns result', async () => {
20
- const result = await launchHandlerAsync();
47
+ it('launches a bare Studio outside any deploy.nevermore.json', async () => {
48
+ const result = await launchHandlerAsync({ cwd: tempDir });
21
49
 
22
- expect(launchStudioAsync).toHaveBeenCalled();
50
+ expect(launchStudioAsync).toHaveBeenCalledWith({});
23
51
  expect(result.launched).toBe(true);
24
52
  expect(result.summary).toBe('Studio launched');
25
53
  });
@@ -27,12 +55,12 @@ describe('launchHandlerAsync', () => {
27
55
  it('passes place path to launchStudioAsync', async () => {
28
56
  const result = await launchHandlerAsync({
29
57
  placePath: '/tmp/game.rbxl',
58
+ cwd: tempDir,
30
59
  });
31
60
 
32
61
  expect(launchStudioAsync).toHaveBeenCalledWith({
33
62
  placePath: '/tmp/game.rbxl',
34
63
  });
35
- expect(result.launched).toBe(true);
36
64
  expect(result.summary).toBe('Studio launched with /tmp/game.rbxl');
37
65
  });
38
66
 
@@ -40,6 +68,7 @@ describe('launchHandlerAsync', () => {
40
68
  const result = await launchHandlerAsync({
41
69
  placeId: 84760113521251,
42
70
  universeId: 9893751595,
71
+ cwd: tempDir,
43
72
  });
44
73
 
45
74
  expect(launchStudioAsync).toHaveBeenCalledWith({
@@ -52,37 +81,125 @@ describe('launchHandlerAsync', () => {
52
81
  });
53
82
 
54
83
  it('summarizes a cloud place id without a universe id', async () => {
55
- const result = await launchHandlerAsync({ placeId: 123 });
84
+ const result = await launchHandlerAsync({ placeId: 123, cwd: tempDir });
56
85
 
57
86
  expect(result.summary).toBe('Studio launched with place 123');
58
87
  });
59
88
 
60
- it('passes an empty options object when nothing is specified', async () => {
61
- await launchHandlerAsync({});
89
+ it('propagates errors from launchStudioAsync', async () => {
90
+ vi.mocked(launchStudioAsync).mockRejectedValueOnce(
91
+ new Error('Studio not found')
92
+ );
62
93
 
63
- expect(launchStudioAsync).toHaveBeenCalledWith({});
94
+ await expect(launchHandlerAsync({ cwd: tempDir })).rejects.toThrow(
95
+ 'Studio not found'
96
+ );
64
97
  });
98
+ });
65
99
 
66
- it('returns correct summary without place path', async () => {
67
- const result = await launchHandlerAsync({});
100
+ describe('launchHandlerAsync with deploy.nevermore.json', () => {
101
+ it("opens the default target's place from a parent directory's config", async () => {
102
+ await writeDeployConfigAsync(tempDir, { targets: { test: place(111) } });
103
+ const nested = path.join(tempDir, 'src', 'Server');
104
+ await fs.mkdir(nested, { recursive: true });
68
105
 
106
+ const result = await launchHandlerAsync({ cwd: nested });
107
+
108
+ expect(launchStudioAsync).toHaveBeenCalledWith({
109
+ placeId: 111,
110
+ universeId: 900,
111
+ });
112
+ expect(result).toMatchObject({
113
+ deployTarget: 'test',
114
+ placeId: 111,
115
+ universeId: 900,
116
+ });
117
+ expect(result.summary).toBe(
118
+ `Studio launched with 'test' (place 111, universe 900) from ${path.join(
119
+ '..',
120
+ '..',
121
+ 'deploy.nevermore.json'
122
+ )}`
123
+ );
124
+ });
125
+
126
+ it('opens a named target and narrows to one of its places', async () => {
127
+ await writeDeployConfigAsync(tempDir, {
128
+ targets: {
129
+ test: place(111),
130
+ integration: { places: [place(222, 'hub'), place(333, 'arena')] },
131
+ },
132
+ });
133
+
134
+ const result = await launchHandlerAsync({
135
+ deployTarget: 'integration.places.arena',
136
+ cwd: tempDir,
137
+ });
138
+
139
+ expect(launchStudioAsync).toHaveBeenCalledWith({
140
+ placeId: 333,
141
+ universeId: 900,
142
+ });
143
+ expect(result.deployTarget).toBe('integration.places.arena');
144
+ });
145
+
146
+ it('asks which place to open for a target with several', async () => {
147
+ await writeDeployConfigAsync(tempDir, {
148
+ targets: {
149
+ integration: { places: [place(222, 'hub'), place(333, 'arena')] },
150
+ },
151
+ });
152
+
153
+ await expect(
154
+ launchHandlerAsync({ deployTarget: 'integration', cwd: tempDir })
155
+ ).rejects.toThrow(
156
+ "Target 'integration' has 2 places. Pick one:\n - integration.places.hub\n - integration.places.arena"
157
+ );
158
+ expect(launchStudioAsync).not.toHaveBeenCalled();
159
+ });
160
+
161
+ it('skips a config without targets, like a repo root universe id', async () => {
162
+ await writeDeployConfigAsync(tempDir, { universeId: 900 });
163
+
164
+ const result = await launchHandlerAsync({ cwd: tempDir });
165
+
166
+ expect(launchStudioAsync).toHaveBeenCalledWith({});
69
167
  expect(result.summary).toBe('Studio launched');
70
168
  });
71
169
 
72
- it('propagates errors from launchStudioAsync', async () => {
73
- vi.mocked(launchStudioAsync).mockRejectedValueOnce(
74
- new Error('Studio not found')
170
+ it('asks for a target when the config has no default', async () => {
171
+ await writeDeployConfigAsync(tempDir, {
172
+ targets: { alpha: place(1), beta: place(2) },
173
+ });
174
+
175
+ await expect(launchHandlerAsync({ cwd: tempDir })).rejects.toThrow(
176
+ 'has several targets and no default. Name one: alpha, beta'
75
177
  );
178
+ });
76
179
 
77
- await expect(launchHandlerAsync()).rejects.toThrow('Studio not found');
180
+ it('fails on a target when no deploy.nevermore.json is found', async () => {
181
+ await expect(
182
+ launchHandlerAsync({ deployTarget: 'test', cwd: tempDir })
183
+ ).rejects.toThrow(/No deploy.nevermore.json in .* to find target 'test'/);
78
184
  });
79
185
 
80
- it('result shape matches LaunchResult interface', async () => {
81
- const result = await launchHandlerAsync();
186
+ it('refuses a target together with --place', async () => {
187
+ await expect(
188
+ launchHandlerAsync({
189
+ deployTarget: 'test',
190
+ placePath: '/tmp/game.rbxl',
191
+ cwd: tempDir,
192
+ })
193
+ ).rejects.toThrow('not both');
194
+ });
195
+
196
+ it('prefers an explicit --place over the config', async () => {
197
+ await writeDeployConfigAsync(tempDir, { targets: { test: place(111) } });
198
+
199
+ await launchHandlerAsync({ placePath: '/tmp/game.rbxl', cwd: tempDir });
82
200
 
83
- expect(result).toHaveProperty('launched');
84
- expect(result).toHaveProperty('summary');
85
- expect(typeof result.launched).toBe('boolean');
86
- expect(typeof result.summary).toBe('string');
201
+ expect(launchStudioAsync).toHaveBeenCalledWith({
202
+ placePath: '/tmp/game.rbxl',
203
+ });
87
204
  });
88
205
  });
@@ -1,39 +1,92 @@
1
1
  /**
2
- * `process launch` — launch Roblox Studio, optionally with a place file.
2
+ * `process launch` — launch Roblox Studio, optionally with a place file, a
3
+ * cloud place, or a target from the nearest `deploy.nevermore.json`.
3
4
  */
4
5
 
6
+ import * as path from 'path';
5
7
  import { defineCommand } from '../../framework/define-command.js';
6
8
  import { arg } from '../../framework/arg-builder.js';
7
9
  import { launchStudioAsync } from '../../../process/studio-process-manager.js';
10
+ import {
11
+ DEPLOY_CONFIG_FILE_NAME,
12
+ resolveDeployPlaceAsync,
13
+ } from '../../../deploy/deploy-places.js';
8
14
 
9
15
  export interface LaunchOptions {
10
16
  placePath?: string;
11
17
  placeId?: number;
12
18
  universeId?: number;
19
+ /** A `deploy.nevermore.json` target, e.g. `test` or `integration.places.hub`. */
20
+ deployTarget?: string;
21
+ /** Where to start looking for `deploy.nevermore.json`. Default: the current directory. */
22
+ cwd?: string;
13
23
  }
14
24
 
15
25
  export interface LaunchResult {
16
26
  launched: boolean;
27
+ /** The `deploy.nevermore.json` target that was opened, if any. */
28
+ deployTarget?: string;
29
+ placeId?: number;
30
+ universeId?: number;
17
31
  summary: string;
18
32
  }
19
33
 
20
34
  export async function launchHandlerAsync(
21
35
  options: LaunchOptions = {}
22
36
  ): Promise<LaunchResult> {
23
- await launchStudioAsync(options);
24
- const target =
25
- options.placeId != null
26
- ? `place ${options.placeId}${
27
- options.universeId != null ? ` (universe ${options.universeId})` : ''
37
+ const hasExplicitPlace =
38
+ options.placePath !== undefined || options.placeId !== undefined;
39
+ if (hasExplicitPlace && options.deployTarget !== undefined) {
40
+ throw new Error(
41
+ `Pass a deploy target or --place / --place-id, not both (got '${options.deployTarget}')`
42
+ );
43
+ }
44
+
45
+ const deployPlace = hasExplicitPlace
46
+ ? undefined
47
+ : await resolveDeployPlaceAsync(
48
+ options.cwd ?? process.cwd(),
49
+ options.deployTarget
50
+ );
51
+ if (deployPlace) {
52
+ const { placeId, universeId } = deployPlace.place;
53
+ await launchStudioAsync({ placeId, universeId });
54
+ const configDir = path.relative(
55
+ options.cwd ?? process.cwd(),
56
+ path.dirname(deployPlace.configPath)
57
+ );
58
+ return {
59
+ launched: true,
60
+ deployTarget: deployPlace.selector,
61
+ placeId,
62
+ universeId,
63
+ summary: `Studio launched with '${
64
+ deployPlace.selector
65
+ }' (place ${placeId}, universe ${universeId}) from ${path.join(
66
+ configDir,
67
+ DEPLOY_CONFIG_FILE_NAME
68
+ )}`,
69
+ };
70
+ }
71
+
72
+ const { placePath, placeId, universeId } = options;
73
+ await launchStudioAsync({ placePath, placeId, universeId });
74
+ const opened =
75
+ placeId != null
76
+ ? `place ${placeId}${
77
+ universeId != null ? ` (universe ${universeId})` : ''
28
78
  }`
29
- : options.placePath;
79
+ : placePath;
30
80
  return {
31
81
  launched: true,
32
- summary: `Studio launched${target ? ` with ${target}` : ''}`,
82
+ placeId,
83
+ universeId,
84
+ summary: `Studio launched${opened ? ` with ${opened}` : ''}`,
33
85
  };
34
86
  }
35
87
 
36
88
  interface LaunchArgs {
89
+ deployTarget?: string;
37
90
  place?: string;
38
91
  placeId?: number;
39
92
  universeId?: number;
@@ -42,11 +95,17 @@ interface LaunchArgs {
42
95
  export const launchCommand = defineCommand<LaunchArgs, LaunchResult>({
43
96
  group: 'process',
44
97
  name: 'launch',
45
- description: 'Launch Roblox Studio',
98
+ description:
99
+ "Launch Roblox Studio, by default with the place of the nearest deploy.nevermore.json's default target",
46
100
  category: 'infrastructure',
47
101
  safety: 'none',
48
102
  scope: 'standalone',
49
103
  args: {
104
+ deployTarget: arg.positional({
105
+ description:
106
+ 'deploy.nevermore.json target to open, e.g. test or integration.places.hub (default: its default target)',
107
+ required: false,
108
+ }),
50
109
  place: arg.option({ description: 'Path to a .rbxl place file' }),
51
110
  placeId: arg.option({
52
111
  description:
@@ -61,6 +120,7 @@ export const launchCommand = defineCommand<LaunchArgs, LaunchResult>({
61
120
  },
62
121
  handler: async (args) =>
63
122
  launchHandlerAsync({
123
+ deployTarget: args.deployTarget,
64
124
  placePath: args.place,
65
125
  placeId: args.placeId,
66
126
  universeId: args.universeId,
@@ -26,6 +26,7 @@ function createSessionInfo(overrides: Partial<SessionInfo> = {}): SessionInfo {
26
26
  function createMockConnection(sessions: SessionInfo[]) {
27
27
  return {
28
28
  listSessions: () => sessions,
29
+ findSessions: () => sessions,
29
30
  getSession: (id: string) => sessions.find((s) => s.sessionId === id),
30
31
  } as any;
31
32
  }
@@ -2,7 +2,10 @@
2
2
  * `process list` — list connected Studio sessions.
3
3
  */
4
4
 
5
- import { defineCommand } from '../../framework/define-command.js';
5
+ import {
6
+ defineCommand,
7
+ type SessionTargeting,
8
+ } from '../../framework/define-command.js';
6
9
  import { OutputHelper } from '@quenty/cli-output-helpers';
7
10
  import {
8
11
  formatTable,
@@ -22,15 +25,18 @@ export interface SessionsResult {
22
25
  * List all connected Studio sessions with a summary message.
23
26
  */
24
27
  export async function listSessionsHandlerAsync(
25
- connection: BridgeConnection
28
+ connection: BridgeConnection,
29
+ targeting: SessionTargeting = {}
26
30
  ): Promise<SessionsResult> {
27
- const sessions = connection.listSessions();
31
+ const sessions = connection.findSessions(targeting.target, targeting.context);
28
32
 
29
33
  if (sessions.length === 0) {
30
34
  return {
31
35
  sessions: [],
32
36
  summary:
33
- 'No active sessions. Is Studio running with the studio-bridge plugin?',
37
+ connection.listSessions().length > 0
38
+ ? 'No sessions match --target/--context.'
39
+ : 'No active sessions. Is Studio running with the studio-bridge plugin?',
34
40
  };
35
41
  }
36
42
 
@@ -43,7 +49,7 @@ export async function listSessionsHandlerAsync(
43
49
  const sessionColumns: TableColumn<SessionInfo>[] = [
44
50
  {
45
51
  header: 'Session',
46
- value: (s) => s.sessionId.slice(0, 8),
52
+ value: (s) => s.sessionId,
47
53
  format: (v) => OutputHelper.formatHint(v),
48
54
  },
49
55
  { header: 'Context', value: (s) => s.context },
@@ -67,9 +73,11 @@ export const listCommand = defineCommand({
67
73
  category: 'infrastructure',
68
74
  safety: 'read',
69
75
  scope: 'connection',
76
+ coversAllSessions: true,
70
77
  args: {},
71
78
  cli: {
72
79
  format: formatSessionsTable,
73
80
  },
74
- handler: async (connection) => listSessionsHandlerAsync(connection),
81
+ handler: async (connection, _args, targeting) =>
82
+ listSessionsHandlerAsync(connection, targeting),
75
83
  });
@@ -11,6 +11,9 @@ import { OutputHelper } from '@quenty/cli-output-helpers';
11
11
  import { defineCommand } from '../../framework/define-command.js';
12
12
  import { arg } from '../../framework/arg-builder.js';
13
13
  import { resolveScriptContentAsync } from '../../../cli/resolve-script-content.js';
14
+ import { isJsonOutputEnabled } from '../../../cli/cli-output-context.js';
15
+ import { formatReturnValues } from '../../console/exec/exec.js';
16
+ import type { SerializedReturnValue } from '../../../server/web-socket-protocol.js';
14
17
 
15
18
  export interface ProcessRunOptions {
16
19
  scriptContent: string;
@@ -20,10 +23,17 @@ export interface ProcessRunOptions {
20
23
  verbose: boolean;
21
24
  showLogs: boolean;
22
25
  filePath?: string;
26
+ quiet?: boolean;
27
+ /** Passed to the script as `...`. */
28
+ args?: string[];
23
29
  }
24
30
 
25
31
  export interface ProcessRunResult {
26
32
  success: boolean;
33
+ output: string[];
34
+ error?: string;
35
+ returnValues?: SerializedReturnValue[];
36
+ durationMs: number;
27
37
  summary: string;
28
38
  }
29
39
 
@@ -32,6 +42,7 @@ interface ProcessRunArgs {
32
42
  file?: string;
33
43
  place?: string;
34
44
  timeout?: number;
45
+ scriptArgs?: string[];
35
46
  }
36
47
 
37
48
  export async function processRunHandlerAsync(
@@ -42,13 +53,11 @@ export async function processRunHandlerAsync(
42
53
  '../../../cli/script-executor.js'
43
54
  );
44
55
 
45
- // executeScriptAsync calls process.exit internally, so this return
46
- // is only reachable in test scenarios where it's mocked.
47
- await executeScriptAsync(options);
56
+ const result = await executeScriptAsync(options);
48
57
 
49
58
  return {
50
- success: true,
51
- summary: 'Script execution completed.',
59
+ ...result,
60
+ summary: result.success ? 'Script completed.' : 'Script failed.',
52
61
  };
53
62
  }
54
63
 
@@ -80,6 +89,16 @@ export const processRunCommand = defineCommand<
80
89
  description: 'Execution timeout in milliseconds',
81
90
  type: 'number',
82
91
  }),
92
+ scriptArgs: arg.passthrough({
93
+ description:
94
+ 'Arguments after --, passed to the script as ... (all strings)',
95
+ }),
96
+ },
97
+ cli: {
98
+ format: (result) =>
99
+ result.returnValues && result.returnValues.length > 0
100
+ ? formatReturnValues(result.returnValues)
101
+ : '',
83
102
  },
84
103
  handler: async (args) => {
85
104
  const { scriptContent, filePath } = await resolveScriptContentAsync(args);
@@ -92,6 +111,8 @@ export const processRunCommand = defineCommand<
92
111
  verbose: OutputHelper.isVerbose(),
93
112
  showLogs: true,
94
113
  filePath,
114
+ quiet: isJsonOutputEnabled(),
115
+ args: args.scriptArgs,
95
116
  });
96
117
  },
97
118
  // No MCP config -- process run is CLI-only
@@ -17,14 +17,19 @@ vi.mock('../../bridge/index.js', () => {
17
17
  import { BridgeConnection } from '../../bridge/index.js';
18
18
  import { serveHandlerAsync } from './serve.js';
19
19
 
20
- function createMockConnection(port: number): EventEmitter & {
20
+ function createMockConnection(
21
+ port: number,
22
+ role: 'host' | 'client' = 'host'
23
+ ): EventEmitter & {
21
24
  disconnectAsync: ReturnType<typeof vi.fn>;
22
25
  port: number;
26
+ role: 'host' | 'client';
23
27
  } {
24
28
  const emitter = new EventEmitter();
25
29
  return Object.assign(emitter, {
26
30
  disconnectAsync: vi.fn().mockResolvedValue(undefined),
27
31
  port,
32
+ role,
28
33
  });
29
34
  }
30
35
 
@@ -86,6 +91,16 @@ describe('serveHandlerAsync', () => {
86
91
  );
87
92
  });
88
93
 
94
+ it('exits instead of lingering as a client when a host already runs', async () => {
95
+ mockConnection = createMockConnection(38741, 'client');
96
+ connectAsyncMock.mockResolvedValue(mockConnection);
97
+
98
+ await expect(serveHandlerAsync({ port: 38741 })).rejects.toThrow(
99
+ 'Port 38741 is already in use'
100
+ );
101
+ expect(mockConnection.disconnectAsync).toHaveBeenCalled();
102
+ });
103
+
89
104
  it('re-throws non-EADDRINUSE errors', async () => {
90
105
  connectAsyncMock.mockRejectedValue(new Error('some other error'));
91
106
 
@@ -98,7 +113,7 @@ describe('serveHandlerAsync', () => {
98
113
  const result = await serveHandlerAsync({ timeout: 10 });
99
114
 
100
115
  expect(mockConnection.disconnectAsync).toHaveBeenCalled();
101
- expect(result).toEqual({ port: 38741, event: 'stopped' });
116
+ expect(result).toMatchObject({ port: 38741, event: 'stopped' });
102
117
  });
103
118
 
104
119
  it('logs JSON startup when json option is set', async () => {
@@ -7,6 +7,7 @@ import { defineCommand } from '../framework/define-command.js';
7
7
  import { arg } from '../framework/arg-builder.js';
8
8
  import { BridgeConnection } from '../../bridge/index.js';
9
9
  import type { BridgeSession } from '../../bridge/index.js';
10
+ import { isJsonOutputEnabled } from '../../cli/cli-output-context.js';
10
11
 
11
12
  export interface ServeOptions {
12
13
  port?: number;
@@ -17,6 +18,8 @@ export interface ServeOptions {
17
18
  export interface ServeResult {
18
19
  port: number;
19
20
  event: string;
21
+ timestamp: string;
22
+ summary: string;
20
23
  }
21
24
 
22
25
  /** Blocks until shutdown signal or timeout. */
@@ -24,6 +27,12 @@ export async function serveHandlerAsync(
24
27
  options: ServeOptions = {}
25
28
  ): Promise<ServeResult> {
26
29
  const port = options.port ?? 38741;
30
+ options = { ...options, json: options.json || isJsonOutputEnabled() };
31
+
32
+ const alreadyRunning = new Error(
33
+ `Port ${port} is already in use. A bridge host is already running. ` +
34
+ `Connect as a client with any studio-bridge command, or use --port to start on a different port.`
35
+ );
27
36
 
28
37
  let connection: BridgeConnection;
29
38
  try {
@@ -37,14 +46,18 @@ export async function serveHandlerAsync(
37
46
  'code' in err &&
38
47
  (err as NodeJS.ErrnoException).code === 'EADDRINUSE'
39
48
  ) {
40
- throw new Error(
41
- `Port ${port} is already in use. A bridge host is already running. ` +
42
- `Connect as a client with any studio-bridge command, or use --port to start on a different port.`
43
- );
49
+ throw alreadyRunning;
44
50
  }
45
51
  throw err;
46
52
  }
47
53
 
54
+ if (connection.role !== 'host') {
55
+ await connection.disconnectAsync();
56
+ throw alreadyRunning;
57
+ }
58
+
59
+ const listeningPort = connection.port;
60
+
48
61
  // Log startup
49
62
  if (options.json) {
50
63
  console.log(
@@ -136,13 +149,19 @@ export async function serveHandlerAsync(
136
149
  });
137
150
  }
138
151
 
139
- return { port: connection.port, event: 'stopped' };
152
+ return {
153
+ port: listeningPort,
154
+ event: 'stopped',
155
+ timestamp: new Date().toISOString(),
156
+ summary: 'Bridge host stopped.',
157
+ };
140
158
  }
141
159
 
142
160
  export const serveCommand = defineCommand<ServeOptions, ServeResult>({
143
161
  group: null,
144
162
  name: 'serve',
145
- description: 'Start the bridge server',
163
+ description:
164
+ 'Start the bridge server (optional: keeps Studio connected, so commands run in about a second instead of ten)',
146
165
  category: 'infrastructure',
147
166
  safety: 'none',
148
167
  scope: 'standalone',