@tui-sandbox/library 9.1.10 → 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/browser/assets/{index-pw1tOGNt.js → index-BVkLGLTD.js} +1 -1
- package/dist/browser/index.html +1 -1
- package/dist/src/browser/neovim-client.d.ts +1 -0
- package/dist/src/browser/neovim-client.js +6 -1
- package/dist/src/browser/neovim-client.js.map +1 -1
- package/dist/src/client/terminal-terminal-client.d.ts +3 -1
- package/dist/src/client/terminal-terminal-client.js +4 -0
- package/dist/src/client/terminal-terminal-client.js.map +1 -1
- package/dist/src/server/cypress-support/contents.js +5 -0
- package/dist/src/server/cypress-support/contents.js.map +1 -1
- package/dist/src/server/neovim/index.js +2 -29
- package/dist/src/server/neovim/index.js.map +1 -1
- package/dist/src/server/server.d.ts +15 -0
- package/dist/src/server/server.js +3 -0
- package/dist/src/server/server.js.map +1 -1
- package/dist/src/server/terminal/index.d.ts +3 -0
- package/dist/src/server/terminal/index.js +11 -0
- package/dist/src/server/terminal/index.js.map +1 -1
- package/dist/src/server/terminal/runBlockingShellCommand.d.ts +4 -0
- package/dist/src/server/terminal/runBlockingShellCommand.js +34 -0
- package/dist/src/server/terminal/runBlockingShellCommand.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/browser/neovim-client.ts +7 -1
- package/src/client/terminal-terminal-client.ts +7 -2
- package/src/server/cypress-support/contents.ts +5 -0
- package/src/server/neovim/index.ts +2 -31
- package/src/server/server.ts +4 -0
- package/src/server/terminal/index.ts +23 -0
- package/src/server/terminal/runBlockingShellCommand.ts +45 -0
package/package.json
CHANGED
|
@@ -61,6 +61,7 @@ declare global {
|
|
|
61
61
|
|
|
62
62
|
export type GenericTerminalBrowserApi = {
|
|
63
63
|
dir: TestDirectory
|
|
64
|
+
runBlockingShellCommand(input: BlockingCommandClientInput): Promise<BlockingShellCommandOutput>
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
/** Entrypoint for the test runner (cypress) */
|
|
@@ -69,5 +70,10 @@ window.startTerminalApplication = async function (
|
|
|
69
70
|
): Promise<GenericTerminalBrowserApi> {
|
|
70
71
|
const terminal = terminalClient.get()
|
|
71
72
|
const testDirectory = await terminal.startTerminalApplication(args)
|
|
72
|
-
return {
|
|
73
|
+
return {
|
|
74
|
+
dir: testDirectory,
|
|
75
|
+
runBlockingShellCommand(input) {
|
|
76
|
+
return terminal.runBlockingShellCommand(input)
|
|
77
|
+
},
|
|
78
|
+
}
|
|
73
79
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createTRPCClient, httpBatchLink, splitLink, unstable_httpSubscriptionLink } from "@trpc/client"
|
|
2
2
|
import type { Terminal } from "@xterm/xterm"
|
|
3
3
|
import "@xterm/xterm/css/xterm.css"
|
|
4
|
-
import type { AppRouter } from "../server/server.js"
|
|
4
|
+
import type { AppRouter, BlockingCommandClientInput } from "../server/server.js"
|
|
5
5
|
import type { StartTerminalGenericArguments } from "../server/terminal/TerminalTestApplication.js"
|
|
6
|
-
import type { TestDirectory } from "../server/types.js"
|
|
6
|
+
import type { BlockingShellCommandOutput, TestDirectory } from "../server/types.js"
|
|
7
7
|
import "./style.css"
|
|
8
8
|
import { getTabId, startTerminal } from "./websocket-client.js"
|
|
9
9
|
|
|
@@ -83,4 +83,9 @@ export class TerminalTerminalClient {
|
|
|
83
83
|
|
|
84
84
|
return testDirectory
|
|
85
85
|
}
|
|
86
|
+
|
|
87
|
+
public async runBlockingShellCommand(input: BlockingCommandClientInput): Promise<BlockingShellCommandOutput> {
|
|
88
|
+
await this.ready
|
|
89
|
+
return this.trpc.terminal.runBlockingShellCommand.mutate({ ...input, tabId: this.tabId })
|
|
90
|
+
}
|
|
86
91
|
}
|
|
@@ -35,6 +35,10 @@ export type TerminalTestApplicationContext = {
|
|
|
35
35
|
* keystrokes as input. Requires the application to be running. */
|
|
36
36
|
typeIntoTerminal(text: string, options?: Partial<Cypress.TypeOptions>): void
|
|
37
37
|
|
|
38
|
+
/** Runs a shell command in a blocking manner, waiting for the command to
|
|
39
|
+
* finish before returning. Requires the terminal to be running. */
|
|
40
|
+
runBlockingShellCommand(input: BlockingCommandClientInput): Cypress.Chainable<BlockingShellCommandOutput>
|
|
41
|
+
|
|
38
42
|
/** The test directory, providing type-safe access to its file and directory structure */
|
|
39
43
|
dir: TestDirectory<MyTestDirectory>
|
|
40
44
|
}
|
|
@@ -168,6 +172,7 @@ afterEach(async () => {
|
|
|
168
172
|
await Promise.race([timeout, testNeovim.runExCommand({ command: "messages" })])
|
|
169
173
|
} finally {
|
|
170
174
|
clearTimeout(timeoutId) // Ensure the timeout is cleared
|
|
175
|
+
testNeovim = undefined
|
|
171
176
|
}
|
|
172
177
|
})
|
|
173
178
|
`
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import assert from "assert"
|
|
2
|
-
import { exec } from "child_process"
|
|
3
2
|
import "core-js/proposals/async-explicit-resource-management.js"
|
|
4
3
|
import { access } from "fs/promises"
|
|
5
4
|
import path from "path"
|
|
6
|
-
import util from "util"
|
|
7
5
|
import type { BlockingCommandInput, ExCommandInput, LuaCodeInput } from "../server.js"
|
|
6
|
+
import { executeBlockingShellCommand } from "../terminal/runBlockingShellCommand.js"
|
|
8
7
|
import type {
|
|
9
8
|
BlockingShellCommandOutput,
|
|
10
9
|
RunExCommandOutput,
|
|
@@ -124,36 +123,8 @@ export async function runBlockingShellCommand(
|
|
|
124
123
|
const testDirectory = neovim.state?.testDirectory
|
|
125
124
|
assert(testDirectory, `Test directory not found for client id ${input.tabId.tabId}. Maybe neovim's not started yet?`)
|
|
126
125
|
|
|
127
|
-
const execPromise = util.promisify(exec)
|
|
128
126
|
const env = neovim.getEnvironmentVariables(testDirectory, input.envOverrides)
|
|
129
|
-
|
|
130
|
-
signal: signal,
|
|
131
|
-
shell: input.shell,
|
|
132
|
-
uid: input.uid,
|
|
133
|
-
gid: input.gid,
|
|
134
|
-
cwd: input.cwd ?? env["HOME"],
|
|
135
|
-
env,
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
const result = await processPromise
|
|
140
|
-
console.log(
|
|
141
|
-
`Successfully ran shell blockingCommand (${input.command}) with stdout: ${result.stdout}, stderr: ${result.stderr}`
|
|
142
|
-
)
|
|
143
|
-
return {
|
|
144
|
-
type: "success",
|
|
145
|
-
stdout: result.stdout,
|
|
146
|
-
stderr: result.stderr,
|
|
147
|
-
} satisfies BlockingShellCommandOutput
|
|
148
|
-
} catch (e) {
|
|
149
|
-
console.warn(`Error running shell blockingCommand (${input.command})`, e)
|
|
150
|
-
if (allowFailure) {
|
|
151
|
-
return {
|
|
152
|
-
type: "failed",
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
throw new Error(`Error running shell blockingCommand (${input.command})`, { cause: e })
|
|
156
|
-
}
|
|
127
|
+
return executeBlockingShellCommand(input, signal, allowFailure, env)
|
|
157
128
|
}
|
|
158
129
|
|
|
159
130
|
export async function runLuaCode(options: LuaCodeInput): Promise<RunLuaCodeOutput> {
|
package/src/server/server.ts
CHANGED
|
@@ -72,6 +72,10 @@ export async function createAppRouter(config: DirectoriesConfig) {
|
|
|
72
72
|
sendStdin: trpc.procedure.input(z.object({ tabId: tabIdSchema, data: z.string() })).mutation(options => {
|
|
73
73
|
return terminal.sendStdin(options.input)
|
|
74
74
|
}),
|
|
75
|
+
|
|
76
|
+
runBlockingShellCommand: trpc.procedure.input(blockingCommandInputSchema).mutation(async options => {
|
|
77
|
+
return terminal.runBlockingShellCommand(options.signal, options.input, options.input.allowFailure ?? false)
|
|
78
|
+
}),
|
|
75
79
|
}),
|
|
76
80
|
|
|
77
81
|
neovim: trpc.router({
|
|
@@ -2,10 +2,13 @@ import assert from "assert"
|
|
|
2
2
|
import "core-js/proposals/async-explicit-resource-management.js"
|
|
3
3
|
import type { TerminalDimensions } from "../neovim/NeovimApplication.js"
|
|
4
4
|
import { prepareNewTestDirectory } from "../neovim/prepareNewTestDirectory.js"
|
|
5
|
+
import type { BlockingCommandInput } from "../server.js"
|
|
6
|
+
import type { BlockingShellCommandOutput } from "../types.js"
|
|
5
7
|
import type { DirectoriesConfig } from "../updateTestdirectorySchemaFile.js"
|
|
6
8
|
import { convertEventEmitterToAsyncGenerator } from "../utilities/generator.js"
|
|
7
9
|
import { Lazy } from "../utilities/Lazy.js"
|
|
8
10
|
import type { TabId } from "../utilities/tabId.js"
|
|
11
|
+
import { executeBlockingShellCommand } from "./runBlockingShellCommand.js"
|
|
9
12
|
import TerminalTestApplication from "./TerminalTestApplication.js"
|
|
10
13
|
|
|
11
14
|
const terminals = new Map<TabId["tabId"], TerminalTestApplication>()
|
|
@@ -60,3 +63,23 @@ export async function sendStdin(options: { tabId: TabId; data: string }): Promis
|
|
|
60
63
|
|
|
61
64
|
await app.application.write(options.data)
|
|
62
65
|
}
|
|
66
|
+
|
|
67
|
+
export async function runBlockingShellCommand(
|
|
68
|
+
signal: AbortSignal | undefined,
|
|
69
|
+
input: BlockingCommandInput,
|
|
70
|
+
allowFailure: boolean
|
|
71
|
+
): Promise<BlockingShellCommandOutput> {
|
|
72
|
+
const tabId = input.tabId.tabId
|
|
73
|
+
const app = terminals.get(tabId)
|
|
74
|
+
assert(app !== undefined, `Terminal instance for clientId not found - cannot send stdin. Maybe it's not started yet?`)
|
|
75
|
+
assert(
|
|
76
|
+
app.application,
|
|
77
|
+
`Terminal application not found for client id ${input.tabId.tabId}. Maybe it's not started yet?`
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
const testDirectory = app.state?.testDirectory
|
|
81
|
+
assert(testDirectory, `Test directory not found for client id ${input.tabId.tabId}. Maybe neovim's not started yet?`)
|
|
82
|
+
|
|
83
|
+
const env = app.getEnvironmentVariables(testDirectory, input.envOverrides)
|
|
84
|
+
return executeBlockingShellCommand(input, signal, allowFailure, env)
|
|
85
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { exec } from "child_process"
|
|
2
|
+
import "core-js/proposals/async-explicit-resource-management.js"
|
|
3
|
+
import util from "util"
|
|
4
|
+
import type { BlockingCommandInput } from "../server.js"
|
|
5
|
+
import type { BlockingShellCommandOutput } from "../types.js"
|
|
6
|
+
|
|
7
|
+
export async function executeBlockingShellCommand(
|
|
8
|
+
input: BlockingCommandInput,
|
|
9
|
+
signal: AbortSignal | undefined,
|
|
10
|
+
allowFailure: boolean,
|
|
11
|
+
env: NodeJS.ProcessEnv
|
|
12
|
+
): Promise<BlockingShellCommandOutput> {
|
|
13
|
+
const execPromise = util.promisify(exec)
|
|
14
|
+
|
|
15
|
+
const cwd = input.cwd ?? env["HOME"]
|
|
16
|
+
|
|
17
|
+
const processPromise = execPromise(input.command, {
|
|
18
|
+
signal: signal,
|
|
19
|
+
shell: input.shell,
|
|
20
|
+
uid: input.uid,
|
|
21
|
+
gid: input.gid,
|
|
22
|
+
cwd: cwd,
|
|
23
|
+
env,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const result = await processPromise
|
|
28
|
+
console.log(
|
|
29
|
+
`Successfully ran shell blockingCommand (${input.command}) with stdout: ${result.stdout}, stderr: ${result.stderr}`
|
|
30
|
+
)
|
|
31
|
+
return {
|
|
32
|
+
type: "success",
|
|
33
|
+
stdout: result.stdout,
|
|
34
|
+
stderr: result.stderr,
|
|
35
|
+
} satisfies BlockingShellCommandOutput
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.warn(`Error running shell blockingCommand (${input.command})`, e)
|
|
38
|
+
if (allowFailure) {
|
|
39
|
+
return {
|
|
40
|
+
type: "failed",
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Error running shell blockingCommand (${input.command})`, { cause: e })
|
|
44
|
+
}
|
|
45
|
+
}
|