@quenty/studio-bridge 0.1.1-canary.656.73a74af.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 +15 -0
- package/LICENSE.md +21 -0
- package/README.md +179 -0
- package/dist/src/cli/args/global-args.d.ts +10 -0
- package/dist/src/cli/args/global-args.d.ts.map +1 -0
- package/dist/src/cli/args/global-args.js +2 -0
- package/dist/src/cli/args/global-args.js.map +1 -0
- package/dist/src/cli/cli.d.ts +11 -0
- package/dist/src/cli/cli.d.ts.map +1 -0
- package/dist/src/cli/cli.js +65 -0
- package/dist/src/cli/cli.js.map +1 -0
- package/dist/src/cli/commands/exec-command.d.ts +15 -0
- package/dist/src/cli/commands/exec-command.d.ts.map +1 -0
- package/dist/src/cli/commands/exec-command.js +35 -0
- package/dist/src/cli/commands/exec-command.js.map +1 -0
- package/dist/src/cli/commands/run-command.d.ts +15 -0
- package/dist/src/cli/commands/run-command.d.ts.map +1 -0
- package/dist/src/cli/commands/run-command.js +47 -0
- package/dist/src/cli/commands/run-command.js.map +1 -0
- package/dist/src/cli/commands/terminal/terminal-command.d.ts +17 -0
- package/dist/src/cli/commands/terminal/terminal-command.d.ts.map +1 -0
- package/dist/src/cli/commands/terminal/terminal-command.js +41 -0
- package/dist/src/cli/commands/terminal/terminal-command.js.map +1 -0
- package/dist/src/cli/commands/terminal/terminal-editor.d.ts +43 -0
- package/dist/src/cli/commands/terminal/terminal-editor.d.ts.map +1 -0
- package/dist/src/cli/commands/terminal/terminal-editor.js +430 -0
- package/dist/src/cli/commands/terminal/terminal-editor.js.map +1 -0
- package/dist/src/cli/commands/terminal/terminal-mode.d.ts +13 -0
- package/dist/src/cli/commands/terminal/terminal-mode.d.ts.map +1 -0
- package/dist/src/cli/commands/terminal/terminal-mode.js +141 -0
- package/dist/src/cli/commands/terminal/terminal-mode.js.map +1 -0
- package/dist/src/cli/index.d.ts +2 -0
- package/dist/src/cli/index.d.ts.map +1 -0
- package/dist/src/cli/index.js +2 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cli/script-executor.d.ts +23 -0
- package/dist/src/cli/script-executor.d.ts.map +1 -0
- package/dist/src/cli/script-executor.js +112 -0
- package/dist/src/cli/script-executor.js.map +1 -0
- package/dist/src/index.d.ts +20 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +18 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/plugin/index.d.ts +3 -0
- package/dist/src/plugin/index.d.ts.map +1 -0
- package/dist/src/plugin/index.js +2 -0
- package/dist/src/plugin/index.js.map +1 -0
- package/dist/src/plugin/plugin-injector.d.ts +19 -0
- package/dist/src/plugin/plugin-injector.d.ts.map +1 -0
- package/dist/src/plugin/plugin-injector.js +57 -0
- package/dist/src/plugin/plugin-injector.js.map +1 -0
- package/dist/src/plugin/plugin-injector.test.d.ts +2 -0
- package/dist/src/plugin/plugin-injector.test.d.ts.map +1 -0
- package/dist/src/plugin/plugin-injector.test.js +31 -0
- package/dist/src/plugin/plugin-injector.test.js.map +1 -0
- package/dist/src/process/index.d.ts +5 -0
- package/dist/src/process/index.d.ts.map +1 -0
- package/dist/src/process/index.js +3 -0
- package/dist/src/process/index.js.map +1 -0
- package/dist/src/process/place-builder.d.ts +16 -0
- package/dist/src/process/place-builder.d.ts.map +1 -0
- package/dist/src/process/place-builder.js +45 -0
- package/dist/src/process/place-builder.js.map +1 -0
- package/dist/src/process/studio-process-manager.d.ts +25 -0
- package/dist/src/process/studio-process-manager.d.ts.map +1 -0
- package/dist/src/process/studio-process-manager.js +121 -0
- package/dist/src/process/studio-process-manager.js.map +1 -0
- package/dist/src/process/studio-process-manager.test.d.ts +2 -0
- package/dist/src/process/studio-process-manager.test.d.ts.map +1 -0
- package/dist/src/process/studio-process-manager.test.js +42 -0
- package/dist/src/process/studio-process-manager.test.js.map +1 -0
- package/dist/src/server/index.d.ts +5 -0
- package/dist/src/server/index.d.ts.map +1 -0
- package/dist/src/server/index.js +3 -0
- package/dist/src/server/index.js.map +1 -0
- package/dist/src/server/studio-bridge-server.d.ts +67 -0
- package/dist/src/server/studio-bridge-server.d.ts.map +1 -0
- package/dist/src/server/studio-bridge-server.js +338 -0
- package/dist/src/server/studio-bridge-server.js.map +1 -0
- package/dist/src/server/studio-bridge-server.test.d.ts +9 -0
- package/dist/src/server/studio-bridge-server.test.d.ts.map +1 -0
- package/dist/src/server/studio-bridge-server.test.js +471 -0
- package/dist/src/server/studio-bridge-server.test.js.map +1 -0
- package/dist/src/server/web-socket-protocol.d.ts +48 -0
- package/dist/src/server/web-socket-protocol.d.ts.map +1 -0
- package/dist/src/server/web-socket-protocol.js +59 -0
- package/dist/src/server/web-socket-protocol.js.map +1 -0
- package/dist/src/server/web-socket-protocol.smoke.test.d.ts +6 -0
- package/dist/src/server/web-socket-protocol.smoke.test.d.ts.map +1 -0
- package/dist/src/server/web-socket-protocol.smoke.test.js +187 -0
- package/dist/src/server/web-socket-protocol.smoke.test.js.map +1 -0
- package/dist/src/server/web-socket-protocol.test.d.ts +2 -0
- package/dist/src/server/web-socket-protocol.test.d.ts.map +1 -0
- package/dist/src/server/web-socket-protocol.test.js +150 -0
- package/dist/src/server/web-socket-protocol.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +41 -0
- package/src/cli/args/global-args.ts +9 -0
- package/src/cli/cli.ts +78 -0
- package/src/cli/commands/exec-command.ts +48 -0
- package/src/cli/commands/run-command.ts +63 -0
- package/src/cli/commands/terminal/terminal-command.ts +54 -0
- package/src/cli/commands/terminal/terminal-editor.ts +500 -0
- package/src/cli/commands/terminal/terminal-mode.ts +184 -0
- package/src/cli/index.ts +1 -0
- package/src/cli/script-executor.ts +149 -0
- package/src/index.ts +43 -0
- package/src/plugin/index.ts +2 -0
- package/src/plugin/plugin-injector.test.ts +35 -0
- package/src/plugin/plugin-injector.ts +91 -0
- package/src/process/index.ts +9 -0
- package/src/process/place-builder.ts +63 -0
- package/src/process/studio-process-manager.test.ts +53 -0
- package/src/process/studio-process-manager.ts +143 -0
- package/src/server/index.ts +20 -0
- package/src/server/studio-bridge-server.test.ts +623 -0
- package/src/server/studio-bridge-server.ts +483 -0
- package/src/server/web-socket-protocol.smoke.test.ts +246 -0
- package/src/server/web-socket-protocol.test.ts +185 -0
- package/src/server/web-socket-protocol.ts +132 -0
- package/templates/default-test-place/default.project.json +11 -0
- package/templates/studio-bridge-plugin/default.project.json +6 -0
- package/templates/studio-bridge-plugin/plugin-template.server.lua +194 -0
- package/tsconfig.json +16 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## 0.1.1-canary.656.73a74af.0 (2026-02-17)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Add a terminal mode to studio-bridge for easier debugging ([92cdca9](https://github.com/Quenty/NevermoreEngine/commit/92cdca97ee6ece9a8622559f8846f59b831788de))
|
|
12
|
+
* Add initial studio-bridge package that can replace run-in-roblox ([aec737f](https://github.com/Quenty/NevermoreEngine/commit/aec737fd0eb3f2b045fc469a2b46f833de84a24b))
|
|
13
|
+
* Refactor studio bridge ([8afe642](https://github.com/Quenty/NevermoreEngine/commit/8afe6424b6635eaa0155734c085934051de88da6))
|
|
14
|
+
* Use reporting system for studio bridge too (a bit ugly) ([20b675c](https://github.com/Quenty/NevermoreEngine/commit/20b675cb22cb46c88b556f4afdda2700dd1258dd))
|
|
15
|
+
* Use yargs in studio-bridge cli ([2203601](https://github.com/Quenty/NevermoreEngine/commit/220360168e79d57cd576150134949d8f2325a38f))
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2014-2026 James Onnen (Quenty)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# @quenty/studio-bridge
|
|
2
|
+
|
|
3
|
+
WebSocket-based bridge for running Luau scripts in Roblox Studio.
|
|
4
|
+
|
|
5
|
+
## How It Works
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────┐ WebSocket ┌──────────────────┐
|
|
9
|
+
│ Node.js │◄───────────────►│ Studio Plugin │
|
|
10
|
+
│ Server │ ws://localhost │ (auto-injected) │
|
|
11
|
+
│ │ │ │
|
|
12
|
+
│ 1. Start WS │ │ 4. Connect + hello│
|
|
13
|
+
│ 2. Inject │ │ 5. Run script │
|
|
14
|
+
│ plugin │ │ 6. Stream output │
|
|
15
|
+
│ 3. Launch │ │ 7. scriptComplete │
|
|
16
|
+
│ Studio │ │ │
|
|
17
|
+
└─────────────┘ └──────────────────┘
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
1. Start WebSocket server on a random port
|
|
21
|
+
2. Build a `.rbxm` plugin via `rojo build --plugin` with the port and session ID baked in
|
|
22
|
+
3. Plugin is placed in Studio's plugins folder, launch Studio
|
|
23
|
+
4. Plugin connects, handshakes with session ID
|
|
24
|
+
5. Server sends `execute` with Luau script, plugin runs it via `loadstring()` + `xpcall()`
|
|
25
|
+
6. Plugin streams `LogService` output back as batched messages
|
|
26
|
+
7. Plugin sends `scriptComplete` — server can send another `execute` or `shutdown`
|
|
27
|
+
|
|
28
|
+
The session ID (random UUID) prevents stale plugins from previous runs from interfering.
|
|
29
|
+
|
|
30
|
+
## CLI
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Run a script file
|
|
34
|
+
studio-bridge run test.lua
|
|
35
|
+
|
|
36
|
+
# Run inline script
|
|
37
|
+
studio-bridge exec 'print("hello world")'
|
|
38
|
+
|
|
39
|
+
# With a specific place file (builds a minimal place via rojo if omitted)
|
|
40
|
+
studio-bridge run test.lua --place build/test.rbxl
|
|
41
|
+
|
|
42
|
+
# Interactive terminal mode (keeps Studio alive between executions)
|
|
43
|
+
studio-bridge terminal
|
|
44
|
+
|
|
45
|
+
# Terminal mode with initial script
|
|
46
|
+
studio-bridge terminal --place build/test.rbxl --script init.lua
|
|
47
|
+
|
|
48
|
+
# Debug output
|
|
49
|
+
studio-bridge run test.lua --verbose
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Global Options
|
|
53
|
+
|
|
54
|
+
| Option | Alias | Default | Description |
|
|
55
|
+
|--------|-------|---------|-------------|
|
|
56
|
+
| `--place` | `-p` | — | Path to a `.rbxl` place file (builds minimal place via rojo if omitted) |
|
|
57
|
+
| `--timeout` | — | `120000` | Timeout in milliseconds |
|
|
58
|
+
| `--verbose` | — | `false` | Show internal debug output |
|
|
59
|
+
| `--logs` / `--no-logs` | — | `true` | Show execution logs in spinner mode |
|
|
60
|
+
|
|
61
|
+
### Terminal Mode
|
|
62
|
+
|
|
63
|
+
Keeps Studio alive and provides an interactive REPL. Type Luau, see results, repeat — no re-launch between executions.
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
$ studio-bridge terminal --place build/test.rbxl
|
|
67
|
+
Studio connected.
|
|
68
|
+
|
|
69
|
+
────────────────────────────────────────────────────────
|
|
70
|
+
❯ print("hello")
|
|
71
|
+
────────────────────────────────────────────────────────
|
|
72
|
+
ctrl+enter to run · ctrl+c to clear · .help for commands
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
| Key | Action |
|
|
76
|
+
|-----|--------|
|
|
77
|
+
| Enter | New line |
|
|
78
|
+
| Ctrl+Enter | Execute buffer |
|
|
79
|
+
| Ctrl+C | Clear buffer (exit if empty) |
|
|
80
|
+
| Ctrl+D | Exit |
|
|
81
|
+
|
|
82
|
+
| Command | Description |
|
|
83
|
+
|---------|-------------|
|
|
84
|
+
| `.help` | Show keybindings and commands |
|
|
85
|
+
| `.exit` | Exit terminal mode |
|
|
86
|
+
| `.run <file>` | Execute a Luau file |
|
|
87
|
+
| `.clear` | Clear the editor buffer |
|
|
88
|
+
|
|
89
|
+
## API
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { StudioBridge } from '@quenty/studio-bridge';
|
|
93
|
+
|
|
94
|
+
const bridge = new StudioBridge({ placePath: './build/test.rbxl' });
|
|
95
|
+
await bridge.startAsync();
|
|
96
|
+
|
|
97
|
+
const result = await bridge.executeAsync({
|
|
98
|
+
scriptContent: 'print("Hello from studio-bridge!")',
|
|
99
|
+
timeoutMs: 90_000,
|
|
100
|
+
onOutput: (level, body) => console.log(`[${level}] ${body}`),
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
console.log(result.success); // boolean
|
|
104
|
+
console.log(result.logs); // all captured output, newline-separated
|
|
105
|
+
|
|
106
|
+
// Can call executeAsync() again without relaunching Studio
|
|
107
|
+
await bridge.stopAsync();
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `StudioBridgeServerOptions`
|
|
111
|
+
|
|
112
|
+
| Field | Type | Default | Description |
|
|
113
|
+
|-------|------|---------|-------------|
|
|
114
|
+
| `placePath` | `string` | — | Path to `.rbxl` file (auto-builds via rojo if omitted) |
|
|
115
|
+
| `timeoutMs` | `number` | `120_000` | Default timeout for operations |
|
|
116
|
+
| `onPhase` | `(phase) => void` | — | Progress callback: `building`, `launching`, `connecting`, `executing`, `done` |
|
|
117
|
+
| `sessionId` | `string` | auto UUID | Session ID for concurrent isolation |
|
|
118
|
+
|
|
119
|
+
### `ExecuteOptions`
|
|
120
|
+
|
|
121
|
+
| Field | Type | Default | Description |
|
|
122
|
+
|-------|------|---------|-------------|
|
|
123
|
+
| `scriptContent` | `string` | required | Luau source code to execute |
|
|
124
|
+
| `timeoutMs` | `number` | inherited | Timeout for this execution |
|
|
125
|
+
| `onOutput` | `(level, body) => void` | — | Called for each log message |
|
|
126
|
+
|
|
127
|
+
### `StudioBridgeResult`
|
|
128
|
+
|
|
129
|
+
| Field | Type | Description |
|
|
130
|
+
|-------|------|-------------|
|
|
131
|
+
| `success` | `boolean` | `true` if the script ran without errors |
|
|
132
|
+
| `logs` | `string` | All captured output, newline-separated |
|
|
133
|
+
|
|
134
|
+
## WebSocket Protocol
|
|
135
|
+
|
|
136
|
+
All messages are JSON: `{ "type": string, "payload": object }`.
|
|
137
|
+
|
|
138
|
+
**Plugin to Server:**
|
|
139
|
+
|
|
140
|
+
| Type | Payload | Description |
|
|
141
|
+
|------|---------|-------------|
|
|
142
|
+
| `hello` | `{ sessionId }` | Handshake |
|
|
143
|
+
| `output` | `{ messages: [{ level, body }] }` | Batched log output |
|
|
144
|
+
| `scriptComplete` | `{ success, error? }` | Script finished |
|
|
145
|
+
|
|
146
|
+
Output levels: `"Print"`, `"Info"`, `"Warning"`, `"Error"` (matches `Enum.MessageType`).
|
|
147
|
+
|
|
148
|
+
**Server to Plugin:**
|
|
149
|
+
|
|
150
|
+
| Type | Payload | Description |
|
|
151
|
+
|------|---------|-------------|
|
|
152
|
+
| `welcome` | `{ sessionId }` | Handshake accepted |
|
|
153
|
+
| `execute` | `{ script }` | Luau script to run |
|
|
154
|
+
| `shutdown` | `{}` | Disconnect |
|
|
155
|
+
|
|
156
|
+
## Testing
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
pnpm test # Unit tests (no Studio needed)
|
|
160
|
+
pnpm test:watch # Watch mode
|
|
161
|
+
pnpm test:integration # End-to-end (requires Studio)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
| Layer | What it tests | Studio? |
|
|
165
|
+
|-------|--------------|---------|
|
|
166
|
+
| Unit (`pnpm test`) | Protocol, template substitution, path resolution, WebSocket lifecycle | No |
|
|
167
|
+
| Integration (`pnpm test:integration`) | Full pipeline: rojo build, plugin injection, Studio launch, output capture | Yes |
|
|
168
|
+
|
|
169
|
+
## Platform Support
|
|
170
|
+
|
|
171
|
+
| Platform | Studio Location | Plugins Folder |
|
|
172
|
+
|----------|----------------|----------------|
|
|
173
|
+
| Windows | `%LOCALAPPDATA%\Roblox\Versions\*\RobloxStudioBeta.exe` | `%LOCALAPPDATA%\Roblox\Plugins\` |
|
|
174
|
+
| macOS | `/Applications/RobloxStudio.app/Contents/MacOS/RobloxStudioBeta` | `~/Documents/Roblox/Plugins/` |
|
|
175
|
+
|
|
176
|
+
## Future Plans
|
|
177
|
+
|
|
178
|
+
- **StudioTestService integration** — Use `ExecuteRunModeAsync()` / `EndTest()` for better isolation vs. `loadstring()`
|
|
179
|
+
- **Structured test results** — Protocol extension for typed result messages instead of log parsing
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-args.d.ts","sourceRoot":"","sources":["../../../../src/cli/args/global-args.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-args.js","sourceRoot":"","sources":["../../../../src/cli/args/global-args.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry point for @quenty/studio-bridge.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* studio-bridge run <file.lua>
|
|
7
|
+
* studio-bridge exec 'print("hello")'
|
|
8
|
+
* studio-bridge terminal [--script <file.lua>]
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/cli/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry point for @quenty/studio-bridge.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* studio-bridge run <file.lua>
|
|
7
|
+
* studio-bridge exec 'print("hello")'
|
|
8
|
+
* studio-bridge terminal [--script <file.lua>]
|
|
9
|
+
*/
|
|
10
|
+
import yargs from 'yargs';
|
|
11
|
+
import { hideBin } from 'yargs/helpers';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
import { dirname, join } from 'path';
|
|
14
|
+
import { OutputHelper } from '@quenty/cli-output-helpers';
|
|
15
|
+
import { VersionChecker } from '@quenty/nevermore-cli-helpers';
|
|
16
|
+
import { RunCommand } from './commands/run-command.js';
|
|
17
|
+
import { ExecCommand } from './commands/exec-command.js';
|
|
18
|
+
import { TerminalCommand } from './commands/terminal/terminal-command.js';
|
|
19
|
+
const versionData = await VersionChecker.checkForUpdatesAsync({
|
|
20
|
+
humanReadableName: 'Studio Bridge',
|
|
21
|
+
packageName: '@quenty/studio-bridge',
|
|
22
|
+
registryUrl: 'https://registry.npmjs.org/',
|
|
23
|
+
packageJsonPath: join(dirname(fileURLToPath(import.meta.url)), '../../../package.json'),
|
|
24
|
+
});
|
|
25
|
+
yargs(hideBin(process.argv))
|
|
26
|
+
.scriptName('studio-bridge')
|
|
27
|
+
.version((versionData
|
|
28
|
+
? VersionChecker.getVersionDisplayName(versionData)
|
|
29
|
+
: undefined))
|
|
30
|
+
.option('place', {
|
|
31
|
+
alias: 'p',
|
|
32
|
+
description: 'Path to a .rbxl place file (builds a minimal place via rojo if omitted)',
|
|
33
|
+
type: 'string',
|
|
34
|
+
global: true,
|
|
35
|
+
})
|
|
36
|
+
.option('timeout', {
|
|
37
|
+
description: 'Timeout in milliseconds',
|
|
38
|
+
type: 'number',
|
|
39
|
+
default: 120_000,
|
|
40
|
+
global: true,
|
|
41
|
+
})
|
|
42
|
+
.option('verbose', {
|
|
43
|
+
description: 'Show internal debug output',
|
|
44
|
+
type: 'boolean',
|
|
45
|
+
default: false,
|
|
46
|
+
global: true,
|
|
47
|
+
})
|
|
48
|
+
.option('logs', {
|
|
49
|
+
description: 'Show execution logs in spinner mode',
|
|
50
|
+
type: 'boolean',
|
|
51
|
+
default: true,
|
|
52
|
+
global: true,
|
|
53
|
+
})
|
|
54
|
+
.middleware((argv) => {
|
|
55
|
+
OutputHelper.setVerbose(argv.verbose);
|
|
56
|
+
})
|
|
57
|
+
.usage(OutputHelper.formatInfo('Usage: $0 <command> [options]'))
|
|
58
|
+
.command(new ExecCommand())
|
|
59
|
+
.command(new RunCommand())
|
|
60
|
+
.command(new TerminalCommand())
|
|
61
|
+
.recommendCommands()
|
|
62
|
+
.demandCommand(1, OutputHelper.formatHint("Hint: See 'studio-bridge help' for more help"))
|
|
63
|
+
.wrap(null)
|
|
64
|
+
.strict().argv;
|
|
65
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE1E,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,oBAAoB,CAAC;IAC5D,iBAAiB,EAAE,eAAe;IAClC,WAAW,EAAE,uBAAuB;IACpC,WAAW,EAAE,6BAA6B;IAC1C,eAAe,EAAE,IAAI,CACnB,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EACvC,uBAAuB,CACxB;CACF,CAAC,CAAC;AAEH,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;KACzB,UAAU,CAAC,eAAe,CAAC;KAC3B,OAAO,CACN,CAAC,WAAW;IACV,CAAC,CAAC,cAAc,CAAC,qBAAqB,CAAC,WAAW,CAAC;IACnD,CAAC,CAAC,SAAS,CAAQ,CACtB;KACA,MAAM,CAAC,OAAO,EAAE;IACf,KAAK,EAAE,GAAG;IACV,WAAW,EACT,yEAAyE;IAC3E,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,IAAI;CACb,CAAC;KACD,MAAM,CAAC,SAAS,EAAE;IACjB,WAAW,EAAE,yBAAyB;IACtC,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,IAAI;CACb,CAAC;KACD,MAAM,CAAC,SAAS,EAAE;IACjB,WAAW,EAAE,4BAA4B;IACzC,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,IAAI;CACb,CAAC;KACD,MAAM,CAAC,MAAM,EAAE;IACd,WAAW,EAAE,qCAAqC;IAClD,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,IAAI;IACb,MAAM,EAAE,IAAI;CACb,CAAC;KACD,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE;IACnB,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,OAAkB,CAAC,CAAC;AACnD,CAAC,CAAC;KACD,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,+BAA+B,CAAC,CAAC;KAC/D,OAAO,CAAC,IAAI,WAAW,EAAS,CAAC;KACjC,OAAO,CAAC,IAAI,UAAU,EAAS,CAAC;KAChC,OAAO,CAAC,IAAI,eAAe,EAAS,CAAC;KACrC,iBAAiB,EAAE;KACnB,aAAa,CACZ,CAAC,EACD,YAAY,CAAC,UAAU,CAAC,8CAA8C,CAAC,CACxE;KACA,IAAI,CAAC,IAAI,CAAC;KACV,MAAM,EAAE,CAAC,IAAI,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `studio-bridge exec <code>` — execute inline Luau code in Roblox Studio.
|
|
3
|
+
*/
|
|
4
|
+
import { Argv, CommandModule } from 'yargs';
|
|
5
|
+
import type { StudioBridgeGlobalArgs } from '../args/global-args.js';
|
|
6
|
+
export interface ExecArgs extends StudioBridgeGlobalArgs {
|
|
7
|
+
code: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class ExecCommand<T> implements CommandModule<T, ExecArgs> {
|
|
10
|
+
command: string;
|
|
11
|
+
describe: string;
|
|
12
|
+
builder: (args: Argv<T>) => Argv<ExecArgs>;
|
|
13
|
+
handler: (args: ExecArgs) => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=exec-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/exec-command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAMrE,MAAM,WAAW,QAAS,SAAQ,sBAAsB;IACtD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,WAAW,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC;IACxD,OAAO,SAAiB;IACxB,QAAQ,SAA+C;IAEvD,OAAO,GAAI,MAAM,IAAI,CAAC,CAAC,CAAC,KAOd,IAAI,CAAC,QAAQ,CAAC,CAC7B;IAEK,OAAO,GAAU,MAAM,QAAQ,mBAgBpC;CACH"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `studio-bridge exec <code>` — execute inline Luau code in Roblox Studio.
|
|
3
|
+
*/
|
|
4
|
+
import { OutputHelper } from '@quenty/cli-output-helpers';
|
|
5
|
+
import { executeScriptAsync, resolvePlacePathAsync, } from '../script-executor.js';
|
|
6
|
+
export class ExecCommand {
|
|
7
|
+
command = 'exec <code>';
|
|
8
|
+
describe = 'Execute inline Luau code in Roblox Studio';
|
|
9
|
+
builder = (args) => {
|
|
10
|
+
args.positional('code', {
|
|
11
|
+
describe: 'Luau code to execute',
|
|
12
|
+
type: 'string',
|
|
13
|
+
demandOption: true,
|
|
14
|
+
});
|
|
15
|
+
return args;
|
|
16
|
+
};
|
|
17
|
+
handler = async (args) => {
|
|
18
|
+
try {
|
|
19
|
+
const placePath = await resolvePlacePathAsync(args.place);
|
|
20
|
+
await executeScriptAsync({
|
|
21
|
+
scriptContent: args.code,
|
|
22
|
+
packageName: 'script',
|
|
23
|
+
placePath,
|
|
24
|
+
timeoutMs: args.timeout,
|
|
25
|
+
verbose: args.verbose,
|
|
26
|
+
showLogs: args.logs,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
OutputHelper.error(err instanceof Error ? err.message : String(err));
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=exec-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-command.js","sourceRoot":"","sources":["../../../../src/cli/commands/exec-command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EACL,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAM/B,MAAM,OAAO,WAAW;IACf,OAAO,GAAG,aAAa,CAAC;IACxB,QAAQ,GAAG,2CAA2C,CAAC;IAEvD,OAAO,GAAG,CAAC,IAAa,EAAE,EAAE;QACjC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;YACtB,QAAQ,EAAE,sBAAsB;YAChC,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QAEH,OAAO,IAAsB,CAAC;IAChC,CAAC,CAAC;IAEK,OAAO,GAAG,KAAK,EAAE,IAAc,EAAE,EAAE;QACxC,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAE1D,MAAM,kBAAkB,CAAC;gBACvB,aAAa,EAAE,IAAI,CAAC,IAAI;gBACxB,WAAW,EAAE,QAAQ;gBACrB,SAAS;gBACT,SAAS,EAAE,IAAI,CAAC,OAAO;gBACvB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,QAAQ,EAAE,IAAI,CAAC,IAAI;aACpB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,YAAY,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;CACH"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `studio-bridge run <file>` — execute a Luau script file in Roblox Studio.
|
|
3
|
+
*/
|
|
4
|
+
import { Argv, CommandModule } from 'yargs';
|
|
5
|
+
import type { StudioBridgeGlobalArgs } from '../args/global-args.js';
|
|
6
|
+
export interface RunArgs extends StudioBridgeGlobalArgs {
|
|
7
|
+
file: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class RunCommand<T> implements CommandModule<T, RunArgs> {
|
|
10
|
+
command: string;
|
|
11
|
+
describe: string;
|
|
12
|
+
builder: (args: Argv<T>) => Argv<RunArgs>;
|
|
13
|
+
handler: (args: RunArgs) => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=run-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/run-command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAMrE,MAAM,WAAW,OAAQ,SAAQ,sBAAsB;IACrD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,UAAU,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC;IACtD,OAAO,SAAgB;IACvB,QAAQ,SAAiD;IAEzD,OAAO,GAAI,MAAM,IAAI,CAAC,CAAC,CAAC,KAOd,IAAI,CAAC,OAAO,CAAC,CAC5B;IAEK,OAAO,GAAU,MAAM,OAAO,mBA6BnC;CACH"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `studio-bridge run <file>` — execute a Luau script file in Roblox Studio.
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs/promises';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { OutputHelper } from '@quenty/cli-output-helpers';
|
|
7
|
+
import { executeScriptAsync, resolvePlacePathAsync, } from '../script-executor.js';
|
|
8
|
+
export class RunCommand {
|
|
9
|
+
command = 'run <file>';
|
|
10
|
+
describe = 'Execute a Luau script file in Roblox Studio';
|
|
11
|
+
builder = (args) => {
|
|
12
|
+
args.positional('file', {
|
|
13
|
+
describe: 'Path to a Luau script file',
|
|
14
|
+
type: 'string',
|
|
15
|
+
demandOption: true,
|
|
16
|
+
});
|
|
17
|
+
return args;
|
|
18
|
+
};
|
|
19
|
+
handler = async (args) => {
|
|
20
|
+
try {
|
|
21
|
+
const scriptPath = path.resolve(args.file);
|
|
22
|
+
let scriptContent;
|
|
23
|
+
try {
|
|
24
|
+
scriptContent = await fs.readFile(scriptPath, 'utf-8');
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
OutputHelper.error(`Could not read script file: ${scriptPath}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
const placePath = await resolvePlacePathAsync(args.place);
|
|
31
|
+
const packageName = path.basename(args.file, path.extname(args.file));
|
|
32
|
+
await executeScriptAsync({
|
|
33
|
+
scriptContent,
|
|
34
|
+
packageName,
|
|
35
|
+
placePath,
|
|
36
|
+
timeoutMs: args.timeout,
|
|
37
|
+
verbose: args.verbose,
|
|
38
|
+
showLogs: args.logs,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
OutputHelper.error(err instanceof Error ? err.message : String(err));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=run-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-command.js","sourceRoot":"","sources":["../../../../src/cli/commands/run-command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EACL,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAM/B,MAAM,OAAO,UAAU;IACd,OAAO,GAAG,YAAY,CAAC;IACvB,QAAQ,GAAG,6CAA6C,CAAC;IAEzD,OAAO,GAAG,CAAC,IAAa,EAAE,EAAE;QACjC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;YACtB,QAAQ,EAAE,4BAA4B;YACtC,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QAEH,OAAO,IAAqB,CAAC;IAC/B,CAAC,CAAC;IAEK,OAAO,GAAG,KAAK,EAAE,IAAa,EAAE,EAAE;QACvC,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,aAAqB,CAAC;YAC1B,IAAI,CAAC;gBACH,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACzD,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY,CAAC,KAAK,CAAC,+BAA+B,UAAU,EAAE,CAAC,CAAC;gBAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAC/B,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CACxB,CAAC;YAEF,MAAM,kBAAkB,CAAC;gBACvB,aAAa;gBACb,WAAW;gBACX,SAAS;gBACT,SAAS,EAAE,IAAI,CAAC,OAAO;gBACvB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,QAAQ,EAAE,IAAI,CAAC,IAAI;aACpB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,YAAY,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;CACH"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `studio-bridge terminal` — interactive REPL mode for executing Luau
|
|
3
|
+
* scripts repeatedly in a persistent Studio session.
|
|
4
|
+
*/
|
|
5
|
+
import { Argv, CommandModule } from 'yargs';
|
|
6
|
+
import type { StudioBridgeGlobalArgs } from '../../args/global-args.js';
|
|
7
|
+
export interface TerminalArgs extends StudioBridgeGlobalArgs {
|
|
8
|
+
script?: string;
|
|
9
|
+
'script-text'?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class TerminalCommand<T> implements CommandModule<T, TerminalArgs> {
|
|
12
|
+
command: string;
|
|
13
|
+
describe: string;
|
|
14
|
+
builder: (args: Argv<T>) => Argv<TerminalArgs>;
|
|
15
|
+
handler: (args: TerminalArgs) => Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=terminal-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-command.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/terminal/terminal-command.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAGxE,MAAM,WAAW,YAAa,SAAQ,sBAAsB;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,eAAe,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,EAAE,YAAY,CAAC;IAChE,OAAO,SAAc;IACrB,QAAQ,SACgE;IAExE,OAAO,GAAI,MAAM,IAAI,CAAC,CAAC,CAAC,KAad,IAAI,CAAC,YAAY,CAAC,CACjC;IAEK,OAAO,GAAU,MAAM,YAAY,mBAgBxC;CACH"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `studio-bridge terminal` — interactive REPL mode for executing Luau
|
|
3
|
+
* scripts repeatedly in a persistent Studio session.
|
|
4
|
+
*/
|
|
5
|
+
import { OutputHelper } from '@quenty/cli-output-helpers';
|
|
6
|
+
import { resolvePlacePathAsync } from '../../script-executor.js';
|
|
7
|
+
export class TerminalCommand {
|
|
8
|
+
command = 'terminal';
|
|
9
|
+
describe = 'Interactive terminal mode — keep Studio alive and execute scripts via REPL';
|
|
10
|
+
builder = (args) => {
|
|
11
|
+
args.option('script', {
|
|
12
|
+
alias: 's',
|
|
13
|
+
describe: 'Path to a Luau script to run on connect',
|
|
14
|
+
type: 'string',
|
|
15
|
+
});
|
|
16
|
+
args.option('script-text', {
|
|
17
|
+
alias: 't',
|
|
18
|
+
describe: 'Inline Luau code to run on connect',
|
|
19
|
+
type: 'string',
|
|
20
|
+
});
|
|
21
|
+
return args;
|
|
22
|
+
};
|
|
23
|
+
handler = async (args) => {
|
|
24
|
+
try {
|
|
25
|
+
const placePath = await resolvePlacePathAsync(args.place);
|
|
26
|
+
const { runTerminalMode } = await import('./terminal-mode.js');
|
|
27
|
+
await runTerminalMode({
|
|
28
|
+
placePath,
|
|
29
|
+
scriptPath: args.script,
|
|
30
|
+
scriptText: args['script-text'],
|
|
31
|
+
timeoutMs: args.timeout,
|
|
32
|
+
verbose: args.verbose,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
OutputHelper.error(err instanceof Error ? err.message : String(err));
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=terminal-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-command.js","sourceRoot":"","sources":["../../../../../src/cli/commands/terminal/terminal-command.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAOjE,MAAM,OAAO,eAAe;IACnB,OAAO,GAAG,UAAU,CAAC;IACrB,QAAQ,GACb,4EAA4E,CAAC;IAExE,OAAO,GAAG,CAAC,IAAa,EAAE,EAAE;QACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;YACpB,KAAK,EAAE,GAAG;YACV,QAAQ,EAAE,yCAAyC;YACnD,IAAI,EAAE,QAAQ;SACf,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE;YACzB,KAAK,EAAE,GAAG;YACV,QAAQ,EAAE,oCAAoC;YAC9C,IAAI,EAAE,QAAQ;SACf,CAAC,CAAC;QAEH,OAAO,IAA0B,CAAC;IACpC,CAAC,CAAC;IAEK,OAAO,GAAG,KAAK,EAAE,IAAkB,EAAE,EAAE;QAC5C,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAE1D,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC/D,MAAM,eAAe,CAAC;gBACpB,SAAS;gBACT,UAAU,EAAE,IAAI,CAAC,MAAM;gBACvB,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC;gBAC/B,SAAS,EAAE,IAAI,CAAC,OAAO;gBACvB,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,YAAY,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;CACH"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw-mode multi-line terminal editor with ANSI rendering.
|
|
3
|
+
*
|
|
4
|
+
* Provides a Claude Code-inspired input UI with:
|
|
5
|
+
* - Multi-line editing (Enter = newline, Ctrl+Enter = submit)
|
|
6
|
+
* - Cursor movement (arrows, Home/End)
|
|
7
|
+
* - Dot-commands (.help, .exit, .run <file>, .clear)
|
|
8
|
+
* - Status bar with keybinding hints
|
|
9
|
+
*/
|
|
10
|
+
import { EventEmitter } from 'events';
|
|
11
|
+
export interface TerminalEditorEvents {
|
|
12
|
+
submit: [buffer: string];
|
|
13
|
+
exit: [];
|
|
14
|
+
}
|
|
15
|
+
export declare class TerminalEditor extends EventEmitter {
|
|
16
|
+
private _lines;
|
|
17
|
+
private _cursorRow;
|
|
18
|
+
private _cursorCol;
|
|
19
|
+
private _renderedLineCount;
|
|
20
|
+
/** Terminal row (0-indexed from top of rendered block) where the cursor sits */
|
|
21
|
+
private _cursorTerminalRow;
|
|
22
|
+
private _active;
|
|
23
|
+
private _onKeypress;
|
|
24
|
+
private _onResize;
|
|
25
|
+
constructor();
|
|
26
|
+
start(): void;
|
|
27
|
+
stop(): void;
|
|
28
|
+
private _handleInput;
|
|
29
|
+
private _bufferText;
|
|
30
|
+
private _insertText;
|
|
31
|
+
private _insertNewline;
|
|
32
|
+
private _deleteBackward;
|
|
33
|
+
private _deleteForward;
|
|
34
|
+
private _moveCursorHorizontal;
|
|
35
|
+
private _moveCursorVertical;
|
|
36
|
+
private _submit;
|
|
37
|
+
private _handleDotCommand;
|
|
38
|
+
private _runFile;
|
|
39
|
+
private _clearEditor;
|
|
40
|
+
private _eraseRendered;
|
|
41
|
+
_render(): void;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=terminal-editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-editor.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/terminal/terminal-editor.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAQtC,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzB,IAAI,EAAE,EAAE,CAAC;CACV;AA0BD,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,kBAAkB,CAAK;IAC/B,gFAAgF;IAChF,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAuC;IAC1D,OAAO,CAAC,SAAS,CAA2B;;IAU5C,KAAK,IAAI,IAAI;IAkBb,IAAI,IAAI,IAAI;IAgCZ,OAAO,CAAC,YAAY;IA6HpB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,qBAAqB;IAmB7B,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,OAAO;IAef,OAAO,CAAC,iBAAiB;YA+DX,QAAQ;IAiBtB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,cAAc;IAqBtB,OAAO,IAAI,IAAI;CAgDhB"}
|