@quenty/studio-bridge 0.21.1 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -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,111 +1,92 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
and children up to a specified depth.
|
|
7
|
-
|
|
8
|
-
Protocol:
|
|
9
|
-
Request: { type: "queryDataModel", path: "Workspace.SpawnLocation", depth: 1, properties: [], includeAttributes: true }
|
|
10
|
-
Response: { type: "dataModelResult", payload: { instance: DataModelInstance } }
|
|
11
|
-
]]
|
|
1
|
+
--!strict
|
|
2
|
+
--[=[
|
|
3
|
+
Action that resolves a dot-separated path to an Instance and answers with it
|
|
4
|
+
serialized, along with its properties, attributes, and children down to
|
|
5
|
+
`depth`.
|
|
12
6
|
|
|
13
|
-
|
|
7
|
+
Request: `{ type: "queryDataModel", payload: { path, depth?, properties?, includeAttributes? } }`
|
|
8
|
+
Response: `{ type: "dataModelResult", payload: { instance: DataModelInstance } }`
|
|
14
9
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-- ---------------------------------------------------------------------------
|
|
10
|
+
@class QueryDataModelAction
|
|
11
|
+
]=]
|
|
18
12
|
|
|
13
|
+
local COMMON_PROPERTIES = { "Name", "ClassName" }
|
|
19
14
|
local SKIP_PROPERTIES = {
|
|
20
15
|
Parent = true,
|
|
21
16
|
}
|
|
22
17
|
|
|
23
|
-
local
|
|
24
|
-
local t = typeof(value)
|
|
18
|
+
local QueryDataModelAction = {}
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
20
|
+
--[=[
|
|
21
|
+
Registers the `queryDataModel` handler.
|
|
22
|
+
]=]
|
|
23
|
+
function QueryDataModelAction.register(router: any)
|
|
24
|
+
router:setResponseType("queryDataModel", "dataModelResult")
|
|
25
|
+
router:register(
|
|
26
|
+
"queryDataModel",
|
|
27
|
+
function(payload: { [string]: any }, _requestId: string, _sessionId: string): { [string]: any }?
|
|
28
|
+
local path = payload.path
|
|
29
|
+
if type(path) ~= "string" then
|
|
30
|
+
return nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
local instance = QueryDataModelAction._resolveInstance(path)
|
|
34
|
+
if not instance then
|
|
35
|
+
return {
|
|
36
|
+
success = false,
|
|
37
|
+
code = "INSTANCE_NOT_FOUND",
|
|
38
|
+
message = `Instance not found at path: {path}`,
|
|
39
|
+
}
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
instance = QueryDataModelAction._serializeInstance(
|
|
44
|
+
instance,
|
|
45
|
+
payload.depth or 0,
|
|
46
|
+
payload.properties,
|
|
47
|
+
payload.includeAttributes == true
|
|
48
|
+
),
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
)
|
|
51
52
|
end
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
--[[
|
|
55
|
+
Walks `path` down from game, falling back to GetService for top-level names
|
|
56
|
+
that are not children by that name. A leading "game" is optional.
|
|
57
|
+
]]
|
|
58
|
+
function QueryDataModelAction._resolveInstance(path: string): Instance?
|
|
59
|
+
local parts = string.split(path, ".")
|
|
60
|
+
local startIndex = if parts[1] == "game" then 2 else 1
|
|
55
61
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
end
|
|
62
|
+
local current: Instance = game
|
|
63
|
+
for index = startIndex, #parts do
|
|
64
|
+
local part = parts[index]
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
for _, propName in propertyFilter do
|
|
66
|
-
if not SKIP_PROPERTIES[propName] then
|
|
67
|
-
local ok, value = pcall(function()
|
|
68
|
-
return (instance :: any)[propName]
|
|
69
|
-
end)
|
|
70
|
-
if ok then
|
|
71
|
-
result[propName] = serializeValue(value)
|
|
72
|
-
end
|
|
73
|
-
end
|
|
66
|
+
local ok, child = pcall(current.FindFirstChild, current, part)
|
|
67
|
+
if ok and child then
|
|
68
|
+
current = child
|
|
69
|
+
continue
|
|
74
70
|
end
|
|
75
|
-
else
|
|
76
|
-
-- No filter: read common properties
|
|
77
|
-
local commonProps = { "Name", "ClassName" }
|
|
78
|
-
for _, propName in commonProps do
|
|
79
|
-
local ok, value = pcall(function()
|
|
80
|
-
return (instance :: any)[propName]
|
|
81
|
-
end)
|
|
82
|
-
if ok then
|
|
83
|
-
result[propName] = serializeValue(value)
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
71
|
|
|
88
|
-
|
|
89
|
-
|
|
72
|
+
if current ~= game then
|
|
73
|
+
return nil
|
|
74
|
+
end
|
|
90
75
|
|
|
91
|
-
local
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return instance:GetAttributes()
|
|
95
|
-
end)
|
|
96
|
-
if ok and attrs then
|
|
97
|
-
for key, value in attrs do
|
|
98
|
-
result[key] = serializeValue(value)
|
|
76
|
+
local serviceOk, service = pcall(game.GetService, game, part)
|
|
77
|
+
if not (serviceOk and service) then
|
|
78
|
+
return nil
|
|
99
79
|
end
|
|
80
|
+
current = service
|
|
100
81
|
end
|
|
101
|
-
return result
|
|
102
|
-
end
|
|
103
82
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
-- ---------------------------------------------------------------------------
|
|
83
|
+
return current
|
|
84
|
+
end
|
|
107
85
|
|
|
108
|
-
|
|
86
|
+
--[[
|
|
87
|
+
A nil filter reads the common properties, an empty one reads none.
|
|
88
|
+
]]
|
|
89
|
+
function QueryDataModelAction._serializeInstance(
|
|
109
90
|
instance: Instance,
|
|
110
91
|
depth: number,
|
|
111
92
|
propertyFilter: { string }?,
|
|
@@ -116,15 +97,18 @@ local function serializeInstance(
|
|
|
116
97
|
name = instance.Name,
|
|
117
98
|
className = instance.ClassName,
|
|
118
99
|
path = instance:GetFullName(),
|
|
119
|
-
properties =
|
|
120
|
-
attributes = if includeAttributes then
|
|
100
|
+
properties = QueryDataModelAction._serializeProperties(instance, propertyFilter or COMMON_PROPERTIES),
|
|
101
|
+
attributes = if includeAttributes then QueryDataModelAction._serializeAttributes(instance) else {},
|
|
121
102
|
childCount = #children,
|
|
122
103
|
}
|
|
123
104
|
|
|
124
105
|
if depth > 0 then
|
|
125
106
|
local serializedChildren = {}
|
|
126
107
|
for _, child in children do
|
|
127
|
-
table.insert(
|
|
108
|
+
table.insert(
|
|
109
|
+
serializedChildren,
|
|
110
|
+
QueryDataModelAction._serializeInstance(child, depth - 1, propertyFilter, includeAttributes)
|
|
111
|
+
)
|
|
128
112
|
end
|
|
129
113
|
node.children = serializedChildren
|
|
130
114
|
end
|
|
@@ -132,75 +116,63 @@ local function serializeInstance(
|
|
|
132
116
|
return node
|
|
133
117
|
end
|
|
134
118
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
local parts = string.split(path, ".")
|
|
142
|
-
local startIndex = 1
|
|
143
|
-
|
|
144
|
-
-- Skip leading "game" since we start from game
|
|
145
|
-
if parts[1] == "game" then
|
|
146
|
-
startIndex = 2
|
|
147
|
-
end
|
|
119
|
+
function QueryDataModelAction._serializeProperties(instance: Instance, propertyNames: { string }): { [string]: any }
|
|
120
|
+
local result = {}
|
|
121
|
+
for _, propertyName in propertyNames do
|
|
122
|
+
if SKIP_PROPERTIES[propertyName] then
|
|
123
|
+
continue
|
|
124
|
+
end
|
|
148
125
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
-- Try as a service first (e.g. "Workspace", "ReplicatedStorage")
|
|
153
|
-
local ok, child = pcall(function()
|
|
154
|
-
return current:FindFirstChild(part)
|
|
126
|
+
-- Roblox exposes no property list, so read each name and skip the ones that throw
|
|
127
|
+
local ok, value = pcall(function()
|
|
128
|
+
return (instance :: any)[propertyName]
|
|
155
129
|
end)
|
|
156
|
-
if
|
|
157
|
-
|
|
158
|
-
if current == game then
|
|
159
|
-
local serviceOk, service = pcall(function()
|
|
160
|
-
return game:GetService(part)
|
|
161
|
-
end)
|
|
162
|
-
if serviceOk and service then
|
|
163
|
-
current = service
|
|
164
|
-
continue
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
return nil
|
|
130
|
+
if ok then
|
|
131
|
+
result[propertyName] = QueryDataModelAction._serializeValue(value)
|
|
168
132
|
end
|
|
169
|
-
current = child
|
|
170
133
|
end
|
|
171
|
-
|
|
172
|
-
return current
|
|
134
|
+
return result
|
|
173
135
|
end
|
|
174
136
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
router:register("queryDataModel", function(payload: { [string]: any }, _requestId: string, _sessionId: string)
|
|
182
|
-
local path = payload.path
|
|
183
|
-
if not path or type(path) ~= "string" then
|
|
184
|
-
return nil -- ActionRouter will return UNKNOWN_REQUEST for nil
|
|
185
|
-
end
|
|
137
|
+
function QueryDataModelAction._serializeAttributes(instance: Instance): { [string]: any }
|
|
138
|
+
local result = {}
|
|
139
|
+
local ok, attributes = pcall(instance.GetAttributes, instance)
|
|
140
|
+
if not ok then
|
|
141
|
+
return result
|
|
142
|
+
end
|
|
186
143
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
144
|
+
for key, value in attributes do
|
|
145
|
+
result[key] = QueryDataModelAction._serializeValue(value)
|
|
146
|
+
end
|
|
147
|
+
return result
|
|
148
|
+
end
|
|
190
149
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
return {
|
|
194
|
-
success = false,
|
|
195
|
-
code = "INSTANCE_NOT_FOUND",
|
|
196
|
-
message = `Instance not found at path: {path}`,
|
|
197
|
-
}
|
|
198
|
-
end
|
|
150
|
+
function QueryDataModelAction._serializeValue(value: any): any
|
|
151
|
+
local valueType = typeof(value)
|
|
199
152
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
153
|
+
if valueType == "nil" or valueType == "string" or valueType == "number" or valueType == "boolean" then
|
|
154
|
+
return value
|
|
155
|
+
elseif valueType == "Vector3" then
|
|
156
|
+
return { type = "Vector3", value = { value.X, value.Y, value.Z } }
|
|
157
|
+
elseif valueType == "Vector2" then
|
|
158
|
+
return { type = "Vector2", value = { value.X, value.Y } }
|
|
159
|
+
elseif valueType == "CFrame" then
|
|
160
|
+
return { type = "CFrame", value = { value:GetComponents() } }
|
|
161
|
+
elseif valueType == "Color3" then
|
|
162
|
+
return { type = "Color3", value = { value.R, value.G, value.B } }
|
|
163
|
+
elseif valueType == "UDim2" then
|
|
164
|
+
return { type = "UDim2", value = { value.X.Scale, value.X.Offset, value.Y.Scale, value.Y.Offset } }
|
|
165
|
+
elseif valueType == "UDim" then
|
|
166
|
+
return { type = "UDim", value = { value.Scale, value.Offset } }
|
|
167
|
+
elseif valueType == "BrickColor" then
|
|
168
|
+
return { type = "BrickColor", name = value.Name, value = value.Number }
|
|
169
|
+
elseif valueType == "EnumItem" then
|
|
170
|
+
return { type = "EnumItem", enum = tostring(value.EnumType), name = value.Name, value = value.Value }
|
|
171
|
+
elseif valueType == "Instance" then
|
|
172
|
+
return { type = "Instance", className = value.ClassName, path = value:GetFullName() }
|
|
173
|
+
else
|
|
174
|
+
return { type = "Unsupported", typeName = valueType, toString = tostring(value) }
|
|
175
|
+
end
|
|
204
176
|
end
|
|
205
177
|
|
|
206
178
|
return QueryDataModelAction
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--[[
|
|
3
|
+
@class query-data-model.spec.lua
|
|
4
|
+
]]
|
|
5
|
+
|
|
6
|
+
local require = require(script.Parent.loader).load(script)
|
|
7
|
+
|
|
8
|
+
local HttpService = game:GetService("HttpService")
|
|
9
|
+
|
|
10
|
+
local ActionRouter = require("ActionRouter")
|
|
11
|
+
local Jest = require("Jest")
|
|
12
|
+
local QueryDataModelAction = require("query-data-model")
|
|
13
|
+
|
|
14
|
+
local describe = Jest.Globals.describe
|
|
15
|
+
local expect = Jest.Globals.expect
|
|
16
|
+
local it = Jest.Globals.it
|
|
17
|
+
|
|
18
|
+
local function setup(): any
|
|
19
|
+
local router = ActionRouter.new()
|
|
20
|
+
QueryDataModelAction.register(router)
|
|
21
|
+
|
|
22
|
+
local root = Instance.new("Folder")
|
|
23
|
+
root.Name = `QueryDataModelSpec{HttpService:GenerateGUID(false)}`
|
|
24
|
+
root:SetAttribute("Offset", Vector3.new(1, 2, 3))
|
|
25
|
+
|
|
26
|
+
local value = Instance.new("IntValue")
|
|
27
|
+
value.Name = "Score"
|
|
28
|
+
value.Value = 42
|
|
29
|
+
value.Parent = root
|
|
30
|
+
|
|
31
|
+
local nested = Instance.new("Folder")
|
|
32
|
+
nested.Name = "Nested"
|
|
33
|
+
nested.Parent = value
|
|
34
|
+
|
|
35
|
+
root.Parent = workspace
|
|
36
|
+
|
|
37
|
+
local controller = {
|
|
38
|
+
root = root,
|
|
39
|
+
rootPath = `Workspace.{root.Name}`,
|
|
40
|
+
query = function(payload: { [string]: any }): any
|
|
41
|
+
return router:Dispatch({ type = "queryDataModel", sessionId = "session-1", payload = payload })
|
|
42
|
+
end,
|
|
43
|
+
Destroy = function(_self)
|
|
44
|
+
root:Destroy()
|
|
45
|
+
end,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return controller
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe("queryDataModel", function()
|
|
52
|
+
it("should answer dataModelResult with the instance's common properties", function()
|
|
53
|
+
local controller = setup()
|
|
54
|
+
|
|
55
|
+
local response = controller.query({ path = controller.rootPath })
|
|
56
|
+
|
|
57
|
+
expect(response.type).toEqual("dataModelResult")
|
|
58
|
+
expect(response.payload.instance).toEqual({
|
|
59
|
+
name = controller.root.Name,
|
|
60
|
+
className = "Folder",
|
|
61
|
+
path = controller.root:GetFullName(),
|
|
62
|
+
properties = { Name = controller.root.Name, ClassName = "Folder" },
|
|
63
|
+
attributes = {},
|
|
64
|
+
childCount = 1,
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
controller:Destroy()
|
|
68
|
+
end)
|
|
69
|
+
|
|
70
|
+
it("should accept a leading game", function()
|
|
71
|
+
local controller = setup()
|
|
72
|
+
|
|
73
|
+
local response = controller.query({ path = `game.{controller.rootPath}` })
|
|
74
|
+
|
|
75
|
+
expect(response.payload.instance.name).toEqual(controller.root.Name)
|
|
76
|
+
|
|
77
|
+
controller:Destroy()
|
|
78
|
+
end)
|
|
79
|
+
|
|
80
|
+
it("should include children down to the requested depth", function()
|
|
81
|
+
local controller = setup()
|
|
82
|
+
|
|
83
|
+
local response = controller.query({ path = controller.rootPath, depth = 1 })
|
|
84
|
+
|
|
85
|
+
local children = response.payload.instance.children
|
|
86
|
+
expect(#children).toEqual(1)
|
|
87
|
+
expect(children[1].name).toEqual("Score")
|
|
88
|
+
expect(children[1].childCount).toEqual(1)
|
|
89
|
+
expect(children[1].children).toBeNil()
|
|
90
|
+
|
|
91
|
+
controller:Destroy()
|
|
92
|
+
end)
|
|
93
|
+
|
|
94
|
+
it("should read only the requested properties, skipping Parent and unknown names", function()
|
|
95
|
+
local controller = setup()
|
|
96
|
+
|
|
97
|
+
local response = controller.query({
|
|
98
|
+
path = `{controller.rootPath}.Score`,
|
|
99
|
+
properties = { "Value", "Parent", "NotAProperty" },
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
expect(response.payload.instance.properties).toEqual({ Value = 42 })
|
|
103
|
+
|
|
104
|
+
controller:Destroy()
|
|
105
|
+
end)
|
|
106
|
+
|
|
107
|
+
it("should read no properties for an empty list", function()
|
|
108
|
+
local controller = setup()
|
|
109
|
+
|
|
110
|
+
local response = controller.query({ path = controller.rootPath, properties = {} })
|
|
111
|
+
|
|
112
|
+
expect(response.payload.instance.properties).toEqual({})
|
|
113
|
+
|
|
114
|
+
controller:Destroy()
|
|
115
|
+
end)
|
|
116
|
+
|
|
117
|
+
it("should serialize attributes when asked", function()
|
|
118
|
+
local controller = setup()
|
|
119
|
+
|
|
120
|
+
local response = controller.query({ path = controller.rootPath, includeAttributes = true })
|
|
121
|
+
|
|
122
|
+
expect(response.payload.instance.attributes).toEqual({
|
|
123
|
+
Offset = { type = "Vector3", value = { 1, 2, 3 } },
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
controller:Destroy()
|
|
127
|
+
end)
|
|
128
|
+
|
|
129
|
+
it("should answer INSTANCE_NOT_FOUND for a missing path", function()
|
|
130
|
+
local controller = setup()
|
|
131
|
+
|
|
132
|
+
local response = controller.query({ path = `{controller.rootPath}.Missing` })
|
|
133
|
+
|
|
134
|
+
expect(response.type).toEqual("error")
|
|
135
|
+
expect(response.payload).toEqual({
|
|
136
|
+
code = "INSTANCE_NOT_FOUND",
|
|
137
|
+
message = `Instance not found at path: {controller.rootPath}.Missing`,
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
controller:Destroy()
|
|
141
|
+
end)
|
|
142
|
+
|
|
143
|
+
it("should send nothing without a path", function()
|
|
144
|
+
local controller = setup()
|
|
145
|
+
|
|
146
|
+
expect(controller.query({})).toBeNil()
|
|
147
|
+
|
|
148
|
+
controller:Destroy()
|
|
149
|
+
end)
|
|
150
|
+
end)
|
|
@@ -74,7 +74,7 @@ describe('logs formatter', () => {
|
|
|
74
74
|
const text = formatLogsText(result);
|
|
75
75
|
expect(text).toContain('Hello');
|
|
76
76
|
expect(text).toContain('Boom');
|
|
77
|
-
expect(text).toContain('(2
|
|
77
|
+
expect(text).toContain('(2 shown, 2 in buffer)');
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
it('is wired into command definition', () => {
|
|
@@ -123,10 +123,16 @@ describe('list formatter', () => {
|
|
|
123
123
|
describe('info formatter', () => {
|
|
124
124
|
it('formats key-value pairs', () => {
|
|
125
125
|
const result = {
|
|
126
|
+
sessionId: 'my-place-1a2b-edit',
|
|
127
|
+
instanceId: 'my-place-1a2b',
|
|
128
|
+
context: 'edit' as const,
|
|
129
|
+
origin: 'user' as const,
|
|
126
130
|
state: 'Edit' as const,
|
|
127
131
|
placeName: 'MyPlace',
|
|
128
132
|
placeId: 123,
|
|
129
133
|
gameId: 456,
|
|
134
|
+
plugin: { version: 'abc', expectedVersion: 'abc', upToDate: true },
|
|
135
|
+
connectedAt: new Date().toISOString(),
|
|
130
136
|
summary: 'Mode: Edit, Place: MyPlace (123)',
|
|
131
137
|
};
|
|
132
138
|
|
|
@@ -98,6 +98,34 @@ describe('loadActionSourcesAsync', () => {
|
|
|
98
98
|
expect(results[0].name).toBe('action');
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
+
it('skips .spec.lua files', async () => {
|
|
102
|
+
await fs.writeFile(path.join(tmpDir, 'action.lua'), 'included');
|
|
103
|
+
await fs.writeFile(path.join(tmpDir, 'action.spec.lua'), 'not included');
|
|
104
|
+
|
|
105
|
+
const results = await loadActionSourcesAsync(tmpDir);
|
|
106
|
+
|
|
107
|
+
expect(results.map((r) => r.name)).toEqual(['action']);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('finds every shipped action and none of their specs', async () => {
|
|
111
|
+
const results = await loadActionSourcesAsync();
|
|
112
|
+
|
|
113
|
+
expect(results.map((r) => r.name).sort()).toEqual([
|
|
114
|
+
'capture-screenshot',
|
|
115
|
+
'end-playtest',
|
|
116
|
+
'execute',
|
|
117
|
+
'export-instances',
|
|
118
|
+
'find-instances',
|
|
119
|
+
'grep-scripts',
|
|
120
|
+
'import-instances',
|
|
121
|
+
'query-data-model',
|
|
122
|
+
'query-logs',
|
|
123
|
+
'query-state',
|
|
124
|
+
'run-playtest-script',
|
|
125
|
+
'start-playtest',
|
|
126
|
+
]);
|
|
127
|
+
});
|
|
128
|
+
|
|
101
129
|
it('returns empty array for empty directory', async () => {
|
|
102
130
|
const results = await loadActionSourcesAsync(tmpDir);
|
|
103
131
|
expect(results).toHaveLength(0);
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* as its `.ts` file (e.g. `exec.lua` next to `exec.ts`). These files
|
|
7
7
|
* are Luau modules that register action handlers in the plugin's
|
|
8
8
|
* ActionRouter at runtime.
|
|
9
|
+
*
|
|
10
|
+
* `.spec.lua` files beside them are Jest specs. They are never pushed,
|
|
11
|
+
* since anything pushed runs inside the user's Studio.
|
|
9
12
|
*/
|
|
10
13
|
|
|
11
14
|
import { createHash } from 'crypto';
|
|
@@ -26,7 +29,8 @@ export interface ActionSource {
|
|
|
26
29
|
|
|
27
30
|
/**
|
|
28
31
|
* Recursively scan `baseDir` for `.lua` files and return their contents
|
|
29
|
-
* as `ActionSource` entries. Only files that end in `.lua` are included
|
|
32
|
+
* as `ActionSource` entries. Only files that end in `.lua` are included,
|
|
33
|
+
* and `.spec.lua` files are skipped.
|
|
30
34
|
*/
|
|
31
35
|
export async function loadActionSourcesAsync(
|
|
32
36
|
baseDir?: string
|
|
@@ -54,7 +58,7 @@ async function scanDirAsync(
|
|
|
54
58
|
const fullPath = path.join(currentDir, entry.name);
|
|
55
59
|
if (entry.isDirectory()) {
|
|
56
60
|
await scanDirAsync(baseDir, fullPath, results);
|
|
57
|
-
} else if (entry.name
|
|
61
|
+
} else if (isActionFile(entry.name)) {
|
|
58
62
|
const source = await fs.readFile(fullPath, 'utf-8');
|
|
59
63
|
const name = path.basename(entry.name, '.lua');
|
|
60
64
|
const relativePath = path.relative(baseDir, fullPath);
|
|
@@ -63,3 +67,7 @@ async function scanDirAsync(
|
|
|
63
67
|
}
|
|
64
68
|
}
|
|
65
69
|
}
|
|
70
|
+
|
|
71
|
+
function isActionFile(fileName: string): boolean {
|
|
72
|
+
return fileName.endsWith('.lua') && !fileName.endsWith('.spec.lua');
|
|
73
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Argument definition DSL and schema converters.
|
|
3
3
|
*
|
|
4
|
-
* `arg.positional()`, `arg.option()`, and `arg.
|
|
4
|
+
* `arg.positional()`, `arg.option()`, `arg.flag()`, and `arg.passthrough()` produce `ArgDefinition`
|
|
5
5
|
* objects that carry enough metadata to generate both yargs options and
|
|
6
6
|
* JSON Schema properties for MCP tools.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
export type ArgKind = 'positional' | 'option' | 'flag';
|
|
9
|
+
export type ArgKind = 'positional' | 'option' | 'flag' | 'passthrough';
|
|
10
10
|
export type ArgType = 'string' | 'number' | 'boolean';
|
|
11
11
|
|
|
12
12
|
export interface ArgDefinition {
|
|
@@ -33,6 +33,8 @@ export const arg = {
|
|
|
33
33
|
type?: 'string' | 'number';
|
|
34
34
|
required?: boolean;
|
|
35
35
|
choices?: readonly string[];
|
|
36
|
+
/** Collect every remaining positional into an array (`<name..>`). */
|
|
37
|
+
array?: boolean;
|
|
36
38
|
}): ArgDefinition {
|
|
37
39
|
return {
|
|
38
40
|
kind: 'positional',
|
|
@@ -40,6 +42,7 @@ export const arg = {
|
|
|
40
42
|
description: config.description,
|
|
41
43
|
required: config.required ?? true,
|
|
42
44
|
choices: config.choices,
|
|
45
|
+
array: config.array,
|
|
43
46
|
};
|
|
44
47
|
},
|
|
45
48
|
|
|
@@ -91,6 +94,22 @@ export const arg = {
|
|
|
91
94
|
default: config.default ?? false,
|
|
92
95
|
};
|
|
93
96
|
},
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Collect everything after `--` as a list of strings, unparsed.
|
|
100
|
+
*
|
|
101
|
+
* ```ts
|
|
102
|
+
* args: { scriptArgs: arg.passthrough({ description: 'Passed to the script' }) }
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
passthrough(config: { description: string }): ArgDefinition {
|
|
106
|
+
return {
|
|
107
|
+
kind: 'passthrough',
|
|
108
|
+
type: 'string',
|
|
109
|
+
description: config.description,
|
|
110
|
+
array: true,
|
|
111
|
+
};
|
|
112
|
+
},
|
|
94
113
|
};
|
|
95
114
|
|
|
96
115
|
export interface YargsPositional {
|
|
@@ -100,6 +119,7 @@ export interface YargsPositional {
|
|
|
100
119
|
type: 'string' | 'number';
|
|
101
120
|
demandOption?: boolean;
|
|
102
121
|
choices?: readonly string[];
|
|
122
|
+
array?: boolean;
|
|
103
123
|
};
|
|
104
124
|
}
|
|
105
125
|
|
|
@@ -118,7 +138,9 @@ export function toYargsOptions(
|
|
|
118
138
|
const options: Record<string, Record<string, unknown>> = {};
|
|
119
139
|
|
|
120
140
|
for (const [name, def] of Object.entries(args)) {
|
|
121
|
-
if (def.kind === '
|
|
141
|
+
if (def.kind === 'passthrough') {
|
|
142
|
+
continue;
|
|
143
|
+
} else if (def.kind === 'positional') {
|
|
122
144
|
positionals.push({
|
|
123
145
|
name,
|
|
124
146
|
options: {
|
|
@@ -126,6 +148,7 @@ export function toYargsOptions(
|
|
|
126
148
|
type: def.type as 'string' | 'number',
|
|
127
149
|
demandOption: def.required,
|
|
128
150
|
...(def.choices ? { choices: def.choices } : {}),
|
|
151
|
+
...(def.array ? { array: true } : {}),
|
|
129
152
|
},
|
|
130
153
|
});
|
|
131
154
|
} else {
|