@quenty/studio-bridge 0.21.1 → 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 (482) hide show
  1. package/CHANGELOG.md +6 -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/plugin/persistent-plugin-installer.d.ts.map +1 -1
  277. package/dist/src/plugin/persistent-plugin-installer.js +2 -1
  278. package/dist/src/plugin/persistent-plugin-installer.js.map +1 -1
  279. package/dist/src/plugin/persistent-plugin-installer.test.js +3 -0
  280. package/dist/src/plugin/persistent-plugin-installer.test.js.map +1 -1
  281. package/dist/src/plugin/plugin-build-version.d.ts +7 -0
  282. package/dist/src/plugin/plugin-build-version.d.ts.map +1 -0
  283. package/dist/src/plugin/plugin-build-version.js +42 -0
  284. package/dist/src/plugin/plugin-build-version.js.map +1 -0
  285. package/dist/src/plugin/plugin-build-version.test.d.ts +2 -0
  286. package/dist/src/plugin/plugin-build-version.test.d.ts.map +1 -0
  287. package/dist/src/plugin/plugin-build-version.test.js +41 -0
  288. package/dist/src/plugin/plugin-build-version.test.js.map +1 -0
  289. package/dist/src/plugin/plugin-injector.d.ts.map +1 -1
  290. package/dist/src/plugin/plugin-injector.js +7 -1
  291. package/dist/src/plugin/plugin-injector.js.map +1 -1
  292. package/dist/src/process/studio-process-closer.d.ts +35 -0
  293. package/dist/src/process/studio-process-closer.d.ts.map +1 -0
  294. package/dist/src/process/studio-process-closer.js +129 -0
  295. package/dist/src/process/studio-process-closer.js.map +1 -0
  296. package/dist/src/process/studio-process-closer.test.d.ts +2 -0
  297. package/dist/src/process/studio-process-closer.test.d.ts.map +1 -0
  298. package/dist/src/process/studio-process-closer.test.js +80 -0
  299. package/dist/src/process/studio-process-closer.test.js.map +1 -0
  300. package/dist/src/process/studio-settings.d.ts +14 -0
  301. package/dist/src/process/studio-settings.d.ts.map +1 -0
  302. package/dist/src/process/studio-settings.js +50 -0
  303. package/dist/src/process/studio-settings.js.map +1 -0
  304. package/dist/src/process/studio-settings.test.d.ts +2 -0
  305. package/dist/src/process/studio-settings.test.d.ts.map +1 -0
  306. package/dist/src/process/studio-settings.test.js +16 -0
  307. package/dist/src/process/studio-settings.test.js.map +1 -0
  308. package/dist/src/process/studio-window-state.d.ts +13 -0
  309. package/dist/src/process/studio-window-state.d.ts.map +1 -0
  310. package/dist/src/process/studio-window-state.js +48 -0
  311. package/dist/src/process/studio-window-state.js.map +1 -0
  312. package/dist/src/server/studio-bridge-server.d.ts +3 -1
  313. package/dist/src/server/studio-bridge-server.d.ts.map +1 -1
  314. package/dist/src/server/studio-bridge-server.js +12 -4
  315. package/dist/src/server/studio-bridge-server.js.map +1 -1
  316. package/dist/src/server/web-socket-protocol.d.ts +173 -6
  317. package/dist/src/server/web-socket-protocol.d.ts.map +1 -1
  318. package/dist/src/server/web-socket-protocol.js +244 -1
  319. package/dist/src/server/web-socket-protocol.js.map +1 -1
  320. package/dist/src/server/web-socket-protocol.test.js +48 -0
  321. package/dist/src/server/web-socket-protocol.test.js.map +1 -1
  322. package/dist/src/test/e2e/persistent-session.test.js +121 -0
  323. package/dist/src/test/e2e/persistent-session.test.js.map +1 -1
  324. package/dist/src/test/e2e/split-server.test.d.ts +3 -5
  325. package/dist/src/test/e2e/split-server.test.d.ts.map +1 -1
  326. package/dist/src/test/e2e/split-server.test.js +3 -5
  327. package/dist/src/test/e2e/split-server.test.js.map +1 -1
  328. package/dist/tsconfig.tsbuildinfo +1 -1
  329. package/docker/Dockerfile +3 -0
  330. package/package.json +8 -6
  331. package/src/bridge/bridge-connection.test.ts +126 -0
  332. package/src/bridge/bridge-connection.ts +217 -22
  333. package/src/bridge/bridge-session.test.ts +6 -4
  334. package/src/bridge/bridge-session.ts +273 -28
  335. package/src/bridge/index.ts +3 -0
  336. package/src/bridge/internal/bridge-client.test.ts +23 -0
  337. package/src/bridge/internal/bridge-client.ts +25 -7
  338. package/src/bridge/internal/bridge-host.test.ts +38 -0
  339. package/src/bridge/internal/bridge-host.ts +47 -0
  340. package/src/bridge/internal/hand-off.ts +4 -1
  341. package/src/bridge/internal/host-protocol.test.ts +15 -0
  342. package/src/bridge/internal/host-protocol.ts +148 -37
  343. package/src/bridge/internal/instance-state.ts +34 -0
  344. package/src/bridge/internal/transport-client.ts +2 -1
  345. package/src/bridge/internal/transport-server.ts +5 -1
  346. package/src/bridge/types.ts +47 -2
  347. package/src/cli/adapters/cli-command-adapter-handler.test.ts +28 -0
  348. package/src/cli/adapters/cli-command-adapter.ts +150 -18
  349. package/src/cli/adapters/group-builder.test.ts +34 -2
  350. package/src/cli/adapters/group-builder.ts +52 -20
  351. package/src/cli/adapters/help-formatter.test.ts +1 -1
  352. package/src/cli/adapters/help-formatter.ts +4 -3
  353. package/src/cli/adapters/playtest-edit-guard.test.ts +54 -0
  354. package/src/cli/args/global-args.ts +1 -1
  355. package/src/cli/cli-output-context.test.ts +55 -0
  356. package/src/cli/cli-output-context.ts +50 -0
  357. package/src/cli/cli.ts +49 -17
  358. package/src/cli/managed-studio-run.test.ts +71 -0
  359. package/src/cli/managed-studio-run.ts +135 -0
  360. package/src/cli/resolve-session.test.ts +1 -1
  361. package/src/cli/resolve-session.ts +1 -1
  362. package/src/cli/script-executor.ts +99 -51
  363. package/src/commands/console/exec/exec.test.ts +96 -3
  364. package/src/commands/console/exec/exec.ts +59 -6
  365. package/src/commands/console/exec/execute.lua +356 -240
  366. package/src/commands/console/exec/execute.spec.lua +286 -0
  367. package/src/commands/console/logs/logs.test.ts +76 -4
  368. package/src/commands/console/logs/logs.ts +132 -17
  369. package/src/commands/console/logs/query-logs.lua +85 -52
  370. package/src/commands/console/logs/query-logs.spec.lua +132 -0
  371. package/src/commands/explorer/export/export-instances.lua +108 -0
  372. package/src/commands/explorer/export/export-instances.spec.lua +87 -0
  373. package/src/commands/explorer/export/export.test.ts +27 -0
  374. package/src/commands/explorer/export/export.ts +60 -0
  375. package/src/commands/explorer/find/find-instances.lua +174 -0
  376. package/src/commands/explorer/find/find-instances.spec.lua +122 -0
  377. package/src/commands/explorer/find/find.test.ts +53 -0
  378. package/src/commands/explorer/find/find.ts +113 -0
  379. package/src/commands/explorer/grep/grep-scripts.lua +214 -0
  380. package/src/commands/explorer/grep/grep-scripts.spec.lua +130 -0
  381. package/src/commands/explorer/grep/grep.test.ts +45 -0
  382. package/src/commands/explorer/grep/grep.ts +93 -0
  383. package/src/commands/explorer/import/import-instances.lua +106 -0
  384. package/src/commands/explorer/import/import-instances.spec.lua +84 -0
  385. package/src/commands/explorer/import/import.test.ts +60 -0
  386. package/src/commands/explorer/import/import.ts +66 -0
  387. package/src/commands/explorer/query/query-data-model.lua +124 -152
  388. package/src/commands/explorer/query/query-data-model.spec.lua +150 -0
  389. package/src/commands/formatters.test.ts +7 -1
  390. package/src/commands/framework/action-loader.test.ts +28 -0
  391. package/src/commands/framework/action-loader.ts +10 -2
  392. package/src/commands/framework/arg-builder.ts +26 -3
  393. package/src/commands/framework/define-command.ts +32 -3
  394. package/src/commands/framework/index.ts +1 -0
  395. package/src/commands/index.ts +50 -0
  396. package/src/commands/linux/inject-credentials/inject-credentials.ts +1 -3
  397. package/src/commands/linux/setup/setup.ts +1 -3
  398. package/src/commands/linux/status/status.ts +105 -98
  399. package/src/commands/playtest/player/add/add.ts +85 -0
  400. package/src/commands/playtest/player/list/list.ts +57 -0
  401. package/src/commands/playtest/player/playtest-players.test.ts +146 -0
  402. package/src/commands/playtest/player/playtest-players.ts +270 -0
  403. package/src/commands/playtest/player/remove/remove.ts +78 -0
  404. package/src/commands/playtest/playtest-sessions.test.ts +143 -0
  405. package/src/commands/playtest/playtest-sessions.ts +417 -0
  406. package/src/commands/playtest/restart/restart.ts +199 -0
  407. package/src/commands/playtest/run/playtest-runner.luau +264 -0
  408. package/src/commands/playtest/run/playtest-runner.spec.lua +71 -0
  409. package/src/commands/playtest/run/run-playtest-script.lua +139 -0
  410. package/src/commands/playtest/run/run-playtest-script.spec.lua +43 -0
  411. package/src/commands/playtest/run/run.ts +239 -0
  412. package/src/commands/playtest/start/start-playtest.lua +108 -0
  413. package/src/commands/playtest/start/start.ts +138 -0
  414. package/src/commands/playtest/stop/end-playtest.lua +47 -0
  415. package/src/commands/playtest/stop/stop.ts +51 -0
  416. package/src/commands/process/close/close.test.ts +250 -0
  417. package/src/commands/process/close/close.ts +183 -17
  418. package/src/commands/process/info/info.test.ts +198 -44
  419. package/src/commands/process/info/info.ts +204 -15
  420. package/src/commands/process/info/query-state.lua +42 -29
  421. package/src/commands/process/info/query-state.spec.lua +39 -0
  422. package/src/commands/process/launch/launch.test.ts +138 -21
  423. package/src/commands/process/launch/launch.ts +69 -9
  424. package/src/commands/process/list/list.test.ts +1 -0
  425. package/src/commands/process/list/list.ts +14 -6
  426. package/src/commands/process/run/run.ts +26 -5
  427. package/src/commands/serve/serve.test.ts +17 -2
  428. package/src/commands/serve/serve.ts +25 -6
  429. package/src/commands/viewport/screenshot/capture-screenshot.lua +175 -182
  430. package/src/commands/viewport/screenshot/capture-screenshot.spec.lua +129 -0
  431. package/src/commands/viewport/screenshot/screenshot.test.ts +7 -10
  432. package/src/commands/viewport/screenshot/screenshot.ts +6 -1
  433. package/src/deploy/deploy-places.test.ts +127 -0
  434. package/src/deploy/deploy-places.ts +229 -0
  435. package/src/index.ts +11 -0
  436. package/src/plugin/persistent-plugin-installer.test.ts +4 -0
  437. package/src/plugin/persistent-plugin-installer.ts +2 -1
  438. package/src/plugin/plugin-build-version.test.ts +55 -0
  439. package/src/plugin/plugin-build-version.ts +53 -0
  440. package/src/plugin/plugin-injector.ts +7 -1
  441. package/src/process/studio-process-closer.test.ts +107 -0
  442. package/src/process/studio-process-closer.ts +187 -0
  443. package/src/process/studio-settings.test.ts +18 -0
  444. package/src/process/studio-settings.ts +61 -0
  445. package/src/process/studio-window-state.ts +65 -0
  446. package/src/server/studio-bridge-server.ts +15 -4
  447. package/src/server/web-socket-protocol.test.ts +55 -0
  448. package/src/server/web-socket-protocol.ts +468 -8
  449. package/src/test/e2e/persistent-session.test.ts +137 -0
  450. package/src/test/e2e/split-server.test.ts +3 -5
  451. package/templates/studio-bridge-plugin/default.project.json +3 -0
  452. package/templates/studio-bridge-plugin/src/Shared/ActionRouter.lua +208 -159
  453. package/templates/studio-bridge-plugin/src/Shared/ActionRouter.spec.lua +418 -0
  454. package/templates/studio-bridge-plugin/src/Shared/BuiltInActions.lua +94 -0
  455. package/templates/studio-bridge-plugin/src/Shared/BuiltInActions.spec.lua +166 -0
  456. package/templates/studio-bridge-plugin/src/Shared/DiscoveryStateMachine.lua +118 -137
  457. package/templates/studio-bridge-plugin/src/Shared/DiscoveryStateMachine.spec.lua +228 -0
  458. package/templates/studio-bridge-plugin/src/Shared/MessageBuffer.lua +80 -109
  459. package/templates/studio-bridge-plugin/src/Shared/MessageBuffer.spec.lua +116 -0
  460. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeConnection.lua +233 -0
  461. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeConnection.spec.lua +239 -0
  462. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeLogUtils.lua +53 -0
  463. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeLogUtils.spec.lua +27 -0
  464. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeSessionUtils.lua +164 -0
  465. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeSessionUtils.spec.lua +159 -0
  466. package/templates/studio-bridge-plugin/src/StudioBridgePlugin.server.lua +266 -368
  467. package/templates/studio-bridge-plugin/src/Vendor/png.lua +8 -2
  468. package/test/default.project.json +41 -0
  469. package/test/jest.config.lua +3 -0
  470. package/test/scripts/Server/ServerMain.server.lua +10 -0
  471. package/tsconfig.json +1 -0
  472. package/templates/studio-bridge-plugin/src/Shared/Protocol.lua +0 -132
  473. package/templates/studio-bridge-plugin-test/test/actions.test.lua +0 -580
  474. package/templates/studio-bridge-plugin-test/test/discovery.test.lua +0 -622
  475. package/templates/studio-bridge-plugin-test/test/execute-handler.test.lua +0 -517
  476. package/templates/studio-bridge-plugin-test/test/hash-lifecycle.test.lua +0 -814
  477. package/templates/studio-bridge-plugin-test/test/integration.test.lua +0 -1020
  478. package/templates/studio-bridge-plugin-test/test/new-actions.test.lua +0 -339
  479. package/templates/studio-bridge-plugin-test/test/plugin-entry.test.lua +0 -493
  480. package/templates/studio-bridge-plugin-test/test/protocol.test.lua +0 -506
  481. package/templates/studio-bridge-plugin-test/test/roblox-mocks.lua +0 -108
  482. package/templates/studio-bridge-plugin-test/test/test-runner.lua +0 -112
@@ -0,0 +1,190 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ vi.mock('../../../process/studio-process-closer.js', async (importOriginal) => {
3
+ const actual = await importOriginal();
4
+ return {
5
+ ...actual,
6
+ listStudioProcessesAsync: vi.fn(),
7
+ closeStudioProcessAsync: vi.fn(),
8
+ };
9
+ });
10
+ import * as fs from 'fs/promises';
11
+ import * as os from 'os';
12
+ import * as path from 'path';
13
+ import { closeDeployTargetAsync, processCloseHandlerAsync } from './close.js';
14
+ import { closeStudioProcessAsync, listStudioProcessesAsync, } from '../../../process/studio-process-closer.js';
15
+ const queryStateAsync = async () => ({ placeId: 0 });
16
+ const session = {
17
+ info: { sessionId: 'test-place-edit', placeName: 'test-place.rbxl' },
18
+ queryStateAsync,
19
+ };
20
+ describe('processCloseHandlerAsync', () => {
21
+ beforeEach(() => {
22
+ vi.mocked(listStudioProcessesAsync).mockResolvedValue([
23
+ { pid: 10, windowTitle: 'C:\\places\\test-place.rbxl - Roblox Studio' },
24
+ { pid: 20, windowTitle: 'Other - Roblox Studio' },
25
+ ]);
26
+ vi.mocked(closeStudioProcessAsync).mockReset().mockResolvedValue(true);
27
+ });
28
+ it('closes the Studio window showing the session place', async () => {
29
+ const result = await processCloseHandlerAsync(session);
30
+ expect(closeStudioProcessAsync).toHaveBeenCalledWith(10, {
31
+ force: undefined,
32
+ });
33
+ expect(result).toMatchObject({ success: true, pid: 10 });
34
+ });
35
+ it('closes the Studio a single-process playtest runs in', async () => {
36
+ const server = {
37
+ info: {
38
+ sessionId: 'test-place-server',
39
+ instanceId: 'test-place',
40
+ context: 'server',
41
+ placeName: 'Game',
42
+ },
43
+ queryStateAsync,
44
+ };
45
+ const connection = {
46
+ listSessions: () => [
47
+ {
48
+ sessionId: 'test-place-server',
49
+ instanceId: 'test-place',
50
+ context: 'server',
51
+ placeName: 'test-place.rbxl',
52
+ },
53
+ ],
54
+ };
55
+ const result = await processCloseHandlerAsync(server, {}, connection);
56
+ expect(result).toMatchObject({ success: true, pid: 10 });
57
+ });
58
+ it('refuses a multiplayer test process without --pid', async () => {
59
+ const client = {
60
+ info: {
61
+ sessionId: 'test-place-client-player1',
62
+ instanceId: 'test-place',
63
+ context: 'client',
64
+ placeName: 'Game',
65
+ },
66
+ queryStateAsync,
67
+ };
68
+ const connection = {
69
+ listSessions: () => ['player1', 'player2'].map((player) => ({
70
+ sessionId: `test-place-client-${player}`,
71
+ instanceId: 'test-place',
72
+ context: 'client',
73
+ placeName: 'test-place.rbxl',
74
+ playerName: player,
75
+ })),
76
+ };
77
+ const result = await processCloseHandlerAsync(client, {}, connection);
78
+ expect(result.success).toBe(false);
79
+ expect(result.summary).toContain("'studio-bridge playtest stop'");
80
+ expect(closeStudioProcessAsync).not.toHaveBeenCalled();
81
+ });
82
+ it('finds a cloud place by the place id Studio was launched with', async () => {
83
+ vi.mocked(listStudioProcessesAsync).mockResolvedValue([
84
+ {
85
+ pid: 30,
86
+ windowTitle: 'My Game (abc123) - Roblox Studio',
87
+ commandLine: 'RobloxStudioBeta.exe roblox-studio:1+placeId:555+universeId:9',
88
+ },
89
+ ]);
90
+ const cloudSession = {
91
+ info: { sessionId: 'place1-edit', placeName: 'Place1', placeId: 0 },
92
+ queryStateAsync: async () => ({ placeId: 555 }),
93
+ };
94
+ const result = await processCloseHandlerAsync(cloudSession);
95
+ expect(result).toMatchObject({ success: true, pid: 30 });
96
+ });
97
+ it('passes --force through', async () => {
98
+ await processCloseHandlerAsync(session, { force: true });
99
+ expect(closeStudioProcessAsync).toHaveBeenCalledWith(10, { force: true });
100
+ });
101
+ it('suggests --force when Studio stays open', async () => {
102
+ vi.mocked(closeStudioProcessAsync).mockResolvedValue(false);
103
+ const result = await processCloseHandlerAsync(session);
104
+ expect(result.success).toBe(false);
105
+ expect(result.summary).toContain('--force');
106
+ });
107
+ it('fails without closing when no window shows the place', async () => {
108
+ vi.mocked(listStudioProcessesAsync).mockResolvedValue([
109
+ { pid: 20, windowTitle: 'Other - Roblox Studio' },
110
+ ]);
111
+ const result = await processCloseHandlerAsync(session);
112
+ expect(result.success).toBe(false);
113
+ expect(closeStudioProcessAsync).not.toHaveBeenCalled();
114
+ });
115
+ it('asks for --pid when several windows show the place', async () => {
116
+ vi.mocked(listStudioProcessesAsync).mockResolvedValue([
117
+ { pid: 10, windowTitle: 'C:\\a\\test-place.rbxl - Roblox Studio' },
118
+ { pid: 11, windowTitle: 'C:\\b\\test-place.rbxl - Roblox Studio' },
119
+ ]);
120
+ const result = await processCloseHandlerAsync(session);
121
+ expect(result.success).toBe(false);
122
+ expect(result.summary).toContain('--pid');
123
+ expect(closeStudioProcessAsync).not.toHaveBeenCalled();
124
+ });
125
+ it('closes the process picked with --pid', async () => {
126
+ const result = await processCloseHandlerAsync(session, { pid: 20 });
127
+ expect(closeStudioProcessAsync).toHaveBeenCalledWith(20, {
128
+ force: undefined,
129
+ });
130
+ expect(result.success).toBe(true);
131
+ });
132
+ });
133
+ describe('closeDeployTargetAsync', () => {
134
+ let tempDir;
135
+ beforeEach(async () => {
136
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'close-test-'));
137
+ await fs.writeFile(path.join(tempDir, 'deploy.nevermore.json'), JSON.stringify({
138
+ targets: {
139
+ test: { universeId: 9, placeId: 555, project: 'test.project.json' },
140
+ },
141
+ }));
142
+ vi.mocked(closeStudioProcessAsync).mockReset().mockResolvedValue(true);
143
+ });
144
+ afterEach(async () => {
145
+ await fs.rm(tempDir, { recursive: true, force: true });
146
+ });
147
+ it('closes a Studio launched with the target place, connected or not', async () => {
148
+ vi.mocked(listStudioProcessesAsync).mockResolvedValue([
149
+ {
150
+ pid: 40,
151
+ windowTitle: 'My Game (abc123) - Roblox Studio',
152
+ commandLine: 'RobloxStudioBeta.exe roblox-studio:1+placeId:555',
153
+ },
154
+ { pid: 41, windowTitle: 'Other - Roblox Studio' },
155
+ ]);
156
+ const connection = { listInstances: () => [], listSessions: () => [] };
157
+ const result = await closeDeployTargetAsync(connection, 'test', {}, tempDir);
158
+ expect(closeStudioProcessAsync).toHaveBeenCalledWith(40, {
159
+ force: undefined,
160
+ });
161
+ expect(result).toMatchObject({
162
+ success: true,
163
+ deployTarget: 'test',
164
+ pid: 40,
165
+ });
166
+ });
167
+ it('closes the connected Studio showing the target place', async () => {
168
+ vi.mocked(listStudioProcessesAsync).mockResolvedValue([
169
+ { pid: 50, windowTitle: 'My Game (abc123) - Roblox Studio' },
170
+ ]);
171
+ const editSession = {
172
+ info: {
173
+ sessionId: 'place1-1a2b-edit',
174
+ instanceId: 'place1-1a2b',
175
+ context: 'edit',
176
+ placeName: 'My Game (abc123)',
177
+ },
178
+ queryStateAsync: async () => ({ placeId: 555 }),
179
+ };
180
+ const connection = {
181
+ listInstances: () => [{ instanceId: 'place1-1a2b', placeId: 555 }],
182
+ listSessions: () => [editSession.info],
183
+ resolveSessionAsync: vi.fn().mockResolvedValue(editSession),
184
+ };
185
+ const result = await closeDeployTargetAsync(connection, 'test', {}, tempDir);
186
+ expect(connection.resolveSessionAsync).toHaveBeenCalledWith('place1-1a2b', 'edit');
187
+ expect(result).toMatchObject({ success: true, pid: 50 });
188
+ });
189
+ });
190
+ //# sourceMappingURL=close.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close.test.js","sourceRoot":"","sources":["../../../../../src/commands/process/close/close.test.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,57 @@
1
1
  /**
2
- * `process info` — query the current Studio state (mode, place info)
3
- * from a connected session.
2
+ * `process info` — report on one Studio session: its place and run mode, the
3
+ * playtest running in its Studio, its window, and whether its plugin is
4
+ * current.
4
5
  */
5
- import type { BridgeSession } from '../../../bridge/index.js';
6
- import type { StudioState } from '../../../bridge/index.js';
6
+ import type { BridgeConnection, BridgeSession, SessionContext, SessionInfo, SessionOrigin, StudioState } from '../../../bridge/index.js';
7
+ export interface PlaytestInfo {
8
+ mode: 'play' | 'run';
9
+ /** Set for a multiplayer test: how many of its clients are connected. */
10
+ playerCount?: number;
11
+ sessions: Array<{
12
+ sessionId: string;
13
+ context: SessionContext;
14
+ playerName?: string;
15
+ }>;
16
+ }
7
17
  export interface StateResult {
18
+ sessionId: string;
19
+ instanceId: string;
20
+ context: SessionContext;
21
+ origin: SessionOrigin;
22
+ /** The run mode of this session's own DataModel. */
8
23
  state: StudioState;
9
24
  placeId: number;
10
25
  placeName: string;
11
26
  gameId: number;
27
+ /** The camera viewport in pixels. Absent without a camera. */
28
+ viewportSize?: [number, number];
29
+ /** Absent from older plugins. */
30
+ studioVersion?: string;
31
+ plugin: {
32
+ version: string;
33
+ /** The version `studio-bridge plugin install` would install. */
34
+ expectedVersion: string;
35
+ upToDate: boolean;
36
+ };
37
+ /**
38
+ * The playtest running in this session's Studio, as seen through the
39
+ * sessions it opened. Absent when none is running or its sessions are not
40
+ * connected.
41
+ */
42
+ playtest?: PlaytestInfo;
43
+ /** The Studio window showing the place. Absent when it cannot be told apart. */
44
+ window?: {
45
+ pid: number;
46
+ focused: boolean;
47
+ minimized: boolean;
48
+ };
49
+ connectedAt: string;
12
50
  summary: string;
13
51
  }
14
- export declare function queryStateHandlerAsync(session: BridgeSession): Promise<StateResult>;
52
+ export declare function queryStateHandlerAsync(session: BridgeSession, connection?: BridgeConnection): Promise<StateResult>;
53
+ /** The playtest of `instanceId`, from the sessions it opened. */
54
+ export declare function describePlaytest(sessions: SessionInfo[], instanceId: string): PlaytestInfo | undefined;
15
55
  export declare function formatStateText(result: StateResult): string;
16
56
  export declare const infoCommand: import("../../framework/define-command.js").CommandDefinition<unknown, StateResult>;
17
57
  //# sourceMappingURL=info.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../../../../src/commands/process/info/info.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAG5D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,WAAW,CAAC,CAUtB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAO3D;AAED,eAAO,MAAM,WAAW,qFAYtB,CAAC"}
1
+ {"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../../../../src/commands/process/info/info.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACZ,MAAM,0BAA0B,CAAC;AASlC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,cAAc,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,aAAa,CAAC;IACtB,oDAAoD;IACpD,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,iCAAiC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;QAChB,gEAAgE;QAChE,eAAe,EAAE,MAAM,CAAC;QACxB,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;IACF;;;;OAIG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,gFAAgF;IAChF,MAAM,CAAC,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,EAAE,OAAO,CAAC;KACpB,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,aAAa,EACtB,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,WAAW,CAAC,CA0CtB;AAED,iEAAiE;AACjE,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,WAAW,EAAE,EACvB,UAAU,EAAE,MAAM,GACjB,YAAY,GAAG,SAAS,CAoB1B;AAmDD,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAiC3D;AAED,eAAO,MAAM,WAAW,qFActB,CAAC"}
@@ -1,31 +1,135 @@
1
1
  /**
2
- * `process info` — query the current Studio state (mode, place info)
3
- * from a connected session.
2
+ * `process info` — report on one Studio session: its place and run mode, the
3
+ * playtest running in its Studio, its window, and whether its plugin is
4
+ * current.
4
5
  */
6
+ import { OutputHelper } from '@quenty/cli-output-helpers';
5
7
  import { defineCommand } from '../../framework/define-command.js';
6
8
  import { colorizeState } from '../format-state.js';
7
- export async function queryStateHandlerAsync(session) {
8
- const result = await session.queryStateAsync();
9
+ import { listStudioProcessesAsync, matchStudioProcesses, } from '../../../process/studio-process-closer.js';
10
+ import { tryGetStudioWindowStateAsync } from '../../../process/studio-window-state.js';
11
+ import { getPluginBuildVersionAsync } from '../../../plugin/plugin-build-version.js';
12
+ export async function queryStateHandlerAsync(session, connection) {
13
+ // Listed sessions carry the edit session's place name for a playtest
14
+ const listed = connection
15
+ ?.listSessions()
16
+ .find((s) => s.sessionId === session.info.sessionId);
17
+ const playtest = connection
18
+ ? describePlaytest(connection.listSessions(), session.info.instanceId)
19
+ : undefined;
20
+ // Each process of a multiplayer test has its own window; otherwise a
21
+ // playtest shows in the edit window
22
+ const ownWindow = session.info.context !== 'edit' && playtest?.playerCount !== undefined;
23
+ const [result, expectedVersion] = await Promise.all([
24
+ session.queryStateAsync(),
25
+ getPluginBuildVersionAsync(),
26
+ ]);
27
+ const window = await tryGetWindowAsync(ownWindow ? [result.placeName] : [result.placeName, listed?.placeName], ownWindow ? undefined : result.placeId);
9
28
  return {
29
+ sessionId: session.info.sessionId,
30
+ instanceId: session.info.instanceId,
31
+ context: session.info.context,
32
+ origin: session.info.origin,
10
33
  state: result.state,
11
34
  placeId: result.placeId,
12
- placeName: result.placeName,
35
+ placeName: listed?.placeName || result.placeName,
13
36
  gameId: result.gameId,
37
+ viewportSize: result.viewportSize,
38
+ studioVersion: result.studioVersion,
39
+ plugin: {
40
+ version: session.info.pluginVersion,
41
+ expectedVersion,
42
+ upToDate: session.info.pluginVersion === expectedVersion,
43
+ },
44
+ playtest,
45
+ window,
46
+ connectedAt: new Date(session.info.connectedAt).toISOString(),
14
47
  summary: `Mode: ${result.state}, Place: ${result.placeName} (${result.placeId})`,
15
48
  };
16
49
  }
50
+ /** The playtest of `instanceId`, from the sessions it opened. */
51
+ export function describePlaytest(sessions, instanceId) {
52
+ const playtestSessions = sessions.filter((s) => s.instanceId === instanceId && s.context !== 'edit');
53
+ if (playtestSessions.length === 0)
54
+ return undefined;
55
+ const clients = playtestSessions.filter((s) => s.context === 'client');
56
+ const isMultiplayer = clients.some((s) => s.sessionId !== `${instanceId}-client`);
57
+ return {
58
+ mode: clients.length > 0 ? 'play' : 'run',
59
+ playerCount: isMultiplayer ? clients.length : undefined,
60
+ sessions: playtestSessions.map((s) => ({
61
+ sessionId: s.sessionId,
62
+ context: s.context,
63
+ playerName: s.playerName,
64
+ })),
65
+ };
66
+ }
67
+ /**
68
+ * The Studio window titled with the first of `placeNames` that any window
69
+ * has, when exactly one does. A multiplayer test's processes title their
70
+ * windows with their own DataModel's name, and its clients all share one;
71
+ * a single-process playtest shares the edit window.
72
+ */
73
+ async function tryGetWindowAsync(placeNames, placeId) {
74
+ const processes = await listStudioProcessesAsync().catch(() => []);
75
+ for (const placeName of placeNames) {
76
+ if (!placeName)
77
+ continue;
78
+ const matches = matchStudioProcesses(processes, placeName, placeId);
79
+ if (matches.length === 0)
80
+ continue;
81
+ if (matches.length > 1)
82
+ return undefined;
83
+ const pid = matches[0].pid;
84
+ const state = await tryGetStudioWindowStateAsync(pid);
85
+ return state ? { pid, ...state } : undefined;
86
+ }
87
+ return undefined;
88
+ }
89
+ function formatAge(isoTime) {
90
+ const seconds = Math.max(0, Math.round((Date.now() - Date.parse(isoTime)) / 1000));
91
+ if (seconds < 60)
92
+ return `${seconds}s ago`;
93
+ if (seconds < 3600)
94
+ return `${Math.floor(seconds / 60)}m ago`;
95
+ return `${Math.floor(seconds / 3600)}h ${Math.floor((seconds % 3600) / 60)}m ago`;
96
+ }
97
+ function formatPlaytest(playtest) {
98
+ if (!playtest)
99
+ return 'none running';
100
+ const kind = playtest.playerCount !== undefined
101
+ ? `multiplayer, ${playtest.playerCount} player${playtest.playerCount === 1 ? '' : 's'}`
102
+ : `${playtest.mode} mode`;
103
+ return `running (${kind}): ${playtest.sessions
104
+ .map((s) => s.sessionId)
105
+ .join(', ')}`;
106
+ }
17
107
  export function formatStateText(result) {
18
- return [
19
- `Mode: ${colorizeState(result.state)}`,
20
- `Place: ${result.placeName}`,
21
- `PlaceId: ${result.placeId}`,
22
- `GameId: ${result.gameId}`,
23
- ].join('\n');
108
+ const lines = [
109
+ `Session: ${OutputHelper.formatHint(result.sessionId)} (${result.context}, ${result.origin}, connected ${formatAge(result.connectedAt)})`,
110
+ `Mode: ${colorizeState(result.state)}`,
111
+ `Playtest: ${formatPlaytest(result.playtest)}`,
112
+ `Place: ${result.placeName} (PlaceId ${result.placeId}, GameId ${result.gameId})`,
113
+ ];
114
+ if (result.viewportSize) {
115
+ lines.push(`Viewport: ${result.viewportSize[0]}x${result.viewportSize[1]}`);
116
+ }
117
+ if (result.window) {
118
+ const { pid, focused, minimized } = result.window;
119
+ lines.push(`Window: pid ${pid}, ${minimized ? 'minimized' : 'open'}, ${focused ? 'focused' : 'not focused'}`);
120
+ }
121
+ if (result.studioVersion) {
122
+ lines.push(`Studio: ${result.studioVersion}`);
123
+ }
124
+ lines.push(`Plugin: ${result.plugin.version || 'unknown'} ${result.plugin.upToDate
125
+ ? '(up to date)'
126
+ : OutputHelper.formatWarning(`(out of date, expected ${result.plugin.expectedVersion}; run 'studio-bridge plugin install')`)}`);
127
+ return lines.join('\n');
24
128
  }
25
129
  export const infoCommand = defineCommand({
26
130
  group: 'process',
27
131
  name: 'info',
28
- description: 'Query the current Studio state (mode, place info)',
132
+ description: 'Report on a Studio session: mode, playtest, place, window and plugin version',
29
133
  category: 'execution',
30
134
  safety: 'read',
31
135
  scope: 'session',
@@ -33,6 +137,6 @@ export const infoCommand = defineCommand({
33
137
  cli: {
34
138
  format: formatStateText,
35
139
  },
36
- handler: async (session) => queryStateHandlerAsync(session),
140
+ handler: async (session, _args, connection) => queryStateHandlerAsync(session, connection),
37
141
  });
38
142
  //# sourceMappingURL=info.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"info.js","sourceRoot":"","sources":["../../../../../src/commands/process/info/info.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAGlE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAUnD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAAsB;IAEtB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,eAAe,EAAE,CAAC;IAE/C,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,SAAS,MAAM,CAAC,KAAK,YAAY,MAAM,CAAC,SAAS,KAAK,MAAM,CAAC,OAAO,GAAG;KACjF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAmB;IACjD,OAAO;QACL,YAAY,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACzC,YAAY,MAAM,CAAC,SAAS,EAAE;QAC9B,YAAY,MAAM,CAAC,OAAO,EAAE;QAC5B,YAAY,MAAM,CAAC,MAAM,EAAE;KAC5B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;IACvC,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,mDAAmD;IAChE,QAAQ,EAAE,WAAW;IACrB,MAAM,EAAE,MAAM;IACd,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,EAAE;IACR,GAAG,EAAE;QACH,MAAM,EAAE,eAAe;KACxB;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,sBAAsB,CAAC,OAAO,CAAC;CAC5D,CAAC,CAAC"}
1
+ {"version":3,"file":"info.js","sourceRoot":"","sources":["../../../../../src/commands/process/info/info.ts"],"names":[],"mappings":"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"}
@@ -2,57 +2,159 @@
2
2
  * Unit tests for the info (state) command handler.
3
3
  */
4
4
  import { describe, it, expect, vi } from 'vitest';
5
- import { queryStateHandlerAsync } from './info.js';
6
- function createMockSession(stateResult) {
5
+ vi.mock('../../../process/studio-process-closer.js', async (importOriginal) => {
6
+ const actual = await importOriginal();
7
7
  return {
8
- queryStateAsync: vi.fn().mockResolvedValue(stateResult),
8
+ ...actual,
9
+ listStudioProcessesAsync: vi.fn(async () => [
10
+ { pid: 42, windowTitle: 'C:/places/TestPlace - Roblox Studio' },
11
+ ]),
9
12
  };
13
+ });
14
+ vi.mock('../../../process/studio-window-state.js', () => ({
15
+ tryGetStudioWindowStateAsync: vi.fn(async () => ({
16
+ focused: true,
17
+ minimized: false,
18
+ })),
19
+ }));
20
+ vi.mock('../../../plugin/plugin-build-version.js', () => ({
21
+ getPluginBuildVersionAsync: async () => 'abc123',
22
+ }));
23
+ import { describePlaytest, formatStateText, queryStateHandlerAsync, } from './info.js';
24
+ function sessionInfo(sessionId, context, overrides = {}) {
25
+ return {
26
+ sessionId,
27
+ instanceId: 'test-place-3f9a',
28
+ context,
29
+ origin: 'user',
30
+ placeName: 'TestPlace',
31
+ pluginVersion: 'abc123',
32
+ connectedAt: new Date('2026-10-27T18:00:00Z'),
33
+ ...overrides,
34
+ };
35
+ }
36
+ function createMockSession(stateResult, infoOverrides = {}) {
37
+ return {
38
+ info: sessionInfo('test-place-3f9a-edit', 'edit', infoOverrides),
39
+ queryStateAsync: vi.fn().mockResolvedValue({
40
+ state: 'Edit',
41
+ placeId: 12345,
42
+ placeName: 'TestPlace',
43
+ gameId: 67890,
44
+ ...stateResult,
45
+ }),
46
+ };
47
+ }
48
+ function createConnection(sessions) {
49
+ return { listSessions: () => sessions };
10
50
  }
11
51
  describe('queryStateHandlerAsync', () => {
12
- it('returns state result with summary', async () => {
13
- const session = createMockSession({
52
+ it('reports the session, place and run mode', async () => {
53
+ const session = createMockSession({ studioVersion: '0.744.0.7440803' });
54
+ const result = await queryStateHandlerAsync(session);
55
+ expect(result).toMatchObject({
56
+ sessionId: 'test-place-3f9a-edit',
57
+ instanceId: 'test-place-3f9a',
58
+ context: 'edit',
59
+ origin: 'user',
14
60
  state: 'Edit',
15
61
  placeId: 12345,
16
62
  placeName: 'TestPlace',
17
63
  gameId: 67890,
64
+ studioVersion: '0.744.0.7440803',
65
+ connectedAt: '2026-10-27T18:00:00.000Z',
18
66
  });
19
- const result = await queryStateHandlerAsync(session);
20
- expect(result.state).toBe('Edit');
21
- expect(result.placeId).toBe(12345);
22
- expect(result.placeName).toBe('TestPlace');
23
- expect(result.gameId).toBe(67890);
24
- expect(result.summary).toContain('Edit');
25
- expect(result.summary).toContain('TestPlace');
26
- expect(result.summary).toContain('12345');
27
- });
28
- it('calls session.queryStateAsync', async () => {
29
- const session = createMockSession({
30
- state: 'Play',
31
- placeId: 100,
32
- placeName: 'GamePlace',
33
- gameId: 200,
67
+ expect(result.summary).toBe('Mode: Edit, Place: TestPlace (12345)');
68
+ });
69
+ it('compares the plugin version with the one the CLI installs', async () => {
70
+ const current = await queryStateHandlerAsync(createMockSession({}));
71
+ const stale = await queryStateHandlerAsync(createMockSession({}, { pluginVersion: 'old999' }));
72
+ expect(current.plugin).toEqual({
73
+ version: 'abc123',
74
+ expectedVersion: 'abc123',
75
+ upToDate: true,
76
+ });
77
+ expect(stale.plugin.upToDate).toBe(false);
78
+ expect(formatStateText(stale)).toContain("out of date, expected abc123; run 'studio-bridge plugin install'");
79
+ });
80
+ it("reports the playtest running in the session's Studio", async () => {
81
+ const session = createMockSession({});
82
+ const connection = createConnection([
83
+ session.info,
84
+ sessionInfo('test-place-3f9a-server', 'server'),
85
+ sessionInfo('test-place-3f9a-client', 'client', {
86
+ playerName: 'Player1',
87
+ }),
88
+ ]);
89
+ const result = await queryStateHandlerAsync(session, connection);
90
+ expect(result.playtest).toEqual({
91
+ mode: 'play',
92
+ playerCount: undefined,
93
+ sessions: [
94
+ {
95
+ sessionId: 'test-place-3f9a-server',
96
+ context: 'server',
97
+ playerName: undefined,
98
+ },
99
+ {
100
+ sessionId: 'test-place-3f9a-client',
101
+ context: 'client',
102
+ playerName: 'Player1',
103
+ },
104
+ ],
105
+ });
106
+ expect(formatStateText(result)).toContain('Playtest: running (play mode): test-place-3f9a-server, test-place-3f9a-client');
107
+ });
108
+ it("finds a playtest's window by its DataModel's name, not the edit window", async () => {
109
+ const session = createMockSession({ state: 'Server', placeName: 'TestPlace' }, { sessionId: 'test-place-3f9a-server', context: 'server' });
110
+ const connection = createConnection([
111
+ sessionInfo('test-place-3f9a-edit', 'edit'),
112
+ session.info,
113
+ sessionInfo('test-place-3f9a-client-player1', 'client'),
114
+ sessionInfo('test-place-3f9a-client-player2', 'client'),
115
+ ]);
116
+ const result = await queryStateHandlerAsync(session, connection);
117
+ expect(result.window?.pid).toBe(42);
118
+ session.queryStateAsync.mockResolvedValue({
119
+ state: 'Server',
120
+ placeId: 0,
121
+ placeName: 'Server',
122
+ gameId: 0,
34
123
  });
35
- await queryStateHandlerAsync(session);
36
- expect(session.queryStateAsync).toHaveBeenCalledOnce();
37
- });
38
- it('handles different state values correctly', async () => {
39
- for (const state of ['Edit', 'Play', 'Paused', 'Run', 'Server', 'Client']) {
40
- const session = createMockSession({
41
- state,
42
- placeId: 1,
43
- placeName: 'Place',
44
- gameId: 2,
45
- });
46
- const result = await queryStateHandlerAsync(session);
47
- expect(result.state).toBe(state);
48
- expect(result.summary).toContain(state);
49
- }
124
+ const unmatched = await queryStateHandlerAsync(session, connection);
125
+ expect(unmatched.window).toBeUndefined();
50
126
  });
51
127
  it('propagates errors from session', async () => {
52
- const session = {
53
- queryStateAsync: vi.fn().mockRejectedValue(new Error('Connection lost')),
54
- };
128
+ const session = createMockSession({});
129
+ session.queryStateAsync.mockRejectedValue(new Error('Connection lost'));
55
130
  await expect(queryStateHandlerAsync(session)).rejects.toThrow('Connection lost');
56
131
  });
132
+ it('reports the window showing the place', async () => {
133
+ const result = await queryStateHandlerAsync(createMockSession({}));
134
+ expect(result.window).toEqual({ pid: 42, focused: true, minimized: false });
135
+ expect(formatStateText(result)).toContain('Window: pid 42, open, focused');
136
+ });
137
+ it('leaves the window out when no window shows the place', async () => {
138
+ const result = await queryStateHandlerAsync(createMockSession({ placeName: 'Elsewhere' }));
139
+ expect(result.window).toBeUndefined();
140
+ });
141
+ });
142
+ describe('describePlaytest', () => {
143
+ it('is absent without playtest sessions', () => {
144
+ expect(describePlaytest([sessionInfo('test-place-3f9a-edit', 'edit')], 'test-place-3f9a')).toBeUndefined();
145
+ });
146
+ it('reports run mode when only the server connected', () => {
147
+ expect(describePlaytest([sessionInfo('test-place-3f9a-server', 'server')], 'test-place-3f9a')?.mode).toBe('run');
148
+ });
149
+ it('counts the players of a multiplayer test', () => {
150
+ const playtest = describePlaytest([
151
+ sessionInfo('test-place-3f9a-server', 'server'),
152
+ sessionInfo('test-place-3f9a-client-player1', 'client'),
153
+ sessionInfo('test-place-3f9a-client-player2', 'client'),
154
+ sessionInfo('other-1a2b-server', 'server', { instanceId: 'other' }),
155
+ ], 'test-place-3f9a');
156
+ expect(playtest?.playerCount).toBe(2);
157
+ expect(playtest?.sessions).toHaveLength(3);
158
+ });
57
159
  });
58
160
  //# sourceMappingURL=info.test.js.map