@quenty/studio-bridge 0.21.1 → 0.22.1

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 +10 -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,239 @@
1
+ /**
2
+ * `playtest run` — start a playtest, execute Luau inside it, then stop it.
3
+ *
4
+ * The code runs in the playtest's server by default, or its client with
5
+ * `--context client`. Its output and return values come back the same way as
6
+ * `console exec`.
7
+ *
8
+ * In the server, the edit session plants a runner script in the playtest
9
+ * (playtest-runner.luau), so this works even when Studio does not load user
10
+ * plugins into playtests. The client has no such path: it needs the
11
+ * playtest's client session, so it needs that Studio setting on.
12
+ */
13
+
14
+ import * as fs from 'fs/promises';
15
+ import { resolvePackagePath } from '@quenty/nevermore-template-helpers';
16
+ import { defineCommand } from '../../framework/define-command.js';
17
+ import { arg } from '../../framework/arg-builder.js';
18
+ import { resolveScriptContentAsync } from '../../../cli/resolve-script-content.js';
19
+ import {
20
+ execHandlerAsync,
21
+ formatExecText,
22
+ type ExecResult as CommandExecResult,
23
+ } from '../../console/exec/exec.js';
24
+ import type {
25
+ BridgeConnection,
26
+ BridgeSession,
27
+ ExecResult,
28
+ PlaytestMode,
29
+ SessionContext,
30
+ } from '../../../bridge/index.js';
31
+ import type { SerializedReturnValue } from '../../../server/web-socket-protocol.js';
32
+ import {
33
+ endPlaytestAsync,
34
+ getPlaytestContexts,
35
+ startPlaytestAsync,
36
+ } from '../playtest-sessions.js';
37
+
38
+ export interface PlaytestRunOptions {
39
+ scriptContent: string;
40
+ mode: PlaytestMode;
41
+ /** Which playtest DataModel runs the code. */
42
+ context: SessionContext;
43
+ /** Picks the edit session to start the playtest from. */
44
+ target?: string;
45
+ timeout?: number;
46
+ /** Passed to the script as `...`. */
47
+ args?: string[];
48
+ }
49
+
50
+ /** Matches `console exec`'s default execution timeout. */
51
+ const DEFAULT_TIMEOUT_MS = 120_000;
52
+
53
+ export interface PlaytestRunResult {
54
+ success: boolean;
55
+ /** Absent when the script ran through the planted runner. */
56
+ playtestId?: string;
57
+ output: string[];
58
+ error?: string;
59
+ returnValues?: SerializedReturnValue[];
60
+ /** Set when the script ran but the playtest could not be stopped. */
61
+ stopError?: string;
62
+ summary: string;
63
+ }
64
+
65
+ interface PlaytestRunArgs {
66
+ code?: string;
67
+ file?: string;
68
+ mode?: PlaytestMode;
69
+ timeout?: number;
70
+ scriptArgs?: string[];
71
+ }
72
+
73
+ export async function playtestRunHandlerAsync(
74
+ connection: BridgeConnection,
75
+ options: PlaytestRunOptions
76
+ ): Promise<PlaytestRunResult> {
77
+ if (!getPlaytestContexts(options.mode).includes(options.context)) {
78
+ throw new Error(
79
+ `A ${options.mode} mode playtest has no ${options.context} session to run code in`
80
+ );
81
+ }
82
+
83
+ const editSession = await connection.resolveSessionAsync(
84
+ options.target,
85
+ 'edit'
86
+ );
87
+
88
+ if (options.context === 'server') {
89
+ return runWithPlantedRunnerAsync(editSession, options);
90
+ }
91
+
92
+ const playtest = await startPlaytestAsync(
93
+ connection,
94
+ editSession,
95
+ options.mode
96
+ );
97
+
98
+ let result: PlaytestRunResult;
99
+ try {
100
+ const session = playtest.sessions[options.context];
101
+ if (!session) {
102
+ throw new Error(`Playtest has no ${options.context} session`);
103
+ }
104
+
105
+ result = {
106
+ ...(await execHandlerAsync(session, {
107
+ scriptContent: options.scriptContent,
108
+ timeout: options.timeout,
109
+ args: options.args,
110
+ })),
111
+ playtestId: playtest.playtestId,
112
+ };
113
+ } catch (err) {
114
+ await tryEndPlaytestAsync(connection, playtest.sessions.server);
115
+ throw err;
116
+ }
117
+
118
+ // A playtest left running keeps the script's result worth reporting
119
+ const stopError = await tryEndPlaytestAsync(
120
+ connection,
121
+ playtest.sessions.server
122
+ );
123
+ return stopError ? { ...result, stopError } : result;
124
+ }
125
+
126
+ async function runWithPlantedRunnerAsync(
127
+ editSession: BridgeSession,
128
+ options: PlaytestRunOptions
129
+ ): Promise<PlaytestRunResult> {
130
+ const runnerSource = await fs.readFile(
131
+ resolvePackagePath(
132
+ import.meta.url,
133
+ 'src',
134
+ 'commands',
135
+ 'playtest',
136
+ 'run',
137
+ 'playtest-runner.luau'
138
+ ),
139
+ 'utf-8'
140
+ );
141
+
142
+ const result = await editSession.runPlaytestScriptAsync({
143
+ mode: options.mode,
144
+ script: options.scriptContent,
145
+ runnerSource,
146
+ timeoutSec: (options.timeout ?? DEFAULT_TIMEOUT_MS) / 1000,
147
+ args: options.args,
148
+ });
149
+
150
+ return toCommandResult(result);
151
+ }
152
+
153
+ /** Shapes a bridge ExecResult the way `console exec` reports it. */
154
+ function toCommandResult(result: ExecResult): CommandExecResult {
155
+ return {
156
+ success: result.success,
157
+ output: result.output.map((entry) => entry.body),
158
+ error: result.error,
159
+ returnValues: result.returnValues,
160
+ summary: result.success
161
+ ? 'Script executed successfully'
162
+ : `Script failed: ${result.error}`,
163
+ };
164
+ }
165
+
166
+ /** Ends the playtest, returning why it could not instead of throwing. */
167
+ async function tryEndPlaytestAsync(
168
+ connection: BridgeConnection,
169
+ serverSession: BridgeSession | undefined
170
+ ): Promise<string | undefined> {
171
+ // The script may have ended the playtest itself
172
+ if (!serverSession?.isConnected) {
173
+ return undefined;
174
+ }
175
+
176
+ try {
177
+ await endPlaytestAsync(connection, serverSession);
178
+ return undefined;
179
+ } catch (err) {
180
+ return err instanceof Error ? err.message : String(err);
181
+ }
182
+ }
183
+
184
+ export const playtestRunCommand = defineCommand<
185
+ PlaytestRunArgs,
186
+ PlaytestRunResult
187
+ >({
188
+ group: 'playtest',
189
+ name: 'run',
190
+ description:
191
+ 'Start a playtest, execute Luau in it, then stop it (--context picks server or client)',
192
+ category: 'execution',
193
+ safety: 'mutate',
194
+ scope: 'connection',
195
+ args: {
196
+ code: arg.positional({
197
+ description: 'Inline Luau code to execute',
198
+ required: false,
199
+ }),
200
+ file: arg.option({
201
+ description: 'Path to a Luau script file to execute',
202
+ alias: 'f',
203
+ }),
204
+ mode: arg.option({
205
+ description:
206
+ 'play runs a server and a client with a player, run runs only the server',
207
+ choices: ['play', 'run'],
208
+ default: 'play',
209
+ }),
210
+ timeout: arg.option({
211
+ description: 'Execution timeout in milliseconds',
212
+ type: 'number',
213
+ }),
214
+ scriptArgs: arg.passthrough({
215
+ description:
216
+ 'Arguments after --, passed to the script as ... (all strings)',
217
+ }),
218
+ },
219
+ cli: {
220
+ format: (result) =>
221
+ result.stopError
222
+ ? `${formatExecText(result)}\nPlaytest is still running: ${
223
+ result.stopError
224
+ }`
225
+ : formatExecText(result),
226
+ },
227
+ handler: async (connection, args, targeting) => {
228
+ const { scriptContent } = await resolveScriptContentAsync(args);
229
+
230
+ return playtestRunHandlerAsync(connection, {
231
+ scriptContent,
232
+ mode: args.mode ?? 'play',
233
+ context: targeting.context ?? 'server',
234
+ target: targeting.target,
235
+ timeout: args.timeout,
236
+ args: args.scriptArgs,
237
+ });
238
+ },
239
+ });
@@ -0,0 +1,108 @@
1
+ --!strict
2
+ --[=[
3
+ Action that starts a Studio playtest through StudioTestService, answering with
4
+ `playtestEnded` once the playtest is over.
5
+
6
+ - ExecutePlayModeAsync and ExecuteRunModeAsync yield until the playtest ends,
7
+ so the reply comes at the end, not the start. The bridge learns the
8
+ playtest started from its server session connecting.
9
+ - A playtest already in progress fails the call only after it yields, so a
10
+ refusal also arrives as a `playtestEnded` reply, with `success = false`.
11
+ - With `players`, it starts a multiplayer test instead: a server and a
12
+ client per player, each in its own Studio process.
13
+ - The playtest id, bridge port and edit instance id ride along as the test
14
+ args. The playtest's DataModels cannot make the HTTP requests port
15
+ discovery needs, so the plugin in each connects straight to that port,
16
+ registers under the edit session's instance, and answers with the
17
+ playtest id when asked which playtest it belongs to.
18
+
19
+ Request: `{ type: "startPlaytest", payload: { mode: "play" | "run", playtestId, bridgePort, instanceId, players? } }`
20
+ Response: `{ type: "playtestEnded", payload: { playtestId, success, error? } }`
21
+
22
+ @class StartPlaytestAction
23
+ ]=]
24
+
25
+ local StartPlaytestAction = {}
26
+
27
+ type SendMessage = (message: { [string]: any }) -> ()
28
+
29
+ --[=[
30
+ Registers the `startPlaytest` handler. The reply waits for the playtest to
31
+ end, so it needs `sendMessage`.
32
+ ]=]
33
+ function StartPlaytestAction.register(router: any, sendMessage: SendMessage?)
34
+ router:setResponseType("startPlaytest", "playtestEnded")
35
+ router:register(
36
+ "startPlaytest",
37
+ function(payload: { [string]: any }, requestId: string, sessionId: string): { [string]: any }?
38
+ local mode = payload.mode
39
+ if mode ~= "play" and mode ~= "run" then
40
+ error(`Unknown playtest mode: {tostring(mode)}`)
41
+ end
42
+
43
+ local playtestId = payload.playtestId
44
+ local bridgePort = payload.bridgePort
45
+ local instanceId = payload.instanceId
46
+ if type(playtestId) ~= "string" or type(bridgePort) ~= "number" or type(instanceId) ~= "string" then
47
+ error("Missing playtestId, bridgePort or instanceId in startPlaytest request")
48
+ end
49
+
50
+ if not sendMessage then
51
+ error("Starting a playtest requires a sendMessage callback")
52
+ end
53
+
54
+ local players = payload.players
55
+ if players ~= nil and (type(players) ~= "number" or players < 1) then
56
+ error(`Invalid player count: {tostring(players)}`)
57
+ end
58
+
59
+ local testArgs = {
60
+ studioBridgePlaytestId = playtestId,
61
+ studioBridgePort = bridgePort,
62
+ studioBridgeInstanceId = instanceId,
63
+ studioBridgePlayers = players,
64
+ }
65
+ task.spawn(StartPlaytestAction._runAsync, sendMessage, mode, testArgs, requestId, sessionId)
66
+
67
+ -- Replied through sendMessage, so the router must not reply as well
68
+ return nil
69
+ end
70
+ )
71
+ end
72
+
73
+ function StartPlaytestAction._runAsync(
74
+ sendMessage: SendMessage,
75
+ mode: string,
76
+ testArgs: {
77
+ studioBridgePlaytestId: string,
78
+ studioBridgePort: number,
79
+ studioBridgeInstanceId: string,
80
+ studioBridgePlayers: number?,
81
+ },
82
+ requestId: string,
83
+ sessionId: string
84
+ )
85
+ local ok, err = pcall(function()
86
+ local studioTestService = game:GetService("StudioTestService") :: any
87
+ if testArgs.studioBridgePlayers then
88
+ studioTestService:ExecuteMultiplayerTestAsync(testArgs.studioBridgePlayers, testArgs)
89
+ elseif mode == "play" then
90
+ studioTestService:ExecutePlayModeAsync(testArgs)
91
+ else
92
+ studioTestService:ExecuteRunModeAsync(testArgs)
93
+ end
94
+ end)
95
+
96
+ sendMessage({
97
+ type = "playtestEnded",
98
+ sessionId = sessionId,
99
+ requestId = if requestId ~= "" then requestId else nil,
100
+ payload = {
101
+ playtestId = testArgs.studioBridgePlaytestId,
102
+ success = ok,
103
+ error = if ok then nil else tostring(err),
104
+ },
105
+ })
106
+ end
107
+
108
+ return StartPlaytestAction
@@ -0,0 +1,138 @@
1
+ /**
2
+ * `playtest start` — start a StudioTestService playtest and leave it running.
3
+ *
4
+ * Resolves once the playtest's sessions connect, so the next command can
5
+ * target them with `--context server` or `--context client`.
6
+ */
7
+
8
+ import { defineCommand } from '../../framework/define-command.js';
9
+ import { arg } from '../../framework/arg-builder.js';
10
+ import type {
11
+ BridgeConnection,
12
+ PlaytestMode,
13
+ SessionContext,
14
+ } from '../../../bridge/index.js';
15
+ import {
16
+ startPlaytestAsync,
17
+ type StartedPlaytest,
18
+ } from '../playtest-sessions.js';
19
+
20
+ export interface PlaytestStartOptions {
21
+ mode: PlaytestMode;
22
+ /** Starts a multiplayer test with this many players. */
23
+ players?: number;
24
+ target?: string;
25
+ }
26
+
27
+ export interface PlaytestStartResult {
28
+ playtestId: string;
29
+ mode: PlaytestMode;
30
+ /** How many players a multiplayer test started with. */
31
+ playerCount?: number;
32
+ sessions: Array<{
33
+ sessionId: string;
34
+ context: SessionContext;
35
+ playerName?: string;
36
+ }>;
37
+ summary: string;
38
+ }
39
+
40
+ interface PlaytestStartArgs {
41
+ mode?: PlaytestMode;
42
+ players?: number;
43
+ }
44
+
45
+ export async function playtestStartHandlerAsync(
46
+ connection: BridgeConnection,
47
+ options: PlaytestStartOptions
48
+ ): Promise<PlaytestStartResult> {
49
+ const editSession = await connection.resolveSessionAsync(
50
+ options.target,
51
+ 'edit'
52
+ );
53
+ const playtest = await startPlaytestAsync(
54
+ connection,
55
+ editSession,
56
+ options.mode,
57
+ options.players
58
+ );
59
+
60
+ return toPlaytestStartResult(
61
+ playtest,
62
+ `Playtest started (${describePlaytest(playtest)})`
63
+ );
64
+ }
65
+
66
+ /** `play mode`, `run mode`, or `3 players` for a multiplayer test. */
67
+ export function describePlaytest(playtest: {
68
+ mode: PlaytestMode;
69
+ players?: number;
70
+ }): string {
71
+ return playtest.players !== undefined
72
+ ? `${playtest.players} player${playtest.players === 1 ? '' : 's'}`
73
+ : `${playtest.mode} mode`;
74
+ }
75
+
76
+ /** Report a started playtest and the sessions it opened. */
77
+ export function toPlaytestStartResult(
78
+ playtest: StartedPlaytest,
79
+ summary: string
80
+ ): PlaytestStartResult {
81
+ return {
82
+ playtestId: playtest.playtestId,
83
+ mode: playtest.mode,
84
+ playerCount: playtest.players,
85
+ sessions: [playtest.sessions.server, ...playtest.clients]
86
+ .filter((session) => session !== undefined)
87
+ .map((session) => ({
88
+ sessionId: session.info.sessionId,
89
+ context: session.context,
90
+ playerName: session.info.playerName,
91
+ })),
92
+ summary,
93
+ };
94
+ }
95
+
96
+ export function formatPlaytestStartText(result: PlaytestStartResult): string {
97
+ return [
98
+ result.summary,
99
+ ...result.sessions.map(
100
+ (session) => ` ${session.context.padEnd(7)}${session.sessionId}`
101
+ ),
102
+ ].join('\n');
103
+ }
104
+
105
+ export const playtestStartCommand = defineCommand<
106
+ PlaytestStartArgs,
107
+ PlaytestStartResult
108
+ >({
109
+ group: 'playtest',
110
+ name: 'start',
111
+ description:
112
+ 'Start a playtest and leave it running (--target picks the edit session)',
113
+ category: 'execution',
114
+ safety: 'mutate',
115
+ scope: 'connection',
116
+ args: {
117
+ mode: arg.option({
118
+ description:
119
+ 'play runs a server and a client with a player, run runs only the server',
120
+ choices: ['play', 'run'],
121
+ default: 'play',
122
+ }),
123
+ players: arg.option({
124
+ description:
125
+ 'Start a multiplayer test: a server and a client per player, each in its own Studio window',
126
+ type: 'number',
127
+ }),
128
+ },
129
+ cli: {
130
+ format: formatPlaytestStartText,
131
+ },
132
+ handler: async (connection, args, targeting) =>
133
+ playtestStartHandlerAsync(connection, {
134
+ mode: args.mode ?? 'play',
135
+ players: args.players,
136
+ target: targeting.target,
137
+ }),
138
+ });
@@ -0,0 +1,47 @@
1
+ --!strict
2
+ --[=[
3
+ Action that ends the playtest the session belongs to, answering with the
4
+ playtest id studio-bridge started it under and the mode it runs in, so the
5
+ playtest can be restarted the same way.
6
+
7
+ StudioTestService only allows `EndTest` in the server DataModel of a running
8
+ playtest, so this must target the server session. The playtest stops after
9
+ the reply is sent, since stopping tears down the DataModel answering.
10
+
11
+ Request: `{ type: "endPlaytest", payload: {} }`
12
+ Response: `{ type: "endPlaytestResult", payload: { playtestId?, mode, players? } }`
13
+
14
+ @class EndPlaytestAction
15
+ ]=]
16
+
17
+ local EndPlaytestAction = {}
18
+
19
+ --[=[
20
+ Registers the `endPlaytest` handler.
21
+ ]=]
22
+ function EndPlaytestAction.register(router: any)
23
+ router:setResponseType("endPlaytest", "endPlaytestResult")
24
+ router:register("endPlaytest", function(_payload: { [string]: any }, _requestId: string, _sessionId: string)
25
+ local runService = game:GetService("RunService")
26
+ if not (runService:IsRunning() and runService:IsServer()) then
27
+ error("Only the server session of a running playtest can end it")
28
+ end
29
+
30
+ local studioTestService = game:GetService("StudioTestService") :: any
31
+ local testArgs = studioTestService:GetTestArgs()
32
+
33
+ -- EndTest rejects nil; the value goes unused, since the bridge reads results through execute
34
+ task.defer(function()
35
+ studioTestService:EndTest(true)
36
+ end)
37
+
38
+ local isStudioBridgeTest = type(testArgs) == "table"
39
+ return {
40
+ playtestId = if isStudioBridgeTest then testArgs.studioBridgePlaytestId else nil,
41
+ mode = if runService:IsRunMode() then "run" else "play",
42
+ players = if isStudioBridgeTest then testArgs.studioBridgePlayers else nil,
43
+ }
44
+ end)
45
+ end
46
+
47
+ return EndPlaytestAction
@@ -0,0 +1,51 @@
1
+ /**
2
+ * `playtest stop` — end a running playtest from its server session.
3
+ */
4
+
5
+ import { defineCommand } from '../../framework/define-command.js';
6
+ import type { BridgeConnection } from '../../../bridge/index.js';
7
+ import {
8
+ endPlaytestAsync,
9
+ resolvePlaytestServerSessionAsync,
10
+ } from '../playtest-sessions.js';
11
+
12
+ export interface PlaytestStopOptions {
13
+ target?: string;
14
+ }
15
+
16
+ export interface PlaytestStopResult {
17
+ /** Absent when the playtest was not started by studio-bridge. */
18
+ playtestId?: string;
19
+ summary: string;
20
+ }
21
+
22
+ export async function playtestStopHandlerAsync(
23
+ connection: BridgeConnection,
24
+ options: PlaytestStopOptions = {}
25
+ ): Promise<PlaytestStopResult> {
26
+ const serverSession = await resolvePlaytestServerSessionAsync(
27
+ connection,
28
+ options.target
29
+ );
30
+ const { playtestId } = await endPlaytestAsync(connection, serverSession);
31
+
32
+ return {
33
+ playtestId,
34
+ summary: 'Playtest stopped',
35
+ };
36
+ }
37
+
38
+ export const playtestStopCommand = defineCommand<
39
+ Record<string, never>,
40
+ PlaytestStopResult
41
+ >({
42
+ group: 'playtest',
43
+ name: 'stop',
44
+ description: 'Stop the running playtest (--target picks its server session)',
45
+ category: 'execution',
46
+ safety: 'mutate',
47
+ scope: 'connection',
48
+ args: {},
49
+ handler: async (connection, _args, targeting) =>
50
+ playtestStopHandlerAsync(connection, { target: targeting.target }),
51
+ });