@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
|
@@ -1,317 +1,433 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
--!strict
|
|
2
|
+
--[=[
|
|
3
|
+
Action that compiles and runs Luau code sent by the bridge, answering with a
|
|
4
|
+
`scriptComplete` message.
|
|
5
|
+
|
|
6
|
+
- Echoes the request's `requestId` on every response.
|
|
7
|
+
- Fails with `SCRIPT_LOAD_ERROR` when the code does not compile,
|
|
8
|
+
`SCRIPT_RUNTIME_ERROR` with a `traceback` when it throws, and
|
|
9
|
+
`SCRIPT_TIMEOUT` when it outlives `payload.timeoutMs`. A timed out script
|
|
10
|
+
is cancelled, so the requests queued behind it still run.
|
|
11
|
+
- Passes `payload.args`, a list of strings, to the script as `...`.
|
|
12
|
+
- Runs concurrent requests one at a time, in arrival order.
|
|
13
|
+
- Returns everything printed while the script runs, read from LogService, so
|
|
14
|
+
output from required modules and from threads the script starts comes back.
|
|
15
|
+
- Marshals everything the script returns onto `payload.returnValues`, so a
|
|
16
|
+
caller reads a result as a value instead of scraping it out of the output.
|
|
17
|
+
|
|
18
|
+
Loaded standalone inside the plugin, so it cannot require anything.
|
|
19
|
+
|
|
20
|
+
Compiles through the router's `Compile`, which still works in a playtest's
|
|
21
|
+
client where `loadstring` does not exist. Routers from older plugins have no
|
|
22
|
+
`Compile`, and fall back to `loadstring`.
|
|
23
|
+
|
|
24
|
+
@class ExecuteAction
|
|
25
|
+
]=]
|
|
19
26
|
|
|
20
|
-
local
|
|
27
|
+
local MAX_DEPTH = 64
|
|
28
|
+
local CHUNK_NAME = "=exec"
|
|
29
|
+
local PLUGIN_PREFIX = "[StudioBridge]"
|
|
30
|
+
-- Tracebacks name this module's frames the way its first line does
|
|
31
|
+
local OWN_FRAME_PREFIX = string.match(debug.traceback(), "^([^\n]-):%d+")
|
|
21
32
|
|
|
22
|
-
|
|
23
|
-
-- Internal queue for sequential execution
|
|
24
|
-
-- ---------------------------------------------------------------------------
|
|
33
|
+
local ExecuteAction = {}
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
{}
|
|
28
|
-
local _processing = false
|
|
35
|
+
type SendMessage = (message: { [string]: any }) -> ()
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
type QueuedRequest = {
|
|
38
|
+
payload: { [string]: any },
|
|
39
|
+
requestId: string?,
|
|
40
|
+
sessionId: string,
|
|
41
|
+
sendMessage: SendMessage?,
|
|
42
|
+
receivedAt: number,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type LogEntry = {
|
|
46
|
+
level: string,
|
|
47
|
+
body: string,
|
|
48
|
+
timestamp: number,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
local LOG_LEVELS: { [Enum.MessageType]: string } = {
|
|
52
|
+
[Enum.MessageType.MessageOutput] = "Print",
|
|
53
|
+
[Enum.MessageType.MessageInfo] = "Info",
|
|
54
|
+
[Enum.MessageType.MessageWarning] = "Warning",
|
|
55
|
+
[Enum.MessageType.MessageError] = "Error",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
local queue: { QueuedRequest } = {}
|
|
59
|
+
local isProcessing = false
|
|
60
|
+
local compile: (source: string, chunkName: string?) -> (any, string?) = loadstring :: any
|
|
61
|
+
|
|
62
|
+
--[=[
|
|
63
|
+
Registers the `execute` handler. With `sendMessage`, requests queue and each
|
|
64
|
+
reply is sent directly; without it, the reply goes back through the router.
|
|
65
|
+
]=]
|
|
66
|
+
function ExecuteAction.register(router: any, sendMessage: SendMessage?)
|
|
67
|
+
if type(router.Compile) == "function" then
|
|
68
|
+
compile = function(source: string, chunkName: string?)
|
|
69
|
+
return router:Compile(source, chunkName)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
33
72
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
73
|
+
router:setResponseType("execute", "scriptComplete")
|
|
74
|
+
router:register("execute", function(payload: { [string]: any }, requestId: string, sessionId: string)
|
|
75
|
+
if not sendMessage then
|
|
76
|
+
return ExecuteAction._handleExecute(payload, requestId, sessionId, nil)
|
|
77
|
+
end
|
|
38
78
|
|
|
39
|
-
|
|
79
|
+
table.insert(queue, {
|
|
80
|
+
payload = payload,
|
|
81
|
+
requestId = requestId,
|
|
82
|
+
sessionId = sessionId,
|
|
83
|
+
sendMessage = sendMessage,
|
|
84
|
+
receivedAt = os.clock(),
|
|
85
|
+
})
|
|
86
|
+
ExecuteAction._processQueue()
|
|
40
87
|
|
|
41
|
-
|
|
42
|
-
|
|
88
|
+
-- Replied through sendMessage, so the router must not reply as well
|
|
89
|
+
return nil
|
|
90
|
+
end)
|
|
43
91
|
end
|
|
44
92
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
93
|
+
--[=[
|
|
94
|
+
Cancels every queued request, replying `ACTION_REPLACED` to each.
|
|
95
|
+
]=]
|
|
96
|
+
function ExecuteAction.teardown()
|
|
97
|
+
for _, request in queue do
|
|
98
|
+
if request.sendMessage then
|
|
99
|
+
request.sendMessage({
|
|
100
|
+
type = "scriptComplete",
|
|
101
|
+
sessionId = request.sessionId,
|
|
102
|
+
requestId = request.requestId,
|
|
103
|
+
payload = {
|
|
104
|
+
success = false,
|
|
105
|
+
error = "Action re-registered, request cancelled",
|
|
106
|
+
code = "ACTION_REPLACED",
|
|
107
|
+
},
|
|
108
|
+
})
|
|
60
109
|
end
|
|
61
|
-
return array
|
|
62
110
|
end
|
|
63
111
|
|
|
64
|
-
|
|
65
|
-
for key, item in value do
|
|
66
|
-
map[if type(key) == "string" then key else tostring(key)] = serializeValue(item, depth + 1, seen)
|
|
67
|
-
end
|
|
68
|
-
return map
|
|
112
|
+
ExecuteAction._resetQueue()
|
|
69
113
|
end
|
|
70
114
|
|
|
71
|
-
|
|
72
|
-
|
|
115
|
+
--[=[
|
|
116
|
+
Runs an execute request and returns its response payload, bypassing the queue.
|
|
117
|
+
]=]
|
|
118
|
+
function ExecuteAction.handleExecute(
|
|
119
|
+
payload: { [string]: any },
|
|
120
|
+
requestId: string?,
|
|
121
|
+
sessionId: string
|
|
122
|
+
): { [string]: any }?
|
|
123
|
+
return ExecuteAction._handleExecute(payload, requestId, sessionId, nil)
|
|
124
|
+
end
|
|
73
125
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
-- inf and nan have no JSON spelling, and encoding one produces a
|
|
78
|
-
-- document the server cannot decode -- losing the entire message.
|
|
79
|
-
if value ~= value or value == math.huge or value == -math.huge then
|
|
80
|
-
return unsupported("number", tostring(value))
|
|
81
|
-
end
|
|
82
|
-
return value
|
|
83
|
-
elseif valueType == "table" then
|
|
84
|
-
if depth > MAX_DEPTH then
|
|
85
|
-
return unsupported("table", "<max depth exceeded>")
|
|
86
|
-
end
|
|
87
|
-
if seen[value] then
|
|
88
|
-
return unsupported("table", "<cycle>")
|
|
89
|
-
end
|
|
90
|
-
seen[value] = true
|
|
91
|
-
local serialized = serializeTable(value, depth, seen)
|
|
92
|
-
seen[value] = nil
|
|
93
|
-
return serialized
|
|
94
|
-
elseif valueType == "Vector3" then
|
|
95
|
-
return { type = "Vector3", value = { value.X, value.Y, value.Z } }
|
|
96
|
-
elseif valueType == "Vector2" then
|
|
97
|
-
return { type = "Vector2", value = { value.X, value.Y } }
|
|
98
|
-
elseif valueType == "CFrame" then
|
|
99
|
-
return { type = "CFrame", value = { value:GetComponents() } }
|
|
100
|
-
elseif valueType == "Color3" then
|
|
101
|
-
return { type = "Color3", value = { value.R, value.G, value.B } }
|
|
102
|
-
elseif valueType == "UDim2" then
|
|
103
|
-
return { type = "UDim2", value = { value.X.Scale, value.X.Offset, value.Y.Scale, value.Y.Offset } }
|
|
104
|
-
elseif valueType == "UDim" then
|
|
105
|
-
return { type = "UDim", value = { value.Scale, value.Offset } }
|
|
106
|
-
elseif valueType == "BrickColor" then
|
|
107
|
-
return { type = "BrickColor", name = value.Name, value = value.Number }
|
|
108
|
-
elseif valueType == "EnumItem" then
|
|
109
|
-
return { type = "EnumItem", enum = tostring(value.EnumType), name = value.Name, value = value.Value }
|
|
110
|
-
elseif valueType == "Instance" then
|
|
111
|
-
return { type = "Instance", className = value.ClassName, path = value:GetFullName() }
|
|
112
|
-
else
|
|
113
|
-
return unsupported(valueType, tostring(value))
|
|
114
|
-
end
|
|
126
|
+
function ExecuteAction._resetQueue()
|
|
127
|
+
queue = {}
|
|
128
|
+
isProcessing = false
|
|
115
129
|
end
|
|
116
130
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
131
|
+
function ExecuteAction._processQueue()
|
|
132
|
+
if isProcessing then
|
|
133
|
+
return
|
|
134
|
+
end
|
|
135
|
+
isProcessing = true
|
|
136
|
+
|
|
137
|
+
while #queue > 0 do
|
|
138
|
+
local request = table.remove(queue, 1) :: QueuedRequest
|
|
139
|
+
ExecuteAction._handleExecute(
|
|
140
|
+
request.payload,
|
|
141
|
+
request.requestId,
|
|
142
|
+
request.sessionId,
|
|
143
|
+
request.sendMessage,
|
|
144
|
+
request.receivedAt
|
|
145
|
+
)
|
|
128
146
|
end
|
|
129
|
-
return returnValues
|
|
130
|
-
end
|
|
131
147
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
-- ---------------------------------------------------------------------------
|
|
148
|
+
isProcessing = false
|
|
149
|
+
end
|
|
135
150
|
|
|
136
|
-
-- Handle an execute request by compiling and running the provided code.
|
|
137
|
-
-- Captures print/warn output by temporarily intercepting the globals.
|
|
138
151
|
function ExecuteAction._handleExecute(
|
|
139
152
|
payload: { [string]: any },
|
|
140
153
|
requestId: string?,
|
|
141
154
|
sessionId: string,
|
|
142
|
-
sendMessage:
|
|
155
|
+
sendMessage: SendMessage?,
|
|
156
|
+
receivedAt: number?
|
|
143
157
|
): { [string]: any }?
|
|
144
|
-
|
|
158
|
+
-- An empty requestId means none was sent
|
|
159
|
+
local effectiveRequestId = if requestId ~= "" then requestId else nil
|
|
145
160
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
end
|
|
161
|
+
local function reply(responsePayload: { [string]: any }): { [string]: any }?
|
|
162
|
+
if not sendMessage then
|
|
163
|
+
return responsePayload
|
|
164
|
+
end
|
|
151
165
|
|
|
152
|
-
|
|
153
|
-
local function buildResponse(responsePayload: { [string]: any }): { [string]: any }
|
|
154
|
-
local msg: { [string]: any } = {
|
|
166
|
+
sendMessage({
|
|
155
167
|
type = "scriptComplete",
|
|
156
168
|
sessionId = sessionId,
|
|
169
|
+
requestId = effectiveRequestId,
|
|
157
170
|
payload = responsePayload,
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
msg.requestId = effectiveRequestId
|
|
161
|
-
end
|
|
162
|
-
return msg
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
-- Helper to send or return the result
|
|
166
|
-
local function sendResult(responsePayload: { [string]: any }): { [string]: any }?
|
|
167
|
-
if sendMessage then
|
|
168
|
-
sendMessage(buildResponse(responsePayload))
|
|
169
|
-
return nil
|
|
170
|
-
end
|
|
171
|
-
return responsePayload
|
|
171
|
+
})
|
|
172
|
+
return nil
|
|
172
173
|
end
|
|
173
174
|
|
|
174
|
-
|
|
175
|
-
|
|
175
|
+
local code = payload and (payload.script or payload.code)
|
|
176
|
+
if type(code) ~= "string" then
|
|
177
|
+
return reply({ success = false, error = "Missing code in execute request", code = "SCRIPT_LOAD_ERROR" })
|
|
176
178
|
end
|
|
177
179
|
|
|
178
|
-
local compileOk,
|
|
180
|
+
local compileOk, fn, compileErr = pcall(compile, code, CHUNK_NAME)
|
|
179
181
|
if not compileOk then
|
|
180
|
-
return
|
|
182
|
+
return reply({ success = false, error = tostring(fn), code = "SCRIPT_LOAD_ERROR" })
|
|
181
183
|
end
|
|
182
|
-
if not
|
|
183
|
-
return
|
|
184
|
+
if not fn then
|
|
185
|
+
return reply({
|
|
186
|
+
success = false,
|
|
187
|
+
error = if compileErr then tostring(compileErr) else "Failed to compile script",
|
|
188
|
+
code = "SCRIPT_LOAD_ERROR",
|
|
189
|
+
})
|
|
184
190
|
end
|
|
185
191
|
|
|
186
|
-
local
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
-- environment. Local variable shadowing doesn't work because loadstring'd
|
|
190
|
-
-- code accesses the global environment, not this module's locals.
|
|
191
|
-
local captured: { { level: string, body: string, timestamp: number } } = {}
|
|
192
|
-
local env = getfenv(fn)
|
|
193
|
-
local originalPrint = env.print
|
|
194
|
-
local originalWarn = env.warn
|
|
195
|
-
|
|
196
|
-
env.print = function(...)
|
|
197
|
-
local parts = {}
|
|
198
|
-
for i = 1, select("#", ...) do
|
|
199
|
-
parts[i] = tostring(select(i, ...))
|
|
200
|
-
end
|
|
201
|
-
local body = table.concat(parts, "\t")
|
|
202
|
-
table.insert(captured, { level = "Print", body = body, timestamp = os.clock() })
|
|
203
|
-
originalPrint(...)
|
|
192
|
+
local args = payload.args or {}
|
|
193
|
+
if type(args) ~= "table" then
|
|
194
|
+
return reply({ success = false, error = "Script args must be a list", code = "SCRIPT_LOAD_ERROR" })
|
|
204
195
|
end
|
|
205
196
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
197
|
+
local timeoutMs = payload.timeoutMs
|
|
198
|
+
local timeoutSeconds = if type(timeoutMs) == "number" then timeoutMs / 1000 else nil
|
|
199
|
+
-- The caller's timeout started when it sent the request, not when its turn came
|
|
200
|
+
if timeoutSeconds and receivedAt then
|
|
201
|
+
timeoutSeconds -= os.clock() - receivedAt
|
|
202
|
+
if timeoutSeconds <= 0 then
|
|
203
|
+
return reply({
|
|
204
|
+
success = false,
|
|
205
|
+
error = `Script timed out after {timeoutMs}ms waiting behind other scripts, and never ran`,
|
|
206
|
+
code = "SCRIPT_TIMEOUT",
|
|
207
|
+
})
|
|
210
208
|
end
|
|
211
|
-
local body = table.concat(parts, "\t")
|
|
212
|
-
table.insert(captured, { level = "Warning", body = body, timestamp = os.clock() })
|
|
213
|
-
originalWarn(...)
|
|
214
209
|
end
|
|
215
210
|
|
|
216
|
-
local
|
|
217
|
-
local
|
|
211
|
+
local captured: { LogEntry } = {}
|
|
212
|
+
local logConnection = ExecuteAction._captureOutput(captured)
|
|
213
|
+
local status, result = ExecuteAction._runAsync(fn, timeoutSeconds, args)
|
|
218
214
|
|
|
219
|
-
--
|
|
220
|
-
|
|
221
|
-
|
|
215
|
+
-- MessageOut can fire a frame late, after the script's last print
|
|
216
|
+
task.wait()
|
|
217
|
+
logConnection:Disconnect()
|
|
222
218
|
|
|
223
|
-
if
|
|
224
|
-
return
|
|
219
|
+
if status == "timeout" then
|
|
220
|
+
return reply({
|
|
225
221
|
success = false,
|
|
226
|
-
error =
|
|
222
|
+
error = `Script timed out after {timeoutMs}ms and was cancelled`,
|
|
223
|
+
code = "SCRIPT_TIMEOUT",
|
|
224
|
+
output = captured,
|
|
225
|
+
})
|
|
226
|
+
elseif status == "error" then
|
|
227
|
+
return reply({
|
|
228
|
+
success = false,
|
|
229
|
+
error = result.message,
|
|
230
|
+
traceback = result.traceback,
|
|
227
231
|
code = "SCRIPT_RUNTIME_ERROR",
|
|
228
232
|
output = captured,
|
|
229
233
|
})
|
|
230
234
|
end
|
|
231
235
|
|
|
232
|
-
return
|
|
236
|
+
return reply({
|
|
233
237
|
success = true,
|
|
234
238
|
output = captured,
|
|
235
|
-
returnValues =
|
|
239
|
+
returnValues = ExecuteAction._serializeReturnValues(result),
|
|
236
240
|
})
|
|
237
241
|
end
|
|
238
242
|
|
|
239
|
-
--
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if
|
|
245
|
-
return
|
|
243
|
+
--[[
|
|
244
|
+
Drops the frames of this module's own wrapper from a traceback, leaving only
|
|
245
|
+
the script's.
|
|
246
|
+
]]
|
|
247
|
+
function ExecuteAction._dropOwnFrames(traceback: string): string
|
|
248
|
+
if not OWN_FRAME_PREFIX then
|
|
249
|
+
return traceback
|
|
246
250
|
end
|
|
247
|
-
_processing = true
|
|
248
251
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
+
local lines = {}
|
|
253
|
+
for _, line in string.split(traceback, "\n") do
|
|
254
|
+
if string.sub(line, 1, #OWN_FRAME_PREFIX + 1) ~= `{OWN_FRAME_PREFIX}:` then
|
|
255
|
+
table.insert(lines, line)
|
|
256
|
+
end
|
|
252
257
|
end
|
|
258
|
+
return table.concat(lines, "\n")
|
|
259
|
+
end
|
|
253
260
|
|
|
254
|
-
|
|
261
|
+
--[[
|
|
262
|
+
Collects every message logged until the connection is disconnected, other
|
|
263
|
+
than the plugin's own.
|
|
264
|
+
]]
|
|
265
|
+
function ExecuteAction._captureOutput(captured: { LogEntry }): RBXScriptConnection
|
|
266
|
+
return game:GetService("LogService").MessageOut:Connect(function(message: string, messageType: Enum.MessageType)
|
|
267
|
+
if string.sub(message, 1, #PLUGIN_PREFIX) == PLUGIN_PREFIX then
|
|
268
|
+
return
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
table.insert(captured, {
|
|
272
|
+
level = LOG_LEVELS[messageType] or "Print",
|
|
273
|
+
body = message,
|
|
274
|
+
timestamp = os.clock(),
|
|
275
|
+
})
|
|
276
|
+
end)
|
|
255
277
|
end
|
|
256
278
|
|
|
257
|
-
--
|
|
258
|
-
|
|
259
|
-
|
|
279
|
+
--[[
|
|
280
|
+
Runs `fn` with `args` in its own thread. Returns "ok" and everything it returned
|
|
281
|
+
(pcall-style, status first), "error" and its message and traceback, or
|
|
282
|
+
"timeout" once `timeoutSec` passes, after cancelling the thread.
|
|
283
|
+
]]
|
|
284
|
+
function ExecuteAction._runAsync(fn: (...any) -> ...any, timeoutSec: number?, args: { any }?): (string, any)
|
|
285
|
+
local callerThread = coroutine.running()
|
|
286
|
+
local isWaiting = false
|
|
287
|
+
local outcome: { status: string, result: any }? = nil
|
|
288
|
+
|
|
289
|
+
local function finish(status: string, result: any)
|
|
290
|
+
if outcome then
|
|
291
|
+
return
|
|
292
|
+
end
|
|
293
|
+
outcome = { status = status, result = result }
|
|
294
|
+
if isWaiting then
|
|
295
|
+
task.defer(callerThread)
|
|
296
|
+
end
|
|
297
|
+
end
|
|
260
298
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
sessionId = sessionId,
|
|
271
|
-
sendMessage = sendMessage,
|
|
272
|
-
})
|
|
273
|
-
_processQueue()
|
|
274
|
-
-- Return nil so the ActionRouter does not generate a response
|
|
275
|
-
return nil
|
|
299
|
+
local scriptThread = task.spawn(function()
|
|
300
|
+
local packed = table.pack(xpcall(fn, function(err)
|
|
301
|
+
return {
|
|
302
|
+
message = tostring(err),
|
|
303
|
+
traceback = ExecuteAction._dropOwnFrames(debug.traceback(nil, 2)),
|
|
304
|
+
}
|
|
305
|
+
end, table.unpack(args or {})))
|
|
306
|
+
if packed[1] then
|
|
307
|
+
finish("ok", packed)
|
|
276
308
|
else
|
|
277
|
-
|
|
278
|
-
return ExecuteAction._handleExecute(payload, requestId, sessionId, nil)
|
|
309
|
+
finish("error", packed[2])
|
|
279
310
|
end
|
|
280
311
|
end)
|
|
312
|
+
|
|
313
|
+
if not outcome then
|
|
314
|
+
local timeoutThread = if timeoutSec
|
|
315
|
+
then task.delay(timeoutSec, function()
|
|
316
|
+
if not outcome then
|
|
317
|
+
pcall(task.cancel, scriptThread)
|
|
318
|
+
finish("timeout", nil)
|
|
319
|
+
end
|
|
320
|
+
end)
|
|
321
|
+
else nil
|
|
322
|
+
|
|
323
|
+
isWaiting = true
|
|
324
|
+
coroutine.yield()
|
|
325
|
+
if timeoutThread then
|
|
326
|
+
pcall(task.cancel, timeoutThread)
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
local final = outcome :: { status: string, result: any }
|
|
331
|
+
return final.status, final.result
|
|
281
332
|
end
|
|
282
333
|
|
|
283
|
-
--
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
334
|
+
--[[
|
|
335
|
+
Marshals what a script returned, in order, skipping the pcall status. A nil
|
|
336
|
+
becomes an explicit marker: a JSON array cannot hold a hole, and dropping it
|
|
337
|
+
would shift every later value into the wrong position.
|
|
338
|
+
]]
|
|
339
|
+
function ExecuteAction._serializeReturnValues(packed: { n: number, [number]: any }): { any }
|
|
340
|
+
local returnValues = {}
|
|
341
|
+
for index = 2, packed.n do
|
|
342
|
+
local serialized = ExecuteAction._serializeValue(packed[index], 1, {})
|
|
343
|
+
if serialized == nil then
|
|
344
|
+
serialized = { type = "Nil" }
|
|
345
|
+
end
|
|
346
|
+
returnValues[index - 1] = serialized
|
|
347
|
+
end
|
|
348
|
+
return returnValues
|
|
290
349
|
end
|
|
291
350
|
|
|
292
|
-
--
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
351
|
+
--[[
|
|
352
|
+
Produces the SerializedReturnValue shapes declared in web-socket-protocol.ts.
|
|
353
|
+
Duplicates the marshaller in query-data-model.lua, since actions cannot
|
|
354
|
+
require each other.
|
|
355
|
+
]]
|
|
356
|
+
function ExecuteAction._serializeValue(value: any, depth: number, seen: { [any]: boolean }): any
|
|
357
|
+
local valueType = typeof(value)
|
|
358
|
+
|
|
359
|
+
if valueType == "nil" or valueType == "string" or valueType == "boolean" then
|
|
360
|
+
return value
|
|
361
|
+
elseif valueType == "number" then
|
|
362
|
+
-- inf and nan have no JSON spelling, and encoding one produces a
|
|
363
|
+
-- document the server cannot decode, losing the entire message
|
|
364
|
+
if value ~= value or value == math.huge or value == -math.huge then
|
|
365
|
+
return ExecuteAction._unsupported("number", tostring(value))
|
|
366
|
+
end
|
|
367
|
+
return value
|
|
368
|
+
elseif valueType == "table" then
|
|
369
|
+
if depth > MAX_DEPTH then
|
|
370
|
+
return ExecuteAction._unsupported("table", "<max depth exceeded>")
|
|
371
|
+
end
|
|
372
|
+
if seen[value] then
|
|
373
|
+
return ExecuteAction._unsupported("table", "<cycle>")
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
seen[value] = true
|
|
377
|
+
local serialized = ExecuteAction._serializeTable(value, depth, seen)
|
|
378
|
+
seen[value] = nil
|
|
379
|
+
return serialized
|
|
380
|
+
elseif valueType == "Vector3" then
|
|
381
|
+
return { type = "Vector3", value = { value.X, value.Y, value.Z } }
|
|
382
|
+
elseif valueType == "Vector2" then
|
|
383
|
+
return { type = "Vector2", value = { value.X, value.Y } }
|
|
384
|
+
elseif valueType == "CFrame" then
|
|
385
|
+
return { type = "CFrame", value = { value:GetComponents() } }
|
|
386
|
+
elseif valueType == "Color3" then
|
|
387
|
+
return { type = "Color3", value = { value.R, value.G, value.B } }
|
|
388
|
+
elseif valueType == "UDim2" then
|
|
389
|
+
return { type = "UDim2", value = { value.X.Scale, value.X.Offset, value.Y.Scale, value.Y.Offset } }
|
|
390
|
+
elseif valueType == "UDim" then
|
|
391
|
+
return { type = "UDim", value = { value.Scale, value.Offset } }
|
|
392
|
+
elseif valueType == "BrickColor" then
|
|
393
|
+
return { type = "BrickColor", name = value.Name, value = value.Number }
|
|
394
|
+
elseif valueType == "EnumItem" then
|
|
395
|
+
return { type = "EnumItem", enum = tostring(value.EnumType), name = value.Name, value = value.Value }
|
|
396
|
+
elseif valueType == "Instance" then
|
|
397
|
+
return { type = "Instance", className = value.ClassName, path = value:GetFullName() }
|
|
398
|
+
else
|
|
399
|
+
return ExecuteAction._unsupported(valueType, tostring(value))
|
|
400
|
+
end
|
|
296
401
|
end
|
|
297
402
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
403
|
+
--[[
|
|
404
|
+
An array-like table becomes a JSON array, anything else a JSON object with
|
|
405
|
+
string keys. Mixed tables take the object branch on purpose: JSONEncode
|
|
406
|
+
rejects them, and a rejected encode drops the whole scriptComplete message.
|
|
407
|
+
]]
|
|
408
|
+
function ExecuteAction._serializeTable(value: { [any]: any }, depth: number, seen: { [any]: boolean }): any
|
|
409
|
+
local count = 0
|
|
410
|
+
for _ in value do
|
|
411
|
+
count += 1
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
if count == #value then
|
|
415
|
+
local array = {}
|
|
416
|
+
for index = 1, count do
|
|
417
|
+
array[index] = ExecuteAction._serializeValue(value[index], depth + 1, seen)
|
|
311
418
|
end
|
|
419
|
+
return array
|
|
312
420
|
end
|
|
313
|
-
|
|
314
|
-
|
|
421
|
+
|
|
422
|
+
local map: { [string]: any } = {}
|
|
423
|
+
for key, item in value do
|
|
424
|
+
map[if type(key) == "string" then key else tostring(key)] = ExecuteAction._serializeValue(item, depth + 1, seen)
|
|
425
|
+
end
|
|
426
|
+
return map
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
function ExecuteAction._unsupported(typeName: string, text: string): { [string]: any }
|
|
430
|
+
return { type = "Unsupported", typeName = typeName, toString = text }
|
|
315
431
|
end
|
|
316
432
|
|
|
317
433
|
return ExecuteAction
|