@tui-sandbox/library 10.6.1 → 10.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/src/server/TestServer.js +7 -5
- package/dist/src/server/TestServer.js.map +1 -1
- package/dist/src/server/applications/neovim/NeovimApplication.js +6 -2
- package/dist/src/server/applications/neovim/NeovimApplication.js.map +1 -1
- package/dist/src/server/applications/neovim/NeovimJavascriptApiClient.js +2 -2
- package/dist/src/server/applications/neovim/NeovimJavascriptApiClient.js.map +1 -1
- package/dist/src/server/applications/neovim/api.js +15 -6
- package/dist/src/server/applications/neovim/api.js.map +1 -1
- package/dist/src/server/applications/neovim/environment/createTempDir.js +3 -1
- package/dist/src/server/applications/neovim/environment/createTempDir.js.map +1 -1
- package/dist/src/server/applications/neovim/prepareNewTestDirectory.js +3 -1
- package/dist/src/server/applications/neovim/prepareNewTestDirectory.js.map +1 -1
- package/dist/src/server/applications/terminal/TerminalTestApplication.js +3 -1
- package/dist/src/server/applications/terminal/TerminalTestApplication.js.map +1 -1
- package/dist/src/server/applications/terminal/runBlockingShellCommand.js +3 -2
- package/dist/src/server/applications/terminal/runBlockingShellCommand.js.map +1 -1
- package/dist/src/server/cypress-support/createCypressSupportFile.js +5 -3
- package/dist/src/server/cypress-support/createCypressSupportFile.js.map +1 -1
- package/dist/src/server/dirtree/index.js +3 -1
- package/dist/src/server/dirtree/index.js.map +1 -1
- package/dist/src/server/updateTestdirectorySchemaFile.js +3 -1
- package/dist/src/server/updateTestdirectorySchemaFile.js.map +1 -1
- package/dist/src/server/utilities/DisposableSingleApplication.js +3 -1
- package/dist/src/server/utilities/DisposableSingleApplication.js.map +1 -1
- package/dist/src/server/utilities/TerminalApplication.js +6 -4
- package/dist/src/server/utilities/TerminalApplication.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/src/server/TestServer.ts +7 -5
- package/src/server/applications/neovim/NeovimApplication.ts +7 -2
- package/src/server/applications/neovim/NeovimJavascriptApiClient.ts +4 -2
- package/src/server/applications/neovim/api.ts +16 -6
- package/src/server/applications/neovim/environment/createTempDir.ts +4 -1
- package/src/server/applications/neovim/prepareNewTestDirectory.ts +4 -1
- package/src/server/applications/terminal/TerminalTestApplication.ts +4 -1
- package/src/server/applications/terminal/runBlockingShellCommand.ts +4 -2
- package/src/server/cypress-support/createCypressSupportFile.ts +6 -3
- package/src/server/dirtree/index.ts +3 -1
- package/src/server/updateTestdirectorySchemaFile.ts +4 -1
- package/src/server/utilities/DisposableSingleApplication.ts +4 -1
- package/src/server/utilities/TerminalApplication.ts +7 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tui-sandbox/library",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.7.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/mikavilpas/tui-sandbox"
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@catppuccin/palette": "1.7.1",
|
|
15
|
-
"@trpc/client": "11.4.
|
|
16
|
-
"@trpc/server": "11.4.
|
|
15
|
+
"@trpc/client": "11.4.3",
|
|
16
|
+
"@trpc/server": "11.4.3",
|
|
17
17
|
"@xterm/addon-attach": "0.11.0",
|
|
18
18
|
"@xterm/addon-fit": "0.10.0",
|
|
19
19
|
"@xterm/xterm": "5.5.0",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"express": "5.1.0",
|
|
25
25
|
"neovim": "5.3.0",
|
|
26
26
|
"node-pty": "1.0.0",
|
|
27
|
-
"prettier": "3.6.
|
|
27
|
+
"prettier": "3.6.2",
|
|
28
28
|
"tsx": "4.20.3",
|
|
29
29
|
"type-fest": "4.41.0",
|
|
30
30
|
"winston": "3.17.0"
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@types/command-exists": "1.2.3",
|
|
34
34
|
"@types/cors": "2.8.19",
|
|
35
35
|
"@types/express": "5.0.3",
|
|
36
|
-
"@types/node": "24.0.
|
|
36
|
+
"@types/node": "24.0.6",
|
|
37
37
|
"nodemon": "3.1.10",
|
|
38
38
|
"vite": "7.0.0",
|
|
39
39
|
"vitest": "3.2.4",
|
package/src/server/TestServer.ts
CHANGED
|
@@ -6,6 +6,7 @@ import express from "express"
|
|
|
6
6
|
import { accessSync } from "fs"
|
|
7
7
|
import path from "path"
|
|
8
8
|
import { fileURLToPath } from "url"
|
|
9
|
+
import { debuglog } from "util"
|
|
9
10
|
|
|
10
11
|
export type TestServerSettings = {
|
|
11
12
|
port: number
|
|
@@ -13,12 +14,13 @@ export type TestServerSettings = {
|
|
|
13
14
|
|
|
14
15
|
const __filename = fileURLToPath(import.meta.url)
|
|
15
16
|
const __dirname = path.dirname(__filename)
|
|
17
|
+
const log = debuglog("tui-sandbox.TestServer")
|
|
16
18
|
|
|
17
19
|
export class TestServer {
|
|
18
20
|
public constructor(private readonly settings: TestServerSettings) {}
|
|
19
21
|
|
|
20
22
|
public async startAndRun(appRouter: AnyTRPCRouter): Promise<void> {
|
|
21
|
-
|
|
23
|
+
log("🚀 Server starting")
|
|
22
24
|
|
|
23
25
|
const app = express()
|
|
24
26
|
app.use(
|
|
@@ -39,7 +41,7 @@ export class TestServer {
|
|
|
39
41
|
} catch (e) {
|
|
40
42
|
// This is normal when developing the tui-sandbox library locally. It
|
|
41
43
|
// should always exist when using it as an npm package, however.
|
|
42
|
-
console.
|
|
44
|
+
console.warn(
|
|
43
45
|
`⚠️ Warning: Looks like the tui-sandbox root contents directory is not accessible at: ${publicPath}`
|
|
44
46
|
)
|
|
45
47
|
}
|
|
@@ -55,16 +57,16 @@ export class TestServer {
|
|
|
55
57
|
|
|
56
58
|
const server = app.listen(this.settings.port, "0.0.0.0")
|
|
57
59
|
|
|
58
|
-
console.
|
|
60
|
+
console.info(`✅ Server listening on port ${this.settings.port}`)
|
|
59
61
|
|
|
60
62
|
await Promise.race([once(process, "SIGTERM"), once(process, "SIGINT")])
|
|
61
|
-
|
|
63
|
+
log("😴 Shutting down...")
|
|
62
64
|
server.close(error => {
|
|
63
65
|
if (error) {
|
|
64
66
|
console.error("Error closing server", error)
|
|
65
67
|
process.exit(1)
|
|
66
68
|
}
|
|
67
|
-
|
|
69
|
+
log("Server closed")
|
|
68
70
|
process.exit(0)
|
|
69
71
|
})
|
|
70
72
|
}
|
|
@@ -5,12 +5,15 @@ import { access } from "fs/promises"
|
|
|
5
5
|
import type { NeovimClient as NeovimApiClient } from "neovim"
|
|
6
6
|
import { tmpdir } from "os"
|
|
7
7
|
import path, { join } from "path"
|
|
8
|
+
import { debuglog } from "util"
|
|
8
9
|
import type { TestDirectory, TestEnvironmentCommonEnvironmentVariables } from "../../types.js"
|
|
9
10
|
import { DisposableSingleApplication } from "../../utilities/DisposableSingleApplication.js"
|
|
10
11
|
import type { Lazy } from "../../utilities/Lazy.js"
|
|
11
12
|
import { TerminalApplication } from "../../utilities/TerminalApplication.js"
|
|
12
13
|
import { connectNeovimApi } from "./NeovimJavascriptApiClient.js"
|
|
13
14
|
|
|
15
|
+
const log = debuglog("tui-sandbox-neovim-application")
|
|
16
|
+
|
|
14
17
|
/*
|
|
15
18
|
|
|
16
19
|
Usage:
|
|
@@ -170,7 +173,7 @@ export class NeovimApplication implements AsyncDisposable {
|
|
|
170
173
|
client: connectNeovimApi(socketPath),
|
|
171
174
|
}
|
|
172
175
|
|
|
173
|
-
|
|
176
|
+
log(`🚀 Started Neovim instance ${processId}`)
|
|
174
177
|
}
|
|
175
178
|
|
|
176
179
|
public getEnvironmentVariables(
|
|
@@ -202,7 +205,9 @@ export class NeovimApplication implements AsyncDisposable {
|
|
|
202
205
|
|
|
203
206
|
try {
|
|
204
207
|
await access(this.state.socketPath)
|
|
205
|
-
|
|
208
|
+
// this is probably not dangerous, but I'm not sure why it sometimes
|
|
209
|
+
// happens. It's better to report it than to hide it.
|
|
210
|
+
log(`Socket file ${this.state.socketPath} should have been removed by neovim when it exited.`)
|
|
206
211
|
return
|
|
207
212
|
} catch (e) {
|
|
208
213
|
// all good
|
|
@@ -4,6 +4,8 @@ import { attach } from "neovim"
|
|
|
4
4
|
import { createLogger, format, transports } from "winston"
|
|
5
5
|
import { Lazy } from "../../utilities/Lazy.js"
|
|
6
6
|
|
|
7
|
+
// const log = debuglog("tui-sandbox.neovim.NeovimJavascriptApiClient")
|
|
8
|
+
|
|
7
9
|
export type NeovimJavascriptApiClient = NeovimApiClient
|
|
8
10
|
|
|
9
11
|
export type PollingInterval = 100
|
|
@@ -28,10 +30,10 @@ export function connectNeovimApi(socketPath: string): Lazy<Promise<NeovimJavascr
|
|
|
28
30
|
for (let i = 0; i < 100; i++) {
|
|
29
31
|
try {
|
|
30
32
|
await access(socketPath)
|
|
31
|
-
//
|
|
33
|
+
// log(`socket file ${socketPath} created after at attempt ${i + 1}`)
|
|
32
34
|
break
|
|
33
35
|
} catch (e) {
|
|
34
|
-
//
|
|
36
|
+
// log(`polling for socket file ${socketPath} to be created (attempt ${i + 1})`)
|
|
35
37
|
await new Promise(resolve => setTimeout(resolve, 100 satisfies PollingInterval))
|
|
36
38
|
}
|
|
37
39
|
}
|
|
@@ -2,6 +2,7 @@ import assert from "assert"
|
|
|
2
2
|
import "core-js/proposals/async-explicit-resource-management.js"
|
|
3
3
|
import { access } from "fs/promises"
|
|
4
4
|
import path from "path"
|
|
5
|
+
import { debuglog } from "util"
|
|
5
6
|
import type { BlockingCommandInput } from "../../blockingCommandInputSchema.js"
|
|
6
7
|
import type {
|
|
7
8
|
BlockingShellCommandOutput,
|
|
@@ -26,6 +27,8 @@ const resources: Lazy<AsyncDisposableStack> = new Lazy(() => {
|
|
|
26
27
|
return new AsyncDisposableStack()
|
|
27
28
|
})
|
|
28
29
|
|
|
30
|
+
const log = debuglog("tui-sandbox.neovim.api")
|
|
31
|
+
|
|
29
32
|
export async function installDependencies(testEnvironmentPath: string, config: DirectoriesConfig): Promise<void> {
|
|
30
33
|
await using app = new NeovimApplication(testEnvironmentPath)
|
|
31
34
|
const testDirectory = await prepareNewTestDirectory(config)
|
|
@@ -33,12 +36,17 @@ export async function installDependencies(testEnvironmentPath: string, config: D
|
|
|
33
36
|
try {
|
|
34
37
|
await access(prepareFilePath)
|
|
35
38
|
} catch (e) {
|
|
39
|
+
// show the output here because it's typically shown in the console before
|
|
40
|
+
// the tests start. It's also sensitive to outside changes.
|
|
41
|
+
//
|
|
42
|
+
// eslint-disable-next-line no-restricted-properties
|
|
36
43
|
console.log(
|
|
37
44
|
`Neovim prepareFilePath does not exist: ${prepareFilePath}. If you want to run a prepare script before starting the tests, create it.`
|
|
38
45
|
)
|
|
39
46
|
return
|
|
40
47
|
}
|
|
41
48
|
|
|
49
|
+
// eslint-disable-next-line no-restricted-properties
|
|
42
50
|
console.log(`🚀 Running Neovim prepareFilePath ${prepareFilePath}...`)
|
|
43
51
|
|
|
44
52
|
let output = ""
|
|
@@ -53,7 +61,9 @@ export async function installDependencies(testEnvironmentPath: string, config: D
|
|
|
53
61
|
{ cols: 80, rows: 24 }
|
|
54
62
|
)
|
|
55
63
|
await app.application.untilExit()
|
|
64
|
+
// eslint-disable-next-line no-restricted-properties
|
|
56
65
|
console.log(`🚀 Neovim installDependencies output:`)
|
|
66
|
+
// eslint-disable-next-line no-restricted-properties
|
|
57
67
|
console.log(output)
|
|
58
68
|
}
|
|
59
69
|
|
|
@@ -145,7 +155,7 @@ export async function runLuaCode(options: LuaCodeInput): Promise<RunLuaCodeOutpu
|
|
|
145
155
|
throw new Error(`Neovim API not available for client id ${options.tabId.tabId}. Maybe it's not started yet?`)
|
|
146
156
|
}
|
|
147
157
|
|
|
148
|
-
|
|
158
|
+
log(`Neovim ${neovim.application.processId()} running Lua code: ${options.luaCode}`)
|
|
149
159
|
try {
|
|
150
160
|
const value = await api.lua(options.luaCode)
|
|
151
161
|
return { value }
|
|
@@ -179,11 +189,11 @@ export async function waitForLuaCode(
|
|
|
179
189
|
throw new Error(`Neovim API not available for client id ${options.tabId.tabId}. Maybe it's not started yet?`)
|
|
180
190
|
}
|
|
181
191
|
|
|
182
|
-
|
|
192
|
+
log(`Neovim ${neovim.application.processId()} polling Lua code: ${options.luaAssertion}`)
|
|
183
193
|
|
|
184
194
|
let running: boolean = true
|
|
185
195
|
signal?.addEventListener("abort", () => {
|
|
186
|
-
|
|
196
|
+
log(`Polling Lua code: '${options.luaAssertion}' was aborted via signal`)
|
|
187
197
|
running = false
|
|
188
198
|
})
|
|
189
199
|
|
|
@@ -205,7 +215,7 @@ export async function waitForLuaCode(
|
|
|
205
215
|
|
|
206
216
|
try {
|
|
207
217
|
const value = await api.lua(options.luaAssertion)
|
|
208
|
-
|
|
218
|
+
log(`Lua code assertion passed: ${options.luaAssertion} (iteration ${iteration})`)
|
|
209
219
|
|
|
210
220
|
return { value }
|
|
211
221
|
} catch (e) {
|
|
@@ -236,11 +246,11 @@ export async function runExCommand(options: ExCommandInput): Promise<RunExComman
|
|
|
236
246
|
throw new Error(`Neovim API not available for client id ${options.tabId.tabId}. Maybe it's not started yet?`)
|
|
237
247
|
}
|
|
238
248
|
|
|
239
|
-
|
|
249
|
+
log(`Neovim ${neovim.application.processId()} running Ex command: ${options.command}`)
|
|
240
250
|
try {
|
|
241
251
|
const output = await api.commandOutput(options.command)
|
|
242
252
|
if (options.log) {
|
|
243
|
-
console.
|
|
253
|
+
console.info(`:${options.command} output: ${output}`)
|
|
244
254
|
}
|
|
245
255
|
return { value: output }
|
|
246
256
|
} catch (e) {
|
|
@@ -4,11 +4,14 @@ import { Type } from "dree"
|
|
|
4
4
|
import { constants, readdirSync, statSync } from "fs"
|
|
5
5
|
import { access, mkdir, mkdtemp } from "fs/promises"
|
|
6
6
|
import path from "path"
|
|
7
|
+
import { debuglog } from "util"
|
|
7
8
|
import { convertDree, getDirectoryTree } from "../../../dirtree/index.js"
|
|
8
9
|
import type { TestDirectory } from "../../../types.js"
|
|
9
10
|
import type { DirectoriesConfig } from "../../../updateTestdirectorySchemaFile.js"
|
|
10
11
|
import { updateTestdirectorySchemaFile } from "../../../updateTestdirectorySchemaFile.js"
|
|
11
12
|
|
|
13
|
+
const log = debuglog("tui-sandbox.createTempDir")
|
|
14
|
+
|
|
12
15
|
export async function createTempDir(config: DirectoriesConfig): Promise<TestDirectory> {
|
|
13
16
|
try {
|
|
14
17
|
// before calling this function, the testEnvironmentPath should already exist
|
|
@@ -21,7 +24,7 @@ export async function createTempDir(config: DirectoriesConfig): Promise<TestDire
|
|
|
21
24
|
|
|
22
25
|
execSync(`cp -R '${path.join(config.testEnvironmentPath, entry)}' ${dir}/`)
|
|
23
26
|
})
|
|
24
|
-
|
|
27
|
+
log(`Created test directory at ${dir}`)
|
|
25
28
|
|
|
26
29
|
const tree = convertDree(getDirectoryTree(dir).dree)
|
|
27
30
|
assert(tree.type === Type.DIRECTORY)
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { access, mkdir } from "fs/promises"
|
|
2
|
+
import { debuglog } from "util"
|
|
2
3
|
import type { TestDirectory } from "../../types.js"
|
|
3
4
|
import type { DirectoriesConfig } from "../../updateTestdirectorySchemaFile.js"
|
|
4
5
|
import { createTempDir, removeTestDirectories } from "./environment/createTempDir.js"
|
|
5
6
|
|
|
7
|
+
const log = debuglog("tui-sandbox.neovim.prepareNewTestDirectory")
|
|
8
|
+
|
|
6
9
|
export async function prepareNewTestDirectory(config: DirectoriesConfig): Promise<TestDirectory> {
|
|
7
10
|
try {
|
|
8
11
|
// if the directory does not exist, create it
|
|
9
12
|
await access(config.testEnvironmentPath)
|
|
10
13
|
} catch {
|
|
11
|
-
|
|
14
|
+
log(`Creating testEnvironmentPath directory at ${config.testEnvironmentPath}`)
|
|
12
15
|
await mkdir(config.testEnvironmentPath, { recursive: true })
|
|
13
16
|
}
|
|
14
17
|
|
|
@@ -2,11 +2,14 @@ import assert from "assert"
|
|
|
2
2
|
import { exec } from "child_process"
|
|
3
3
|
import EventEmitter from "events"
|
|
4
4
|
import { join } from "path"
|
|
5
|
+
import { debuglog } from "util"
|
|
5
6
|
import type { TestDirectory, TestEnvironmentCommonEnvironmentVariables } from "../../types.js"
|
|
6
7
|
import { DisposableSingleApplication } from "../../utilities/DisposableSingleApplication.js"
|
|
7
8
|
import { TerminalApplication } from "../../utilities/TerminalApplication.js"
|
|
8
9
|
import type { StdoutOrStderrMessage, TerminalDimensions } from "../neovim/NeovimApplication.js"
|
|
9
10
|
|
|
11
|
+
const log = debuglog("tui-sandbox.terminal.TerminalTestApplication")
|
|
12
|
+
|
|
10
13
|
type ResettableState = {
|
|
11
14
|
testDirectory: TestDirectory
|
|
12
15
|
}
|
|
@@ -70,7 +73,7 @@ export default class TerminalTestApplication implements AsyncDisposable {
|
|
|
70
73
|
|
|
71
74
|
this.state = { testDirectory }
|
|
72
75
|
|
|
73
|
-
|
|
76
|
+
log(`🚀 Started Terminal instance ${processId}`)
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
public getEnvironmentVariables(
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { exec } from "child_process"
|
|
2
2
|
import "core-js/proposals/async-explicit-resource-management.js"
|
|
3
3
|
import { join } from "path"
|
|
4
|
-
import util from "util"
|
|
4
|
+
import util, { debuglog } from "util"
|
|
5
5
|
import type { BlockingCommandInput } from "../../blockingCommandInputSchema.js"
|
|
6
6
|
import type { BlockingShellCommandOutput, TestDirectory } from "../../types.js"
|
|
7
7
|
|
|
8
|
+
const log = debuglog("tui-sandbox.terminal.runBlockingShellCommand")
|
|
9
|
+
|
|
8
10
|
export async function executeBlockingShellCommand(
|
|
9
11
|
testDirectory: TestDirectory,
|
|
10
12
|
input: BlockingCommandInput,
|
|
@@ -30,7 +32,7 @@ export async function executeBlockingShellCommand(
|
|
|
30
32
|
cwd,
|
|
31
33
|
env,
|
|
32
34
|
})
|
|
33
|
-
|
|
35
|
+
log(
|
|
34
36
|
`Successfully ran shell blockingCommand (${input.command}) in cwd: '${cwd}' with stdout: ${result.stdout}, stderr: ${result.stderr}`
|
|
35
37
|
)
|
|
36
38
|
return {
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from "fs"
|
|
2
2
|
import { mkdir, stat } from "fs/promises"
|
|
3
3
|
import path from "path"
|
|
4
|
+
import { debuglog } from "util"
|
|
4
5
|
import { createCypressSupportFileContents } from "./contents.js"
|
|
5
6
|
|
|
7
|
+
const log = debuglog("tui-sandbox.dirtree")
|
|
8
|
+
|
|
6
9
|
export type CreateCypressSupportFileArgs = {
|
|
7
10
|
cypressSupportDirectoryPath: string
|
|
8
11
|
supportFileName: string
|
|
@@ -24,7 +27,7 @@ export async function createCypressSupportFile({
|
|
|
24
27
|
try {
|
|
25
28
|
await stat(configModificationsDirectoryPath)
|
|
26
29
|
} catch (error) {
|
|
27
|
-
console.
|
|
30
|
+
console.info(
|
|
28
31
|
`Creating config-modifications directory at ${configModificationsDirectoryPath}. You can put Neovim startup scripts into this directory, and load them when starting your Neovim test.`
|
|
29
32
|
)
|
|
30
33
|
await mkdir(configModificationsDirectoryPath, { recursive: true })
|
|
@@ -37,14 +40,14 @@ export async function createCypressSupportFile({
|
|
|
37
40
|
try {
|
|
38
41
|
oldSchema = readFileSync(outputFilePath, "utf-8")
|
|
39
42
|
} catch (error) {
|
|
40
|
-
console.
|
|
43
|
+
console.warn(`No existing cypress support file found at ${outputFilePath}`)
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
if (oldSchema !== text) {
|
|
44
47
|
// it's important to not write the file if the schema hasn't changed
|
|
45
48
|
// because file watchers will trigger on file changes and we don't want to
|
|
46
49
|
// trigger a build if the schema hasn't changed
|
|
47
|
-
|
|
50
|
+
log(`🪛 Writing cypress support file to ${outputFilePath}`)
|
|
48
51
|
writeFileSync(outputFilePath, text)
|
|
49
52
|
return "updated"
|
|
50
53
|
} else {
|
|
@@ -3,8 +3,10 @@ import { scan, Type } from "dree"
|
|
|
3
3
|
import { readlinkSync } from "fs"
|
|
4
4
|
import { format, resolveConfig } from "prettier"
|
|
5
5
|
import { fileURLToPath } from "url"
|
|
6
|
+
import { debuglog } from "util"
|
|
6
7
|
import { jsonToZod } from "./json-to-zod.js"
|
|
7
8
|
|
|
9
|
+
const log = debuglog("tui-sandbox.dirtree")
|
|
8
10
|
type TreeResult = { dree: Dree | undefined; allFiles: Dree[] }
|
|
9
11
|
|
|
10
12
|
/** Convert a directory tree to a TypeScript type. This is useful for testing
|
|
@@ -117,7 +119,7 @@ export async function buildSchemaForDirectoryTree(result: TreeResult, name: stri
|
|
|
117
119
|
const __filename = fileURLToPath(import.meta.url)
|
|
118
120
|
|
|
119
121
|
export async function buildTestDirectorySchema(testDirectoryPath: string): Promise<string> {
|
|
120
|
-
|
|
122
|
+
log("Building schema for test directory", testDirectoryPath)
|
|
121
123
|
const dree = getDirectoryTree(testDirectoryPath)
|
|
122
124
|
let text = await buildSchemaForDirectoryTree(dree, "MyTestDirectory")
|
|
123
125
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from "fs"
|
|
2
|
+
import { debuglog } from "util"
|
|
2
3
|
import { buildTestDirectorySchema } from "./dirtree/index.js"
|
|
3
4
|
|
|
5
|
+
const log = debuglog("tui-sandbox.updateTestdirectorySchemaFile")
|
|
6
|
+
|
|
4
7
|
export type DirectoriesConfig = {
|
|
5
8
|
testEnvironmentPath: string
|
|
6
9
|
outputFilePath: string
|
|
@@ -23,7 +26,7 @@ export async function updateTestdirectorySchemaFile({
|
|
|
23
26
|
try {
|
|
24
27
|
oldSchema = readFileSync(outputFilePath, "utf-8")
|
|
25
28
|
} catch (error) {
|
|
26
|
-
|
|
29
|
+
log("No existing schema file found, creating a new one")
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
if (oldSchema !== newSchema) {
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import assert from "assert"
|
|
2
|
+
import { debuglog } from "util"
|
|
2
3
|
import type { ExitInfo, TerminalApplication } from "./TerminalApplication.js"
|
|
3
4
|
|
|
4
5
|
export type StartableApplication = Pick<TerminalApplication, "write" | "processId" | "killAndWait" | "untilExit">
|
|
5
6
|
|
|
7
|
+
const log = debuglog("tui-sandbox.DisposableSingleApplication")
|
|
8
|
+
|
|
6
9
|
/** A testable application that can be started, killed, and given input. For a
|
|
7
10
|
* single instance of this interface, only a single instance can be running at
|
|
8
11
|
* a time.
|
|
@@ -40,7 +43,7 @@ export class DisposableSingleApplication implements AsyncDisposable {
|
|
|
40
43
|
if (this.processId() === undefined) {
|
|
41
44
|
return
|
|
42
45
|
}
|
|
43
|
-
|
|
46
|
+
log(`Killing current application ${this.processId()}...`)
|
|
44
47
|
await this.application?.killAndWait()
|
|
45
48
|
}
|
|
46
49
|
}
|
|
@@ -4,8 +4,11 @@ import { createLogger, format, transports } from "winston"
|
|
|
4
4
|
import type { ITerminalDimensions } from "@xterm/addon-fit"
|
|
5
5
|
import type { IPty } from "node-pty"
|
|
6
6
|
import pty from "node-pty"
|
|
7
|
+
import { debuglog } from "util"
|
|
7
8
|
import type { StartableApplication } from "./DisposableSingleApplication.js"
|
|
8
9
|
|
|
10
|
+
const log = debuglog("tui-sandbox.TerminalApplication")
|
|
11
|
+
|
|
9
12
|
export type ExitInfo = { exitCode: number; signal: number | undefined }
|
|
10
13
|
|
|
11
14
|
// NOTE separating stdout and stderr is not supported by node-pty
|
|
@@ -55,7 +58,7 @@ export class TerminalApplication implements StartableApplication {
|
|
|
55
58
|
env?: NodeJS.ProcessEnv
|
|
56
59
|
dimensions: ITerminalDimensions
|
|
57
60
|
}): TerminalApplication {
|
|
58
|
-
|
|
61
|
+
log(`Starting '${command}' with args '${args.join(" ")}' in cwd '${cwd}'`)
|
|
59
62
|
|
|
60
63
|
const ptyProcess = pty.spawn(command, args, {
|
|
61
64
|
name: "xterm-color",
|
|
@@ -66,7 +69,7 @@ export class TerminalApplication implements StartableApplication {
|
|
|
66
69
|
})
|
|
67
70
|
ptyProcess.onData(onStdoutOrStderr)
|
|
68
71
|
ptyProcess.onExit(({ exitCode, signal }) => {
|
|
69
|
-
|
|
72
|
+
log(`Child process exited with code ${exitCode} and signal ${signal}`)
|
|
70
73
|
})
|
|
71
74
|
|
|
72
75
|
const processId = ptyProcess.pid
|
|
@@ -90,8 +93,8 @@ export class TerminalApplication implements StartableApplication {
|
|
|
90
93
|
}
|
|
91
94
|
|
|
92
95
|
public async killAndWait(): Promise<void> {
|
|
93
|
-
|
|
96
|
+
log(`💣 Killing process ${this.processId}`)
|
|
94
97
|
this.subProcess.kill()
|
|
95
|
-
|
|
98
|
+
log(`💥 Killed process ${this.processId}`)
|
|
96
99
|
}
|
|
97
100
|
}
|