@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,418 @@
1
+ --!strict
2
+ --[[
3
+ @class ActionRouter.spec.lua
4
+ ]]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local ActionRouter = require("ActionRouter")
9
+ local Jest = require("Jest")
10
+
11
+ local describe = Jest.Globals.describe
12
+ local expect = Jest.Globals.expect
13
+ local it = Jest.Globals.it
14
+
15
+ local function createMessage(messageType: string, payload: { [string]: any }?, requestId: string?): ActionRouter.Message
16
+ return {
17
+ type = messageType,
18
+ sessionId = "session-1",
19
+ payload = payload or {},
20
+ requestId = requestId,
21
+ }
22
+ end
23
+
24
+ describe("ActionRouter:Dispatch()", function()
25
+ it("should answer an unknown message type with UNKNOWN_REQUEST", function()
26
+ local router = ActionRouter.new()
27
+
28
+ local response = router:Dispatch(createMessage("nope", nil, "req-1"))
29
+
30
+ expect(response).toEqual({
31
+ type = "error",
32
+ sessionId = "session-1",
33
+ requestId = "req-1",
34
+ payload = {
35
+ code = "UNKNOWN_REQUEST",
36
+ message = "Unknown message type: nope",
37
+ },
38
+ })
39
+ end)
40
+
41
+ it("should wrap a handler's return as <type>Result", function()
42
+ local router = ActionRouter.new()
43
+ router:register("ping", function(payload)
44
+ return { echo = payload.value }
45
+ end)
46
+
47
+ local response = router:Dispatch(createMessage("ping", { value = 5 }, "req-2"))
48
+
49
+ expect(response).toEqual({
50
+ type = "pingResult",
51
+ sessionId = "session-1",
52
+ requestId = "req-2",
53
+ payload = { echo = 5 },
54
+ })
55
+ end)
56
+
57
+ it("should use the response type set for the message type", function()
58
+ local router = ActionRouter.new()
59
+ router:register("ping", function()
60
+ return {}
61
+ end)
62
+ router:setResponseType("ping", "pong")
63
+
64
+ local response = router:Dispatch(createMessage("ping"))
65
+
66
+ expect(response and response.type).toEqual("pong")
67
+ end)
68
+
69
+ it("should pass the payload, requestId, and sessionId to the handler", function()
70
+ local router = ActionRouter.new()
71
+ local received = {}
72
+ router:register("ping", function(payload, requestId, sessionId)
73
+ received = { payload = payload, requestId = requestId, sessionId = sessionId }
74
+ return nil
75
+ end)
76
+
77
+ router:Dispatch(createMessage("ping", { value = 1 }, "req-3"))
78
+
79
+ expect(received).toEqual({ payload = { value = 1 }, requestId = "req-3", sessionId = "session-1" })
80
+ end)
81
+
82
+ it("should pass an empty requestId when the message has none", function()
83
+ local router = ActionRouter.new()
84
+ local receivedRequestId = nil
85
+ router:register("ping", function(_payload, requestId)
86
+ receivedRequestId = requestId
87
+ return nil
88
+ end)
89
+
90
+ router:Dispatch(createMessage("ping"))
91
+
92
+ expect(receivedRequestId).toEqual("")
93
+ end)
94
+
95
+ it("should send nothing when the handler returns nil", function()
96
+ local router = ActionRouter.new()
97
+ router:register("ping", function()
98
+ return nil
99
+ end)
100
+
101
+ expect(router:Dispatch(createMessage("ping"))).toBeNil()
102
+ end)
103
+
104
+ it("should answer a handler's failure as an error with its code", function()
105
+ local router = ActionRouter.new()
106
+ router:register("ping", function()
107
+ return { success = false, code = "INSTANCE_NOT_FOUND", message = "Instance not found" }
108
+ end)
109
+
110
+ local response = router:Dispatch(createMessage("ping", nil, "req-5"))
111
+
112
+ expect(response).toEqual({
113
+ type = "error",
114
+ sessionId = "session-1",
115
+ requestId = "req-5",
116
+ payload = {
117
+ code = "INSTANCE_NOT_FOUND",
118
+ message = "Instance not found",
119
+ },
120
+ })
121
+ end)
122
+
123
+ it("should answer a throwing handler with INTERNAL_ERROR", function()
124
+ local router = ActionRouter.new()
125
+ router:register("ping", function()
126
+ error("boom")
127
+ end)
128
+
129
+ local response = router:Dispatch(createMessage("ping", nil, "req-4"))
130
+
131
+ expect(response and response.type).toEqual("error")
132
+ expect(response and response.requestId).toEqual("req-4")
133
+ expect(response and response.payload.code).toEqual("INTERNAL_ERROR")
134
+ expect(response and response.payload.message).toContain("boom")
135
+ end)
136
+ end)
137
+
138
+ describe("ActionRouter:RegisterAction()", function()
139
+ it("should install a module through its register function", function()
140
+ local router = ActionRouter.new()
141
+
142
+ local ok, err = router:RegisterAction(
143
+ "greet",
144
+ [[
145
+ return {
146
+ register = function(router)
147
+ router:register("greet", function(payload)
148
+ return { greeting = "hi " .. payload.name }
149
+ end)
150
+ end,
151
+ }
152
+ ]],
153
+ nil,
154
+ nil,
155
+ nil,
156
+ "hash-1"
157
+ )
158
+
159
+ expect(ok).toEqual(true)
160
+ expect(err).toBeNil()
161
+
162
+ local response = router:Dispatch(createMessage("greet", { name = "bob" }))
163
+ expect(response and response.payload).toEqual({ greeting = "hi bob" })
164
+ end)
165
+
166
+ it("should hand sendMessage and logBuffer to the module's register", function()
167
+ local router = ActionRouter.new()
168
+ local sendMessage = function() end
169
+ local logBuffer = {}
170
+ local received: { [string]: any } = {}
171
+ router:register("capture", function(payload)
172
+ received = payload
173
+ return nil
174
+ end)
175
+
176
+ router:RegisterAction(
177
+ "probe",
178
+ [[
179
+ return {
180
+ register = function(router, sendMessage, logBuffer)
181
+ router:Dispatch({
182
+ type = "capture",
183
+ sessionId = "s",
184
+ payload = { sendMessage = sendMessage, logBuffer = logBuffer },
185
+ })
186
+ end,
187
+ }
188
+ ]],
189
+ sendMessage,
190
+ logBuffer
191
+ )
192
+
193
+ expect(received.sendMessage).toBe(sendMessage)
194
+ expect(received.logBuffer).toBe(logBuffer)
195
+ end)
196
+
197
+ it("should register a bare function under the action name", function()
198
+ local router = ActionRouter.new()
199
+
200
+ local ok = router:RegisterAction("double", "return function(payload) return { value = payload.value * 2 } end")
201
+
202
+ expect(ok).toEqual(true)
203
+
204
+ local response = router:Dispatch(createMessage("double", { value = 21 }))
205
+ expect(response and response.payload).toEqual({ value = 42 })
206
+ end)
207
+
208
+ it("should apply the response type override", function()
209
+ local router = ActionRouter.new()
210
+
211
+ router:RegisterAction("double", "return function() return {} end", nil, nil, "doubled")
212
+
213
+ local response = router:Dispatch(createMessage("double"))
214
+ expect(response and response.type).toEqual("doubled")
215
+ end)
216
+
217
+ it("should fail on source that does not compile", function()
218
+ local router = ActionRouter.new()
219
+
220
+ local ok, err = router:RegisterAction("broken", "return {")
221
+
222
+ expect(ok).toEqual(false)
223
+ expect(err).toContain("Failed to load action source")
224
+ end)
225
+
226
+ it("should fail on a module that throws while loading", function()
227
+ local router = ActionRouter.new()
228
+
229
+ local ok, err = router:RegisterAction("broken", "error('load boom')")
230
+
231
+ expect(ok).toEqual(false)
232
+ expect(err).toContain("Failed to execute action module")
233
+ end)
234
+
235
+ it("should fail on a module whose register throws", function()
236
+ local router = ActionRouter.new()
237
+
238
+ local ok, err = router:RegisterAction("broken", "return { register = function() error('register boom') end }")
239
+
240
+ expect(ok).toEqual(false)
241
+ expect(err).toContain("register() failed")
242
+ end)
243
+
244
+ it("should fail on a module that returns neither a table nor a function", function()
245
+ local router = ActionRouter.new()
246
+
247
+ local ok, err = router:RegisterAction("broken", "return 5")
248
+
249
+ expect(ok).toEqual(false)
250
+ expect(err).toContain("must return a table")
251
+ end)
252
+
253
+ it("should skip reloading when the same hash is installed", function()
254
+ local router = ActionRouter.new()
255
+ router:RegisterAction("counter", "return function() return { version = 1 } end", nil, nil, nil, "hash-1")
256
+
257
+ local ok =
258
+ router:RegisterAction("counter", "return function() return { version = 2 } end", nil, nil, nil, "hash-1")
259
+
260
+ expect(ok).toEqual(true)
261
+
262
+ local response = router:Dispatch(createMessage("counter"))
263
+ expect(response and response.payload).toEqual({ version = 1 })
264
+ end)
265
+
266
+ it("should replace the action and tear the old module down on a new hash", function()
267
+ local router = ActionRouter.new()
268
+ local tornDown = {}
269
+ router:register("recordTeardown", function(payload)
270
+ table.insert(tornDown, payload.name)
271
+ return nil
272
+ end)
273
+
274
+ router:RegisterAction(
275
+ "multi",
276
+ [[
277
+ local router
278
+ return {
279
+ register = function(r)
280
+ router = r
281
+ r:register("multiA", function() return { version = 1 } end)
282
+ r:register("multiB", function() return { version = 1 } end)
283
+ end,
284
+ teardown = function()
285
+ router:Dispatch({ type = "recordTeardown", sessionId = "s", payload = { name = "v1" } })
286
+ end,
287
+ }
288
+ ]],
289
+ nil,
290
+ nil,
291
+ nil,
292
+ "hash-1"
293
+ )
294
+
295
+ router:RegisterAction(
296
+ "multi",
297
+ [[
298
+ return {
299
+ register = function(r)
300
+ r:register("multiA", function() return { version = 2 } end)
301
+ end,
302
+ }
303
+ ]],
304
+ nil,
305
+ nil,
306
+ nil,
307
+ "hash-2"
308
+ )
309
+
310
+ expect(tornDown).toEqual({ "v1" })
311
+
312
+ local responseA = router:Dispatch(createMessage("multiA"))
313
+ local responseB = router:Dispatch(createMessage("multiB"))
314
+ expect(responseA and responseA.payload).toEqual({ version = 2 })
315
+ expect(responseB and responseB.payload.code).toEqual("UNKNOWN_REQUEST")
316
+ end)
317
+ end)
318
+
319
+ describe("ActionRouter:Compile()", function()
320
+ it("should compile source into a callable function", function()
321
+ local router = ActionRouter.new()
322
+
323
+ local fn = router:Compile("return 1 + 2")
324
+
325
+ expect(fn()).toEqual(3)
326
+ end)
327
+
328
+ it("should return the compile error for invalid source", function()
329
+ local router = ActionRouter.new()
330
+
331
+ local fn, err = router:Compile("local x = = 1", "=test")
332
+
333
+ expect(fn).toBeNil()
334
+ expect(err).toEqual(expect.stringContaining("Expected identifier"))
335
+ end)
336
+ end)
337
+
338
+ describe("ActionRouter:Destroy()", function()
339
+ it("should tear down every action and drop all handlers", function()
340
+ local router = ActionRouter.new()
341
+ local tornDown = {}
342
+ router:register("recordTeardown", function(payload)
343
+ table.insert(tornDown, payload.name)
344
+ return nil
345
+ end)
346
+
347
+ router:RegisterAction(
348
+ "action",
349
+ [[
350
+ local router
351
+ return {
352
+ register = function(r)
353
+ router = r
354
+ r:register("actionA", function() return {} end)
355
+ end,
356
+ teardown = function()
357
+ router:Dispatch({ type = "recordTeardown", sessionId = "s", payload = { name = "action" } })
358
+ end,
359
+ }
360
+ ]],
361
+ nil,
362
+ nil,
363
+ nil,
364
+ "hash-1"
365
+ )
366
+
367
+ router:Destroy()
368
+
369
+ expect(tornDown).toEqual({ "action" })
370
+ expect(router:GetInstalledActions()).toEqual({})
371
+ local response = router:Dispatch(createMessage("actionA"))
372
+ expect(response and response.payload.code).toEqual("UNKNOWN_REQUEST")
373
+ end)
374
+ end)
375
+
376
+ describe("ActionRouter:GetInstalledActions()", function()
377
+ it("should map each hashed action to its hash", function()
378
+ local router = ActionRouter.new()
379
+ router:RegisterAction("a", "return function() return {} end", nil, nil, nil, "hash-a")
380
+ router:RegisterAction("b", "return function() return {} end", nil, nil, nil, "hash-b")
381
+ router:RegisterAction("unhashed", "return function() return {} end")
382
+
383
+ expect(router:GetInstalledActions()).toEqual({ a = "hash-a", b = "hash-b" })
384
+ end)
385
+ end)
386
+
387
+ describe("ActionRouter:GetActionHandlerNames()", function()
388
+ it("should list the handlers an action registered", function()
389
+ local router = ActionRouter.new()
390
+ router:RegisterAction(
391
+ "multi",
392
+ [[
393
+ return {
394
+ register = function(r)
395
+ r:register("multiA", function() return {} end)
396
+ r:register("multiB", function() return {} end)
397
+ end,
398
+ }
399
+ ]],
400
+ nil,
401
+ nil,
402
+ nil,
403
+ "hash-1"
404
+ )
405
+
406
+ local handlerNames = router:GetActionHandlerNames("multi")
407
+ assert(handlerNames, "No handler names")
408
+ table.sort(handlerNames)
409
+
410
+ expect(handlerNames).toEqual({ "multiA", "multiB" })
411
+ end)
412
+
413
+ it("should return nil for an action that is not installed", function()
414
+ local router = ActionRouter.new()
415
+
416
+ expect(router:GetActionHandlerNames("missing")).toBeNil()
417
+ end)
418
+ end)
@@ -0,0 +1,94 @@
1
+ --!strict
2
+ --[=[
3
+ The two handlers the plugin ships with. Everything else is pushed by the
4
+ bridge over the wire through them.
5
+
6
+ - `registerAction` installs action source, skipping it when the same content
7
+ hash is already installed.
8
+ - `syncActions` reports which actions the bridge needs to push, by comparing
9
+ its content hashes against the installed ones.
10
+
11
+ @class BuiltInActions
12
+ ]=]
13
+
14
+ local StudioBridgeLogUtils = require(script.Parent.StudioBridgeLogUtils)
15
+
16
+ local BuiltInActions = {}
17
+
18
+ type ActionRouter = any
19
+
20
+ --[=[
21
+ Registers both built-in handlers. `sendMessage` and `logBuffer` are handed on
22
+ to every action installed through `registerAction`.
23
+ ]=]
24
+ function BuiltInActions.register(router: ActionRouter, sendMessage: (message: { [string]: any }) -> (), logBuffer: any)
25
+ router:register("registerAction", function(payload)
26
+ return BuiltInActions._registerAction(router, payload, sendMessage, logBuffer)
27
+ end)
28
+ router:setResponseType("registerAction", "registerActionResult")
29
+
30
+ router:register("syncActions", function(payload)
31
+ return BuiltInActions._syncActions(router, payload)
32
+ end)
33
+ router:setResponseType("syncActions", "syncActionsResult")
34
+ end
35
+
36
+ function BuiltInActions._registerAction(
37
+ router: ActionRouter,
38
+ payload: { [string]: any },
39
+ sendMessage: (message: { [string]: any }) -> (),
40
+ logBuffer: any
41
+ ): { [string]: any }
42
+ local name = payload.name
43
+ local source = payload.source
44
+ local hash = if type(payload.hash) == "string" then payload.hash else nil
45
+
46
+ if type(name) ~= "string" or type(source) ~= "string" then
47
+ return {
48
+ name = if type(name) == "string" then name else "unknown",
49
+ success = false,
50
+ error = "Invalid registerAction payload: name and source are required strings",
51
+ }
52
+ end
53
+
54
+ if hash and router:GetInstalledActions()[name] == hash then
55
+ return {
56
+ name = name,
57
+ success = true,
58
+ skipped = true,
59
+ hash = hash,
60
+ handlers = router:GetActionHandlerNames(name),
61
+ }
62
+ end
63
+
64
+ local success, err = router:RegisterAction(name, source, sendMessage, logBuffer, payload.responseType, hash)
65
+
66
+ return {
67
+ name = name,
68
+ success = success,
69
+ skipped = false,
70
+ hash = hash,
71
+ handlers = success and router:GetActionHandlerNames(name) or {},
72
+ error = err,
73
+ }
74
+ end
75
+
76
+ function BuiltInActions._syncActions(router: ActionRouter, payload: { [string]: any }): { [string]: any }
77
+ StudioBridgeLogUtils.setVerbose(payload.verbose == true)
78
+
79
+ local installed = router:GetInstalledActions()
80
+
81
+ local needed: { string } = {}
82
+ for name, bridgeHash in payload.actions or {} do
83
+ if installed[name] ~= bridgeHash then
84
+ table.insert(needed, name)
85
+ end
86
+ end
87
+
88
+ return {
89
+ needed = needed,
90
+ installed = installed,
91
+ }
92
+ end
93
+
94
+ return BuiltInActions
@@ -0,0 +1,166 @@
1
+ --!strict
2
+ --[[
3
+ @class BuiltInActions.spec.lua
4
+ ]]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local ActionRouter = require("ActionRouter")
9
+ local BuiltInActions = require("BuiltInActions")
10
+ local Jest = require("Jest")
11
+ local StudioBridgeLogUtils = require("StudioBridgeLogUtils")
12
+
13
+ local describe = Jest.Globals.describe
14
+ local expect = Jest.Globals.expect
15
+ local it = Jest.Globals.it
16
+
17
+ local ECHO_SOURCE = "return function(payload) return { echo = payload.value } end"
18
+
19
+ local function setup(): any
20
+ local controller = {
21
+ router = ActionRouter.new(),
22
+ sent = {},
23
+ logBuffer = {},
24
+ }
25
+
26
+ BuiltInActions.register(controller.router, function(message)
27
+ table.insert(controller.sent, message)
28
+ end, controller.logBuffer)
29
+
30
+ function controller.dispatch(messageType: string, payload: { [string]: any }): ActionRouter.Message?
31
+ return controller.router:Dispatch({
32
+ type = messageType,
33
+ sessionId = "session-1",
34
+ payload = payload,
35
+ requestId = "req-1",
36
+ })
37
+ end
38
+
39
+ return controller
40
+ end
41
+
42
+ describe("registerAction", function()
43
+ it("should install the action and answer registerActionResult", function()
44
+ local controller = setup()
45
+
46
+ local response = controller.dispatch("registerAction", { name = "echo", source = ECHO_SOURCE, hash = "hash-1" })
47
+
48
+ expect(response and response.type).toEqual("registerActionResult")
49
+ expect(response and response.payload).toEqual({
50
+ name = "echo",
51
+ success = true,
52
+ skipped = false,
53
+ hash = "hash-1",
54
+ handlers = { "echo" },
55
+ })
56
+
57
+ local echoResponse = controller.dispatch("echo", { value = 7 })
58
+ expect(echoResponse and echoResponse.payload).toEqual({ echo = 7 })
59
+ end)
60
+
61
+ it("should skip an action already installed with the same hash", function()
62
+ local controller = setup()
63
+ controller.dispatch("registerAction", { name = "echo", source = ECHO_SOURCE, hash = "hash-1" })
64
+
65
+ local response =
66
+ controller.dispatch("registerAction", { name = "echo", source = "error('unused')", hash = "hash-1" })
67
+
68
+ expect(response and response.payload).toEqual({
69
+ name = "echo",
70
+ success = true,
71
+ skipped = true,
72
+ hash = "hash-1",
73
+ handlers = { "echo" },
74
+ })
75
+ end)
76
+
77
+ it("should hand its sendMessage and logBuffer to installed actions", function()
78
+ local controller = setup()
79
+
80
+ controller.dispatch("registerAction", {
81
+ name = "probe",
82
+ source = [[
83
+ return {
84
+ register = function(router, sendMessage, logBuffer)
85
+ sendMessage({ type = "probe", sawLogBuffer = logBuffer ~= nil })
86
+ end,
87
+ }
88
+ ]],
89
+ })
90
+
91
+ expect(controller.sent).toEqual({ { type = "probe", sawLogBuffer = true } })
92
+ end)
93
+
94
+ it("should apply the requested response type", function()
95
+ local controller = setup()
96
+ controller.dispatch("registerAction", { name = "echo", source = ECHO_SOURCE, responseType = "echoed" })
97
+
98
+ local response = controller.dispatch("echo", { value = 1 })
99
+
100
+ expect(response and response.type).toEqual("echoed")
101
+ end)
102
+
103
+ it("should report a failed install", function()
104
+ local controller = setup()
105
+
106
+ local response =
107
+ controller.dispatch("registerAction", { name = "broken", source = "return {", hash = "hash-1" })
108
+
109
+ expect(response and response.payload.success).toEqual(false)
110
+ expect(response and response.payload.handlers).toEqual({})
111
+ expect(response and response.payload.error).toContain("Failed to load action source")
112
+ end)
113
+
114
+ it("should reject a payload without a name and source", function()
115
+ local controller = setup()
116
+
117
+ local response = controller.dispatch("registerAction", { name = "nosource" })
118
+
119
+ expect(response and response.payload).toEqual({
120
+ name = "nosource",
121
+ success = false,
122
+ error = "Invalid registerAction payload: name and source are required strings",
123
+ })
124
+ end)
125
+ end)
126
+
127
+ describe("syncActions", function()
128
+ it("should list the actions that are missing or out of date", function()
129
+ local controller = setup()
130
+ controller.dispatch("registerAction", { name = "current", source = ECHO_SOURCE, hash = "hash-current" })
131
+ controller.dispatch("registerAction", { name = "stale", source = ECHO_SOURCE, hash = "hash-old" })
132
+
133
+ local response = controller.dispatch("syncActions", {
134
+ actions = {
135
+ current = "hash-current",
136
+ stale = "hash-new",
137
+ missing = "hash-missing",
138
+ },
139
+ })
140
+
141
+ assert(response, "No response")
142
+ table.sort(response.payload.needed)
143
+
144
+ expect(response.type).toEqual("syncActionsResult")
145
+ expect(response.payload.needed).toEqual({ "missing", "stale" })
146
+ expect(response.payload.installed).toEqual({ current = "hash-current", stale = "hash-old" })
147
+ end)
148
+
149
+ it("should need nothing when sent no actions", function()
150
+ local controller = setup()
151
+
152
+ local response = controller.dispatch("syncActions", {})
153
+
154
+ expect(response and response.payload).toEqual({ needed = {}, installed = {} })
155
+ end)
156
+
157
+ it("should follow the bridge's verbose flag for plugin logging", function()
158
+ local controller = setup()
159
+
160
+ controller.dispatch("syncActions", { verbose = true })
161
+ expect(StudioBridgeLogUtils.isVerbose()).toEqual(true)
162
+
163
+ controller.dispatch("syncActions", {})
164
+ expect(StudioBridgeLogUtils.isVerbose()).toEqual(false)
165
+ end)
166
+ end)