@quenty/studio-bridge 0.21.1 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -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/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/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
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--[=[
|
|
3
|
+
Runs a `playtest run` script inside the playtest's server and ends the
|
|
4
|
+
playtest with the result, so running a script does not depend on Studio
|
|
5
|
+
loading user plugins into playtests.
|
|
6
|
+
|
|
7
|
+
The `run-playtest-script` action plants this source as a Script in the edit
|
|
8
|
+
DataModel, with the code as a ModuleScript named `Code` under it, and starts a
|
|
9
|
+
playtest. The playtest copies the edit DataModel, so the runner starts in its
|
|
10
|
+
server. It only acts in the playtest it was planted for: anywhere else, such
|
|
11
|
+
as a place saved while it was planted, it does nothing.
|
|
12
|
+
|
|
13
|
+
The result crosses back through `StudioTestService:EndTest` in the same shape
|
|
14
|
+
as an `execute` reply. Instances cannot cross DataModels, so values are
|
|
15
|
+
marshalled here. Output capture, tracebacks and the marshaller are copies of
|
|
16
|
+
execute.lua's, since the runner cannot require it.
|
|
17
|
+
|
|
18
|
+
@class PlaytestRunner
|
|
19
|
+
]=]
|
|
20
|
+
|
|
21
|
+
local MAX_DEPTH = 64
|
|
22
|
+
local PLUGIN_PREFIX = "[StudioBridge]"
|
|
23
|
+
-- Tracebacks name this module's frames the way its first line does
|
|
24
|
+
local OWN_FRAME_PREFIX = string.match(debug.traceback(), "^([^\n]-):%d+")
|
|
25
|
+
|
|
26
|
+
local PlaytestRunner = {}
|
|
27
|
+
|
|
28
|
+
type LogEntry = {
|
|
29
|
+
level: string,
|
|
30
|
+
body: string,
|
|
31
|
+
timestamp: number,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
local LOG_LEVELS: { [Enum.MessageType]: string } = {
|
|
35
|
+
[Enum.MessageType.MessageOutput] = "Print",
|
|
36
|
+
[Enum.MessageType.MessageInfo] = "Info",
|
|
37
|
+
[Enum.MessageType.MessageWarning] = "Warning",
|
|
38
|
+
[Enum.MessageType.MessageError] = "Error",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
--[=[
|
|
42
|
+
Runs the `Code` module under `runner` and ends the playtest with the result,
|
|
43
|
+
when this playtest is the one `runner` was planted for.
|
|
44
|
+
]=]
|
|
45
|
+
function PlaytestRunner.runAsync(runner: Instance, studioTestService: any, players: Players)
|
|
46
|
+
local argsOk, testArgs = pcall(function()
|
|
47
|
+
return studioTestService:GetTestArgs()
|
|
48
|
+
end)
|
|
49
|
+
if not argsOk or type(testArgs) ~= "table" or testArgs.studioBridgeRunnerId ~= runner:GetAttribute("RunnerId") then
|
|
50
|
+
return
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
local hasEnded = false
|
|
54
|
+
local captured: { LogEntry } = {}
|
|
55
|
+
local function endTest(result: { [string]: any })
|
|
56
|
+
if hasEnded then
|
|
57
|
+
return
|
|
58
|
+
end
|
|
59
|
+
hasEnded = true
|
|
60
|
+
studioTestService:EndTest(result)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
local timeoutSec = testArgs.studioBridgeTimeoutSec
|
|
64
|
+
if type(timeoutSec) == "number" then
|
|
65
|
+
task.delay(timeoutSec, function()
|
|
66
|
+
endTest({
|
|
67
|
+
success = false,
|
|
68
|
+
error = `Script timed out after {timeoutSec}s`,
|
|
69
|
+
code = "SCRIPT_TIMEOUT",
|
|
70
|
+
output = captured,
|
|
71
|
+
})
|
|
72
|
+
end)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
-- The plugin path waits for the client to connect, so match it in play mode
|
|
76
|
+
if testArgs.studioBridgeWaitForPlayer and #players:GetPlayers() == 0 then
|
|
77
|
+
players.PlayerAdded:Wait()
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
local scriptArgs = if type(testArgs.studioBridgeScriptArgs) == "table" then testArgs.studioBridgeScriptArgs else {}
|
|
81
|
+
endTest(PlaytestRunner.run(runner:FindFirstChild("Code"), captured, scriptArgs))
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
--[=[
|
|
85
|
+
Runs a code module with `args`, collecting everything logged while it runs
|
|
86
|
+
into `captured`, and returns the result in the shape of an `execute` reply.
|
|
87
|
+
]=]
|
|
88
|
+
function PlaytestRunner.run(codeModule: Instance?, captured: { LogEntry }, args: { any }?): { [string]: any }
|
|
89
|
+
if not (codeModule and codeModule:IsA("ModuleScript")) then
|
|
90
|
+
return { success = false, error = "Runner has no Code module", code = "SCRIPT_LOAD_ERROR", output = captured }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
local requireOk, fn = pcall(require, codeModule)
|
|
94
|
+
if not requireOk or type(fn) ~= "function" then
|
|
95
|
+
return {
|
|
96
|
+
success = false,
|
|
97
|
+
error = if requireOk then "Code module did not return a function" else tostring(fn),
|
|
98
|
+
code = "SCRIPT_LOAD_ERROR",
|
|
99
|
+
output = captured,
|
|
100
|
+
}
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
local logConnection = PlaytestRunner._captureOutput(captured)
|
|
104
|
+
local returned = table.pack(xpcall(fn, function(err)
|
|
105
|
+
return {
|
|
106
|
+
message = tostring(err),
|
|
107
|
+
traceback = PlaytestRunner._dropOwnFrames(debug.traceback(nil, 2)),
|
|
108
|
+
}
|
|
109
|
+
end, table.unpack(args or {})))
|
|
110
|
+
|
|
111
|
+
-- MessageOut can fire a frame late, after the code's last print
|
|
112
|
+
task.wait()
|
|
113
|
+
logConnection:Disconnect()
|
|
114
|
+
|
|
115
|
+
if not returned[1] then
|
|
116
|
+
return {
|
|
117
|
+
success = false,
|
|
118
|
+
error = returned[2].message,
|
|
119
|
+
traceback = returned[2].traceback,
|
|
120
|
+
code = "SCRIPT_RUNTIME_ERROR",
|
|
121
|
+
output = captured,
|
|
122
|
+
}
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
success = true,
|
|
127
|
+
output = captured,
|
|
128
|
+
returnValues = PlaytestRunner._serializeReturnValues(returned),
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
--[[
|
|
133
|
+
Drops the frames of this module's own wrapper from a traceback, leaving only
|
|
134
|
+
the script's.
|
|
135
|
+
]]
|
|
136
|
+
function PlaytestRunner._dropOwnFrames(traceback: string): string
|
|
137
|
+
if not OWN_FRAME_PREFIX then
|
|
138
|
+
return traceback
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
local lines = {}
|
|
142
|
+
for _, line in string.split(traceback, "\n") do
|
|
143
|
+
if string.sub(line, 1, #OWN_FRAME_PREFIX + 1) ~= `{OWN_FRAME_PREFIX}:` then
|
|
144
|
+
table.insert(lines, line)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
return table.concat(lines, "\n")
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
--[[
|
|
151
|
+
Collects every message logged until the connection is disconnected, other
|
|
152
|
+
than the plugin's own.
|
|
153
|
+
]]
|
|
154
|
+
function PlaytestRunner._captureOutput(captured: { LogEntry }): RBXScriptConnection
|
|
155
|
+
return game:GetService("LogService").MessageOut:Connect(function(message: string, messageType: Enum.MessageType)
|
|
156
|
+
if string.sub(message, 1, #PLUGIN_PREFIX) == PLUGIN_PREFIX then
|
|
157
|
+
return
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
table.insert(captured, {
|
|
161
|
+
level = LOG_LEVELS[messageType] or "Print",
|
|
162
|
+
body = message,
|
|
163
|
+
timestamp = os.clock(),
|
|
164
|
+
})
|
|
165
|
+
end)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
--[[
|
|
169
|
+
Marshals what a script returned, in order, skipping the pcall status. A nil
|
|
170
|
+
becomes an explicit marker, since an array cannot hold a hole.
|
|
171
|
+
]]
|
|
172
|
+
function PlaytestRunner._serializeReturnValues(packed: { n: number, [number]: any }): { any }
|
|
173
|
+
local returnValues = {}
|
|
174
|
+
for index = 2, packed.n do
|
|
175
|
+
local serialized = PlaytestRunner._serializeValue(packed[index], 1, {})
|
|
176
|
+
if serialized == nil then
|
|
177
|
+
serialized = { type = "Nil" }
|
|
178
|
+
end
|
|
179
|
+
returnValues[index - 1] = serialized
|
|
180
|
+
end
|
|
181
|
+
return returnValues
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
--[[
|
|
185
|
+
Produces the SerializedReturnValue shapes declared in web-socket-protocol.ts.
|
|
186
|
+
Copied from execute.lua; keep the two in step.
|
|
187
|
+
]]
|
|
188
|
+
function PlaytestRunner._serializeValue(value: any, depth: number, seen: { [any]: boolean }): any
|
|
189
|
+
local valueType = typeof(value)
|
|
190
|
+
|
|
191
|
+
if valueType == "nil" or valueType == "string" or valueType == "boolean" then
|
|
192
|
+
return value
|
|
193
|
+
elseif valueType == "number" then
|
|
194
|
+
if value ~= value or value == math.huge or value == -math.huge then
|
|
195
|
+
return PlaytestRunner._unsupported("number", tostring(value))
|
|
196
|
+
end
|
|
197
|
+
return value
|
|
198
|
+
elseif valueType == "table" then
|
|
199
|
+
if depth > MAX_DEPTH then
|
|
200
|
+
return PlaytestRunner._unsupported("table", "<max depth exceeded>")
|
|
201
|
+
end
|
|
202
|
+
if seen[value] then
|
|
203
|
+
return PlaytestRunner._unsupported("table", "<cycle>")
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
seen[value] = true
|
|
207
|
+
local serialized = PlaytestRunner._serializeTable(value, depth, seen)
|
|
208
|
+
seen[value] = nil
|
|
209
|
+
return serialized
|
|
210
|
+
elseif valueType == "Vector3" then
|
|
211
|
+
return { type = "Vector3", value = { value.X, value.Y, value.Z } }
|
|
212
|
+
elseif valueType == "Vector2" then
|
|
213
|
+
return { type = "Vector2", value = { value.X, value.Y } }
|
|
214
|
+
elseif valueType == "CFrame" then
|
|
215
|
+
return { type = "CFrame", value = { value:GetComponents() } }
|
|
216
|
+
elseif valueType == "Color3" then
|
|
217
|
+
return { type = "Color3", value = { value.R, value.G, value.B } }
|
|
218
|
+
elseif valueType == "UDim2" then
|
|
219
|
+
return { type = "UDim2", value = { value.X.Scale, value.X.Offset, value.Y.Scale, value.Y.Offset } }
|
|
220
|
+
elseif valueType == "UDim" then
|
|
221
|
+
return { type = "UDim", value = { value.Scale, value.Offset } }
|
|
222
|
+
elseif valueType == "BrickColor" then
|
|
223
|
+
return { type = "BrickColor", name = value.Name, value = value.Number }
|
|
224
|
+
elseif valueType == "EnumItem" then
|
|
225
|
+
return { type = "EnumItem", enum = tostring(value.EnumType), name = value.Name, value = value.Value }
|
|
226
|
+
elseif valueType == "Instance" then
|
|
227
|
+
return { type = "Instance", className = value.ClassName, path = value:GetFullName() }
|
|
228
|
+
else
|
|
229
|
+
return PlaytestRunner._unsupported(valueType, tostring(value))
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
function PlaytestRunner._serializeTable(value: { [any]: any }, depth: number, seen: { [any]: boolean }): any
|
|
234
|
+
local count = 0
|
|
235
|
+
for _ in value do
|
|
236
|
+
count += 1
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
if count == #value then
|
|
240
|
+
local array = {}
|
|
241
|
+
for index = 1, count do
|
|
242
|
+
array[index] = PlaytestRunner._serializeValue(value[index], depth + 1, seen)
|
|
243
|
+
end
|
|
244
|
+
return array
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
local map: { [string]: any } = {}
|
|
248
|
+
for key, item in value do
|
|
249
|
+
map[if type(key) == "string" then key else tostring(key)] =
|
|
250
|
+
PlaytestRunner._serializeValue(item, depth + 1, seen)
|
|
251
|
+
end
|
|
252
|
+
return map
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
function PlaytestRunner._unsupported(typeName: string, text: string): { [string]: any }
|
|
256
|
+
return { type = "Unsupported", typeName = typeName, toString = text }
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
-- Planted as a Script it runs; in the test place it is a ModuleScript specs require
|
|
260
|
+
if script:IsA("Script") then
|
|
261
|
+
task.spawn(PlaytestRunner.runAsync, script, game:GetService("StudioTestService"), game:GetService("Players"))
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
return PlaytestRunner
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--[[
|
|
3
|
+
@class playtest-runner.spec.lua
|
|
4
|
+
]]
|
|
5
|
+
|
|
6
|
+
local require = require(script.Parent.loader).load(script)
|
|
7
|
+
|
|
8
|
+
local Jest = require("Jest")
|
|
9
|
+
local PlaytestRunner = require("playtest-runner")
|
|
10
|
+
|
|
11
|
+
local describe = Jest.Globals.describe
|
|
12
|
+
local expect = Jest.Globals.expect
|
|
13
|
+
local it = Jest.Globals.it
|
|
14
|
+
|
|
15
|
+
local function setup(testArgs: any)
|
|
16
|
+
local ended = {}
|
|
17
|
+
local runner = Instance.new("Folder")
|
|
18
|
+
runner:SetAttribute("RunnerId", "runner-1")
|
|
19
|
+
|
|
20
|
+
local studioTestService = {
|
|
21
|
+
GetTestArgs = function()
|
|
22
|
+
return testArgs
|
|
23
|
+
end,
|
|
24
|
+
EndTest = function(_self, value)
|
|
25
|
+
table.insert(ended, value)
|
|
26
|
+
end,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
runner = runner,
|
|
31
|
+
studioTestService = studioTestService,
|
|
32
|
+
ended = ended,
|
|
33
|
+
Destroy = function()
|
|
34
|
+
runner:Destroy()
|
|
35
|
+
end,
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe("PlaytestRunner.runAsync()", function()
|
|
40
|
+
it("should do nothing in a playtest it was not planted for", function()
|
|
41
|
+
local controller = setup({ studioBridgeRunnerId = "someone-else" })
|
|
42
|
+
|
|
43
|
+
PlaytestRunner.runAsync(controller.runner, controller.studioTestService, game:GetService("Players"))
|
|
44
|
+
|
|
45
|
+
expect(controller.ended).toEqual({})
|
|
46
|
+
controller:Destroy()
|
|
47
|
+
end)
|
|
48
|
+
|
|
49
|
+
it("should end the playtest with a load error when the code module is missing", function()
|
|
50
|
+
local controller = setup({ studioBridgeRunnerId = "runner-1" })
|
|
51
|
+
|
|
52
|
+
PlaytestRunner.runAsync(controller.runner, controller.studioTestService, game:GetService("Players"))
|
|
53
|
+
|
|
54
|
+
expect(#controller.ended).toEqual(1)
|
|
55
|
+
expect(controller.ended[1].success).toEqual(false)
|
|
56
|
+
expect(controller.ended[1].code).toEqual("SCRIPT_LOAD_ERROR")
|
|
57
|
+
controller:Destroy()
|
|
58
|
+
end)
|
|
59
|
+
end)
|
|
60
|
+
|
|
61
|
+
describe("PlaytestRunner._serializeReturnValues()", function()
|
|
62
|
+
it("should keep a nil in its position", function()
|
|
63
|
+
local packed = table.pack(true, 1, nil, Vector3.new(1, 2, 3))
|
|
64
|
+
|
|
65
|
+
expect(PlaytestRunner._serializeReturnValues(packed)).toEqual({
|
|
66
|
+
1,
|
|
67
|
+
{ type = "Nil" },
|
|
68
|
+
{ type = "Vector3", value = { 1, 2, 3 } },
|
|
69
|
+
})
|
|
70
|
+
end)
|
|
71
|
+
end)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--[=[
|
|
3
|
+
Action that runs a script in a fresh playtest's server and answers with
|
|
4
|
+
`scriptComplete`, the same reply as `execute`.
|
|
5
|
+
|
|
6
|
+
It does not need the playtest's own plugin sessions, so it works whether or
|
|
7
|
+
not Studio loads user plugins into playtests.
|
|
8
|
+
|
|
9
|
+
- Compiles the code first, so a syntax error fails here without starting a
|
|
10
|
+
playtest.
|
|
11
|
+
- Plants the runner source the bridge sends as a Script in
|
|
12
|
+
ServerScriptService, with the code as a ModuleScript named `Code` under it.
|
|
13
|
+
The playtest copies the edit DataModel, so the runner starts in its server,
|
|
14
|
+
runs the code and ends the playtest with the result.
|
|
15
|
+
- Removes the runner from the edit DataModel once the playtest ends.
|
|
16
|
+
|
|
17
|
+
Request: `{ type: "runPlaytestScript", payload: { mode: "play" | "run", script, runnerSource, timeoutSec, args? } }`
|
|
18
|
+
Response: `{ type: "scriptComplete", payload: { success, output, returnValues?, error?, code? } }`
|
|
19
|
+
|
|
20
|
+
@class RunPlaytestScriptAction
|
|
21
|
+
]=]
|
|
22
|
+
|
|
23
|
+
local RunPlaytestScriptAction = {}
|
|
24
|
+
|
|
25
|
+
type SendMessage = (message: { [string]: any }) -> ()
|
|
26
|
+
|
|
27
|
+
--[=[
|
|
28
|
+
Registers the `runPlaytestScript` handler. The reply waits for the playtest to
|
|
29
|
+
end, so it needs `sendMessage`.
|
|
30
|
+
]=]
|
|
31
|
+
function RunPlaytestScriptAction.register(router: any, sendMessage: SendMessage?)
|
|
32
|
+
router:setResponseType("runPlaytestScript", "scriptComplete")
|
|
33
|
+
router:register(
|
|
34
|
+
"runPlaytestScript",
|
|
35
|
+
function(payload: { [string]: any }, requestId: string, sessionId: string): { [string]: any }?
|
|
36
|
+
local mode = payload.mode
|
|
37
|
+
if mode ~= "play" and mode ~= "run" then
|
|
38
|
+
error(`Unknown playtest mode: {tostring(mode)}`)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
local code = payload.script
|
|
42
|
+
local runnerSource = payload.runnerSource
|
|
43
|
+
local timeoutSec = payload.timeoutSec
|
|
44
|
+
if type(code) ~= "string" or type(runnerSource) ~= "string" or type(timeoutSec) ~= "number" then
|
|
45
|
+
error("Missing script, runnerSource or timeoutSec in runPlaytestScript request")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
local compileErr = RunPlaytestScriptAction._getCompileError(router, code)
|
|
49
|
+
if compileErr then
|
|
50
|
+
return { success = false, error = compileErr, code = "SCRIPT_LOAD_ERROR", output = {} }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if not sendMessage then
|
|
54
|
+
error("Running a playtest script requires a sendMessage callback")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
task.spawn(function()
|
|
58
|
+
local result = RunPlaytestScriptAction._runAsync(mode, code, runnerSource, timeoutSec, payload.args)
|
|
59
|
+
sendMessage({
|
|
60
|
+
type = "scriptComplete",
|
|
61
|
+
sessionId = sessionId,
|
|
62
|
+
requestId = if requestId ~= "" then requestId else nil,
|
|
63
|
+
payload = result,
|
|
64
|
+
})
|
|
65
|
+
end)
|
|
66
|
+
|
|
67
|
+
-- Replied through sendMessage, so the router must not reply as well
|
|
68
|
+
return nil
|
|
69
|
+
end
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
--[[
|
|
74
|
+
Returns why the code does not compile, or nil when it does. Routers from
|
|
75
|
+
older plugins have no Compile, and the edit DataModel always has loadstring.
|
|
76
|
+
]]
|
|
77
|
+
function RunPlaytestScriptAction._getCompileError(router: any, code: string): string?
|
|
78
|
+
local fn, compileErr
|
|
79
|
+
if type(router.Compile) == "function" then
|
|
80
|
+
fn, compileErr = router:Compile(code)
|
|
81
|
+
else
|
|
82
|
+
fn, compileErr = (loadstring :: any)(code)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
if fn then
|
|
86
|
+
return nil
|
|
87
|
+
end
|
|
88
|
+
return if compileErr then tostring(compileErr) else "Failed to compile script"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
function RunPlaytestScriptAction._runAsync(
|
|
92
|
+
mode: string,
|
|
93
|
+
code: string,
|
|
94
|
+
runnerSource: string,
|
|
95
|
+
timeoutSec: number,
|
|
96
|
+
args: { string }?
|
|
97
|
+
): { [string]: any }
|
|
98
|
+
local runnerId = game:GetService("HttpService"):GenerateGUID(false)
|
|
99
|
+
|
|
100
|
+
local runner = Instance.new("Script")
|
|
101
|
+
runner.Name = "StudioBridgePlaytestRunner"
|
|
102
|
+
runner.Source = runnerSource
|
|
103
|
+
runner:SetAttribute("RunnerId", runnerId)
|
|
104
|
+
|
|
105
|
+
local codeModule = Instance.new("ModuleScript")
|
|
106
|
+
codeModule.Name = "Code"
|
|
107
|
+
-- Wrapping on the first line keeps a top-level `return` legal and line numbers unchanged
|
|
108
|
+
codeModule.Source = `return function(...) {code}\nend`
|
|
109
|
+
codeModule.Parent = runner
|
|
110
|
+
|
|
111
|
+
runner.Parent = game:GetService("ServerScriptService")
|
|
112
|
+
|
|
113
|
+
local ok, result = pcall(function()
|
|
114
|
+
local studioTestService = game:GetService("StudioTestService") :: any
|
|
115
|
+
local testArgs = {
|
|
116
|
+
studioBridgeRunnerId = runnerId,
|
|
117
|
+
studioBridgeTimeoutSec = timeoutSec,
|
|
118
|
+
studioBridgeScriptArgs = args,
|
|
119
|
+
studioBridgeWaitForPlayer = mode == "play",
|
|
120
|
+
}
|
|
121
|
+
if mode == "play" then
|
|
122
|
+
return studioTestService:ExecutePlayModeAsync(testArgs)
|
|
123
|
+
else
|
|
124
|
+
return studioTestService:ExecuteRunModeAsync(testArgs)
|
|
125
|
+
end
|
|
126
|
+
end)
|
|
127
|
+
|
|
128
|
+
runner:Destroy()
|
|
129
|
+
|
|
130
|
+
if not ok then
|
|
131
|
+
return { success = false, error = `Playtest failed to start: {result}`, output = {} }
|
|
132
|
+
end
|
|
133
|
+
if type(result) ~= "table" then
|
|
134
|
+
return { success = false, error = "Playtest was stopped before the script finished", output = {} }
|
|
135
|
+
end
|
|
136
|
+
return result
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
return RunPlaytestScriptAction
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--[[
|
|
3
|
+
@class run-playtest-script.spec.lua
|
|
4
|
+
]]
|
|
5
|
+
|
|
6
|
+
local require = require(script.Parent.loader).load(script)
|
|
7
|
+
|
|
8
|
+
local ActionRouter = require("ActionRouter")
|
|
9
|
+
local Jest = require("Jest")
|
|
10
|
+
local RunPlaytestScriptAction = require("run-playtest-script")
|
|
11
|
+
|
|
12
|
+
local describe = Jest.Globals.describe
|
|
13
|
+
local expect = Jest.Globals.expect
|
|
14
|
+
local it = Jest.Globals.it
|
|
15
|
+
|
|
16
|
+
local function dispatch(payload: { [string]: any }): any
|
|
17
|
+
local router = ActionRouter.new()
|
|
18
|
+
RunPlaytestScriptAction.register(router, function() end)
|
|
19
|
+
|
|
20
|
+
return router:Dispatch({
|
|
21
|
+
type = "runPlaytestScript",
|
|
22
|
+
sessionId = "session-1",
|
|
23
|
+
requestId = "req-1",
|
|
24
|
+
payload = payload,
|
|
25
|
+
})
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe("runPlaytestScript", function()
|
|
29
|
+
it("should fail a script that does not compile without starting a playtest", function()
|
|
30
|
+
local response = dispatch({ mode = "run", script = "local x = = 1", runnerSource = "", timeoutSec = 10 })
|
|
31
|
+
|
|
32
|
+
expect(response.type).toEqual("scriptComplete")
|
|
33
|
+
expect(response.payload.success).toEqual(false)
|
|
34
|
+
expect(response.payload.code).toEqual("SCRIPT_LOAD_ERROR")
|
|
35
|
+
end)
|
|
36
|
+
|
|
37
|
+
it("should reject an unknown mode", function()
|
|
38
|
+
local response = dispatch({ mode = "nope", script = "return 1", runnerSource = "", timeoutSec = 10 })
|
|
39
|
+
|
|
40
|
+
expect(response.type).toEqual("error")
|
|
41
|
+
expect(response.payload.message).toEqual(expect.stringContaining("Unknown playtest mode"))
|
|
42
|
+
end)
|
|
43
|
+
end)
|