@quenty/studio-bridge 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +109 -17
- package/build-scripts/transform-add-session-attribute.lua +1 -0
- package/deploy.nevermore.json +10 -0
- package/dist/src/bridge/bridge-connection.d.ts +26 -2
- package/dist/src/bridge/bridge-connection.d.ts.map +1 -1
- package/dist/src/bridge/bridge-connection.js +159 -14
- package/dist/src/bridge/bridge-connection.js.map +1 -1
- package/dist/src/bridge/bridge-connection.test.js +81 -0
- package/dist/src/bridge/bridge-connection.test.js.map +1 -1
- package/dist/src/bridge/bridge-session.d.ts +35 -2
- package/dist/src/bridge/bridge-session.d.ts.map +1 -1
- package/dist/src/bridge/bridge-session.js +185 -28
- package/dist/src/bridge/bridge-session.js.map +1 -1
- package/dist/src/bridge/bridge-session.test.js +6 -4
- package/dist/src/bridge/bridge-session.test.js.map +1 -1
- package/dist/src/bridge/index.d.ts +1 -1
- package/dist/src/bridge/index.d.ts.map +1 -1
- package/dist/src/bridge/index.js.map +1 -1
- package/dist/src/bridge/internal/bridge-client.d.ts +4 -0
- package/dist/src/bridge/internal/bridge-client.d.ts.map +1 -1
- package/dist/src/bridge/internal/bridge-client.js +20 -7
- package/dist/src/bridge/internal/bridge-client.js.map +1 -1
- package/dist/src/bridge/internal/bridge-client.test.js +18 -0
- package/dist/src/bridge/internal/bridge-client.test.js.map +1 -1
- package/dist/src/bridge/internal/bridge-host.d.ts +13 -1
- package/dist/src/bridge/internal/bridge-host.d.ts.map +1 -1
- package/dist/src/bridge/internal/bridge-host.js +35 -0
- package/dist/src/bridge/internal/bridge-host.js.map +1 -1
- package/dist/src/bridge/internal/bridge-host.test.js +31 -0
- package/dist/src/bridge/internal/bridge-host.test.js.map +1 -1
- package/dist/src/bridge/internal/hand-off.d.ts.map +1 -1
- package/dist/src/bridge/internal/hand-off.js +4 -1
- package/dist/src/bridge/internal/hand-off.js.map +1 -1
- package/dist/src/bridge/internal/host-protocol.d.ts +8 -0
- package/dist/src/bridge/internal/host-protocol.d.ts.map +1 -1
- package/dist/src/bridge/internal/host-protocol.js +120 -13
- package/dist/src/bridge/internal/host-protocol.js.map +1 -1
- package/dist/src/bridge/internal/host-protocol.test.js +13 -0
- package/dist/src/bridge/internal/host-protocol.test.js.map +1 -1
- package/dist/src/bridge/internal/instance-state.d.ts +9 -0
- package/dist/src/bridge/internal/instance-state.d.ts.map +1 -0
- package/dist/src/bridge/internal/instance-state.js +28 -0
- package/dist/src/bridge/internal/instance-state.js.map +1 -0
- package/dist/src/bridge/internal/transport-client.d.ts.map +1 -1
- package/dist/src/bridge/internal/transport-client.js +2 -1
- package/dist/src/bridge/internal/transport-client.js.map +1 -1
- package/dist/src/bridge/internal/transport-server.d.ts.map +1 -1
- package/dist/src/bridge/internal/transport-server.js +5 -1
- package/dist/src/bridge/internal/transport-server.js.map +1 -1
- package/dist/src/bridge/types.d.ts +43 -4
- package/dist/src/bridge/types.d.ts.map +1 -1
- package/dist/src/bridge/types.js.map +1 -1
- package/dist/src/cli/adapters/cli-command-adapter-handler.test.js +24 -0
- package/dist/src/cli/adapters/cli-command-adapter-handler.test.js.map +1 -1
- package/dist/src/cli/adapters/cli-command-adapter.d.ts +6 -0
- package/dist/src/cli/adapters/cli-command-adapter.d.ts.map +1 -1
- package/dist/src/cli/adapters/cli-command-adapter.js +107 -11
- package/dist/src/cli/adapters/cli-command-adapter.js.map +1 -1
- package/dist/src/cli/adapters/group-builder.d.ts +3 -0
- package/dist/src/cli/adapters/group-builder.d.ts.map +1 -1
- package/dist/src/cli/adapters/group-builder.js +34 -15
- package/dist/src/cli/adapters/group-builder.js.map +1 -1
- package/dist/src/cli/adapters/group-builder.test.js +26 -2
- package/dist/src/cli/adapters/group-builder.test.js.map +1 -1
- package/dist/src/cli/adapters/help-formatter.d.ts.map +1 -1
- package/dist/src/cli/adapters/help-formatter.js +4 -3
- package/dist/src/cli/adapters/help-formatter.js.map +1 -1
- package/dist/src/cli/adapters/help-formatter.test.js +1 -1
- package/dist/src/cli/adapters/help-formatter.test.js.map +1 -1
- package/dist/src/cli/adapters/playtest-edit-guard.test.d.ts +2 -0
- package/dist/src/cli/adapters/playtest-edit-guard.test.d.ts.map +1 -0
- package/dist/src/cli/adapters/playtest-edit-guard.test.js +28 -0
- package/dist/src/cli/adapters/playtest-edit-guard.test.js.map +1 -0
- package/dist/src/cli/args/global-args.d.ts +1 -1
- package/dist/src/cli/args/global-args.d.ts.map +1 -1
- package/dist/src/cli/cli-output-context.d.ts +14 -0
- package/dist/src/cli/cli-output-context.d.ts.map +1 -0
- package/dist/src/cli/cli-output-context.js +39 -0
- package/dist/src/cli/cli-output-context.js.map +1 -0
- package/dist/src/cli/cli-output-context.test.d.ts +2 -0
- package/dist/src/cli/cli-output-context.test.d.ts.map +1 -0
- package/dist/src/cli/cli-output-context.test.js +38 -0
- package/dist/src/cli/cli-output-context.test.js.map +1 -0
- package/dist/src/cli/cli.js +40 -17
- package/dist/src/cli/cli.js.map +1 -1
- package/dist/src/cli/managed-studio-run.d.ts +21 -0
- package/dist/src/cli/managed-studio-run.d.ts.map +1 -0
- package/dist/src/cli/managed-studio-run.js +75 -0
- package/dist/src/cli/managed-studio-run.js.map +1 -0
- package/dist/src/cli/managed-studio-run.test.d.ts +2 -0
- package/dist/src/cli/managed-studio-run.test.d.ts.map +1 -0
- package/dist/src/cli/managed-studio-run.test.js +52 -0
- package/dist/src/cli/managed-studio-run.test.js.map +1 -0
- package/dist/src/cli/resolve-session.js +1 -1
- package/dist/src/cli/resolve-session.js.map +1 -1
- package/dist/src/cli/resolve-session.test.js +1 -1
- package/dist/src/cli/resolve-session.test.js.map +1 -1
- package/dist/src/cli/script-executor.d.ts +13 -1
- package/dist/src/cli/script-executor.d.ts.map +1 -1
- package/dist/src/cli/script-executor.js +77 -47
- package/dist/src/cli/script-executor.js.map +1 -1
- package/dist/src/commands/console/exec/exec.d.ts +17 -0
- package/dist/src/commands/console/exec/exec.d.ts.map +1 -1
- package/dist/src/commands/console/exec/exec.js +39 -7
- package/dist/src/commands/console/exec/exec.js.map +1 -1
- package/dist/src/commands/console/exec/exec.test.js +62 -3
- package/dist/src/commands/console/exec/exec.test.js.map +1 -1
- package/dist/src/commands/console/logs/logs.d.ts +30 -2
- package/dist/src/commands/console/logs/logs.d.ts.map +1 -1
- package/dist/src/commands/console/logs/logs.js +82 -7
- package/dist/src/commands/console/logs/logs.js.map +1 -1
- package/dist/src/commands/console/logs/logs.test.js +63 -4
- package/dist/src/commands/console/logs/logs.test.js.map +1 -1
- package/dist/src/commands/explorer/export/export.d.ts +19 -0
- package/dist/src/commands/explorer/export/export.d.ts.map +1 -0
- package/dist/src/commands/explorer/export/export.js +37 -0
- package/dist/src/commands/explorer/export/export.js.map +1 -0
- package/dist/src/commands/explorer/export/export.test.d.ts +2 -0
- package/dist/src/commands/explorer/export/export.test.d.ts.map +1 -0
- package/dist/src/commands/explorer/export/export.test.js +25 -0
- package/dist/src/commands/explorer/export/export.test.js.map +1 -0
- package/dist/src/commands/explorer/find/find.d.ts +28 -0
- package/dist/src/commands/explorer/find/find.d.ts.map +1 -0
- package/dist/src/commands/explorer/find/find.js +75 -0
- package/dist/src/commands/explorer/find/find.js.map +1 -0
- package/dist/src/commands/explorer/find/find.test.d.ts +2 -0
- package/dist/src/commands/explorer/find/find.test.d.ts.map +1 -0
- package/dist/src/commands/explorer/find/find.test.js +44 -0
- package/dist/src/commands/explorer/find/find.test.js.map +1 -0
- package/dist/src/commands/explorer/grep/grep.d.ts +24 -0
- package/dist/src/commands/explorer/grep/grep.d.ts.map +1 -0
- package/dist/src/commands/explorer/grep/grep.js +63 -0
- package/dist/src/commands/explorer/grep/grep.js.map +1 -0
- package/dist/src/commands/explorer/grep/grep.test.d.ts +2 -0
- package/dist/src/commands/explorer/grep/grep.test.d.ts.map +1 -0
- package/dist/src/commands/explorer/grep/grep.test.js +42 -0
- package/dist/src/commands/explorer/grep/grep.test.js.map +1 -0
- package/dist/src/commands/explorer/import/import.d.ts +21 -0
- package/dist/src/commands/explorer/import/import.d.ts.map +1 -0
- package/dist/src/commands/explorer/import/import.js +37 -0
- package/dist/src/commands/explorer/import/import.js.map +1 -0
- package/dist/src/commands/explorer/import/import.test.d.ts +2 -0
- package/dist/src/commands/explorer/import/import.test.d.ts.map +1 -0
- package/dist/src/commands/explorer/import/import.test.js +45 -0
- package/dist/src/commands/explorer/import/import.test.js.map +1 -0
- package/dist/src/commands/formatters.test.js +7 -1
- package/dist/src/commands/formatters.test.js.map +1 -1
- package/dist/src/commands/framework/action-loader.d.ts +5 -1
- package/dist/src/commands/framework/action-loader.d.ts.map +1 -1
- package/dist/src/commands/framework/action-loader.js +9 -2
- package/dist/src/commands/framework/action-loader.js.map +1 -1
- package/dist/src/commands/framework/action-loader.test.js +23 -0
- package/dist/src/commands/framework/action-loader.test.js.map +1 -1
- package/dist/src/commands/framework/arg-builder.d.ts +15 -2
- package/dist/src/commands/framework/arg-builder.d.ts.map +1 -1
- package/dist/src/commands/framework/arg-builder.js +22 -2
- package/dist/src/commands/framework/arg-builder.js.map +1 -1
- package/dist/src/commands/framework/define-command.d.ts +19 -3
- package/dist/src/commands/framework/define-command.d.ts.map +1 -1
- package/dist/src/commands/framework/define-command.js.map +1 -1
- package/dist/src/commands/framework/index.d.ts +1 -1
- package/dist/src/commands/framework/index.d.ts.map +1 -1
- package/dist/src/commands/framework/index.js.map +1 -1
- package/dist/src/commands/index.d.ts +11 -0
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +11 -0
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/linux/inject-credentials/inject-credentials.d.ts.map +1 -1
- package/dist/src/commands/linux/inject-credentials/inject-credentials.js +1 -3
- package/dist/src/commands/linux/inject-credentials/inject-credentials.js.map +1 -1
- package/dist/src/commands/linux/setup/setup.d.ts.map +1 -1
- package/dist/src/commands/linux/setup/setup.js +1 -3
- package/dist/src/commands/linux/setup/setup.js.map +1 -1
- package/dist/src/commands/linux/status/status.d.ts +9 -1
- package/dist/src/commands/linux/status/status.d.ts.map +1 -1
- package/dist/src/commands/linux/status/status.js +66 -86
- package/dist/src/commands/linux/status/status.js.map +1 -1
- package/dist/src/commands/playtest/player/add/add.d.ts +17 -0
- package/dist/src/commands/playtest/player/add/add.d.ts.map +1 -0
- package/dist/src/commands/playtest/player/add/add.js +45 -0
- package/dist/src/commands/playtest/player/add/add.js.map +1 -0
- package/dist/src/commands/playtest/player/list/list.d.ts +13 -0
- package/dist/src/commands/playtest/player/list/list.d.ts.map +1 -0
- package/dist/src/commands/playtest/player/list/list.js +33 -0
- package/dist/src/commands/playtest/player/list/list.js.map +1 -0
- package/dist/src/commands/playtest/player/playtest-players.d.ts +36 -0
- package/dist/src/commands/playtest/player/playtest-players.d.ts.map +1 -0
- package/dist/src/commands/playtest/player/playtest-players.js +187 -0
- package/dist/src/commands/playtest/player/playtest-players.js.map +1 -0
- package/dist/src/commands/playtest/player/playtest-players.test.d.ts +2 -0
- package/dist/src/commands/playtest/player/playtest-players.test.d.ts.map +1 -0
- package/dist/src/commands/playtest/player/playtest-players.test.js +89 -0
- package/dist/src/commands/playtest/player/playtest-players.test.js.map +1 -0
- package/dist/src/commands/playtest/player/remove/remove.d.ts +17 -0
- package/dist/src/commands/playtest/player/remove/remove.d.ts.map +1 -0
- package/dist/src/commands/playtest/player/remove/remove.js +42 -0
- package/dist/src/commands/playtest/player/remove/remove.js.map +1 -0
- package/dist/src/commands/playtest/playtest-sessions.d.ts +49 -0
- package/dist/src/commands/playtest/playtest-sessions.d.ts.map +1 -0
- package/dist/src/commands/playtest/playtest-sessions.js +283 -0
- package/dist/src/commands/playtest/playtest-sessions.js.map +1 -0
- package/dist/src/commands/playtest/playtest-sessions.test.d.ts +2 -0
- package/dist/src/commands/playtest/playtest-sessions.test.d.ts.map +1 -0
- package/dist/src/commands/playtest/playtest-sessions.test.js +87 -0
- package/dist/src/commands/playtest/playtest-sessions.test.js.map +1 -0
- package/dist/src/commands/playtest/restart/restart.d.ts +23 -0
- package/dist/src/commands/playtest/restart/restart.d.ts.map +1 -0
- package/dist/src/commands/playtest/restart/restart.js +105 -0
- package/dist/src/commands/playtest/restart/restart.js.map +1 -0
- package/dist/src/commands/playtest/run/run.d.ts +47 -0
- package/dist/src/commands/playtest/run/run.d.ts.map +1 -0
- package/dist/src/commands/playtest/run/run.js +137 -0
- package/dist/src/commands/playtest/run/run.js.map +1 -0
- package/dist/src/commands/playtest/start/start.d.ts +42 -0
- package/dist/src/commands/playtest/start/start.d.ts.map +1 -0
- package/dist/src/commands/playtest/start/start.js +70 -0
- package/dist/src/commands/playtest/start/start.js.map +1 -0
- package/dist/src/commands/playtest/stop/stop.d.ts +15 -0
- package/dist/src/commands/playtest/stop/stop.d.ts.map +1 -0
- package/dist/src/commands/playtest/stop/stop.js +24 -0
- package/dist/src/commands/playtest/stop/stop.js.map +1 -0
- package/dist/src/commands/process/close/close.d.ts +19 -10
- package/dist/src/commands/process/close/close.d.ts.map +1 -1
- package/dist/src/commands/process/close/close.js +118 -15
- package/dist/src/commands/process/close/close.js.map +1 -1
- package/dist/src/commands/process/close/close.test.d.ts +2 -0
- package/dist/src/commands/process/close/close.test.d.ts.map +1 -0
- package/dist/src/commands/process/close/close.test.js +190 -0
- package/dist/src/commands/process/close/close.test.js.map +1 -0
- package/dist/src/commands/process/info/info.d.ts +45 -5
- package/dist/src/commands/process/info/info.d.ts.map +1 -1
- package/dist/src/commands/process/info/info.js +117 -13
- package/dist/src/commands/process/info/info.js.map +1 -1
- package/dist/src/commands/process/info/info.test.js +140 -38
- package/dist/src/commands/process/info/info.test.js.map +1 -1
- package/dist/src/commands/process/launch/launch.d.ts +11 -1
- package/dist/src/commands/process/launch/launch.d.ts.map +1 -1
- package/dist/src/commands/process/launch/launch.js +37 -7
- package/dist/src/commands/process/launch/launch.js.map +1 -1
- package/dist/src/commands/process/launch/launch.test.js +99 -20
- package/dist/src/commands/process/launch/launch.test.js.map +1 -1
- package/dist/src/commands/process/list/list.d.ts +2 -1
- package/dist/src/commands/process/list/list.d.ts.map +1 -1
- package/dist/src/commands/process/list/list.js +9 -6
- package/dist/src/commands/process/list/list.js.map +1 -1
- package/dist/src/commands/process/list/list.test.js +1 -0
- package/dist/src/commands/process/list/list.test.js.map +1 -1
- package/dist/src/commands/process/run/run.d.ts +9 -0
- package/dist/src/commands/process/run/run.d.ts.map +1 -1
- package/dist/src/commands/process/run/run.js +15 -5
- package/dist/src/commands/process/run/run.js.map +1 -1
- package/dist/src/commands/serve/serve.d.ts +2 -0
- package/dist/src/commands/serve/serve.d.ts.map +1 -1
- package/dist/src/commands/serve/serve.js +17 -4
- package/dist/src/commands/serve/serve.js.map +1 -1
- package/dist/src/commands/serve/serve.test.js +9 -2
- package/dist/src/commands/serve/serve.test.js.map +1 -1
- package/dist/src/commands/viewport/screenshot/screenshot.d.ts.map +1 -1
- package/dist/src/commands/viewport/screenshot/screenshot.js +4 -1
- package/dist/src/commands/viewport/screenshot/screenshot.js.map +1 -1
- package/dist/src/commands/viewport/screenshot/screenshot.test.js +5 -9
- package/dist/src/commands/viewport/screenshot/screenshot.test.js.map +1 -1
- package/dist/src/deploy/deploy-places.d.ts +39 -0
- package/dist/src/deploy/deploy-places.d.ts.map +1 -0
- package/dist/src/deploy/deploy-places.js +162 -0
- package/dist/src/deploy/deploy-places.js.map +1 -0
- package/dist/src/deploy/deploy-places.test.d.ts +2 -0
- package/dist/src/deploy/deploy-places.test.d.ts.map +1 -0
- package/dist/src/deploy/deploy-places.test.js +96 -0
- package/dist/src/deploy/deploy-places.test.js.map +1 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/linux/linux-studio-launcher.d.ts.map +1 -1
- package/dist/src/linux/linux-studio-launcher.js +10 -0
- package/dist/src/linux/linux-studio-launcher.js.map +1 -1
- package/dist/src/linux/linux-studio-launcher.test.d.ts +2 -0
- package/dist/src/linux/linux-studio-launcher.test.d.ts.map +1 -0
- package/dist/src/linux/linux-studio-launcher.test.js +68 -0
- package/dist/src/linux/linux-studio-launcher.test.js.map +1 -0
- package/dist/src/plugin/persistent-plugin-installer.d.ts.map +1 -1
- package/dist/src/plugin/persistent-plugin-installer.js +2 -1
- package/dist/src/plugin/persistent-plugin-installer.js.map +1 -1
- package/dist/src/plugin/persistent-plugin-installer.test.js +3 -0
- package/dist/src/plugin/persistent-plugin-installer.test.js.map +1 -1
- package/dist/src/plugin/plugin-build-version.d.ts +7 -0
- package/dist/src/plugin/plugin-build-version.d.ts.map +1 -0
- package/dist/src/plugin/plugin-build-version.js +42 -0
- package/dist/src/plugin/plugin-build-version.js.map +1 -0
- package/dist/src/plugin/plugin-build-version.test.d.ts +2 -0
- package/dist/src/plugin/plugin-build-version.test.d.ts.map +1 -0
- package/dist/src/plugin/plugin-build-version.test.js +41 -0
- package/dist/src/plugin/plugin-build-version.test.js.map +1 -0
- package/dist/src/plugin/plugin-injector.d.ts.map +1 -1
- package/dist/src/plugin/plugin-injector.js +7 -1
- package/dist/src/plugin/plugin-injector.js.map +1 -1
- package/dist/src/process/studio-process-closer.d.ts +35 -0
- package/dist/src/process/studio-process-closer.d.ts.map +1 -0
- package/dist/src/process/studio-process-closer.js +129 -0
- package/dist/src/process/studio-process-closer.js.map +1 -0
- package/dist/src/process/studio-process-closer.test.d.ts +2 -0
- package/dist/src/process/studio-process-closer.test.d.ts.map +1 -0
- package/dist/src/process/studio-process-closer.test.js +80 -0
- package/dist/src/process/studio-process-closer.test.js.map +1 -0
- package/dist/src/process/studio-settings.d.ts +14 -0
- package/dist/src/process/studio-settings.d.ts.map +1 -0
- package/dist/src/process/studio-settings.js +50 -0
- package/dist/src/process/studio-settings.js.map +1 -0
- package/dist/src/process/studio-settings.test.d.ts +2 -0
- package/dist/src/process/studio-settings.test.d.ts.map +1 -0
- package/dist/src/process/studio-settings.test.js +16 -0
- package/dist/src/process/studio-settings.test.js.map +1 -0
- package/dist/src/process/studio-window-state.d.ts +13 -0
- package/dist/src/process/studio-window-state.d.ts.map +1 -0
- package/dist/src/process/studio-window-state.js +48 -0
- package/dist/src/process/studio-window-state.js.map +1 -0
- package/dist/src/server/studio-bridge-server.d.ts +3 -1
- package/dist/src/server/studio-bridge-server.d.ts.map +1 -1
- package/dist/src/server/studio-bridge-server.js +12 -4
- package/dist/src/server/studio-bridge-server.js.map +1 -1
- package/dist/src/server/web-socket-protocol.d.ts +173 -6
- package/dist/src/server/web-socket-protocol.d.ts.map +1 -1
- package/dist/src/server/web-socket-protocol.js +244 -1
- package/dist/src/server/web-socket-protocol.js.map +1 -1
- package/dist/src/server/web-socket-protocol.test.js +48 -0
- package/dist/src/server/web-socket-protocol.test.js.map +1 -1
- package/dist/src/test/e2e/persistent-session.test.js +121 -0
- package/dist/src/test/e2e/persistent-session.test.js.map +1 -1
- package/dist/src/test/e2e/split-server.test.d.ts +3 -5
- package/dist/src/test/e2e/split-server.test.d.ts.map +1 -1
- package/dist/src/test/e2e/split-server.test.js +3 -5
- package/dist/src/test/e2e/split-server.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/docker/Dockerfile +3 -0
- package/package.json +8 -6
- package/src/bridge/bridge-connection.test.ts +126 -0
- package/src/bridge/bridge-connection.ts +217 -22
- package/src/bridge/bridge-session.test.ts +6 -4
- package/src/bridge/bridge-session.ts +273 -28
- package/src/bridge/index.ts +3 -0
- package/src/bridge/internal/bridge-client.test.ts +23 -0
- package/src/bridge/internal/bridge-client.ts +25 -7
- package/src/bridge/internal/bridge-host.test.ts +38 -0
- package/src/bridge/internal/bridge-host.ts +47 -0
- package/src/bridge/internal/hand-off.ts +4 -1
- package/src/bridge/internal/host-protocol.test.ts +15 -0
- package/src/bridge/internal/host-protocol.ts +148 -37
- package/src/bridge/internal/instance-state.ts +34 -0
- package/src/bridge/internal/transport-client.ts +2 -1
- package/src/bridge/internal/transport-server.ts +5 -1
- package/src/bridge/types.ts +47 -2
- package/src/cli/adapters/cli-command-adapter-handler.test.ts +28 -0
- package/src/cli/adapters/cli-command-adapter.ts +150 -18
- package/src/cli/adapters/group-builder.test.ts +34 -2
- package/src/cli/adapters/group-builder.ts +52 -20
- package/src/cli/adapters/help-formatter.test.ts +1 -1
- package/src/cli/adapters/help-formatter.ts +4 -3
- package/src/cli/adapters/playtest-edit-guard.test.ts +54 -0
- package/src/cli/args/global-args.ts +1 -1
- package/src/cli/cli-output-context.test.ts +55 -0
- package/src/cli/cli-output-context.ts +50 -0
- package/src/cli/cli.ts +49 -17
- package/src/cli/managed-studio-run.test.ts +71 -0
- package/src/cli/managed-studio-run.ts +135 -0
- package/src/cli/resolve-session.test.ts +1 -1
- package/src/cli/resolve-session.ts +1 -1
- package/src/cli/script-executor.ts +99 -51
- package/src/commands/console/exec/exec.test.ts +96 -3
- package/src/commands/console/exec/exec.ts +59 -6
- package/src/commands/console/exec/execute.lua +356 -240
- package/src/commands/console/exec/execute.spec.lua +286 -0
- package/src/commands/console/logs/logs.test.ts +76 -4
- package/src/commands/console/logs/logs.ts +132 -17
- package/src/commands/console/logs/query-logs.lua +85 -52
- package/src/commands/console/logs/query-logs.spec.lua +132 -0
- package/src/commands/explorer/export/export-instances.lua +108 -0
- package/src/commands/explorer/export/export-instances.spec.lua +87 -0
- package/src/commands/explorer/export/export.test.ts +27 -0
- package/src/commands/explorer/export/export.ts +60 -0
- package/src/commands/explorer/find/find-instances.lua +174 -0
- package/src/commands/explorer/find/find-instances.spec.lua +122 -0
- package/src/commands/explorer/find/find.test.ts +53 -0
- package/src/commands/explorer/find/find.ts +113 -0
- package/src/commands/explorer/grep/grep-scripts.lua +214 -0
- package/src/commands/explorer/grep/grep-scripts.spec.lua +130 -0
- package/src/commands/explorer/grep/grep.test.ts +45 -0
- package/src/commands/explorer/grep/grep.ts +93 -0
- package/src/commands/explorer/import/import-instances.lua +106 -0
- package/src/commands/explorer/import/import-instances.spec.lua +84 -0
- package/src/commands/explorer/import/import.test.ts +60 -0
- package/src/commands/explorer/import/import.ts +66 -0
- package/src/commands/explorer/query/query-data-model.lua +124 -152
- package/src/commands/explorer/query/query-data-model.spec.lua +150 -0
- package/src/commands/formatters.test.ts +7 -1
- package/src/commands/framework/action-loader.test.ts +28 -0
- package/src/commands/framework/action-loader.ts +10 -2
- package/src/commands/framework/arg-builder.ts +26 -3
- package/src/commands/framework/define-command.ts +32 -3
- package/src/commands/framework/index.ts +1 -0
- package/src/commands/index.ts +50 -0
- package/src/commands/linux/inject-credentials/inject-credentials.ts +1 -3
- package/src/commands/linux/setup/setup.ts +1 -3
- package/src/commands/linux/status/status.ts +105 -98
- package/src/commands/playtest/player/add/add.ts +85 -0
- package/src/commands/playtest/player/list/list.ts +57 -0
- package/src/commands/playtest/player/playtest-players.test.ts +146 -0
- package/src/commands/playtest/player/playtest-players.ts +270 -0
- package/src/commands/playtest/player/remove/remove.ts +78 -0
- package/src/commands/playtest/playtest-sessions.test.ts +143 -0
- package/src/commands/playtest/playtest-sessions.ts +417 -0
- package/src/commands/playtest/restart/restart.ts +199 -0
- package/src/commands/playtest/run/playtest-runner.luau +264 -0
- package/src/commands/playtest/run/playtest-runner.spec.lua +71 -0
- package/src/commands/playtest/run/run-playtest-script.lua +139 -0
- package/src/commands/playtest/run/run-playtest-script.spec.lua +43 -0
- package/src/commands/playtest/run/run.ts +239 -0
- package/src/commands/playtest/start/start-playtest.lua +108 -0
- package/src/commands/playtest/start/start.ts +138 -0
- package/src/commands/playtest/stop/end-playtest.lua +47 -0
- package/src/commands/playtest/stop/stop.ts +51 -0
- package/src/commands/process/close/close.test.ts +250 -0
- package/src/commands/process/close/close.ts +183 -17
- package/src/commands/process/info/info.test.ts +198 -44
- package/src/commands/process/info/info.ts +204 -15
- package/src/commands/process/info/query-state.lua +42 -29
- package/src/commands/process/info/query-state.spec.lua +39 -0
- package/src/commands/process/launch/launch.test.ts +138 -21
- package/src/commands/process/launch/launch.ts +69 -9
- package/src/commands/process/list/list.test.ts +1 -0
- package/src/commands/process/list/list.ts +14 -6
- package/src/commands/process/run/run.ts +26 -5
- package/src/commands/serve/serve.test.ts +17 -2
- package/src/commands/serve/serve.ts +25 -6
- package/src/commands/viewport/screenshot/capture-screenshot.lua +175 -182
- package/src/commands/viewport/screenshot/capture-screenshot.spec.lua +129 -0
- package/src/commands/viewport/screenshot/screenshot.test.ts +7 -10
- package/src/commands/viewport/screenshot/screenshot.ts +6 -1
- package/src/deploy/deploy-places.test.ts +127 -0
- package/src/deploy/deploy-places.ts +229 -0
- package/src/index.ts +11 -0
- package/src/linux/linux-studio-launcher.test.ts +89 -0
- package/src/linux/linux-studio-launcher.ts +11 -0
- package/src/plugin/persistent-plugin-installer.test.ts +4 -0
- package/src/plugin/persistent-plugin-installer.ts +2 -1
- package/src/plugin/plugin-build-version.test.ts +55 -0
- package/src/plugin/plugin-build-version.ts +53 -0
- package/src/plugin/plugin-injector.ts +7 -1
- package/src/process/studio-process-closer.test.ts +107 -0
- package/src/process/studio-process-closer.ts +187 -0
- package/src/process/studio-settings.test.ts +18 -0
- package/src/process/studio-settings.ts +61 -0
- package/src/process/studio-window-state.ts +65 -0
- package/src/server/studio-bridge-server.ts +15 -4
- package/src/server/web-socket-protocol.test.ts +55 -0
- package/src/server/web-socket-protocol.ts +468 -8
- package/src/test/e2e/persistent-session.test.ts +137 -0
- package/src/test/e2e/split-server.test.ts +3 -5
- package/templates/studio-bridge-plugin/default.project.json +3 -0
- package/templates/studio-bridge-plugin/src/Shared/ActionRouter.lua +208 -159
- package/templates/studio-bridge-plugin/src/Shared/ActionRouter.spec.lua +418 -0
- package/templates/studio-bridge-plugin/src/Shared/BuiltInActions.lua +94 -0
- package/templates/studio-bridge-plugin/src/Shared/BuiltInActions.spec.lua +166 -0
- package/templates/studio-bridge-plugin/src/Shared/DiscoveryStateMachine.lua +118 -137
- package/templates/studio-bridge-plugin/src/Shared/DiscoveryStateMachine.spec.lua +228 -0
- package/templates/studio-bridge-plugin/src/Shared/MessageBuffer.lua +80 -109
- package/templates/studio-bridge-plugin/src/Shared/MessageBuffer.spec.lua +116 -0
- package/templates/studio-bridge-plugin/src/Shared/StudioBridgeConnection.lua +233 -0
- package/templates/studio-bridge-plugin/src/Shared/StudioBridgeConnection.spec.lua +239 -0
- package/templates/studio-bridge-plugin/src/Shared/StudioBridgeLogUtils.lua +53 -0
- package/templates/studio-bridge-plugin/src/Shared/StudioBridgeLogUtils.spec.lua +27 -0
- package/templates/studio-bridge-plugin/src/Shared/StudioBridgeSessionUtils.lua +164 -0
- package/templates/studio-bridge-plugin/src/Shared/StudioBridgeSessionUtils.spec.lua +159 -0
- package/templates/studio-bridge-plugin/src/StudioBridgePlugin.server.lua +266 -368
- package/templates/studio-bridge-plugin/src/Vendor/png.lua +8 -2
- package/test/default.project.json +41 -0
- package/test/jest.config.lua +3 -0
- package/test/scripts/Server/ServerMain.server.lua +10 -0
- package/tsconfig.json +1 -0
- package/templates/studio-bridge-plugin/src/Shared/Protocol.lua +0 -132
- package/templates/studio-bridge-plugin-test/test/actions.test.lua +0 -580
- package/templates/studio-bridge-plugin-test/test/discovery.test.lua +0 -622
- package/templates/studio-bridge-plugin-test/test/execute-handler.test.lua +0 -517
- package/templates/studio-bridge-plugin-test/test/hash-lifecycle.test.lua +0 -814
- package/templates/studio-bridge-plugin-test/test/integration.test.lua +0 -1020
- package/templates/studio-bridge-plugin-test/test/new-actions.test.lua +0 -339
- package/templates/studio-bridge-plugin-test/test/plugin-entry.test.lua +0 -493
- package/templates/studio-bridge-plugin-test/test/protocol.test.lua +0 -506
- package/templates/studio-bridge-plugin-test/test/roblox-mocks.lua +0 -108
- package/templates/studio-bridge-plugin-test/test/test-runner.lua +0 -112
|
@@ -439,4 +439,141 @@ describe('persistent session e2e', () => {
|
|
|
439
439
|
const session = await waitPromise;
|
|
440
440
|
expect(session.info.sessionId).toBe(plugin.sessionId);
|
|
441
441
|
});
|
|
442
|
+
|
|
443
|
+
it('client execute is relayed through the host to the plugin', async () => {
|
|
444
|
+
const host = await BridgeConnection.connectAsync({
|
|
445
|
+
port: 0,
|
|
446
|
+
keepAlive: true,
|
|
447
|
+
local: true,
|
|
448
|
+
});
|
|
449
|
+
connections.push(host);
|
|
450
|
+
|
|
451
|
+
const plugin = new MockPluginClient({
|
|
452
|
+
port: host.port,
|
|
453
|
+
instanceId: 'inst-relay',
|
|
454
|
+
capabilities: ['execute', 'syncActions'],
|
|
455
|
+
});
|
|
456
|
+
plugins.push(plugin);
|
|
457
|
+
plugin.autoRespond('syncActions', () => ({
|
|
458
|
+
type: 'syncActionsResult',
|
|
459
|
+
payload: { needed: [], installed: {} },
|
|
460
|
+
}));
|
|
461
|
+
plugin.autoRespond('execute', () => ({
|
|
462
|
+
type: 'scriptComplete',
|
|
463
|
+
payload: { success: true, output: [], returnValues: [42] },
|
|
464
|
+
}));
|
|
465
|
+
await plugin.connectAndRegisterAsync();
|
|
466
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
467
|
+
|
|
468
|
+
const client = await BridgeConnection.connectAsync({
|
|
469
|
+
port: host.port,
|
|
470
|
+
local: true,
|
|
471
|
+
});
|
|
472
|
+
connections.push(client);
|
|
473
|
+
expect(client.role).toBe('client');
|
|
474
|
+
|
|
475
|
+
const session = await client.resolveSessionAsync(plugin.sessionId);
|
|
476
|
+
const result = await session.execAsync('return 42', 2_000);
|
|
477
|
+
|
|
478
|
+
expect(result.success).toBe(true);
|
|
479
|
+
expect(result.returnValues).toEqual([42]);
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
it('host finishes a relayed action before shutting down', async () => {
|
|
483
|
+
const host = await BridgeConnection.connectAsync({
|
|
484
|
+
port: 0,
|
|
485
|
+
keepAlive: true,
|
|
486
|
+
local: true,
|
|
487
|
+
});
|
|
488
|
+
connections.push(host);
|
|
489
|
+
|
|
490
|
+
const plugin = new MockPluginClient({
|
|
491
|
+
port: host.port,
|
|
492
|
+
instanceId: 'inst-drain',
|
|
493
|
+
capabilities: ['execute', 'syncActions'],
|
|
494
|
+
});
|
|
495
|
+
plugins.push(plugin);
|
|
496
|
+
plugin.autoRespond('syncActions', () => ({
|
|
497
|
+
type: 'syncActionsResult',
|
|
498
|
+
payload: { needed: [], installed: {} },
|
|
499
|
+
}));
|
|
500
|
+
plugin.onAnyMessage((msg) => {
|
|
501
|
+
if (msg.type === 'shutdown') {
|
|
502
|
+
void plugin.disconnectAsync();
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
if (msg.type !== 'execute') return;
|
|
506
|
+
setTimeout(() => {
|
|
507
|
+
plugin.sendMessage({
|
|
508
|
+
type: 'scriptComplete',
|
|
509
|
+
sessionId: plugin.sessionId,
|
|
510
|
+
requestId: msg.requestId,
|
|
511
|
+
payload: { success: true, output: [], returnValues: ['late'] },
|
|
512
|
+
});
|
|
513
|
+
}, 300);
|
|
514
|
+
});
|
|
515
|
+
await plugin.connectAndRegisterAsync();
|
|
516
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
517
|
+
|
|
518
|
+
const client = await BridgeConnection.connectAsync({
|
|
519
|
+
port: host.port,
|
|
520
|
+
local: true,
|
|
521
|
+
});
|
|
522
|
+
connections.push(client);
|
|
523
|
+
|
|
524
|
+
const session = await client.resolveSessionAsync(plugin.sessionId);
|
|
525
|
+
const resultPromise = session.execAsync('return "late"', 2_000);
|
|
526
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
527
|
+
const hostShutdown = host.disconnectAsync();
|
|
528
|
+
|
|
529
|
+
const result = await resultPromise;
|
|
530
|
+
await hostShutdown;
|
|
531
|
+
|
|
532
|
+
expect(result.success).toBe(true);
|
|
533
|
+
expect(result.returnValues).toEqual(['late']);
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
it('host stops waiting on a relayed action that never finishes', async () => {
|
|
537
|
+
const host = await BridgeConnection.connectAsync({
|
|
538
|
+
port: 0,
|
|
539
|
+
keepAlive: true,
|
|
540
|
+
local: true,
|
|
541
|
+
});
|
|
542
|
+
connections.push(host);
|
|
543
|
+
|
|
544
|
+
const plugin = new MockPluginClient({
|
|
545
|
+
port: host.port,
|
|
546
|
+
instanceId: 'inst-stuck',
|
|
547
|
+
capabilities: ['execute', 'syncActions'],
|
|
548
|
+
});
|
|
549
|
+
plugins.push(plugin);
|
|
550
|
+
plugin.autoRespond('syncActions', () => ({
|
|
551
|
+
type: 'syncActionsResult',
|
|
552
|
+
payload: { needed: [], installed: {} },
|
|
553
|
+
}));
|
|
554
|
+
plugin.onAnyMessage((msg) => {
|
|
555
|
+
if (msg.type === 'shutdown') {
|
|
556
|
+
void plugin.disconnectAsync();
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
await plugin.connectAndRegisterAsync();
|
|
560
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
561
|
+
|
|
562
|
+
const client = await BridgeConnection.connectAsync({
|
|
563
|
+
port: host.port,
|
|
564
|
+
local: true,
|
|
565
|
+
});
|
|
566
|
+
connections.push(client);
|
|
567
|
+
|
|
568
|
+
const session = await client.resolveSessionAsync(plugin.sessionId);
|
|
569
|
+
const stuck = session.execAsync('while true do task.wait() end', 60_000);
|
|
570
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
571
|
+
|
|
572
|
+
const started = Date.now();
|
|
573
|
+
await host.disconnectAsync({ relayDrainTimeoutMs: 200 });
|
|
574
|
+
|
|
575
|
+
expect(Date.now() - started).toBeLessThan(2_000);
|
|
576
|
+
const result = await stuck;
|
|
577
|
+
expect(result.success).toBe(false);
|
|
578
|
+
});
|
|
442
579
|
});
|
|
@@ -4,11 +4,9 @@
|
|
|
4
4
|
* that multiple clients can coexist with the host without interfering
|
|
5
5
|
* with plugin sessions.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* relay protocol. Split-server relay is tested via BridgeConnection
|
|
11
|
-
* with a mock host (see bridge-connection-remote.test.ts).
|
|
7
|
+
* These tests exercise the real transport layer and connection lifecycle,
|
|
8
|
+
* not the relay protocol. Relay through a real host is covered in
|
|
9
|
+
* persistent-session.test.ts.
|
|
12
10
|
*/
|
|
13
11
|
|
|
14
12
|
import { describe, it, expect, afterEach } from 'vitest';
|
|
@@ -1,164 +1,215 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
--!strict
|
|
2
|
+
--[=[
|
|
3
|
+
Routes incoming studio-bridge messages to handlers by message type, and wraps
|
|
4
|
+
whatever a handler returns into the response message.
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
- An unknown message type answers with an `UNKNOWN_REQUEST` error.
|
|
7
|
+
- A handler that throws answers with an `INTERNAL_ERROR` error.
|
|
8
|
+
- A handler that returns nil sends nothing, which is how an action that
|
|
9
|
+
replies on its own (through `sendMessage`) opts out.
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- Handler returns nil: no response is generated
|
|
11
|
+
Action modules pushed over the wire call `register` and `setResponseType` on
|
|
12
|
+
the router. Those two keep their lowercase names because a persistent plugin
|
|
13
|
+
installed from an older release still runs action source pushed by a newer CLI.
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
]]
|
|
15
|
+
@class ActionRouter
|
|
16
|
+
]=]
|
|
16
17
|
|
|
17
18
|
local ActionRouter = {}
|
|
19
|
+
ActionRouter.ClassName = "ActionRouter"
|
|
18
20
|
ActionRouter.__index = ActionRouter
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
export type Message = {
|
|
23
|
+
type: string,
|
|
24
|
+
sessionId: string,
|
|
25
|
+
payload: { [string]: any },
|
|
26
|
+
requestId: string?,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type Handler = (payload: { [string]: any }, requestId: string, sessionId: string) -> { [string]: any }?
|
|
30
|
+
|
|
31
|
+
export type SendMessage = (message: { [string]: any }) -> ()
|
|
32
|
+
|
|
33
|
+
export type ActionInfo = {
|
|
34
|
+
module: any,
|
|
35
|
+
hash: string,
|
|
36
|
+
handlerNames: { string },
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type ActionRouter = typeof(setmetatable(
|
|
40
|
+
{} :: {
|
|
41
|
+
_handlers: { [string]: Handler },
|
|
42
|
+
_responseTypes: { [string]: string },
|
|
43
|
+
_actions: { [string]: ActionInfo },
|
|
44
|
+
_vendorPng: any?,
|
|
45
|
+
},
|
|
46
|
+
{} :: typeof({ __index = ActionRouter })
|
|
47
|
+
))
|
|
48
|
+
|
|
49
|
+
--[=[
|
|
50
|
+
Constructs a new router with no handlers.
|
|
51
|
+
]=]
|
|
52
|
+
function ActionRouter.new(): ActionRouter
|
|
53
|
+
local self: ActionRouter = setmetatable({} :: any, ActionRouter)
|
|
54
|
+
|
|
55
|
+
self._handlers = {}
|
|
56
|
+
self._responseTypes = {}
|
|
57
|
+
self._actions = {}
|
|
58
|
+
|
|
59
|
+
-- The screenshot action reads its PNG encoder off this field
|
|
60
|
+
self._vendorPng = nil
|
|
23
61
|
|
|
24
|
-
function ActionRouter.new()
|
|
25
|
-
local self = setmetatable({
|
|
26
|
-
_handlers = {} :: {
|
|
27
|
-
[string]: (payload: { [string]: any }, requestId: string, sessionId: string) -> { [string]: any }?,
|
|
28
|
-
},
|
|
29
|
-
_responseTypes = {} :: { [string]: string },
|
|
30
|
-
_actions = {} :: { [string]: { module: any, hash: string, handlerNames: { string } } },
|
|
31
|
-
}, ActionRouter)
|
|
32
62
|
return self
|
|
33
63
|
end
|
|
34
64
|
|
|
35
|
-
--
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
function ActionRouter.register(
|
|
40
|
-
self: any,
|
|
41
|
-
messageType: string,
|
|
42
|
-
handler: (
|
|
43
|
-
payload: { [string]: any },
|
|
44
|
-
requestId: string,
|
|
45
|
-
sessionId: string
|
|
46
|
-
) -> { [string]: any }?
|
|
47
|
-
)
|
|
65
|
+
--[=[
|
|
66
|
+
Sets the handler for a message type, replacing any previous one.
|
|
67
|
+
]=]
|
|
68
|
+
function ActionRouter.register(self: ActionRouter, messageType: string, handler: Handler)
|
|
48
69
|
self._handlers[messageType] = handler
|
|
49
70
|
end
|
|
50
71
|
|
|
51
|
-
--
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
]]
|
|
61
|
-
function ActionRouter.
|
|
62
|
-
self
|
|
63
|
-
|
|
64
|
-
type: string,
|
|
65
|
-
sessionId: string,
|
|
66
|
-
payload: { [string]: any },
|
|
67
|
-
requestId: string?,
|
|
68
|
-
}
|
|
69
|
-
): { [string]: any }?
|
|
70
|
-
local handler = self._handlers[message.type]
|
|
72
|
+
--[=[
|
|
73
|
+
Overrides the response type for a message type. Defaults to `<messageType>Result`.
|
|
74
|
+
]=]
|
|
75
|
+
function ActionRouter.setResponseType(self: ActionRouter, messageType: string, responseType: string)
|
|
76
|
+
self._responseTypes[messageType] = responseType
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
--[=[
|
|
80
|
+
Sets the PNG encoder handed to the screenshot action.
|
|
81
|
+
]=]
|
|
82
|
+
function ActionRouter.SetVendorPng(self: ActionRouter, png: any)
|
|
83
|
+
self._vendorPng = png
|
|
84
|
+
end
|
|
71
85
|
|
|
86
|
+
--[=[
|
|
87
|
+
Dispatches a message to its handler and returns the response message, if any.
|
|
88
|
+
]=]
|
|
89
|
+
function ActionRouter.Dispatch(self: ActionRouter, message: Message): Message?
|
|
90
|
+
local handler = self._handlers[message.type]
|
|
72
91
|
if handler == nil then
|
|
73
|
-
return {
|
|
74
|
-
type = "error",
|
|
75
|
-
sessionId = message.sessionId,
|
|
76
|
-
requestId = message.requestId,
|
|
77
|
-
payload = {
|
|
78
|
-
code = "UNKNOWN_REQUEST",
|
|
79
|
-
message = "Unknown message type: " .. tostring(message.type),
|
|
80
|
-
},
|
|
81
|
-
}
|
|
92
|
+
return ActionRouter._errorResponse(message, "UNKNOWN_REQUEST", `Unknown message type: {tostring(message.type)}`)
|
|
82
93
|
end
|
|
83
94
|
|
|
84
|
-
local
|
|
85
|
-
local ok, result = pcall(handler, message.payload, requestId, message.sessionId)
|
|
86
|
-
|
|
95
|
+
local ok, result = pcall(handler, message.payload, message.requestId or "", message.sessionId)
|
|
87
96
|
if not ok then
|
|
88
|
-
return {
|
|
89
|
-
type = "error",
|
|
90
|
-
sessionId = message.sessionId,
|
|
91
|
-
requestId = message.requestId,
|
|
92
|
-
payload = {
|
|
93
|
-
code = "INTERNAL_ERROR",
|
|
94
|
-
message = "Handler error: " .. tostring(result),
|
|
95
|
-
},
|
|
96
|
-
}
|
|
97
|
+
return ActionRouter._errorResponse(message, "INTERNAL_ERROR", `Handler error: {tostring(result)}`)
|
|
97
98
|
end
|
|
98
99
|
|
|
99
100
|
if result == nil then
|
|
100
101
|
return nil
|
|
101
102
|
end
|
|
102
103
|
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
if result.success == false and type(result.code) == "string" and type(result.message) == "string" then
|
|
105
|
+
return ActionRouter._errorResponse(message, result.code, result.message)
|
|
106
|
+
end
|
|
105
107
|
|
|
106
108
|
return {
|
|
107
|
-
type =
|
|
109
|
+
type = self._responseTypes[message.type] or `{message.type}Result`,
|
|
108
110
|
sessionId = message.sessionId,
|
|
109
111
|
requestId = message.requestId,
|
|
110
112
|
payload = result,
|
|
111
113
|
}
|
|
112
114
|
end
|
|
113
115
|
|
|
114
|
-
--
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
--[=[
|
|
117
|
+
Tears down every installed action and drops all handlers.
|
|
118
|
+
]=]
|
|
119
|
+
function ActionRouter.Destroy(self: ActionRouter)
|
|
120
|
+
for _, action in self._actions do
|
|
121
|
+
if type(action.module) == "table" and type(action.module.teardown) == "function" then
|
|
122
|
+
pcall(action.module.teardown)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
117
125
|
|
|
118
|
-
|
|
119
|
-
self.
|
|
126
|
+
table.clear(self._actions)
|
|
127
|
+
table.clear(self._handlers)
|
|
128
|
+
table.clear(self._responseTypes)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
--[=[
|
|
132
|
+
Compiles Luau source into a function, like `loadstring`. A playtest's client
|
|
133
|
+
has no `loadstring`, so there the source compiles through a ModuleScript
|
|
134
|
+
instead. Returns nil and the compile error when the source does not compile.
|
|
135
|
+
]=]
|
|
136
|
+
function ActionRouter.Compile(_self: ActionRouter, source: string, chunkName: string?): (any, string?)
|
|
137
|
+
local loadstringOk, fn, compileErr = pcall(loadstring :: any, source, chunkName)
|
|
138
|
+
if loadstringOk then
|
|
139
|
+
return fn, compileErr
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
return ActionRouter._compileWithModuleScript(source, chunkName)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
function ActionRouter._compileWithModuleScript(source: string, chunkName: string?): (any, string?)
|
|
146
|
+
local moduleName = if chunkName then string.gsub(chunkName, "^[@=]", "") else "compiled"
|
|
147
|
+
|
|
148
|
+
local moduleScript = Instance.new("ModuleScript")
|
|
149
|
+
moduleScript.Name = moduleName
|
|
150
|
+
-- Wrapping on the first line keeps a top-level `return` legal and line numbers unchanged
|
|
151
|
+
moduleScript.Source = `return function(...) {source}\nend`
|
|
152
|
+
|
|
153
|
+
-- require only reports that the module failed to load; the compile error
|
|
154
|
+
-- itself reaches the output a frame later
|
|
155
|
+
local compileErrors: { string } = {}
|
|
156
|
+
local logConnection = game:GetService("LogService").MessageOut:Connect(function(message, messageType)
|
|
157
|
+
if messageType == Enum.MessageType.MessageError and string.find(message, moduleName, 1, true) == 1 then
|
|
158
|
+
table.insert(compileErrors, message)
|
|
159
|
+
end
|
|
160
|
+
end)
|
|
161
|
+
|
|
162
|
+
local requireOk, result = pcall(require, moduleScript)
|
|
163
|
+
if not requireOk then
|
|
164
|
+
task.wait()
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
logConnection:Disconnect()
|
|
168
|
+
moduleScript:Destroy()
|
|
169
|
+
|
|
170
|
+
if requireOk then
|
|
171
|
+
return result, nil
|
|
172
|
+
end
|
|
173
|
+
return nil, compileErrors[1] or tostring(result)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
function ActionRouter._errorResponse(message: Message, code: string, errorMessage: string): Message
|
|
177
|
+
return {
|
|
178
|
+
type = "error",
|
|
179
|
+
sessionId = message.sessionId,
|
|
180
|
+
requestId = message.requestId,
|
|
181
|
+
payload = {
|
|
182
|
+
code = code,
|
|
183
|
+
message = errorMessage,
|
|
184
|
+
},
|
|
185
|
+
}
|
|
120
186
|
end
|
|
121
187
|
|
|
122
|
-
--
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
If the source defines a simple handler function instead, it is registered
|
|
134
|
-
directly as the handler for the given action name.
|
|
135
|
-
|
|
136
|
-
@param name The action name (used as the message type if not registered otherwise).
|
|
137
|
-
@param source The Luau source code string.
|
|
138
|
-
@param sendMessage Optional callback for actions that send their own responses.
|
|
139
|
-
@param logBuffer Optional log buffer instance.
|
|
140
|
-
@param responseType Optional response type override.
|
|
141
|
-
@param hash Optional content hash for skip-on-same-hash optimization.
|
|
142
|
-
@return success, error?
|
|
143
|
-
]]
|
|
144
|
-
function ActionRouter.registerAction(
|
|
145
|
-
self: any,
|
|
188
|
+
--[=[
|
|
189
|
+
Installs an action from Luau source received over the wire.
|
|
190
|
+
|
|
191
|
+
The source returns either a table with `register(router, sendMessage?, logBuffer?)`
|
|
192
|
+
(and optionally `teardown()`), or a bare handler function registered under `name`.
|
|
193
|
+
|
|
194
|
+
Re-registering a name tears the previous module down and removes its handlers
|
|
195
|
+
first. With a `hash`, the same hash installed twice is a no-op.
|
|
196
|
+
]=]
|
|
197
|
+
function ActionRouter.RegisterAction(
|
|
198
|
+
self: ActionRouter,
|
|
146
199
|
name: string,
|
|
147
200
|
source: string,
|
|
148
|
-
sendMessage:
|
|
201
|
+
sendMessage: SendMessage?,
|
|
149
202
|
logBuffer: any?,
|
|
150
203
|
responseType: string?,
|
|
151
204
|
hash: string?
|
|
152
205
|
): (boolean, string?)
|
|
153
|
-
|
|
154
|
-
if hash and
|
|
206
|
+
local oldAction = self._actions[name]
|
|
207
|
+
if hash and oldAction and oldAction.hash == hash then
|
|
155
208
|
return true, nil
|
|
156
209
|
end
|
|
157
210
|
|
|
158
|
-
-- If an old module exists, tear it down and remove its handlers
|
|
159
|
-
local oldAction = self._actions[name]
|
|
160
211
|
if oldAction then
|
|
161
|
-
if type(oldAction.module.teardown) == "function" then
|
|
212
|
+
if type(oldAction.module) == "table" and type(oldAction.module.teardown) == "function" then
|
|
162
213
|
pcall(oldAction.module.teardown)
|
|
163
214
|
end
|
|
164
215
|
for _, handlerName in oldAction.handlerNames do
|
|
@@ -167,77 +218,75 @@ function ActionRouter.registerAction(
|
|
|
167
218
|
end
|
|
168
219
|
end
|
|
169
220
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
beforeHandlers[k] = true
|
|
221
|
+
local handlersBefore: { [string]: boolean } = {}
|
|
222
|
+
for handlerName in self._handlers do
|
|
223
|
+
handlersBefore[handlerName] = true
|
|
174
224
|
end
|
|
175
225
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return
|
|
179
|
-
end)
|
|
180
|
-
|
|
181
|
-
if not loadOk or not moduleOrErr then
|
|
182
|
-
return false, `Failed to load action source: {moduleOrErr or "loadstring returned nil"}`
|
|
226
|
+
local loadOk, chunkOrErr, compileErr = pcall(self.Compile, self, source, `@action/{name}`)
|
|
227
|
+
if not loadOk or not chunkOrErr then
|
|
228
|
+
return false, `Failed to load action source: {compileErr or chunkOrErr or "compile returned nil"}`
|
|
183
229
|
end
|
|
184
230
|
|
|
185
|
-
|
|
186
|
-
local execOk, moduleTable = pcall(moduleOrErr)
|
|
231
|
+
local execOk, moduleOrErr = pcall(chunkOrErr)
|
|
187
232
|
if not execOk then
|
|
188
|
-
return false, `Failed to execute action module: {
|
|
233
|
+
return false, `Failed to execute action module: {moduleOrErr}`
|
|
189
234
|
end
|
|
190
235
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return false, `register() failed: {regErr}`
|
|
236
|
+
if type(moduleOrErr) == "table" and type(moduleOrErr.register) == "function" then
|
|
237
|
+
local registerOk, registerErr = pcall(moduleOrErr.register, self, sendMessage, logBuffer)
|
|
238
|
+
if not registerOk then
|
|
239
|
+
return false, `register() failed: {registerErr}`
|
|
196
240
|
end
|
|
197
|
-
elseif type(
|
|
198
|
-
|
|
199
|
-
self:register(name, moduleTable)
|
|
241
|
+
elseif type(moduleOrErr) == "function" then
|
|
242
|
+
self:register(name, moduleOrErr)
|
|
200
243
|
else
|
|
201
|
-
return false,
|
|
244
|
+
return false, "Action module must return a table with .register() or a function"
|
|
202
245
|
end
|
|
203
246
|
|
|
204
|
-
-- Set custom response type if provided
|
|
205
247
|
if responseType then
|
|
206
248
|
self._responseTypes[name] = responseType
|
|
207
249
|
end
|
|
208
250
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
table.insert(registeredNames, k)
|
|
251
|
+
local handlerNames: { string } = {}
|
|
252
|
+
for handlerName in self._handlers do
|
|
253
|
+
if not handlersBefore[handlerName] then
|
|
254
|
+
table.insert(handlerNames, handlerName)
|
|
214
255
|
end
|
|
215
256
|
end
|
|
216
257
|
|
|
217
|
-
-- Store in _actions for hash tracking
|
|
218
258
|
if hash then
|
|
219
259
|
self._actions[name] = {
|
|
220
|
-
module =
|
|
260
|
+
module = moduleOrErr,
|
|
221
261
|
hash = hash,
|
|
222
|
-
handlerNames =
|
|
262
|
+
handlerNames = handlerNames,
|
|
223
263
|
}
|
|
224
264
|
end
|
|
225
265
|
|
|
226
266
|
return true, nil
|
|
227
267
|
end
|
|
228
268
|
|
|
229
|
-
--
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
269
|
+
--[=[
|
|
270
|
+
Returns the handler names an installed action registered, or nil when no
|
|
271
|
+
action with a hash is installed under `name`.
|
|
272
|
+
]=]
|
|
273
|
+
function ActionRouter.GetActionHandlerNames(self: ActionRouter, name: string): { string }?
|
|
274
|
+
local action = self._actions[name]
|
|
275
|
+
if not action then
|
|
276
|
+
return nil
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
return table.clone(action.handlerNames)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
--[=[
|
|
283
|
+
Returns action name to content hash for every installed action. The bridge
|
|
284
|
+
compares this against its own hashes to decide which actions to push.
|
|
285
|
+
]=]
|
|
286
|
+
function ActionRouter.GetInstalledActions(self: ActionRouter): { [string]: string }
|
|
287
|
+
local result: { [string]: string } = {}
|
|
288
|
+
for name, action in self._actions do
|
|
289
|
+
result[name] = action.hash
|
|
241
290
|
end
|
|
242
291
|
return result
|
|
243
292
|
end
|