@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
|
@@ -1,205 +1,163 @@
|
|
|
1
1
|
--!optimize 2
|
|
2
|
-
--[[
|
|
3
|
-
|
|
2
|
+
--[=[
|
|
3
|
+
Action that captures the Studio viewport and answers with it as base64.
|
|
4
4
|
|
|
5
|
-
Captures
|
|
6
|
-
|
|
7
|
-
base64-encodes the
|
|
5
|
+
Captures with CaptureService, reads the RGBA pixels through an EditableImage,
|
|
6
|
+
encodes them as PNG when the plugin supplied an encoder (raw RGBA otherwise),
|
|
7
|
+
and base64-encodes the result with EncodingService.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
Request: `{ type: "captureScreenshot", payload: { format?: "png" } }`
|
|
10
|
+
Response: `{ type: "screenshotResult", payload: { data, format, width, height } }`
|
|
11
|
+
|
|
12
|
+
@class CaptureScreenshotAction
|
|
13
|
+
]=]
|
|
13
14
|
|
|
14
|
-
--
|
|
15
|
-
|
|
16
|
-
local _png = nil
|
|
17
|
-
local _disposed = false
|
|
15
|
+
-- ReadPixelsBuffer reads at most 1024x1024
|
|
16
|
+
local MAX_READ_SIZE = 1024
|
|
18
17
|
|
|
19
18
|
local CaptureScreenshotAction = {}
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
-- Helpers
|
|
23
|
-
-- ---------------------------------------------------------------------------
|
|
20
|
+
type SendMessage = (message: { [string]: any }) -> ()
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
22
|
+
export type Services = {
|
|
23
|
+
captureService: any,
|
|
24
|
+
assetService: any,
|
|
25
|
+
encodingService: any,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
-- The plugin hands its PNG encoder over through router._vendorPng
|
|
29
|
+
local png: any = nil
|
|
30
|
+
local isTornDown = false
|
|
31
|
+
|
|
32
|
+
--[=[
|
|
33
|
+
Registers the `captureScreenshot` handler. Capturing replies asynchronously,
|
|
34
|
+
so it needs `sendMessage`.
|
|
35
|
+
]=]
|
|
36
|
+
function CaptureScreenshotAction.register(router: any, sendMessage: SendMessage?)
|
|
37
|
+
isTornDown = false
|
|
38
|
+
png = router._vendorPng
|
|
39
|
+
|
|
40
|
+
router:setResponseType("captureScreenshot", "screenshotResult")
|
|
41
|
+
router:register(
|
|
42
|
+
"captureScreenshot",
|
|
43
|
+
function(_payload: { [string]: any }, requestId: string, sessionId: string): { [string]: any }?
|
|
44
|
+
if not sendMessage then
|
|
45
|
+
return {
|
|
46
|
+
code = "CAPABILITY_NOT_SUPPORTED",
|
|
47
|
+
message = "Screenshot capture requires a sendMessage callback",
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
-- Lune has no task library, so fall back to running inline there
|
|
52
|
+
local spawnOk = pcall(function()
|
|
53
|
+
task.spawn(CaptureScreenshotAction._captureAsync, sendMessage, requestId, sessionId)
|
|
54
|
+
end)
|
|
55
|
+
if not spawnOk then
|
|
56
|
+
CaptureScreenshotAction._captureAsync(sendMessage, requestId, sessionId)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
-- Replied through sendMessage, so the router must not reply as well
|
|
60
|
+
return nil
|
|
61
|
+
end
|
|
62
|
+
)
|
|
35
63
|
end
|
|
36
64
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
if requestId ~= nil and requestId ~= "" then
|
|
44
|
-
msg.requestId = requestId
|
|
45
|
-
end
|
|
46
|
-
return msg
|
|
65
|
+
--[=[
|
|
66
|
+
Stops an in-flight capture from replying.
|
|
67
|
+
]=]
|
|
68
|
+
function CaptureScreenshotAction.teardown()
|
|
69
|
+
isTornDown = true
|
|
47
70
|
end
|
|
48
71
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
72
|
+
function CaptureScreenshotAction._captureAsync(
|
|
73
|
+
sendMessage: SendMessage,
|
|
74
|
+
requestId: string?,
|
|
75
|
+
sessionId: string,
|
|
76
|
+
services: Services?
|
|
77
|
+
)
|
|
78
|
+
local function fail(code: string, message: string)
|
|
79
|
+
sendMessage(CaptureScreenshotAction._buildMessage("error", sessionId, requestId, {
|
|
80
|
+
code = code,
|
|
81
|
+
message = message,
|
|
82
|
+
}))
|
|
83
|
+
end
|
|
52
84
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
85
|
+
-- Resolved here rather than at load, so the module still loads under Lune
|
|
86
|
+
local servicesOk, servicesOrErr = pcall(function()
|
|
87
|
+
return services
|
|
88
|
+
or {
|
|
89
|
+
captureService = game:GetService("CaptureService"),
|
|
90
|
+
assetService = game:GetService("AssetService"),
|
|
91
|
+
encodingService = game:GetService("EncodingService"),
|
|
92
|
+
}
|
|
57
93
|
end)
|
|
58
|
-
if not
|
|
59
|
-
|
|
60
|
-
buildError(sessionId, requestId, "CAPTURE_FAILED", `Required services not available: {captureServiceOrErr}`)
|
|
61
|
-
)
|
|
94
|
+
if not servicesOk then
|
|
95
|
+
fail("CAPTURE_FAILED", `Required services not available: {servicesOrErr}`)
|
|
62
96
|
return
|
|
63
97
|
end
|
|
64
|
-
local
|
|
65
|
-
local
|
|
66
|
-
local EncodingService = encodingServiceOrErr
|
|
67
|
-
|
|
68
|
-
-- Step 1: Capture the viewport via CaptureService
|
|
69
|
-
local callerThread = coroutine.running()
|
|
70
|
-
local contentId: string? = nil
|
|
71
|
-
local captureOk, captureErr = pcall(function()
|
|
72
|
-
CaptureService:CaptureScreenshot(function(id)
|
|
73
|
-
contentId = id
|
|
74
|
-
task.spawn(callerThread)
|
|
75
|
-
end)
|
|
76
|
-
end)
|
|
98
|
+
local assetService = servicesOrErr.assetService
|
|
99
|
+
local encodingService = servicesOrErr.encodingService
|
|
77
100
|
|
|
101
|
+
local captureOk, contentIdOrErr = CaptureScreenshotAction._captureContentIdAsync(servicesOrErr.captureService)
|
|
102
|
+
if isTornDown then
|
|
103
|
+
return
|
|
104
|
+
end
|
|
78
105
|
if not captureOk then
|
|
79
|
-
|
|
106
|
+
fail("CAPTURE_FAILED", `CaptureService failed: {contentIdOrErr}`)
|
|
80
107
|
return
|
|
81
108
|
end
|
|
82
109
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if _disposed then return end
|
|
87
|
-
|
|
88
|
-
if not contentId or contentId == "" then
|
|
89
|
-
sendMessage(buildError(sessionId, requestId, "CAPTURE_FAILED", "CaptureService returned no content ID"))
|
|
110
|
+
local contentId = contentIdOrErr
|
|
111
|
+
if contentId == nil or contentId == "" then
|
|
112
|
+
fail("CAPTURE_FAILED", "CaptureService returned no content ID")
|
|
90
113
|
return
|
|
91
114
|
end
|
|
92
115
|
|
|
93
|
-
-- Step 2: Load into an EditableImage to read pixels
|
|
94
116
|
local editableOk, editableImage = pcall(function()
|
|
95
|
-
return
|
|
117
|
+
return assetService:CreateEditableImageAsync(Content.fromUri(contentId))
|
|
96
118
|
end)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
sendMessage(
|
|
100
|
-
buildError(
|
|
101
|
-
sessionId,
|
|
102
|
-
requestId,
|
|
103
|
-
"EDITABLE_IMAGE_FAILED",
|
|
104
|
-
`Failed to create EditableImage from capture: {editableImage or "unknown error"}`
|
|
105
|
-
)
|
|
106
|
-
)
|
|
119
|
+
if not (editableOk and editableImage) then
|
|
120
|
+
fail("EDITABLE_IMAGE_FAILED", `Failed to create EditableImage from capture: {editableImage or "unknown error"}`)
|
|
107
121
|
return
|
|
108
122
|
end
|
|
109
123
|
|
|
110
|
-
|
|
111
|
-
-- ReadPixelsBuffer has a 1024x1024 limit. If the screenshot is larger,
|
|
112
|
-
-- scale it down into a new EditableImage that fits within the limit.
|
|
113
|
-
local MAX_SIZE = 1024
|
|
114
|
-
local srcWidth = editableImage.Size.X
|
|
115
|
-
local srcHeight = editableImage.Size.Y
|
|
116
|
-
local width = srcWidth
|
|
117
|
-
local height = srcHeight
|
|
118
|
-
|
|
119
|
-
local readTarget = editableImage
|
|
120
|
-
local scaledImage = nil
|
|
121
|
-
|
|
122
|
-
if srcWidth > MAX_SIZE or srcHeight > MAX_SIZE then
|
|
123
|
-
local scale = math.min(MAX_SIZE / srcWidth, MAX_SIZE / srcHeight)
|
|
124
|
-
width = math.floor(srcWidth * scale)
|
|
125
|
-
height = math.floor(srcHeight * scale)
|
|
126
|
-
|
|
127
|
-
local scaleOk, scaleResult = pcall(function()
|
|
128
|
-
local scaled = AssetService:CreateEditableImage({ Size = Vector2.new(width, height) })
|
|
129
|
-
scaled:DrawImageTransformed(
|
|
130
|
-
Vector2.new(width / 2, height / 2), -- center position
|
|
131
|
-
Vector2.new(scale, scale), -- scale
|
|
132
|
-
0, -- rotation
|
|
133
|
-
editableImage
|
|
134
|
-
)
|
|
135
|
-
return scaled
|
|
136
|
-
end)
|
|
137
|
-
|
|
138
|
-
if scaleOk and scaleResult then
|
|
139
|
-
scaledImage = scaleResult
|
|
140
|
-
readTarget = scaleResult
|
|
141
|
-
else
|
|
142
|
-
-- If scaling fails, just read the top-left 1024x1024 corner
|
|
143
|
-
width = math.min(srcWidth, MAX_SIZE)
|
|
144
|
-
height = math.min(srcHeight, MAX_SIZE)
|
|
145
|
-
end
|
|
146
|
-
end
|
|
124
|
+
local readTarget, scaledImage, width, height = CaptureScreenshotAction._fitToReadLimit(assetService, editableImage)
|
|
147
125
|
|
|
148
|
-
local pixelsOk,
|
|
126
|
+
local pixelsOk, pixels = pcall(function()
|
|
149
127
|
return readTarget:ReadPixelsBuffer(Vector2.zero, Vector2.new(width, height))
|
|
150
128
|
end)
|
|
151
129
|
|
|
152
|
-
--
|
|
153
|
-
pcall(
|
|
154
|
-
editableImage:Destroy()
|
|
155
|
-
end)
|
|
130
|
+
-- Free the images right away, they hold the whole capture in memory
|
|
131
|
+
pcall(editableImage.Destroy, editableImage)
|
|
156
132
|
if scaledImage then
|
|
157
|
-
pcall(
|
|
158
|
-
scaledImage:Destroy()
|
|
159
|
-
end)
|
|
133
|
+
pcall(scaledImage.Destroy, scaledImage)
|
|
160
134
|
end
|
|
161
135
|
|
|
162
|
-
if not pixelsOk
|
|
163
|
-
|
|
164
|
-
buildError(
|
|
165
|
-
sessionId,
|
|
166
|
-
requestId,
|
|
167
|
-
"PIXEL_READ_FAILED",
|
|
168
|
-
`Failed to read pixels: {pixelsBuf or "unknown error"}`
|
|
169
|
-
)
|
|
170
|
-
)
|
|
136
|
+
if not (pixelsOk and pixels) then
|
|
137
|
+
fail("PIXEL_READ_FAILED", `Failed to read pixels: {pixels or "unknown error"}`)
|
|
171
138
|
return
|
|
172
139
|
end
|
|
173
140
|
|
|
174
|
-
|
|
175
|
-
local dataBuf = pixelsBuf
|
|
141
|
+
local data = pixels
|
|
176
142
|
local format = "rgba"
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
dataBuf = pngBuf
|
|
143
|
+
if png then
|
|
144
|
+
local pngOk, pngData = pcall(png.encode, pixels, { width = width, height = height })
|
|
145
|
+
if pngOk and pngData then
|
|
146
|
+
data = pngData
|
|
182
147
|
format = "png"
|
|
183
148
|
end
|
|
184
149
|
end
|
|
185
150
|
|
|
186
151
|
local encodeOk, encoded = pcall(function()
|
|
187
|
-
|
|
152
|
+
-- JSONEncode turns a buffer into a { t = "buffer", zbase64 } object, so send a string
|
|
153
|
+
return buffer.tostring(encodingService:Base64Encode(data))
|
|
188
154
|
end)
|
|
189
|
-
if not encodeOk
|
|
190
|
-
|
|
191
|
-
buildError(
|
|
192
|
-
sessionId,
|
|
193
|
-
requestId,
|
|
194
|
-
"ENCODE_FAILED",
|
|
195
|
-
`Failed to base64 encode data: {encoded or "unknown error"}`
|
|
196
|
-
)
|
|
197
|
-
)
|
|
155
|
+
if not (encodeOk and encoded) then
|
|
156
|
+
fail("ENCODE_FAILED", `Failed to base64 encode data: {encoded or "unknown error"}`)
|
|
198
157
|
return
|
|
199
158
|
end
|
|
200
159
|
|
|
201
|
-
|
|
202
|
-
sendMessage(buildResponse(sessionId, requestId, {
|
|
160
|
+
sendMessage(CaptureScreenshotAction._buildMessage("screenshotResult", sessionId, requestId, {
|
|
203
161
|
data = encoded,
|
|
204
162
|
format = format,
|
|
205
163
|
width = width,
|
|
@@ -207,41 +165,76 @@ local function captureAsync(sendMessage: (msg: { [string]: any }) -> (), request
|
|
|
207
165
|
}))
|
|
208
166
|
end
|
|
209
167
|
|
|
210
|
-
--
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
function CaptureScreenshotAction.
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
router:register("captureScreenshot", function(_payload: { [string]: any }, requestId: string, sessionId: string): { [string]: any }?
|
|
221
|
-
if not sendMessage then
|
|
222
|
-
return {
|
|
223
|
-
code = "CAPABILITY_NOT_SUPPORTED",
|
|
224
|
-
message = "Screenshot capture requires a sendMessage callback",
|
|
225
|
-
}
|
|
226
|
-
end
|
|
168
|
+
--[[
|
|
169
|
+
Returns true and the capture's content id, or false and the error
|
|
170
|
+
CaptureService threw. Yields until the capture callback fires.
|
|
171
|
+
]]
|
|
172
|
+
function CaptureScreenshotAction._captureContentIdAsync(captureService: any): (boolean, any)
|
|
173
|
+
local callerThread = coroutine.running()
|
|
174
|
+
local isWaiting = false
|
|
175
|
+
local isReady = false
|
|
176
|
+
local contentId: string? = nil
|
|
227
177
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
178
|
+
local captureOk, captureErr = pcall(function()
|
|
179
|
+
captureService:CaptureScreenshot(function(id)
|
|
180
|
+
contentId = id
|
|
181
|
+
isReady = true
|
|
182
|
+
if isWaiting then
|
|
183
|
+
task.spawn(callerThread)
|
|
184
|
+
end
|
|
232
185
|
end)
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
186
|
+
end)
|
|
187
|
+
if not captureOk then
|
|
188
|
+
return false, captureErr
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
if not isReady then
|
|
192
|
+
isWaiting = true
|
|
193
|
+
coroutine.yield()
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
return true, contentId
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
--[[
|
|
200
|
+
Returns an image no larger than the read limit, scaled down from the capture
|
|
201
|
+
when needed. If scaling fails, falls back to the capture's top-left corner.
|
|
202
|
+
]]
|
|
203
|
+
function CaptureScreenshotAction._fitToReadLimit(assetService: any, editableImage: any): (any, any?, number, number)
|
|
204
|
+
local sourceWidth = editableImage.Size.X
|
|
205
|
+
local sourceHeight = editableImage.Size.Y
|
|
206
|
+
if sourceWidth <= MAX_READ_SIZE and sourceHeight <= MAX_READ_SIZE then
|
|
207
|
+
return editableImage, nil, sourceWidth, sourceHeight
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
local scale = math.min(MAX_READ_SIZE / sourceWidth, MAX_READ_SIZE / sourceHeight)
|
|
211
|
+
local width = math.floor(sourceWidth * scale)
|
|
212
|
+
local height = math.floor(sourceHeight * scale)
|
|
237
213
|
|
|
238
|
-
|
|
239
|
-
|
|
214
|
+
local scaleOk, scaledImage = pcall(function()
|
|
215
|
+
local scaled = assetService:CreateEditableImage({ Size = Vector2.new(width, height) })
|
|
216
|
+
scaled:DrawImageTransformed(Vector2.new(width / 2, height / 2), Vector2.new(scale, scale), 0, editableImage)
|
|
217
|
+
return scaled
|
|
240
218
|
end)
|
|
219
|
+
if scaleOk and scaledImage then
|
|
220
|
+
return scaledImage, scaledImage, width, height
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
return editableImage, nil, math.min(sourceWidth, MAX_READ_SIZE), math.min(sourceHeight, MAX_READ_SIZE)
|
|
241
224
|
end
|
|
242
225
|
|
|
243
|
-
function CaptureScreenshotAction.
|
|
244
|
-
|
|
226
|
+
function CaptureScreenshotAction._buildMessage(
|
|
227
|
+
messageType: string,
|
|
228
|
+
sessionId: string,
|
|
229
|
+
requestId: string?,
|
|
230
|
+
payload: { [string]: any }
|
|
231
|
+
): { [string]: any }
|
|
232
|
+
return {
|
|
233
|
+
type = messageType,
|
|
234
|
+
sessionId = sessionId,
|
|
235
|
+
requestId = if requestId ~= "" then requestId else nil,
|
|
236
|
+
payload = payload,
|
|
237
|
+
}
|
|
245
238
|
end
|
|
246
239
|
|
|
247
240
|
return CaptureScreenshotAction
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--[[
|
|
3
|
+
@class capture-screenshot.spec.lua
|
|
4
|
+
]]
|
|
5
|
+
|
|
6
|
+
local require = require(script.Parent.loader).load(script)
|
|
7
|
+
|
|
8
|
+
local EncodingService = game:GetService("EncodingService")
|
|
9
|
+
local HttpService = game:GetService("HttpService")
|
|
10
|
+
|
|
11
|
+
local ActionRouter = require("ActionRouter")
|
|
12
|
+
local CaptureScreenshotAction = require("capture-screenshot")
|
|
13
|
+
local Jest = require("Jest")
|
|
14
|
+
|
|
15
|
+
local describe = Jest.Globals.describe
|
|
16
|
+
local expect = Jest.Globals.expect
|
|
17
|
+
local it = Jest.Globals.it
|
|
18
|
+
|
|
19
|
+
local function setup()
|
|
20
|
+
CaptureScreenshotAction.register(ActionRouter.new(), function() end)
|
|
21
|
+
|
|
22
|
+
local pixels = buffer.fromstring("\255\0\0\255\0\0\255\255")
|
|
23
|
+
local captureError: string? = nil
|
|
24
|
+
local callsBackImmediately = false
|
|
25
|
+
|
|
26
|
+
local services: CaptureScreenshotAction.Services = {
|
|
27
|
+
captureService = {
|
|
28
|
+
CaptureScreenshot = function(_self, onCaptureReady: (string) -> ())
|
|
29
|
+
if captureError then
|
|
30
|
+
error(captureError)
|
|
31
|
+
end
|
|
32
|
+
if callsBackImmediately then
|
|
33
|
+
onCaptureReady("rbxassetid://1")
|
|
34
|
+
else
|
|
35
|
+
task.defer(onCaptureReady, "rbxassetid://1")
|
|
36
|
+
end
|
|
37
|
+
end,
|
|
38
|
+
},
|
|
39
|
+
assetService = {
|
|
40
|
+
CreateEditableImageAsync = function()
|
|
41
|
+
return {
|
|
42
|
+
Size = Vector2.new(2, 1),
|
|
43
|
+
ReadPixelsBuffer = function()
|
|
44
|
+
return pixels
|
|
45
|
+
end,
|
|
46
|
+
Destroy = function() end,
|
|
47
|
+
}
|
|
48
|
+
end,
|
|
49
|
+
},
|
|
50
|
+
encodingService = EncodingService,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
pixels = pixels,
|
|
55
|
+
setCaptureError = function(message: string)
|
|
56
|
+
captureError = message
|
|
57
|
+
end,
|
|
58
|
+
setCallsBackImmediately = function()
|
|
59
|
+
callsBackImmediately = true
|
|
60
|
+
end,
|
|
61
|
+
captureAsync = function(): { [string]: any }
|
|
62
|
+
local sent: { [string]: any }? = nil
|
|
63
|
+
task.spawn(CaptureScreenshotAction._captureAsync, function(message)
|
|
64
|
+
sent = message
|
|
65
|
+
end, "request-1", "session-1", services)
|
|
66
|
+
|
|
67
|
+
local deadline = os.clock() + 5
|
|
68
|
+
while sent == nil and os.clock() < deadline do
|
|
69
|
+
task.wait()
|
|
70
|
+
end
|
|
71
|
+
assert(sent, "captureScreenshot never replied")
|
|
72
|
+
|
|
73
|
+
return HttpService:JSONDecode(HttpService:JSONEncode(sent))
|
|
74
|
+
end,
|
|
75
|
+
}
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe("captureScreenshot", function()
|
|
79
|
+
it("should answer CAPABILITY_NOT_SUPPORTED without sendMessage", function()
|
|
80
|
+
local router = ActionRouter.new()
|
|
81
|
+
CaptureScreenshotAction.register(router, nil)
|
|
82
|
+
|
|
83
|
+
local response = router:Dispatch({ type = "captureScreenshot", sessionId = "session-1", payload = {} })
|
|
84
|
+
|
|
85
|
+
expect(response).toEqual({
|
|
86
|
+
type = "screenshotResult",
|
|
87
|
+
sessionId = "session-1",
|
|
88
|
+
payload = {
|
|
89
|
+
code = "CAPABILITY_NOT_SUPPORTED",
|
|
90
|
+
message = "Screenshot capture requires a sendMessage callback",
|
|
91
|
+
},
|
|
92
|
+
})
|
|
93
|
+
end)
|
|
94
|
+
|
|
95
|
+
it("should send the pixels as a base64 string through JSON", function()
|
|
96
|
+
local controller = setup()
|
|
97
|
+
|
|
98
|
+
local message = controller.captureAsync()
|
|
99
|
+
|
|
100
|
+
expect(message.type).toBe("screenshotResult")
|
|
101
|
+
expect(message.requestId).toBe("request-1")
|
|
102
|
+
expect(message.payload.format).toBe("rgba")
|
|
103
|
+
expect(message.payload.width).toBe(2)
|
|
104
|
+
expect(message.payload.height).toBe(1)
|
|
105
|
+
expect(typeof(message.payload.data)).toBe("string")
|
|
106
|
+
|
|
107
|
+
local decoded = EncodingService:Base64Decode(buffer.fromstring(message.payload.data))
|
|
108
|
+
expect(buffer.tostring(decoded)).toBe(buffer.tostring(controller.pixels))
|
|
109
|
+
end)
|
|
110
|
+
|
|
111
|
+
it("should finish when CaptureService calls back before returning", function()
|
|
112
|
+
local controller = setup()
|
|
113
|
+
controller.setCallsBackImmediately()
|
|
114
|
+
|
|
115
|
+
local message = controller.captureAsync()
|
|
116
|
+
|
|
117
|
+
expect(message.type).toBe("screenshotResult")
|
|
118
|
+
end)
|
|
119
|
+
|
|
120
|
+
it("should answer CAPTURE_FAILED when CaptureService throws", function()
|
|
121
|
+
local controller = setup()
|
|
122
|
+
controller.setCaptureError("no capture permission")
|
|
123
|
+
|
|
124
|
+
local message = controller.captureAsync()
|
|
125
|
+
|
|
126
|
+
expect(message.type).toBe("error")
|
|
127
|
+
expect(message.payload.code).toBe("CAPTURE_FAILED")
|
|
128
|
+
end)
|
|
129
|
+
end)
|
|
@@ -145,22 +145,19 @@ describe('captureScreenshotHandlerAsync', () => {
|
|
|
145
145
|
);
|
|
146
146
|
});
|
|
147
147
|
|
|
148
|
-
it('
|
|
148
|
+
it('rejects data that is not a base64 string', async () => {
|
|
149
149
|
const session = {
|
|
150
150
|
captureScreenshotAsync: vi.fn().mockResolvedValue({
|
|
151
|
-
data:
|
|
151
|
+
data: { m: null, t: 'buffer', zbase64: 'KLUv' },
|
|
152
152
|
format: 'png',
|
|
153
|
-
width:
|
|
154
|
-
height:
|
|
153
|
+
width: 1,
|
|
154
|
+
height: 1,
|
|
155
155
|
}),
|
|
156
156
|
} as any;
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
expect(result.width).toBe(0);
|
|
162
|
-
expect(result.height).toBe(0);
|
|
163
|
-
expect(result.summary).toBe('Screenshot captured (0x0)');
|
|
158
|
+
await expect(captureScreenshotHandlerAsync(session)).rejects.toThrow(
|
|
159
|
+
'The plugin sent screenshot data as object, not a base64 string'
|
|
160
|
+
);
|
|
164
161
|
});
|
|
165
162
|
|
|
166
163
|
it('passes options without affecting capture', async () => {
|
|
@@ -25,6 +25,11 @@ export async function captureScreenshotHandlerAsync(
|
|
|
25
25
|
_options: ScreenshotOptions = {}
|
|
26
26
|
): Promise<ScreenshotResult> {
|
|
27
27
|
const result: BridgeScreenshotResult = await session.captureScreenshotAsync();
|
|
28
|
+
if (typeof result.data !== 'string') {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`The plugin sent screenshot data as ${typeof result.data}, not a base64 string`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
28
33
|
|
|
29
34
|
let pngBase64: string;
|
|
30
35
|
if (result.format === 'rgba') {
|
|
@@ -32,7 +37,7 @@ export async function captureScreenshotHandlerAsync(
|
|
|
32
37
|
const pngBuffer = rgbaToPng(rgbaBuffer, result.width, result.height);
|
|
33
38
|
pngBase64 = pngBuffer.toString('base64');
|
|
34
39
|
} else {
|
|
35
|
-
pngBase64 = result.data
|
|
40
|
+
pngBase64 = result.data;
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
return {
|