@quenty/studio-bridge 0.21.1 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (482) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +109 -17
  3. package/build-scripts/transform-add-session-attribute.lua +1 -0
  4. package/deploy.nevermore.json +10 -0
  5. package/dist/src/bridge/bridge-connection.d.ts +26 -2
  6. package/dist/src/bridge/bridge-connection.d.ts.map +1 -1
  7. package/dist/src/bridge/bridge-connection.js +159 -14
  8. package/dist/src/bridge/bridge-connection.js.map +1 -1
  9. package/dist/src/bridge/bridge-connection.test.js +81 -0
  10. package/dist/src/bridge/bridge-connection.test.js.map +1 -1
  11. package/dist/src/bridge/bridge-session.d.ts +35 -2
  12. package/dist/src/bridge/bridge-session.d.ts.map +1 -1
  13. package/dist/src/bridge/bridge-session.js +185 -28
  14. package/dist/src/bridge/bridge-session.js.map +1 -1
  15. package/dist/src/bridge/bridge-session.test.js +6 -4
  16. package/dist/src/bridge/bridge-session.test.js.map +1 -1
  17. package/dist/src/bridge/index.d.ts +1 -1
  18. package/dist/src/bridge/index.d.ts.map +1 -1
  19. package/dist/src/bridge/index.js.map +1 -1
  20. package/dist/src/bridge/internal/bridge-client.d.ts +4 -0
  21. package/dist/src/bridge/internal/bridge-client.d.ts.map +1 -1
  22. package/dist/src/bridge/internal/bridge-client.js +20 -7
  23. package/dist/src/bridge/internal/bridge-client.js.map +1 -1
  24. package/dist/src/bridge/internal/bridge-client.test.js +18 -0
  25. package/dist/src/bridge/internal/bridge-client.test.js.map +1 -1
  26. package/dist/src/bridge/internal/bridge-host.d.ts +13 -1
  27. package/dist/src/bridge/internal/bridge-host.d.ts.map +1 -1
  28. package/dist/src/bridge/internal/bridge-host.js +35 -0
  29. package/dist/src/bridge/internal/bridge-host.js.map +1 -1
  30. package/dist/src/bridge/internal/bridge-host.test.js +31 -0
  31. package/dist/src/bridge/internal/bridge-host.test.js.map +1 -1
  32. package/dist/src/bridge/internal/hand-off.d.ts.map +1 -1
  33. package/dist/src/bridge/internal/hand-off.js +4 -1
  34. package/dist/src/bridge/internal/hand-off.js.map +1 -1
  35. package/dist/src/bridge/internal/host-protocol.d.ts +8 -0
  36. package/dist/src/bridge/internal/host-protocol.d.ts.map +1 -1
  37. package/dist/src/bridge/internal/host-protocol.js +120 -13
  38. package/dist/src/bridge/internal/host-protocol.js.map +1 -1
  39. package/dist/src/bridge/internal/host-protocol.test.js +13 -0
  40. package/dist/src/bridge/internal/host-protocol.test.js.map +1 -1
  41. package/dist/src/bridge/internal/instance-state.d.ts +9 -0
  42. package/dist/src/bridge/internal/instance-state.d.ts.map +1 -0
  43. package/dist/src/bridge/internal/instance-state.js +28 -0
  44. package/dist/src/bridge/internal/instance-state.js.map +1 -0
  45. package/dist/src/bridge/internal/transport-client.d.ts.map +1 -1
  46. package/dist/src/bridge/internal/transport-client.js +2 -1
  47. package/dist/src/bridge/internal/transport-client.js.map +1 -1
  48. package/dist/src/bridge/internal/transport-server.d.ts.map +1 -1
  49. package/dist/src/bridge/internal/transport-server.js +5 -1
  50. package/dist/src/bridge/internal/transport-server.js.map +1 -1
  51. package/dist/src/bridge/types.d.ts +43 -4
  52. package/dist/src/bridge/types.d.ts.map +1 -1
  53. package/dist/src/bridge/types.js.map +1 -1
  54. package/dist/src/cli/adapters/cli-command-adapter-handler.test.js +24 -0
  55. package/dist/src/cli/adapters/cli-command-adapter-handler.test.js.map +1 -1
  56. package/dist/src/cli/adapters/cli-command-adapter.d.ts +6 -0
  57. package/dist/src/cli/adapters/cli-command-adapter.d.ts.map +1 -1
  58. package/dist/src/cli/adapters/cli-command-adapter.js +107 -11
  59. package/dist/src/cli/adapters/cli-command-adapter.js.map +1 -1
  60. package/dist/src/cli/adapters/group-builder.d.ts +3 -0
  61. package/dist/src/cli/adapters/group-builder.d.ts.map +1 -1
  62. package/dist/src/cli/adapters/group-builder.js +34 -15
  63. package/dist/src/cli/adapters/group-builder.js.map +1 -1
  64. package/dist/src/cli/adapters/group-builder.test.js +26 -2
  65. package/dist/src/cli/adapters/group-builder.test.js.map +1 -1
  66. package/dist/src/cli/adapters/help-formatter.d.ts.map +1 -1
  67. package/dist/src/cli/adapters/help-formatter.js +4 -3
  68. package/dist/src/cli/adapters/help-formatter.js.map +1 -1
  69. package/dist/src/cli/adapters/help-formatter.test.js +1 -1
  70. package/dist/src/cli/adapters/help-formatter.test.js.map +1 -1
  71. package/dist/src/cli/adapters/playtest-edit-guard.test.d.ts +2 -0
  72. package/dist/src/cli/adapters/playtest-edit-guard.test.d.ts.map +1 -0
  73. package/dist/src/cli/adapters/playtest-edit-guard.test.js +28 -0
  74. package/dist/src/cli/adapters/playtest-edit-guard.test.js.map +1 -0
  75. package/dist/src/cli/args/global-args.d.ts +1 -1
  76. package/dist/src/cli/args/global-args.d.ts.map +1 -1
  77. package/dist/src/cli/cli-output-context.d.ts +14 -0
  78. package/dist/src/cli/cli-output-context.d.ts.map +1 -0
  79. package/dist/src/cli/cli-output-context.js +39 -0
  80. package/dist/src/cli/cli-output-context.js.map +1 -0
  81. package/dist/src/cli/cli-output-context.test.d.ts +2 -0
  82. package/dist/src/cli/cli-output-context.test.d.ts.map +1 -0
  83. package/dist/src/cli/cli-output-context.test.js +38 -0
  84. package/dist/src/cli/cli-output-context.test.js.map +1 -0
  85. package/dist/src/cli/cli.js +40 -17
  86. package/dist/src/cli/cli.js.map +1 -1
  87. package/dist/src/cli/managed-studio-run.d.ts +21 -0
  88. package/dist/src/cli/managed-studio-run.d.ts.map +1 -0
  89. package/dist/src/cli/managed-studio-run.js +75 -0
  90. package/dist/src/cli/managed-studio-run.js.map +1 -0
  91. package/dist/src/cli/managed-studio-run.test.d.ts +2 -0
  92. package/dist/src/cli/managed-studio-run.test.d.ts.map +1 -0
  93. package/dist/src/cli/managed-studio-run.test.js +52 -0
  94. package/dist/src/cli/managed-studio-run.test.js.map +1 -0
  95. package/dist/src/cli/resolve-session.js +1 -1
  96. package/dist/src/cli/resolve-session.js.map +1 -1
  97. package/dist/src/cli/resolve-session.test.js +1 -1
  98. package/dist/src/cli/resolve-session.test.js.map +1 -1
  99. package/dist/src/cli/script-executor.d.ts +13 -1
  100. package/dist/src/cli/script-executor.d.ts.map +1 -1
  101. package/dist/src/cli/script-executor.js +77 -47
  102. package/dist/src/cli/script-executor.js.map +1 -1
  103. package/dist/src/commands/console/exec/exec.d.ts +17 -0
  104. package/dist/src/commands/console/exec/exec.d.ts.map +1 -1
  105. package/dist/src/commands/console/exec/exec.js +39 -7
  106. package/dist/src/commands/console/exec/exec.js.map +1 -1
  107. package/dist/src/commands/console/exec/exec.test.js +62 -3
  108. package/dist/src/commands/console/exec/exec.test.js.map +1 -1
  109. package/dist/src/commands/console/logs/logs.d.ts +30 -2
  110. package/dist/src/commands/console/logs/logs.d.ts.map +1 -1
  111. package/dist/src/commands/console/logs/logs.js +82 -7
  112. package/dist/src/commands/console/logs/logs.js.map +1 -1
  113. package/dist/src/commands/console/logs/logs.test.js +63 -4
  114. package/dist/src/commands/console/logs/logs.test.js.map +1 -1
  115. package/dist/src/commands/explorer/export/export.d.ts +19 -0
  116. package/dist/src/commands/explorer/export/export.d.ts.map +1 -0
  117. package/dist/src/commands/explorer/export/export.js +37 -0
  118. package/dist/src/commands/explorer/export/export.js.map +1 -0
  119. package/dist/src/commands/explorer/export/export.test.d.ts +2 -0
  120. package/dist/src/commands/explorer/export/export.test.d.ts.map +1 -0
  121. package/dist/src/commands/explorer/export/export.test.js +25 -0
  122. package/dist/src/commands/explorer/export/export.test.js.map +1 -0
  123. package/dist/src/commands/explorer/find/find.d.ts +28 -0
  124. package/dist/src/commands/explorer/find/find.d.ts.map +1 -0
  125. package/dist/src/commands/explorer/find/find.js +75 -0
  126. package/dist/src/commands/explorer/find/find.js.map +1 -0
  127. package/dist/src/commands/explorer/find/find.test.d.ts +2 -0
  128. package/dist/src/commands/explorer/find/find.test.d.ts.map +1 -0
  129. package/dist/src/commands/explorer/find/find.test.js +44 -0
  130. package/dist/src/commands/explorer/find/find.test.js.map +1 -0
  131. package/dist/src/commands/explorer/grep/grep.d.ts +24 -0
  132. package/dist/src/commands/explorer/grep/grep.d.ts.map +1 -0
  133. package/dist/src/commands/explorer/grep/grep.js +63 -0
  134. package/dist/src/commands/explorer/grep/grep.js.map +1 -0
  135. package/dist/src/commands/explorer/grep/grep.test.d.ts +2 -0
  136. package/dist/src/commands/explorer/grep/grep.test.d.ts.map +1 -0
  137. package/dist/src/commands/explorer/grep/grep.test.js +42 -0
  138. package/dist/src/commands/explorer/grep/grep.test.js.map +1 -0
  139. package/dist/src/commands/explorer/import/import.d.ts +21 -0
  140. package/dist/src/commands/explorer/import/import.d.ts.map +1 -0
  141. package/dist/src/commands/explorer/import/import.js +37 -0
  142. package/dist/src/commands/explorer/import/import.js.map +1 -0
  143. package/dist/src/commands/explorer/import/import.test.d.ts +2 -0
  144. package/dist/src/commands/explorer/import/import.test.d.ts.map +1 -0
  145. package/dist/src/commands/explorer/import/import.test.js +45 -0
  146. package/dist/src/commands/explorer/import/import.test.js.map +1 -0
  147. package/dist/src/commands/formatters.test.js +7 -1
  148. package/dist/src/commands/formatters.test.js.map +1 -1
  149. package/dist/src/commands/framework/action-loader.d.ts +5 -1
  150. package/dist/src/commands/framework/action-loader.d.ts.map +1 -1
  151. package/dist/src/commands/framework/action-loader.js +9 -2
  152. package/dist/src/commands/framework/action-loader.js.map +1 -1
  153. package/dist/src/commands/framework/action-loader.test.js +23 -0
  154. package/dist/src/commands/framework/action-loader.test.js.map +1 -1
  155. package/dist/src/commands/framework/arg-builder.d.ts +15 -2
  156. package/dist/src/commands/framework/arg-builder.d.ts.map +1 -1
  157. package/dist/src/commands/framework/arg-builder.js +22 -2
  158. package/dist/src/commands/framework/arg-builder.js.map +1 -1
  159. package/dist/src/commands/framework/define-command.d.ts +19 -3
  160. package/dist/src/commands/framework/define-command.d.ts.map +1 -1
  161. package/dist/src/commands/framework/define-command.js.map +1 -1
  162. package/dist/src/commands/framework/index.d.ts +1 -1
  163. package/dist/src/commands/framework/index.d.ts.map +1 -1
  164. package/dist/src/commands/framework/index.js.map +1 -1
  165. package/dist/src/commands/index.d.ts +11 -0
  166. package/dist/src/commands/index.d.ts.map +1 -1
  167. package/dist/src/commands/index.js +11 -0
  168. package/dist/src/commands/index.js.map +1 -1
  169. package/dist/src/commands/linux/inject-credentials/inject-credentials.d.ts.map +1 -1
  170. package/dist/src/commands/linux/inject-credentials/inject-credentials.js +1 -3
  171. package/dist/src/commands/linux/inject-credentials/inject-credentials.js.map +1 -1
  172. package/dist/src/commands/linux/setup/setup.d.ts.map +1 -1
  173. package/dist/src/commands/linux/setup/setup.js +1 -3
  174. package/dist/src/commands/linux/setup/setup.js.map +1 -1
  175. package/dist/src/commands/linux/status/status.d.ts +9 -1
  176. package/dist/src/commands/linux/status/status.d.ts.map +1 -1
  177. package/dist/src/commands/linux/status/status.js +66 -86
  178. package/dist/src/commands/linux/status/status.js.map +1 -1
  179. package/dist/src/commands/playtest/player/add/add.d.ts +17 -0
  180. package/dist/src/commands/playtest/player/add/add.d.ts.map +1 -0
  181. package/dist/src/commands/playtest/player/add/add.js +45 -0
  182. package/dist/src/commands/playtest/player/add/add.js.map +1 -0
  183. package/dist/src/commands/playtest/player/list/list.d.ts +13 -0
  184. package/dist/src/commands/playtest/player/list/list.d.ts.map +1 -0
  185. package/dist/src/commands/playtest/player/list/list.js +33 -0
  186. package/dist/src/commands/playtest/player/list/list.js.map +1 -0
  187. package/dist/src/commands/playtest/player/playtest-players.d.ts +36 -0
  188. package/dist/src/commands/playtest/player/playtest-players.d.ts.map +1 -0
  189. package/dist/src/commands/playtest/player/playtest-players.js +187 -0
  190. package/dist/src/commands/playtest/player/playtest-players.js.map +1 -0
  191. package/dist/src/commands/playtest/player/playtest-players.test.d.ts +2 -0
  192. package/dist/src/commands/playtest/player/playtest-players.test.d.ts.map +1 -0
  193. package/dist/src/commands/playtest/player/playtest-players.test.js +89 -0
  194. package/dist/src/commands/playtest/player/playtest-players.test.js.map +1 -0
  195. package/dist/src/commands/playtest/player/remove/remove.d.ts +17 -0
  196. package/dist/src/commands/playtest/player/remove/remove.d.ts.map +1 -0
  197. package/dist/src/commands/playtest/player/remove/remove.js +42 -0
  198. package/dist/src/commands/playtest/player/remove/remove.js.map +1 -0
  199. package/dist/src/commands/playtest/playtest-sessions.d.ts +49 -0
  200. package/dist/src/commands/playtest/playtest-sessions.d.ts.map +1 -0
  201. package/dist/src/commands/playtest/playtest-sessions.js +283 -0
  202. package/dist/src/commands/playtest/playtest-sessions.js.map +1 -0
  203. package/dist/src/commands/playtest/playtest-sessions.test.d.ts +2 -0
  204. package/dist/src/commands/playtest/playtest-sessions.test.d.ts.map +1 -0
  205. package/dist/src/commands/playtest/playtest-sessions.test.js +87 -0
  206. package/dist/src/commands/playtest/playtest-sessions.test.js.map +1 -0
  207. package/dist/src/commands/playtest/restart/restart.d.ts +23 -0
  208. package/dist/src/commands/playtest/restart/restart.d.ts.map +1 -0
  209. package/dist/src/commands/playtest/restart/restart.js +105 -0
  210. package/dist/src/commands/playtest/restart/restart.js.map +1 -0
  211. package/dist/src/commands/playtest/run/run.d.ts +47 -0
  212. package/dist/src/commands/playtest/run/run.d.ts.map +1 -0
  213. package/dist/src/commands/playtest/run/run.js +137 -0
  214. package/dist/src/commands/playtest/run/run.js.map +1 -0
  215. package/dist/src/commands/playtest/start/start.d.ts +42 -0
  216. package/dist/src/commands/playtest/start/start.d.ts.map +1 -0
  217. package/dist/src/commands/playtest/start/start.js +70 -0
  218. package/dist/src/commands/playtest/start/start.js.map +1 -0
  219. package/dist/src/commands/playtest/stop/stop.d.ts +15 -0
  220. package/dist/src/commands/playtest/stop/stop.d.ts.map +1 -0
  221. package/dist/src/commands/playtest/stop/stop.js +24 -0
  222. package/dist/src/commands/playtest/stop/stop.js.map +1 -0
  223. package/dist/src/commands/process/close/close.d.ts +19 -10
  224. package/dist/src/commands/process/close/close.d.ts.map +1 -1
  225. package/dist/src/commands/process/close/close.js +118 -15
  226. package/dist/src/commands/process/close/close.js.map +1 -1
  227. package/dist/src/commands/process/close/close.test.d.ts +2 -0
  228. package/dist/src/commands/process/close/close.test.d.ts.map +1 -0
  229. package/dist/src/commands/process/close/close.test.js +190 -0
  230. package/dist/src/commands/process/close/close.test.js.map +1 -0
  231. package/dist/src/commands/process/info/info.d.ts +45 -5
  232. package/dist/src/commands/process/info/info.d.ts.map +1 -1
  233. package/dist/src/commands/process/info/info.js +117 -13
  234. package/dist/src/commands/process/info/info.js.map +1 -1
  235. package/dist/src/commands/process/info/info.test.js +140 -38
  236. package/dist/src/commands/process/info/info.test.js.map +1 -1
  237. package/dist/src/commands/process/launch/launch.d.ts +11 -1
  238. package/dist/src/commands/process/launch/launch.d.ts.map +1 -1
  239. package/dist/src/commands/process/launch/launch.js +37 -7
  240. package/dist/src/commands/process/launch/launch.js.map +1 -1
  241. package/dist/src/commands/process/launch/launch.test.js +99 -20
  242. package/dist/src/commands/process/launch/launch.test.js.map +1 -1
  243. package/dist/src/commands/process/list/list.d.ts +2 -1
  244. package/dist/src/commands/process/list/list.d.ts.map +1 -1
  245. package/dist/src/commands/process/list/list.js +9 -6
  246. package/dist/src/commands/process/list/list.js.map +1 -1
  247. package/dist/src/commands/process/list/list.test.js +1 -0
  248. package/dist/src/commands/process/list/list.test.js.map +1 -1
  249. package/dist/src/commands/process/run/run.d.ts +9 -0
  250. package/dist/src/commands/process/run/run.d.ts.map +1 -1
  251. package/dist/src/commands/process/run/run.js +15 -5
  252. package/dist/src/commands/process/run/run.js.map +1 -1
  253. package/dist/src/commands/serve/serve.d.ts +2 -0
  254. package/dist/src/commands/serve/serve.d.ts.map +1 -1
  255. package/dist/src/commands/serve/serve.js +17 -4
  256. package/dist/src/commands/serve/serve.js.map +1 -1
  257. package/dist/src/commands/serve/serve.test.js +9 -2
  258. package/dist/src/commands/serve/serve.test.js.map +1 -1
  259. package/dist/src/commands/viewport/screenshot/screenshot.d.ts.map +1 -1
  260. package/dist/src/commands/viewport/screenshot/screenshot.js +4 -1
  261. package/dist/src/commands/viewport/screenshot/screenshot.js.map +1 -1
  262. package/dist/src/commands/viewport/screenshot/screenshot.test.js +5 -9
  263. package/dist/src/commands/viewport/screenshot/screenshot.test.js.map +1 -1
  264. package/dist/src/deploy/deploy-places.d.ts +39 -0
  265. package/dist/src/deploy/deploy-places.d.ts.map +1 -0
  266. package/dist/src/deploy/deploy-places.js +162 -0
  267. package/dist/src/deploy/deploy-places.js.map +1 -0
  268. package/dist/src/deploy/deploy-places.test.d.ts +2 -0
  269. package/dist/src/deploy/deploy-places.test.d.ts.map +1 -0
  270. package/dist/src/deploy/deploy-places.test.js +96 -0
  271. package/dist/src/deploy/deploy-places.test.js.map +1 -0
  272. package/dist/src/index.d.ts +2 -2
  273. package/dist/src/index.d.ts.map +1 -1
  274. package/dist/src/index.js +1 -1
  275. package/dist/src/index.js.map +1 -1
  276. package/dist/src/plugin/persistent-plugin-installer.d.ts.map +1 -1
  277. package/dist/src/plugin/persistent-plugin-installer.js +2 -1
  278. package/dist/src/plugin/persistent-plugin-installer.js.map +1 -1
  279. package/dist/src/plugin/persistent-plugin-installer.test.js +3 -0
  280. package/dist/src/plugin/persistent-plugin-installer.test.js.map +1 -1
  281. package/dist/src/plugin/plugin-build-version.d.ts +7 -0
  282. package/dist/src/plugin/plugin-build-version.d.ts.map +1 -0
  283. package/dist/src/plugin/plugin-build-version.js +42 -0
  284. package/dist/src/plugin/plugin-build-version.js.map +1 -0
  285. package/dist/src/plugin/plugin-build-version.test.d.ts +2 -0
  286. package/dist/src/plugin/plugin-build-version.test.d.ts.map +1 -0
  287. package/dist/src/plugin/plugin-build-version.test.js +41 -0
  288. package/dist/src/plugin/plugin-build-version.test.js.map +1 -0
  289. package/dist/src/plugin/plugin-injector.d.ts.map +1 -1
  290. package/dist/src/plugin/plugin-injector.js +7 -1
  291. package/dist/src/plugin/plugin-injector.js.map +1 -1
  292. package/dist/src/process/studio-process-closer.d.ts +35 -0
  293. package/dist/src/process/studio-process-closer.d.ts.map +1 -0
  294. package/dist/src/process/studio-process-closer.js +129 -0
  295. package/dist/src/process/studio-process-closer.js.map +1 -0
  296. package/dist/src/process/studio-process-closer.test.d.ts +2 -0
  297. package/dist/src/process/studio-process-closer.test.d.ts.map +1 -0
  298. package/dist/src/process/studio-process-closer.test.js +80 -0
  299. package/dist/src/process/studio-process-closer.test.js.map +1 -0
  300. package/dist/src/process/studio-settings.d.ts +14 -0
  301. package/dist/src/process/studio-settings.d.ts.map +1 -0
  302. package/dist/src/process/studio-settings.js +50 -0
  303. package/dist/src/process/studio-settings.js.map +1 -0
  304. package/dist/src/process/studio-settings.test.d.ts +2 -0
  305. package/dist/src/process/studio-settings.test.d.ts.map +1 -0
  306. package/dist/src/process/studio-settings.test.js +16 -0
  307. package/dist/src/process/studio-settings.test.js.map +1 -0
  308. package/dist/src/process/studio-window-state.d.ts +13 -0
  309. package/dist/src/process/studio-window-state.d.ts.map +1 -0
  310. package/dist/src/process/studio-window-state.js +48 -0
  311. package/dist/src/process/studio-window-state.js.map +1 -0
  312. package/dist/src/server/studio-bridge-server.d.ts +3 -1
  313. package/dist/src/server/studio-bridge-server.d.ts.map +1 -1
  314. package/dist/src/server/studio-bridge-server.js +12 -4
  315. package/dist/src/server/studio-bridge-server.js.map +1 -1
  316. package/dist/src/server/web-socket-protocol.d.ts +173 -6
  317. package/dist/src/server/web-socket-protocol.d.ts.map +1 -1
  318. package/dist/src/server/web-socket-protocol.js +244 -1
  319. package/dist/src/server/web-socket-protocol.js.map +1 -1
  320. package/dist/src/server/web-socket-protocol.test.js +48 -0
  321. package/dist/src/server/web-socket-protocol.test.js.map +1 -1
  322. package/dist/src/test/e2e/persistent-session.test.js +121 -0
  323. package/dist/src/test/e2e/persistent-session.test.js.map +1 -1
  324. package/dist/src/test/e2e/split-server.test.d.ts +3 -5
  325. package/dist/src/test/e2e/split-server.test.d.ts.map +1 -1
  326. package/dist/src/test/e2e/split-server.test.js +3 -5
  327. package/dist/src/test/e2e/split-server.test.js.map +1 -1
  328. package/dist/tsconfig.tsbuildinfo +1 -1
  329. package/docker/Dockerfile +3 -0
  330. package/package.json +8 -6
  331. package/src/bridge/bridge-connection.test.ts +126 -0
  332. package/src/bridge/bridge-connection.ts +217 -22
  333. package/src/bridge/bridge-session.test.ts +6 -4
  334. package/src/bridge/bridge-session.ts +273 -28
  335. package/src/bridge/index.ts +3 -0
  336. package/src/bridge/internal/bridge-client.test.ts +23 -0
  337. package/src/bridge/internal/bridge-client.ts +25 -7
  338. package/src/bridge/internal/bridge-host.test.ts +38 -0
  339. package/src/bridge/internal/bridge-host.ts +47 -0
  340. package/src/bridge/internal/hand-off.ts +4 -1
  341. package/src/bridge/internal/host-protocol.test.ts +15 -0
  342. package/src/bridge/internal/host-protocol.ts +148 -37
  343. package/src/bridge/internal/instance-state.ts +34 -0
  344. package/src/bridge/internal/transport-client.ts +2 -1
  345. package/src/bridge/internal/transport-server.ts +5 -1
  346. package/src/bridge/types.ts +47 -2
  347. package/src/cli/adapters/cli-command-adapter-handler.test.ts +28 -0
  348. package/src/cli/adapters/cli-command-adapter.ts +150 -18
  349. package/src/cli/adapters/group-builder.test.ts +34 -2
  350. package/src/cli/adapters/group-builder.ts +52 -20
  351. package/src/cli/adapters/help-formatter.test.ts +1 -1
  352. package/src/cli/adapters/help-formatter.ts +4 -3
  353. package/src/cli/adapters/playtest-edit-guard.test.ts +54 -0
  354. package/src/cli/args/global-args.ts +1 -1
  355. package/src/cli/cli-output-context.test.ts +55 -0
  356. package/src/cli/cli-output-context.ts +50 -0
  357. package/src/cli/cli.ts +49 -17
  358. package/src/cli/managed-studio-run.test.ts +71 -0
  359. package/src/cli/managed-studio-run.ts +135 -0
  360. package/src/cli/resolve-session.test.ts +1 -1
  361. package/src/cli/resolve-session.ts +1 -1
  362. package/src/cli/script-executor.ts +99 -51
  363. package/src/commands/console/exec/exec.test.ts +96 -3
  364. package/src/commands/console/exec/exec.ts +59 -6
  365. package/src/commands/console/exec/execute.lua +356 -240
  366. package/src/commands/console/exec/execute.spec.lua +286 -0
  367. package/src/commands/console/logs/logs.test.ts +76 -4
  368. package/src/commands/console/logs/logs.ts +132 -17
  369. package/src/commands/console/logs/query-logs.lua +85 -52
  370. package/src/commands/console/logs/query-logs.spec.lua +132 -0
  371. package/src/commands/explorer/export/export-instances.lua +108 -0
  372. package/src/commands/explorer/export/export-instances.spec.lua +87 -0
  373. package/src/commands/explorer/export/export.test.ts +27 -0
  374. package/src/commands/explorer/export/export.ts +60 -0
  375. package/src/commands/explorer/find/find-instances.lua +174 -0
  376. package/src/commands/explorer/find/find-instances.spec.lua +122 -0
  377. package/src/commands/explorer/find/find.test.ts +53 -0
  378. package/src/commands/explorer/find/find.ts +113 -0
  379. package/src/commands/explorer/grep/grep-scripts.lua +214 -0
  380. package/src/commands/explorer/grep/grep-scripts.spec.lua +130 -0
  381. package/src/commands/explorer/grep/grep.test.ts +45 -0
  382. package/src/commands/explorer/grep/grep.ts +93 -0
  383. package/src/commands/explorer/import/import-instances.lua +106 -0
  384. package/src/commands/explorer/import/import-instances.spec.lua +84 -0
  385. package/src/commands/explorer/import/import.test.ts +60 -0
  386. package/src/commands/explorer/import/import.ts +66 -0
  387. package/src/commands/explorer/query/query-data-model.lua +124 -152
  388. package/src/commands/explorer/query/query-data-model.spec.lua +150 -0
  389. package/src/commands/formatters.test.ts +7 -1
  390. package/src/commands/framework/action-loader.test.ts +28 -0
  391. package/src/commands/framework/action-loader.ts +10 -2
  392. package/src/commands/framework/arg-builder.ts +26 -3
  393. package/src/commands/framework/define-command.ts +32 -3
  394. package/src/commands/framework/index.ts +1 -0
  395. package/src/commands/index.ts +50 -0
  396. package/src/commands/linux/inject-credentials/inject-credentials.ts +1 -3
  397. package/src/commands/linux/setup/setup.ts +1 -3
  398. package/src/commands/linux/status/status.ts +105 -98
  399. package/src/commands/playtest/player/add/add.ts +85 -0
  400. package/src/commands/playtest/player/list/list.ts +57 -0
  401. package/src/commands/playtest/player/playtest-players.test.ts +146 -0
  402. package/src/commands/playtest/player/playtest-players.ts +270 -0
  403. package/src/commands/playtest/player/remove/remove.ts +78 -0
  404. package/src/commands/playtest/playtest-sessions.test.ts +143 -0
  405. package/src/commands/playtest/playtest-sessions.ts +417 -0
  406. package/src/commands/playtest/restart/restart.ts +199 -0
  407. package/src/commands/playtest/run/playtest-runner.luau +264 -0
  408. package/src/commands/playtest/run/playtest-runner.spec.lua +71 -0
  409. package/src/commands/playtest/run/run-playtest-script.lua +139 -0
  410. package/src/commands/playtest/run/run-playtest-script.spec.lua +43 -0
  411. package/src/commands/playtest/run/run.ts +239 -0
  412. package/src/commands/playtest/start/start-playtest.lua +108 -0
  413. package/src/commands/playtest/start/start.ts +138 -0
  414. package/src/commands/playtest/stop/end-playtest.lua +47 -0
  415. package/src/commands/playtest/stop/stop.ts +51 -0
  416. package/src/commands/process/close/close.test.ts +250 -0
  417. package/src/commands/process/close/close.ts +183 -17
  418. package/src/commands/process/info/info.test.ts +198 -44
  419. package/src/commands/process/info/info.ts +204 -15
  420. package/src/commands/process/info/query-state.lua +42 -29
  421. package/src/commands/process/info/query-state.spec.lua +39 -0
  422. package/src/commands/process/launch/launch.test.ts +138 -21
  423. package/src/commands/process/launch/launch.ts +69 -9
  424. package/src/commands/process/list/list.test.ts +1 -0
  425. package/src/commands/process/list/list.ts +14 -6
  426. package/src/commands/process/run/run.ts +26 -5
  427. package/src/commands/serve/serve.test.ts +17 -2
  428. package/src/commands/serve/serve.ts +25 -6
  429. package/src/commands/viewport/screenshot/capture-screenshot.lua +175 -182
  430. package/src/commands/viewport/screenshot/capture-screenshot.spec.lua +129 -0
  431. package/src/commands/viewport/screenshot/screenshot.test.ts +7 -10
  432. package/src/commands/viewport/screenshot/screenshot.ts +6 -1
  433. package/src/deploy/deploy-places.test.ts +127 -0
  434. package/src/deploy/deploy-places.ts +229 -0
  435. package/src/index.ts +11 -0
  436. package/src/plugin/persistent-plugin-installer.test.ts +4 -0
  437. package/src/plugin/persistent-plugin-installer.ts +2 -1
  438. package/src/plugin/plugin-build-version.test.ts +55 -0
  439. package/src/plugin/plugin-build-version.ts +53 -0
  440. package/src/plugin/plugin-injector.ts +7 -1
  441. package/src/process/studio-process-closer.test.ts +107 -0
  442. package/src/process/studio-process-closer.ts +187 -0
  443. package/src/process/studio-settings.test.ts +18 -0
  444. package/src/process/studio-settings.ts +61 -0
  445. package/src/process/studio-window-state.ts +65 -0
  446. package/src/server/studio-bridge-server.ts +15 -4
  447. package/src/server/web-socket-protocol.test.ts +55 -0
  448. package/src/server/web-socket-protocol.ts +468 -8
  449. package/src/test/e2e/persistent-session.test.ts +137 -0
  450. package/src/test/e2e/split-server.test.ts +3 -5
  451. package/templates/studio-bridge-plugin/default.project.json +3 -0
  452. package/templates/studio-bridge-plugin/src/Shared/ActionRouter.lua +208 -159
  453. package/templates/studio-bridge-plugin/src/Shared/ActionRouter.spec.lua +418 -0
  454. package/templates/studio-bridge-plugin/src/Shared/BuiltInActions.lua +94 -0
  455. package/templates/studio-bridge-plugin/src/Shared/BuiltInActions.spec.lua +166 -0
  456. package/templates/studio-bridge-plugin/src/Shared/DiscoveryStateMachine.lua +118 -137
  457. package/templates/studio-bridge-plugin/src/Shared/DiscoveryStateMachine.spec.lua +228 -0
  458. package/templates/studio-bridge-plugin/src/Shared/MessageBuffer.lua +80 -109
  459. package/templates/studio-bridge-plugin/src/Shared/MessageBuffer.spec.lua +116 -0
  460. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeConnection.lua +233 -0
  461. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeConnection.spec.lua +239 -0
  462. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeLogUtils.lua +53 -0
  463. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeLogUtils.spec.lua +27 -0
  464. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeSessionUtils.lua +164 -0
  465. package/templates/studio-bridge-plugin/src/Shared/StudioBridgeSessionUtils.spec.lua +159 -0
  466. package/templates/studio-bridge-plugin/src/StudioBridgePlugin.server.lua +266 -368
  467. package/templates/studio-bridge-plugin/src/Vendor/png.lua +8 -2
  468. package/test/default.project.json +41 -0
  469. package/test/jest.config.lua +3 -0
  470. package/test/scripts/Server/ServerMain.server.lua +10 -0
  471. package/tsconfig.json +1 -0
  472. package/templates/studio-bridge-plugin/src/Shared/Protocol.lua +0 -132
  473. package/templates/studio-bridge-plugin-test/test/actions.test.lua +0 -580
  474. package/templates/studio-bridge-plugin-test/test/discovery.test.lua +0 -622
  475. package/templates/studio-bridge-plugin-test/test/execute-handler.test.lua +0 -517
  476. package/templates/studio-bridge-plugin-test/test/hash-lifecycle.test.lua +0 -814
  477. package/templates/studio-bridge-plugin-test/test/integration.test.lua +0 -1020
  478. package/templates/studio-bridge-plugin-test/test/new-actions.test.lua +0 -339
  479. package/templates/studio-bridge-plugin-test/test/plugin-entry.test.lua +0 -493
  480. package/templates/studio-bridge-plugin-test/test/protocol.test.lua +0 -506
  481. package/templates/studio-bridge-plugin-test/test/roblox-mocks.lua +0 -108
  482. package/templates/studio-bridge-plugin-test/test/test-runner.lua +0 -112
@@ -1,814 +0,0 @@
1
- --[[
2
- Tests for Phase 2 action lifecycle: hash-based skip, handler tracking,
3
- getInstalledActions, and syncActions.
4
-
5
- Validates that:
6
- - registerAction with same hash skips re-registration
7
- - registerAction with different hash re-registers (replaces old handlers)
8
- - registerAction without hash always re-registers
9
- - getInstalledActions returns correct hash map
10
- - syncActions returns correct needed/installed lists
11
- - Handler tracking captures newly registered handler names
12
- ]]
13
-
14
- local ActionRouter = require("../../studio-bridge-plugin/src/Shared/ActionRouter")
15
-
16
- -- ---------------------------------------------------------------------------
17
- -- Test helpers
18
- -- ---------------------------------------------------------------------------
19
-
20
- local function assertEqual(actual: any, expected: any, label: string?)
21
- if actual ~= expected then
22
- error(
23
- string.format(
24
- "%sexpected %s, got %s",
25
- if label then label .. ": " else "",
26
- tostring(expected),
27
- tostring(actual)
28
- )
29
- )
30
- end
31
- end
32
-
33
- local function assertNotNil(value: any, label: string?)
34
- if value == nil then
35
- error(string.format("%sexpected non-nil value", if label then label .. ": " else ""))
36
- end
37
- end
38
-
39
- local function assertTrue(value: any, label: string?)
40
- if not value then
41
- error(string.format("%sexpected truthy value, got %s", if label then label .. ": " else "", tostring(value)))
42
- end
43
- end
44
-
45
- local function assertFalse(value: any, label: string?)
46
- if value then
47
- error(string.format("%sexpected falsy value, got %s", if label then label .. ": " else "", tostring(value)))
48
- end
49
- end
50
-
51
- local function assertNil(value: any, label: string?)
52
- if value ~= nil then
53
- error(string.format("%sexpected nil, got %s", if label then label .. ": " else "", tostring(value)))
54
- end
55
- end
56
-
57
- local function assertTableContains(tbl: { any }, value: any, label: string?)
58
- for _, v in tbl do
59
- if v == value then
60
- return
61
- end
62
- end
63
- error(string.format(
64
- "%sexpected table to contain '%s'",
65
- if label then label .. ": " else "",
66
- tostring(value)
67
- ))
68
- end
69
-
70
- -- ---------------------------------------------------------------------------
71
- -- Shared action source helpers
72
- -- ---------------------------------------------------------------------------
73
-
74
- -- A simple action module that registers a handler named "testAction"
75
- local SIMPLE_ACTION_SOURCE = [[
76
- local M = {}
77
- function M.register(router, sendMessage, logBuffer)
78
- router:register("testAction", function(payload, requestId, sessionId)
79
- return { result = "v1" }
80
- end)
81
- router:setResponseType("testAction", "testActionResult")
82
- end
83
- return M
84
- ]]
85
-
86
- -- A different version of the same action module
87
- local SIMPLE_ACTION_SOURCE_V2 = [[
88
- local M = {}
89
- function M.register(router, sendMessage, logBuffer)
90
- router:register("testAction", function(payload, requestId, sessionId)
91
- return { result = "v2" }
92
- end)
93
- router:setResponseType("testAction", "testActionResult")
94
- end
95
- return M
96
- ]]
97
-
98
- -- An action module that registers multiple handlers
99
- local MULTI_HANDLER_SOURCE = [[
100
- local M = {}
101
- function M.register(router, sendMessage, logBuffer)
102
- router:register("sub", function(payload, requestId, sessionId)
103
- return { subscribed = true }
104
- end)
105
- router:setResponseType("sub", "subResult")
106
- router:register("unsub", function(payload, requestId, sessionId)
107
- return { unsubscribed = true }
108
- end)
109
- router:setResponseType("unsub", "unsubResult")
110
- end
111
- return M
112
- ]]
113
-
114
- -- ---------------------------------------------------------------------------
115
- -- Tests
116
- -- ---------------------------------------------------------------------------
117
-
118
- local tests = {}
119
-
120
- -- ===========================================================================
121
- -- Hash-based skip tests
122
- -- ===========================================================================
123
-
124
- table.insert(tests, {
125
- name = "registerAction: same hash skips re-registration",
126
- fn = function()
127
- local router = ActionRouter.new()
128
- local hash = "abc123"
129
-
130
- -- First registration should succeed
131
- local ok1, err1 = router:registerAction("myAction", SIMPLE_ACTION_SOURCE, nil, nil, nil, hash)
132
- assertTrue(ok1, "first registration should succeed")
133
- assertNil(err1, "first registration should not error")
134
-
135
- -- Verify the handler works
136
- local response1 = router:dispatch({
137
- type = "testAction",
138
- sessionId = "sess-1",
139
- requestId = "req-1",
140
- payload = {},
141
- })
142
- assertNotNil(response1, "response from first registration")
143
- assertEqual(response1.payload.result, "v1")
144
-
145
- -- Second registration with same hash should skip (return true, no error)
146
- local ok2, err2 = router:registerAction("myAction", SIMPLE_ACTION_SOURCE, nil, nil, nil, hash)
147
- assertTrue(ok2, "same hash should succeed (skip)")
148
- assertNil(err2, "same hash should not error")
149
-
150
- -- Handler should still work (unchanged)
151
- local response2 = router:dispatch({
152
- type = "testAction",
153
- sessionId = "sess-2",
154
- requestId = "req-2",
155
- payload = {},
156
- })
157
- assertNotNil(response2, "response after skip")
158
- assertEqual(response2.payload.result, "v1", "handler unchanged after skip")
159
- end,
160
- })
161
-
162
- table.insert(tests, {
163
- name = "registerAction: different hash re-registers action",
164
- fn = function()
165
- local router = ActionRouter.new()
166
-
167
- -- Register v1 with hash "abc"
168
- local ok1, _ = router:registerAction("myAction", SIMPLE_ACTION_SOURCE, nil, nil, nil, "abc")
169
- assertTrue(ok1, "v1 registration should succeed")
170
-
171
- -- Verify v1 handler
172
- local r1 = router:dispatch({
173
- type = "testAction",
174
- sessionId = "s1",
175
- requestId = "r1",
176
- payload = {},
177
- })
178
- assertEqual(r1.payload.result, "v1")
179
-
180
- -- Register v2 with different hash "def"
181
- local ok2, _ = router:registerAction("myAction", SIMPLE_ACTION_SOURCE_V2, nil, nil, nil, "def")
182
- assertTrue(ok2, "v2 registration should succeed")
183
-
184
- -- Verify v2 handler replaced v1
185
- local r2 = router:dispatch({
186
- type = "testAction",
187
- sessionId = "s2",
188
- requestId = "r2",
189
- payload = {},
190
- })
191
- assertEqual(r2.payload.result, "v2", "handler should be v2 after re-registration")
192
- end,
193
- })
194
-
195
- table.insert(tests, {
196
- name = "registerAction: nil hash always re-registers",
197
- fn = function()
198
- local router = ActionRouter.new()
199
-
200
- -- Register without hash
201
- local ok1, _ = router:registerAction("myAction", SIMPLE_ACTION_SOURCE, nil, nil, nil, nil)
202
- assertTrue(ok1, "first registration should succeed")
203
-
204
- -- Register again without hash - should not skip
205
- local ok2, _ = router:registerAction("myAction", SIMPLE_ACTION_SOURCE_V2, nil, nil, nil, nil)
206
- assertTrue(ok2, "second registration should succeed")
207
-
208
- -- Should be v2
209
- local r = router:dispatch({
210
- type = "testAction",
211
- sessionId = "s1",
212
- requestId = "r1",
213
- payload = {},
214
- })
215
- assertEqual(r.payload.result, "v2", "handler should be v2 without hash")
216
- end,
217
- })
218
-
219
- -- ===========================================================================
220
- -- Handler tracking tests
221
- -- ===========================================================================
222
-
223
- table.insert(tests, {
224
- name = "registerAction: tracks handler names in _actions",
225
- fn = function()
226
- local router = ActionRouter.new()
227
-
228
- router:registerAction("myAction", SIMPLE_ACTION_SOURCE, nil, nil, nil, "hash1")
229
-
230
- local actionInfo = router._actions["myAction"]
231
- assertNotNil(actionInfo, "action should be tracked")
232
- assertEqual(actionInfo.hash, "hash1", "hash should be stored")
233
- assertNotNil(actionInfo.handlerNames, "handlerNames should exist")
234
- assertEqual(#actionInfo.handlerNames, 1, "should have one handler")
235
- assertEqual(actionInfo.handlerNames[1], "testAction", "handler name should be testAction")
236
- end,
237
- })
238
-
239
- table.insert(tests, {
240
- name = "registerAction: tracks multiple handler names from one module",
241
- fn = function()
242
- local router = ActionRouter.new()
243
-
244
- router:registerAction("multiAction", MULTI_HANDLER_SOURCE, nil, nil, nil, "multi-hash")
245
-
246
- local actionInfo = router._actions["multiAction"]
247
- assertNotNil(actionInfo, "action should be tracked")
248
- assertEqual(#actionInfo.handlerNames, 2, "should have two handlers")
249
-
250
- -- The order may vary, so check both are present
251
- local hasSub = false
252
- local hasUnsub = false
253
- for _, name in actionInfo.handlerNames do
254
- if name == "sub" then hasSub = true end
255
- if name == "unsub" then hasUnsub = true end
256
- end
257
- assertTrue(hasSub, "should have 'sub' handler")
258
- assertTrue(hasUnsub, "should have 'unsub' handler")
259
- end,
260
- })
261
-
262
- table.insert(tests, {
263
- name = "registerAction: re-registration removes old handlers before adding new ones",
264
- fn = function()
265
- local router = ActionRouter.new()
266
-
267
- -- Register multi-handler action
268
- router:registerAction("multiAction", MULTI_HANDLER_SOURCE, nil, nil, nil, "hash-old")
269
-
270
- -- Both handlers should work
271
- local r1 = router:dispatch({
272
- type = "sub",
273
- sessionId = "s1",
274
- requestId = "r1",
275
- payload = {},
276
- })
277
- assertNotNil(r1, "sub handler should exist")
278
- assertEqual(r1.payload.subscribed, true)
279
-
280
- -- Re-register with a single-handler action (different hash)
281
- local SINGLE_SOURCE = [[
282
- local M = {}
283
- function M.register(router, sendMessage, logBuffer)
284
- router:register("newHandler", function(payload, requestId, sessionId)
285
- return { new = true }
286
- end)
287
- end
288
- return M
289
- ]]
290
- router:registerAction("multiAction", SINGLE_SOURCE, nil, nil, nil, "hash-new")
291
-
292
- -- Old handlers should be removed
293
- local r2 = router:dispatch({
294
- type = "sub",
295
- sessionId = "s2",
296
- requestId = "r2",
297
- payload = {},
298
- })
299
- assertEqual(r2.type, "error", "old 'sub' handler should be removed")
300
- assertEqual(r2.payload.code, "UNKNOWN_REQUEST")
301
-
302
- -- New handler should work
303
- local r3 = router:dispatch({
304
- type = "newHandler",
305
- sessionId = "s3",
306
- requestId = "r3",
307
- payload = {},
308
- })
309
- assertNotNil(r3, "newHandler should exist")
310
- assertEqual(r3.payload.new, true)
311
- end,
312
- })
313
-
314
- -- ===========================================================================
315
- -- getInstalledActions tests
316
- -- ===========================================================================
317
-
318
- table.insert(tests, {
319
- name = "getInstalledActions: returns empty map for fresh router",
320
- fn = function()
321
- local router = ActionRouter.new()
322
- local installed = router:getInstalledActions()
323
- local count = 0
324
- for _ in installed do
325
- count = count + 1
326
- end
327
- assertEqual(count, 0, "should be empty")
328
- end,
329
- })
330
-
331
- table.insert(tests, {
332
- name = "getInstalledActions: returns correct hash map after registrations",
333
- fn = function()
334
- local router = ActionRouter.new()
335
-
336
- router:registerAction("action1", SIMPLE_ACTION_SOURCE, nil, nil, nil, "hash-aaa")
337
- router:registerAction("action2", MULTI_HANDLER_SOURCE, nil, nil, nil, "hash-bbb")
338
-
339
- local installed = router:getInstalledActions()
340
- assertEqual(installed["action1"], "hash-aaa", "action1 hash")
341
- assertEqual(installed["action2"], "hash-bbb", "action2 hash")
342
- end,
343
- })
344
-
345
- table.insert(tests, {
346
- name = "getInstalledActions: reflects updated hash after re-registration",
347
- fn = function()
348
- local router = ActionRouter.new()
349
-
350
- router:registerAction("myAction", SIMPLE_ACTION_SOURCE, nil, nil, nil, "old-hash")
351
- assertEqual(router:getInstalledActions()["myAction"], "old-hash")
352
-
353
- router:registerAction("myAction", SIMPLE_ACTION_SOURCE_V2, nil, nil, nil, "new-hash")
354
- assertEqual(router:getInstalledActions()["myAction"], "new-hash", "hash should update")
355
- end,
356
- })
357
-
358
- table.insert(tests, {
359
- name = "getInstalledActions: does not include actions registered without hash",
360
- fn = function()
361
- local router = ActionRouter.new()
362
-
363
- router:registerAction("noHash", SIMPLE_ACTION_SOURCE, nil, nil, nil, nil)
364
- router:registerAction("withHash", MULTI_HANDLER_SOURCE, nil, nil, nil, "some-hash")
365
-
366
- local installed = router:getInstalledActions()
367
- assertNil(installed["noHash"], "no-hash action should not appear")
368
- assertEqual(installed["withHash"], "some-hash", "hashed action should appear")
369
- end,
370
- })
371
-
372
- -- ===========================================================================
373
- -- syncActions handler tests (via dispatch)
374
- -- ===========================================================================
375
-
376
- table.insert(tests, {
377
- name = "syncActions: identifies needed actions when none installed",
378
- fn = function()
379
- local router = ActionRouter.new()
380
-
381
- -- Register the syncActions handler (simulating what StudioBridgePlugin does)
382
- router:register("syncActions", function(payload, requestId, sessionId)
383
- local clientActions = payload.actions or {}
384
- local installed = router:getInstalledActions()
385
- local needed = {}
386
-
387
- for name, clientHash in clientActions do
388
- if installed[name] ~= clientHash then
389
- table.insert(needed, name)
390
- end
391
- end
392
-
393
- return { needed = needed, installed = installed }
394
- end)
395
- router:setResponseType("syncActions", "syncActionsResult")
396
-
397
- local response = router:dispatch({
398
- type = "syncActions",
399
- sessionId = "sess-1",
400
- requestId = "req-1",
401
- payload = {
402
- actions = {
403
- exec = "hash-exec",
404
- logs = "hash-logs",
405
- },
406
- },
407
- })
408
-
409
- assertNotNil(response)
410
- assertEqual(response.type, "syncActionsResult")
411
- assertEqual(#response.payload.needed, 2, "both should be needed")
412
- end,
413
- })
414
-
415
- table.insert(tests, {
416
- name = "syncActions: skips already-installed matching hashes",
417
- fn = function()
418
- local router = ActionRouter.new()
419
-
420
- -- Install one action with a known hash
421
- router:registerAction("action1", SIMPLE_ACTION_SOURCE, nil, nil, nil, "hash-aaa")
422
-
423
- -- Register syncActions handler
424
- router:register("syncActions", function(payload, requestId, sessionId)
425
- local clientActions = payload.actions or {}
426
- local installed = router:getInstalledActions()
427
- local needed = {}
428
-
429
- for name, clientHash in clientActions do
430
- if installed[name] ~= clientHash then
431
- table.insert(needed, name)
432
- end
433
- end
434
-
435
- return { needed = needed, installed = installed }
436
- end)
437
- router:setResponseType("syncActions", "syncActionsResult")
438
-
439
- local response = router:dispatch({
440
- type = "syncActions",
441
- sessionId = "sess-1",
442
- requestId = "req-1",
443
- payload = {
444
- actions = {
445
- action1 = "hash-aaa", -- matches installed
446
- action2 = "hash-bbb", -- not installed
447
- },
448
- },
449
- })
450
-
451
- assertNotNil(response)
452
- assertEqual(#response.payload.needed, 1, "only one should be needed")
453
- assertEqual(response.payload.needed[1], "action2", "action2 should be needed")
454
- assertEqual(response.payload.installed["action1"], "hash-aaa", "installed should include action1")
455
- end,
456
- })
457
-
458
- table.insert(tests, {
459
- name = "syncActions: detects hash mismatch for installed actions",
460
- fn = function()
461
- local router = ActionRouter.new()
462
-
463
- -- Install action with hash "old-hash"
464
- router:registerAction("myAction", SIMPLE_ACTION_SOURCE, nil, nil, nil, "old-hash")
465
-
466
- -- Register syncActions handler
467
- router:register("syncActions", function(payload, requestId, sessionId)
468
- local clientActions = payload.actions or {}
469
- local installed = router:getInstalledActions()
470
- local needed = {}
471
-
472
- for name, clientHash in clientActions do
473
- if installed[name] ~= clientHash then
474
- table.insert(needed, name)
475
- end
476
- end
477
-
478
- return { needed = needed, installed = installed }
479
- end)
480
- router:setResponseType("syncActions", "syncActionsResult")
481
-
482
- local response = router:dispatch({
483
- type = "syncActions",
484
- sessionId = "sess-1",
485
- requestId = "req-1",
486
- payload = {
487
- actions = {
488
- myAction = "new-hash", -- different from installed
489
- },
490
- },
491
- })
492
-
493
- assertNotNil(response)
494
- assertEqual(#response.payload.needed, 1, "mismatched hash should be needed")
495
- assertEqual(response.payload.needed[1], "myAction")
496
- end,
497
- })
498
-
499
- table.insert(tests, {
500
- name = "syncActions: empty client actions returns empty needed",
501
- fn = function()
502
- local router = ActionRouter.new()
503
-
504
- router:registerAction("myAction", SIMPLE_ACTION_SOURCE, nil, nil, nil, "some-hash")
505
-
506
- -- Register syncActions handler
507
- router:register("syncActions", function(payload, requestId, sessionId)
508
- local clientActions = payload.actions or {}
509
- local installed = router:getInstalledActions()
510
- local needed = {}
511
-
512
- for name, clientHash in clientActions do
513
- if installed[name] ~= clientHash then
514
- table.insert(needed, name)
515
- end
516
- end
517
-
518
- return { needed = needed, installed = installed }
519
- end)
520
- router:setResponseType("syncActions", "syncActionsResult")
521
-
522
- local response = router:dispatch({
523
- type = "syncActions",
524
- sessionId = "sess-1",
525
- requestId = "req-1",
526
- payload = {},
527
- })
528
-
529
- assertNotNil(response)
530
- assertEqual(#response.payload.needed, 0, "nothing should be needed")
531
- assertEqual(response.payload.installed["myAction"], "some-hash")
532
- end,
533
- })
534
-
535
- -- ===========================================================================
536
- -- registerAction handler response format (simulating plugin handler)
537
- -- ===========================================================================
538
-
539
- table.insert(tests, {
540
- name = "registerAction handler: returns skipped=true for matching hash",
541
- fn = function()
542
- local router = ActionRouter.new()
543
-
544
- -- Simulate the registerAction built-in handler from StudioBridgePlugin
545
- router:register("registerAction", function(payload, requestId, sessionId)
546
- local name = payload.name
547
- local source = payload.source
548
- local hash = payload.hash
549
-
550
- if type(hash) == "string" and router._actions[name] and router._actions[name].hash == hash then
551
- return {
552
- name = name,
553
- success = true,
554
- skipped = true,
555
- hash = hash,
556
- handlers = router._actions[name].handlerNames,
557
- }
558
- end
559
-
560
- local success, err = router:registerAction(name, source, nil, nil, nil, hash)
561
- local handlers = {}
562
- if success and router._actions[name] then
563
- handlers = router._actions[name].handlerNames
564
- end
565
-
566
- return {
567
- name = name,
568
- success = success,
569
- skipped = false,
570
- hash = hash,
571
- handlers = handlers,
572
- error = err,
573
- }
574
- end)
575
- router:setResponseType("registerAction", "registerActionResult")
576
-
577
- -- First registration
578
- local r1 = router:dispatch({
579
- type = "registerAction",
580
- sessionId = "sess-1",
581
- requestId = "req-1",
582
- payload = { name = "myAction", source = SIMPLE_ACTION_SOURCE, hash = "abc123" },
583
- })
584
- assertNotNil(r1)
585
- assertEqual(r1.type, "registerActionResult")
586
- assertTrue(r1.payload.success, "first registration should succeed")
587
- assertFalse(r1.payload.skipped, "first registration should not be skipped")
588
- assertEqual(r1.payload.hash, "abc123")
589
- assertEqual(#r1.payload.handlers, 1)
590
- assertEqual(r1.payload.handlers[1], "testAction")
591
-
592
- -- Second registration with same hash
593
- local r2 = router:dispatch({
594
- type = "registerAction",
595
- sessionId = "sess-2",
596
- requestId = "req-2",
597
- payload = { name = "myAction", source = SIMPLE_ACTION_SOURCE, hash = "abc123" },
598
- })
599
- assertNotNil(r2)
600
- assertTrue(r2.payload.success, "skip registration should succeed")
601
- assertTrue(r2.payload.skipped, "same hash should be skipped")
602
- assertEqual(r2.payload.hash, "abc123")
603
- assertEqual(#r2.payload.handlers, 1)
604
- end,
605
- })
606
-
607
- table.insert(tests, {
608
- name = "registerAction handler: returns new handlers on hash change",
609
- fn = function()
610
- local router = ActionRouter.new()
611
-
612
- -- Simplified registerAction handler
613
- router:register("registerAction", function(payload, requestId, sessionId)
614
- local name = payload.name
615
- local source = payload.source
616
- local hash = payload.hash
617
-
618
- if type(hash) == "string" and router._actions[name] and router._actions[name].hash == hash then
619
- return {
620
- name = name,
621
- success = true,
622
- skipped = true,
623
- hash = hash,
624
- handlers = router._actions[name].handlerNames,
625
- }
626
- end
627
-
628
- local success, err = router:registerAction(name, source, nil, nil, nil, hash)
629
- local handlers = {}
630
- if success and router._actions[name] then
631
- handlers = router._actions[name].handlerNames
632
- end
633
-
634
- return {
635
- name = name,
636
- success = success,
637
- skipped = false,
638
- hash = hash,
639
- handlers = handlers,
640
- error = err,
641
- }
642
- end)
643
- router:setResponseType("registerAction", "registerActionResult")
644
-
645
- -- Register v1
646
- router:dispatch({
647
- type = "registerAction",
648
- sessionId = "s1",
649
- requestId = "r1",
650
- payload = { name = "myAction", source = SIMPLE_ACTION_SOURCE, hash = "hash-v1" },
651
- })
652
-
653
- -- Register v2 with different hash
654
- local r = router:dispatch({
655
- type = "registerAction",
656
- sessionId = "s2",
657
- requestId = "r2",
658
- payload = { name = "myAction", source = SIMPLE_ACTION_SOURCE_V2, hash = "hash-v2" },
659
- })
660
-
661
- assertNotNil(r)
662
- assertTrue(r.payload.success)
663
- assertFalse(r.payload.skipped, "different hash should not be skipped")
664
- assertEqual(r.payload.hash, "hash-v2")
665
-
666
- -- Verify v2 handler is active
667
- local dispatchResult = router:dispatch({
668
- type = "testAction",
669
- sessionId = "s3",
670
- requestId = "r3",
671
- payload = {},
672
- })
673
- assertEqual(dispatchResult.payload.result, "v2", "v2 handler should be active")
674
- end,
675
- })
676
-
677
- -- ===========================================================================
678
- -- Teardown lifecycle tests
679
- -- ===========================================================================
680
-
681
- table.insert(tests, {
682
- name = "teardown: called before re-registration on hash change",
683
- fn = function()
684
- local router = ActionRouter.new()
685
-
686
- local teardownCalled = false
687
- local SOURCE_WITH_TEARDOWN = [[
688
- local M = {}
689
- local _teardownCalled = false
690
- function M.register(router, sendMessage, logBuffer)
691
- router:register("testAction", function(payload, requestId, sessionId)
692
- return { result = "v1" }
693
- end)
694
- end
695
- function M.teardown()
696
- -- We can't communicate back easily, so we use a global
697
- _G.__test_teardown_called = true
698
- end
699
- return M
700
- ]]
701
- _G.__test_teardown_called = false
702
-
703
- router:registerAction("myAction", SOURCE_WITH_TEARDOWN, nil, nil, nil, "hash-old")
704
- assertFalse(_G.__test_teardown_called, "teardown should not be called on first registration")
705
-
706
- -- Re-register with different hash
707
- local REPLACEMENT_SOURCE = [[
708
- local M = {}
709
- function M.register(router, sendMessage, logBuffer)
710
- router:register("testAction", function(payload, requestId, sessionId)
711
- return { result = "v2" }
712
- end)
713
- end
714
- return M
715
- ]]
716
- router:registerAction("myAction", REPLACEMENT_SOURCE, nil, nil, nil, "hash-new")
717
- assertTrue(_G.__test_teardown_called, "teardown should be called before re-registration")
718
-
719
- -- Clean up global
720
- _G.__test_teardown_called = nil
721
- end,
722
- })
723
-
724
- table.insert(tests, {
725
- name = "teardown: not called when hash matches (skip)",
726
- fn = function()
727
- local router = ActionRouter.new()
728
-
729
- local SOURCE_WITH_TEARDOWN = [[
730
- local M = {}
731
- function M.register(router, sendMessage, logBuffer)
732
- router:register("testAction", function(payload, requestId, sessionId)
733
- return { result = "v1" }
734
- end)
735
- end
736
- function M.teardown()
737
- _G.__test_teardown_called = true
738
- end
739
- return M
740
- ]]
741
- _G.__test_teardown_called = false
742
-
743
- router:registerAction("myAction", SOURCE_WITH_TEARDOWN, nil, nil, nil, "same-hash")
744
- assertFalse(_G.__test_teardown_called, "teardown should not be called on first registration")
745
-
746
- -- Re-register with same hash (should skip entirely)
747
- router:registerAction("myAction", SOURCE_WITH_TEARDOWN, nil, nil, nil, "same-hash")
748
- assertFalse(_G.__test_teardown_called, "teardown should not be called when hash matches")
749
-
750
- _G.__test_teardown_called = nil
751
- end,
752
- })
753
-
754
- table.insert(tests, {
755
- name = "teardown: missing teardown on simple action does not error",
756
- fn = function()
757
- local router = ActionRouter.new()
758
-
759
- -- Register action without teardown function
760
- router:registerAction("myAction", SIMPLE_ACTION_SOURCE, nil, nil, nil, "hash-old")
761
-
762
- -- Re-register with different hash - should not error
763
- local ok, err = router:registerAction("myAction", SIMPLE_ACTION_SOURCE_V2, nil, nil, nil, "hash-new")
764
- assertTrue(ok, "re-registration should succeed without teardown")
765
- assertNil(err, "should not error")
766
-
767
- -- New handler should work
768
- local r = router:dispatch({
769
- type = "testAction",
770
- sessionId = "s1",
771
- requestId = "r1",
772
- payload = {},
773
- })
774
- assertEqual(r.payload.result, "v2", "v2 handler should be active")
775
- end,
776
- })
777
-
778
- table.insert(tests, {
779
- name = "teardown: failure does not block re-registration",
780
- fn = function()
781
- local router = ActionRouter.new()
782
-
783
- local FAILING_TEARDOWN_SOURCE = [[
784
- local M = {}
785
- function M.register(router, sendMessage, logBuffer)
786
- router:register("testAction", function(payload, requestId, sessionId)
787
- return { result = "v1" }
788
- end)
789
- end
790
- function M.teardown()
791
- error("teardown exploded!")
792
- end
793
- return M
794
- ]]
795
-
796
- router:registerAction("myAction", FAILING_TEARDOWN_SOURCE, nil, nil, nil, "hash-old")
797
-
798
- -- Re-register with different hash - teardown will throw but pcall should catch it
799
- local ok, err = router:registerAction("myAction", SIMPLE_ACTION_SOURCE_V2, nil, nil, nil, "hash-new")
800
- assertTrue(ok, "re-registration should succeed despite teardown failure")
801
- assertNil(err, "should not error")
802
-
803
- -- New handler should work
804
- local r = router:dispatch({
805
- type = "testAction",
806
- sessionId = "s1",
807
- requestId = "r1",
808
- payload = {},
809
- })
810
- assertEqual(r.payload.result, "v2", "v2 handler should be active despite teardown failure")
811
- end,
812
- })
813
-
814
- return tests