@tui-sandbox/library 11.7.1 → 11.8.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/browser/assets/{index-CQ6TDc4S.js → index-CAKI925F.js} +2 -2
- package/dist/browser/index.html +1 -1
- package/dist/src/scripts/commands/commandTuiNeovimExec.js +1 -1
- package/dist/src/scripts/commands/commandTuiNeovimExec.js.map +1 -1
- package/dist/src/scripts/commands/commandTuiNeovimPrepare.js +1 -1
- package/dist/src/scripts/commands/commandTuiNeovimPrepare.js.map +1 -1
- package/dist/src/scripts/commands/commandTuiStart.js +1 -1
- package/dist/src/scripts/commands/commandTuiStart.js.map +1 -1
- package/dist/src/scripts/resolveConfig.test.js +1 -0
- package/dist/src/scripts/resolveConfig.test.js.map +1 -1
- package/dist/src/server/applications/neovim/api.d.ts +3 -3
- package/dist/src/server/applications/neovim/api.js +2 -2
- package/dist/src/server/applications/neovim/api.js.map +1 -1
- package/dist/src/server/applications/neovim/environment/createTempDir.d.ts +2 -2
- package/dist/src/server/applications/neovim/environment/createTempDir.js +6 -6
- package/dist/src/server/applications/neovim/environment/createTempDir.js.map +1 -1
- package/dist/src/server/applications/neovim/environment/createTempDir.test.js +6 -2
- package/dist/src/server/applications/neovim/environment/createTempDir.test.js.map +1 -1
- package/dist/src/server/applications/neovim/neovimRouter.d.ts +2 -2
- package/dist/src/server/applications/neovim/neovimRouter.js +7 -4
- package/dist/src/server/applications/neovim/neovimRouter.js.map +1 -1
- package/dist/src/server/applications/neovim/prepareNewTestDirectory.d.ts +2 -2
- package/dist/src/server/applications/neovim/prepareNewTestDirectory.js +4 -4
- package/dist/src/server/applications/neovim/prepareNewTestDirectory.js.map +1 -1
- package/dist/src/server/applications/neovim/prepareNewTestDirectory.test.js +6 -2
- package/dist/src/server/applications/neovim/prepareNewTestDirectory.test.js.map +1 -1
- package/dist/src/server/applications/terminal/api.d.ts +2 -2
- package/dist/src/server/applications/terminal/api.js.map +1 -1
- package/dist/src/server/applications/terminal/terminalRouter.d.ts +2 -2
- package/dist/src/server/applications/terminal/terminalRouter.js +1 -1
- package/dist/src/server/applications/terminal/terminalRouter.js.map +1 -1
- package/dist/src/server/config.js +14 -7
- package/dist/src/server/config.js.map +1 -1
- package/dist/src/server/config.test.d.ts +1 -0
- package/dist/src/server/config.test.js +7 -0
- package/dist/src/server/config.test.js.map +1 -0
- package/dist/src/server/cypress-support/contents.js +2 -1
- package/dist/src/server/cypress-support/contents.js.map +1 -1
- package/dist/src/server/dirtree/index.d.ts +3 -2
- package/dist/src/server/dirtree/index.js +11 -5
- package/dist/src/server/dirtree/index.js.map +1 -1
- package/dist/src/server/dirtree/index.test.js +110 -4
- package/dist/src/server/dirtree/index.test.js.map +1 -1
- package/dist/src/server/server.d.ts +2 -2
- package/dist/src/server/server.js +1 -1
- package/dist/src/server/server.js.map +1 -1
- package/dist/src/server/updateTestdirectorySchemaFile.d.ts +15 -1
- package/dist/src/server/updateTestdirectorySchemaFile.js +13 -4
- package/dist/src/server/updateTestdirectorySchemaFile.js.map +1 -1
- package/dist/src/server/updateTestdirectorySchemaFile.test.js +8 -4
- package/dist/src/server/updateTestdirectorySchemaFile.test.js.map +1 -1
- package/dist/src/server/utilities/Lazy.d.ts +1 -0
- package/dist/src/server/utilities/Lazy.js +3 -0
- package/dist/src/server/utilities/Lazy.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/scripts/commands/commandTuiNeovimExec.ts +1 -1
- package/src/scripts/commands/commandTuiNeovimPrepare.ts +1 -5
- package/src/scripts/commands/commandTuiStart.ts +1 -1
- package/src/scripts/resolveConfig.test.ts +1 -0
- package/src/server/applications/neovim/api.ts +4 -8
- package/src/server/applications/neovim/environment/createTempDir.test.ts +9 -3
- package/src/server/applications/neovim/environment/createTempDir.ts +8 -8
- package/src/server/applications/neovim/neovimRouter.ts +9 -6
- package/src/server/applications/neovim/prepareNewTestDirectory.test.ts +9 -3
- package/src/server/applications/neovim/prepareNewTestDirectory.ts +6 -6
- package/src/server/applications/terminal/api.ts +2 -2
- package/src/server/applications/terminal/terminalRouter.ts +3 -3
- package/src/server/config.test.ts +7 -0
- package/src/server/config.ts +9 -3
- package/src/server/cypress-support/contents.ts +2 -1
- package/src/server/dirtree/index.test.ts +116 -4
- package/src/server/dirtree/index.ts +19 -5
- package/src/server/server.ts +3 -4
- package/src/server/updateTestdirectorySchemaFile.test.ts +12 -7
- package/src/server/updateTestdirectorySchemaFile.ts +29 -7
- package/src/server/utilities/Lazy.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tui-sandbox/library",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.8.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/mikavilpas/tui-sandbox"
|
|
@@ -12,17 +12,17 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@catppuccin/palette": "1.7.1",
|
|
15
|
-
"@trpc/client": "11.5.
|
|
16
|
-
"@trpc/server": "11.5.
|
|
15
|
+
"@trpc/client": "11.5.1",
|
|
16
|
+
"@trpc/server": "11.5.1",
|
|
17
17
|
"@xterm/addon-fit": "0.10.0",
|
|
18
18
|
"@xterm/addon-unicode11": "0.8.0",
|
|
19
19
|
"@xterm/xterm": "5.5.0",
|
|
20
20
|
"concurrently": "9.2.1",
|
|
21
21
|
"cors": "2.8.5",
|
|
22
|
-
"cypress": "15.
|
|
22
|
+
"cypress": "15.1.0",
|
|
23
23
|
"dree": "5.1.5",
|
|
24
24
|
"express": "5.1.0",
|
|
25
|
-
"neovim": "5.
|
|
25
|
+
"neovim": "5.4.0",
|
|
26
26
|
"node-pty": "1.0.0",
|
|
27
27
|
"prettier": "3.6.2",
|
|
28
28
|
"tsx": "4.20.5",
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"@types/command-exists": "1.2.3",
|
|
35
35
|
"@types/cors": "2.8.19",
|
|
36
36
|
"@types/express": "5.0.3",
|
|
37
|
-
"@types/node": "24.3.
|
|
37
|
+
"@types/node": "24.3.1",
|
|
38
38
|
"nodemon": "3.1.10",
|
|
39
|
-
"vite": "7.1.
|
|
39
|
+
"vite": "7.1.5",
|
|
40
40
|
"vitest": "3.2.4"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
@@ -9,7 +9,7 @@ export async function commandTuiNeovimExec(command: NeovimExec, config: TestServ
|
|
|
9
9
|
app.events.on("stdout" satisfies StdoutOrStderrMessage, data => {
|
|
10
10
|
console.log(` neovim output: ${data}`)
|
|
11
11
|
})
|
|
12
|
-
const testDirectory = await prepareNewTestDirectory(config
|
|
12
|
+
const testDirectory = await prepareNewTestDirectory(config)
|
|
13
13
|
await app.startNextAndKillCurrent(
|
|
14
14
|
testDirectory,
|
|
15
15
|
{
|
|
@@ -4,11 +4,7 @@ import type { TestServerConfig } from "../../server/updateTestdirectorySchemaFil
|
|
|
4
4
|
export async function commandTuiNeovimPrepare(config: TestServerConfig): Promise<void> {
|
|
5
5
|
const NVIM_APPNAME = process.env["NVIM_APPNAME"]
|
|
6
6
|
console.log(`🚀 Installing neovim dependencies${NVIM_APPNAME ? ` for NVIM_APPNAME=${NVIM_APPNAME}` : ""}...`)
|
|
7
|
-
await installDependencies(
|
|
8
|
-
config.directories.testEnvironmentPath,
|
|
9
|
-
process.env["NVIM_APPNAME"],
|
|
10
|
-
config.directories
|
|
11
|
-
).catch((err: unknown) => {
|
|
7
|
+
await installDependencies(process.env["NVIM_APPNAME"], config).catch((err: unknown) => {
|
|
12
8
|
console.error("Error installing neovim dependencies", err)
|
|
13
9
|
process.exit(1)
|
|
14
10
|
})
|
|
@@ -18,7 +18,7 @@ export async function commandTuiStart(config: TestServerConfig): Promise<void> {
|
|
|
18
18
|
|
|
19
19
|
async function updateSchemaFile(config: TestServerConfig): Promise<void> {
|
|
20
20
|
try {
|
|
21
|
-
await updateTestdirectorySchemaFile(config
|
|
21
|
+
await updateTestdirectorySchemaFile(config)
|
|
22
22
|
} catch (e) {
|
|
23
23
|
console.error("Failed to updateTestdirectorySchemaFile", e)
|
|
24
24
|
}
|
|
@@ -10,7 +10,7 @@ import type {
|
|
|
10
10
|
StartNeovimGenericArguments,
|
|
11
11
|
TestDirectory,
|
|
12
12
|
} from "../../types.js"
|
|
13
|
-
import type {
|
|
13
|
+
import type { TestServerConfig } from "../../updateTestdirectorySchemaFile.js"
|
|
14
14
|
import { convertEventEmitterToAsyncGenerator } from "../../utilities/generator.js"
|
|
15
15
|
import { Lazy } from "../../utilities/Lazy.js"
|
|
16
16
|
import type { TabId } from "../../utilities/tabId.js"
|
|
@@ -28,12 +28,8 @@ const resources: Lazy<AsyncDisposableStack> = new Lazy(() => {
|
|
|
28
28
|
|
|
29
29
|
const log = debuglog("tui-sandbox.neovim.api")
|
|
30
30
|
|
|
31
|
-
export async function installDependencies(
|
|
32
|
-
testEnvironmentPath
|
|
33
|
-
NVIM_APPNAME: string | undefined,
|
|
34
|
-
config: DirectoriesConfig
|
|
35
|
-
): Promise<void> {
|
|
36
|
-
await using app = new NeovimApplication(testEnvironmentPath)
|
|
31
|
+
export async function installDependencies(NVIM_APPNAME: string | undefined, config: TestServerConfig): Promise<void> {
|
|
32
|
+
await using app = new NeovimApplication(config.directories.testEnvironmentPath)
|
|
37
33
|
const testDirectory = await prepareNewTestDirectory(config)
|
|
38
34
|
const prepareFilePath = path.join(testDirectory.rootPathAbsolute, ".config", NVIM_APPNAME ?? "nvim", "prepare.lua")
|
|
39
35
|
try {
|
|
@@ -102,7 +98,7 @@ export async function start(
|
|
|
102
98
|
options: StartNeovimGenericArguments,
|
|
103
99
|
terminalDimensions: TerminalDimensions,
|
|
104
100
|
tabId: TabId,
|
|
105
|
-
config:
|
|
101
|
+
config: TestServerConfig
|
|
106
102
|
): Promise<TestDirectory> {
|
|
107
103
|
const neovim = neovims.get(tabId.tabId)
|
|
108
104
|
assert(neovim, `Neovim instance not found for client id ${tabId.tabId}`)
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import nodePath from "path"
|
|
2
|
+
import type { PartialDeep } from "type-fest"
|
|
2
3
|
import { expect, it, vi } from "vitest"
|
|
4
|
+
import { createDefaultConfig } from "../../../config.js"
|
|
5
|
+
import type { TestServerConfig } from "../../../updateTestdirectorySchemaFile.js"
|
|
3
6
|
import type { TestDirsPath } from "./createTempDir.js"
|
|
4
7
|
import { createTempDir } from "./createTempDir.js"
|
|
5
8
|
import type { TestTempDirPrefix } from "./TempDirectory.js"
|
|
@@ -11,9 +14,12 @@ it("should create a temp dir with no contents", async () => {
|
|
|
11
14
|
// typically the user will want to have contents, but this should not be an error
|
|
12
15
|
using dir = TempDirectory.create()
|
|
13
16
|
const result = await createTempDir({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
...createDefaultConfig("cwd", {}),
|
|
18
|
+
directories: {
|
|
19
|
+
testEnvironmentPath: dir.path,
|
|
20
|
+
outputFilePath: nodePath.join(dir.path, "MyTestDirectory.ts"),
|
|
21
|
+
},
|
|
22
|
+
} satisfies PartialDeep<TestServerConfig>)
|
|
17
23
|
|
|
18
24
|
expect(result.contents).toEqual({})
|
|
19
25
|
expect(result.testEnvironmentPath).toEqual(dir.path)
|
|
@@ -7,22 +7,22 @@ import path from "path"
|
|
|
7
7
|
import { debuglog } from "util"
|
|
8
8
|
import { convertDree, getDirectoryTree } from "../../../dirtree/index.js"
|
|
9
9
|
import type { TestDirectory } from "../../../types.js"
|
|
10
|
-
import type {
|
|
10
|
+
import type { TestServerConfig } from "../../../updateTestdirectorySchemaFile.js"
|
|
11
11
|
import { updateTestdirectorySchemaFile } from "../../../updateTestdirectorySchemaFile.js"
|
|
12
12
|
|
|
13
13
|
const log = debuglog("tui-sandbox.createTempDir")
|
|
14
14
|
|
|
15
|
-
export async function createTempDir(config:
|
|
15
|
+
export async function createTempDir(config: TestServerConfig): Promise<TestDirectory> {
|
|
16
16
|
try {
|
|
17
17
|
// before calling this function, the testEnvironmentPath should already exist
|
|
18
|
-
statSync(config.testEnvironmentPath)
|
|
19
|
-
const dir = await createUniqueDirectory(config.testEnvironmentPath)
|
|
18
|
+
statSync(config.directories.testEnvironmentPath)
|
|
19
|
+
const dir = await createUniqueDirectory(config.directories.testEnvironmentPath)
|
|
20
20
|
|
|
21
|
-
readdirSync(config.testEnvironmentPath).forEach(entry => {
|
|
21
|
+
readdirSync(config.directories.testEnvironmentPath).forEach(entry => {
|
|
22
22
|
if (entry === ("testdirs" satisfies TestDirsPath)) return
|
|
23
23
|
if (entry === ".repro") return
|
|
24
24
|
|
|
25
|
-
execSync(`cp -R '${path.join(config.testEnvironmentPath, entry)}' ${dir}/`)
|
|
25
|
+
execSync(`cp -R '${path.join(config.directories.testEnvironmentPath, entry)}' ${dir}/`)
|
|
26
26
|
})
|
|
27
27
|
log(`Created test directory at ${dir}`)
|
|
28
28
|
|
|
@@ -33,8 +33,8 @@ export async function createTempDir(config: DirectoriesConfig): Promise<TestDire
|
|
|
33
33
|
return {
|
|
34
34
|
rootPathAbsolute: dir,
|
|
35
35
|
contents: tree.contents,
|
|
36
|
-
testEnvironmentPath: config.testEnvironmentPath,
|
|
37
|
-
testEnvironmentPathRelative: path.relative(config.testEnvironmentPath, dir),
|
|
36
|
+
testEnvironmentPath: config.directories.testEnvironmentPath,
|
|
37
|
+
testEnvironmentPathRelative: path.relative(config.directories.testEnvironmentPath, dir),
|
|
38
38
|
}
|
|
39
39
|
} catch (err) {
|
|
40
40
|
console.error(err)
|
|
@@ -3,7 +3,7 @@ import * as z from "zod"
|
|
|
3
3
|
import { blockingCommandInputSchema } from "../../blockingCommandInputSchema.js"
|
|
4
4
|
import { trpc } from "../../connection/trpc.js"
|
|
5
5
|
import { serverTestDirectorySchema } from "../../types.js"
|
|
6
|
-
import type {
|
|
6
|
+
import type { NeovimIntegrationDefaultAppName, TestServerConfig } from "../../updateTestdirectorySchemaFile.js"
|
|
7
7
|
import { tabIdSchema } from "../../utilities/tabId.js"
|
|
8
8
|
import { timeoutable } from "../../utilities/timeoutable.js"
|
|
9
9
|
import * as neovim from "./api.js"
|
|
@@ -37,7 +37,7 @@ export type RunLuaFileClientInput = Except<RunLuaFileInput, "tabId">
|
|
|
37
37
|
|
|
38
38
|
// let trpc infer the type as that is what it is designed to do
|
|
39
39
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
40
|
-
export function createNeovimRouter(config:
|
|
40
|
+
export function createNeovimRouter(config: TestServerConfig) {
|
|
41
41
|
return trpc.router({
|
|
42
42
|
start: trpc.procedure
|
|
43
43
|
.input(
|
|
@@ -52,7 +52,10 @@ export function createNeovimRouter(config: DirectoriesConfig) {
|
|
|
52
52
|
]),
|
|
53
53
|
startupScriptModifications: z.array(z.string()).optional(),
|
|
54
54
|
additionalEnvironmentVariables: z.record(z.string(), z.string()).optional(),
|
|
55
|
-
NVIM_APPNAME: z
|
|
55
|
+
NVIM_APPNAME: z
|
|
56
|
+
.string()
|
|
57
|
+
.optional()
|
|
58
|
+
.default("nvim" satisfies NeovimIntegrationDefaultAppName),
|
|
56
59
|
}),
|
|
57
60
|
terminalDimensions: z.object({
|
|
58
61
|
cols: z.number(),
|
|
@@ -61,7 +64,7 @@ export function createNeovimRouter(config: DirectoriesConfig) {
|
|
|
61
64
|
})
|
|
62
65
|
)
|
|
63
66
|
.output(serverTestDirectorySchema)
|
|
64
|
-
.mutation(options => {
|
|
67
|
+
.mutation(async options => {
|
|
65
68
|
return neovim.start(
|
|
66
69
|
options.input.startNeovimArguments,
|
|
67
70
|
options.input.terminalDimensions,
|
|
@@ -70,11 +73,11 @@ export function createNeovimRouter(config: DirectoriesConfig) {
|
|
|
70
73
|
)
|
|
71
74
|
}),
|
|
72
75
|
onStdout: trpc.procedure.input(z.object({ client: tabIdSchema })).subscription(options => {
|
|
73
|
-
return neovim.initializeStdout(options.input, options.signal, config.testEnvironmentPath)
|
|
76
|
+
return neovim.initializeStdout(options.input, options.signal, config.directories.testEnvironmentPath)
|
|
74
77
|
}),
|
|
75
78
|
|
|
76
79
|
initializeStdout: trpc.procedure.input(z.object({ client: tabIdSchema })).subscription(options => {
|
|
77
|
-
return neovim.initializeStdout(options.input, options.signal, config.testEnvironmentPath)
|
|
80
|
+
return neovim.initializeStdout(options.input, options.signal, config.directories.testEnvironmentPath)
|
|
78
81
|
}),
|
|
79
82
|
sendStdin: trpc.procedure.input(z.object({ tabId: tabIdSchema, data: z.string() })).mutation(options => {
|
|
80
83
|
return neovim.sendStdin(options.input)
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { rm } from "fs/promises"
|
|
2
2
|
import path from "path"
|
|
3
|
+
import type { PartialDeep } from "type-fest"
|
|
3
4
|
import { assert, describe, expect, it } from "vitest"
|
|
5
|
+
import { createDefaultConfig } from "../../config.js"
|
|
6
|
+
import type { TestServerConfig } from "../../updateTestdirectorySchemaFile.js"
|
|
4
7
|
import { prepareNewTestDirectory } from "./prepareNewTestDirectory.js"
|
|
5
8
|
|
|
6
9
|
describe("prepareNewTestDirectory when the testEnvironmentPath does not exist", () => {
|
|
@@ -9,9 +12,12 @@ describe("prepareNewTestDirectory when the testEnvironmentPath does not exist",
|
|
|
9
12
|
// has not been created yet
|
|
10
13
|
const testEnvironmentPath = "/tmp/test"
|
|
11
14
|
const testDirectory = await prepareNewTestDirectory({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
...createDefaultConfig("cwd", {}),
|
|
16
|
+
directories: {
|
|
17
|
+
outputFilePath: path.join(testEnvironmentPath, "foo.ts"),
|
|
18
|
+
testEnvironmentPath,
|
|
19
|
+
},
|
|
20
|
+
} satisfies PartialDeep<TestServerConfig>)
|
|
15
21
|
|
|
16
22
|
try {
|
|
17
23
|
expect(testDirectory.contents).toEqual({})
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { access, mkdir } from "fs/promises"
|
|
2
2
|
import { debuglog } from "util"
|
|
3
3
|
import type { TestDirectory } from "../../types.js"
|
|
4
|
-
import type {
|
|
4
|
+
import type { TestServerConfig } from "../../updateTestdirectorySchemaFile.js"
|
|
5
5
|
import { createTempDir, removeTestDirectories } from "./environment/createTempDir.js"
|
|
6
6
|
|
|
7
7
|
const log = debuglog("tui-sandbox.neovim.prepareNewTestDirectory")
|
|
8
8
|
|
|
9
|
-
export async function prepareNewTestDirectory(config:
|
|
9
|
+
export async function prepareNewTestDirectory(config: TestServerConfig): Promise<TestDirectory> {
|
|
10
10
|
try {
|
|
11
11
|
// if the directory does not exist, create it
|
|
12
|
-
await access(config.testEnvironmentPath)
|
|
12
|
+
await access(config.directories.testEnvironmentPath)
|
|
13
13
|
} catch {
|
|
14
|
-
log(`Creating testEnvironmentPath directory at ${config.testEnvironmentPath}`)
|
|
15
|
-
await mkdir(config.testEnvironmentPath, { recursive: true })
|
|
14
|
+
log(`Creating testEnvironmentPath directory at ${config.directories.testEnvironmentPath}`)
|
|
15
|
+
await mkdir(config.directories.testEnvironmentPath, { recursive: true })
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
await removeTestDirectories(config.testEnvironmentPath)
|
|
18
|
+
await removeTestDirectories(config.directories.testEnvironmentPath)
|
|
19
19
|
const testDirectory = await createTempDir(config)
|
|
20
20
|
return testDirectory
|
|
21
21
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from "assert"
|
|
2
2
|
import type { BlockingCommandInput } from "../../blockingCommandInputSchema.js"
|
|
3
3
|
import type { BlockingShellCommandOutput, TestDirectory } from "../../types.js"
|
|
4
|
-
import type {
|
|
4
|
+
import type { TestServerConfig } from "../../updateTestdirectorySchemaFile.js"
|
|
5
5
|
import { convertEventEmitterToAsyncGenerator } from "../../utilities/generator.js"
|
|
6
6
|
import { Lazy } from "../../utilities/Lazy.js"
|
|
7
7
|
import type { TabId } from "../../utilities/tabId.js"
|
|
@@ -17,7 +17,7 @@ const resources: Lazy<AsyncDisposableStack> = new Lazy(() => {
|
|
|
17
17
|
|
|
18
18
|
export async function start(
|
|
19
19
|
{ tabId, startTerminalArguments }: StartTerminalInput,
|
|
20
|
-
config:
|
|
20
|
+
config: TestServerConfig
|
|
21
21
|
): Promise<TestDirectory> {
|
|
22
22
|
const app = terminals.get(tabId.tabId)
|
|
23
23
|
assert(app, `Terminal with tabId ${tabId.tabId} not found.`)
|
|
@@ -2,7 +2,7 @@ import * as z from "zod"
|
|
|
2
2
|
import { blockingCommandInputSchema } from "../../blockingCommandInputSchema.js"
|
|
3
3
|
import { trpc } from "../../connection/trpc.js"
|
|
4
4
|
import { serverTestDirectorySchema } from "../../types.js"
|
|
5
|
-
import type {
|
|
5
|
+
import type { TestServerConfig } from "../../updateTestdirectorySchemaFile.js"
|
|
6
6
|
import { tabIdSchema } from "../../utilities/tabId.js"
|
|
7
7
|
import * as terminal from "./api.js"
|
|
8
8
|
|
|
@@ -21,7 +21,7 @@ export type StartTerminalInput = z.infer<typeof startTerminalInputSchema>
|
|
|
21
21
|
|
|
22
22
|
// let trpc infer the type as that is what it is designed to do
|
|
23
23
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
24
|
-
export function createTerminalRouter(config:
|
|
24
|
+
export function createTerminalRouter(config: TestServerConfig) {
|
|
25
25
|
const terminalRouter = trpc.router({
|
|
26
26
|
onStdout: trpc.procedure.input(z.object({ client: tabIdSchema })).subscription(options => {
|
|
27
27
|
return terminal.initializeStdout(options.input, options.signal)
|
|
@@ -30,7 +30,7 @@ export function createTerminalRouter(config: DirectoriesConfig) {
|
|
|
30
30
|
start: trpc.procedure
|
|
31
31
|
.input(startTerminalInputSchema)
|
|
32
32
|
.output(serverTestDirectorySchema)
|
|
33
|
-
.mutation(options => {
|
|
33
|
+
.mutation(async options => {
|
|
34
34
|
return terminal.start(options.input, config)
|
|
35
35
|
}),
|
|
36
36
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createDefaultConfig } from "./config.js"
|
|
2
|
+
import { testServerConfigSchema } from "./updateTestdirectorySchemaFile.js"
|
|
3
|
+
|
|
4
|
+
it("is possible not to customize anything", () => {
|
|
5
|
+
const defaultConfig = createDefaultConfig(process.cwd(), process.env)
|
|
6
|
+
testServerConfigSchema.parse(defaultConfig)
|
|
7
|
+
})
|
package/src/server/config.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import path from "path"
|
|
2
2
|
import type { TestServerConfig } from "./updateTestdirectorySchemaFile.js"
|
|
3
3
|
|
|
4
|
-
export const createDefaultConfig = (cwd: string, environment: NodeJS.ProcessEnv): TestServerConfig =>
|
|
5
|
-
|
|
4
|
+
export const createDefaultConfig = (cwd: string, environment: NodeJS.ProcessEnv): TestServerConfig => {
|
|
5
|
+
return {
|
|
6
6
|
directories: {
|
|
7
7
|
testEnvironmentPath: path.join(cwd, "test-environment/"),
|
|
8
8
|
outputFilePath: path.join(cwd, "MyTestDirectory.ts"),
|
|
9
9
|
},
|
|
10
10
|
port: environment["PORT"] ? parseInt(environment["PORT"]) : 3000,
|
|
11
|
-
|
|
11
|
+
integrations: {
|
|
12
|
+
neovim: {
|
|
13
|
+
NVIM_APPNAMEs: ["nvim"],
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -33,7 +33,7 @@ import type {
|
|
|
33
33
|
import type { StartTerminalGenericArguments } from "@tui-sandbox/library/src/server/applications/terminal/TerminalTestApplication"
|
|
34
34
|
import type { BlockingCommandClientInput } from "@tui-sandbox/library/src/server/blockingCommandInputSchema"
|
|
35
35
|
import type { OverrideProperties } from "type-fest"
|
|
36
|
-
import type { MyTestDirectory, MyTestDirectoryFile } from "../../MyTestDirectory"
|
|
36
|
+
import type { MyNeovimAppName, MyTestDirectory, MyTestDirectoryFile } from "../../MyTestDirectory"
|
|
37
37
|
|
|
38
38
|
export type TerminalTestApplicationContext = {
|
|
39
39
|
/** Types text into the terminal, making the terminal application receive the
|
|
@@ -93,6 +93,7 @@ export type NeovimContext = {
|
|
|
93
93
|
export type MyStartNeovimServerArguments = OverrideProperties<
|
|
94
94
|
StartNeovimGenericArguments,
|
|
95
95
|
{
|
|
96
|
+
NVIM_APPNAME?: MyNeovimAppName
|
|
96
97
|
filename?: MyTestDirectoryFile | { openInVerticalSplits: MyTestDirectoryFile[] }
|
|
97
98
|
startupScriptModifications?: Array<MyNeovimConfigModification<MyTestDirectoryFile>>
|
|
98
99
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import assert from "assert"
|
|
2
2
|
import path from "path"
|
|
3
3
|
import { describe, expect, it } from "vitest"
|
|
4
|
+
import { createDefaultConfig } from "../config.js"
|
|
5
|
+
import type { NeovimIntegrationDefaultAppName, TestServerConfig } from "../updateTestdirectorySchemaFile.js"
|
|
4
6
|
import { Lazy } from "../utilities/Lazy.js"
|
|
5
7
|
import { buildSchemaForDirectoryTree, getDirectoryTree } from "./index.js"
|
|
6
8
|
|
|
@@ -19,7 +21,15 @@ describe("dirtree", () => {
|
|
|
19
21
|
})
|
|
20
22
|
|
|
21
23
|
it("should be able to build a typescript type for the tree", async () => {
|
|
22
|
-
const
|
|
24
|
+
const config: TestServerConfig = {
|
|
25
|
+
...createDefaultConfig("/my/root/path", {}),
|
|
26
|
+
integrations: {
|
|
27
|
+
neovim: {
|
|
28
|
+
NVIM_APPNAMEs: ["nvim" satisfies NeovimIntegrationDefaultAppName, "nvim_alt"],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
const result = await buildSchemaForDirectoryTree(output.get(), "MyDirectoryTree", config)
|
|
23
33
|
|
|
24
34
|
expect(result).toMatchInlineSnapshot(`
|
|
25
35
|
"
|
|
@@ -201,13 +211,15 @@ describe("dirtree", () => {
|
|
|
201
211
|
"symlink-test",
|
|
202
212
|
"."
|
|
203
213
|
])
|
|
204
|
-
export type MyTestDirectoryFile = z.infer<typeof testDirectoryFiles>
|
|
214
|
+
export type MyTestDirectoryFile = z.infer<typeof testDirectoryFiles>
|
|
215
|
+
export type MyNeovimAppName = "nvim" | "nvim_alt""
|
|
205
216
|
`)
|
|
206
217
|
})
|
|
207
218
|
|
|
208
219
|
it("creates an empty schema when the directory cannot be read", async () => {
|
|
220
|
+
const config: TestServerConfig = createDefaultConfig("/my/root/path", {})
|
|
209
221
|
const tree = getDirectoryTree("nonexistent")
|
|
210
|
-
const result = await buildSchemaForDirectoryTree(tree, "MyDirectoryTree")
|
|
222
|
+
const result = await buildSchemaForDirectoryTree(tree, "MyDirectoryTree", config)
|
|
211
223
|
expect(result).toMatchInlineSnapshot(`
|
|
212
224
|
"
|
|
213
225
|
// Note: This file is autogenerated. Do not edit it directly.
|
|
@@ -234,7 +246,107 @@ describe("dirtree", () => {
|
|
|
234
246
|
export type MyDirectoryTree = MyDirectoryTreeContentsSchemaType["contents"]
|
|
235
247
|
|
|
236
248
|
export const testDirectoryFiles = z.enum([])
|
|
237
|
-
export type MyTestDirectoryFile = z.infer<typeof testDirectoryFiles>
|
|
249
|
+
export type MyTestDirectoryFile = z.infer<typeof testDirectoryFiles>
|
|
250
|
+
export type MyNeovimAppName = "nvim""
|
|
238
251
|
`)
|
|
239
252
|
})
|
|
253
|
+
|
|
254
|
+
describe("provides type-safe access to NVIM_APPNAMEs", () => {
|
|
255
|
+
// the user can configure the NVIM_APPNAMEs they are using in their
|
|
256
|
+
// configuration. These should be available for them in a type-safe manner so
|
|
257
|
+
// that they have the least possible friction when coding.
|
|
258
|
+
//
|
|
259
|
+
const smallDirectory = path.resolve(__dirname, "../../../../integration-tests/test-environment/other-subdirectory/")
|
|
260
|
+
|
|
261
|
+
it("when there is a single name", async () => {
|
|
262
|
+
const config: TestServerConfig = createDefaultConfig("/my/root/path", {})
|
|
263
|
+
assert(config.integrations.neovim.NVIM_APPNAMEs.length === 1)
|
|
264
|
+
const tinytree = getDirectoryTree(smallDirectory)
|
|
265
|
+
const result = await buildSchemaForDirectoryTree(tinytree, "MyDirectoryTree", config)
|
|
266
|
+
|
|
267
|
+
expect(result).toMatchInlineSnapshot(`
|
|
268
|
+
"
|
|
269
|
+
// Note: This file is autogenerated. Do not edit it directly.
|
|
270
|
+
//
|
|
271
|
+
// Describes the contents of the test directory, which is a blueprint for
|
|
272
|
+
// files and directories. Tests can create a unique, safe environment for
|
|
273
|
+
// interacting with the contents of such a directory.
|
|
274
|
+
//
|
|
275
|
+
// Having strong typing for the test directory contents ensures that tests can
|
|
276
|
+
// be written with confidence that the files and directories they expect are
|
|
277
|
+
// actually found. Otherwise the tests are brittle and can break easily.
|
|
278
|
+
|
|
279
|
+
import * as z from "zod"
|
|
280
|
+
|
|
281
|
+
export const MyDirectoryTreeSchema = z.object({
|
|
282
|
+
name: z.literal("other-subdirectory/"),
|
|
283
|
+
type: z.literal("directory"),
|
|
284
|
+
contents: z.object({
|
|
285
|
+
"other-sub-file.txt": z.object({ name: z.literal("other-sub-file.txt"), type: z.literal("file") }),
|
|
286
|
+
}),
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
export const MyDirectoryTreeContentsSchema = MyDirectoryTreeSchema.shape.contents
|
|
290
|
+
export type MyDirectoryTreeContentsSchemaType = z.infer<typeof MyDirectoryTreeSchema>
|
|
291
|
+
|
|
292
|
+
export type MyDirectoryTree = MyDirectoryTreeContentsSchemaType["contents"]
|
|
293
|
+
|
|
294
|
+
export const testDirectoryFiles = z.enum([
|
|
295
|
+
"other-sub-file.txt",
|
|
296
|
+
"."
|
|
297
|
+
])
|
|
298
|
+
export type MyTestDirectoryFile = z.infer<typeof testDirectoryFiles>
|
|
299
|
+
export type MyNeovimAppName = "nvim""
|
|
300
|
+
`)
|
|
301
|
+
// 👆🏻 from the default config
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
it("when there are multiple names", async () => {
|
|
305
|
+
const config: TestServerConfig = {
|
|
306
|
+
...createDefaultConfig("/my/root/path", {}),
|
|
307
|
+
integrations: {
|
|
308
|
+
neovim: {
|
|
309
|
+
NVIM_APPNAMEs: ["nvim" satisfies NeovimIntegrationDefaultAppName, "nvim_alt"],
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
}
|
|
313
|
+
const tinytree = getDirectoryTree(smallDirectory)
|
|
314
|
+
const result = await buildSchemaForDirectoryTree(tinytree, "MyDirectoryTree", config)
|
|
315
|
+
|
|
316
|
+
expect(result).toMatchInlineSnapshot(`
|
|
317
|
+
"
|
|
318
|
+
// Note: This file is autogenerated. Do not edit it directly.
|
|
319
|
+
//
|
|
320
|
+
// Describes the contents of the test directory, which is a blueprint for
|
|
321
|
+
// files and directories. Tests can create a unique, safe environment for
|
|
322
|
+
// interacting with the contents of such a directory.
|
|
323
|
+
//
|
|
324
|
+
// Having strong typing for the test directory contents ensures that tests can
|
|
325
|
+
// be written with confidence that the files and directories they expect are
|
|
326
|
+
// actually found. Otherwise the tests are brittle and can break easily.
|
|
327
|
+
|
|
328
|
+
import * as z from "zod"
|
|
329
|
+
|
|
330
|
+
export const MyDirectoryTreeSchema = z.object({
|
|
331
|
+
name: z.literal("other-subdirectory/"),
|
|
332
|
+
type: z.literal("directory"),
|
|
333
|
+
contents: z.object({
|
|
334
|
+
"other-sub-file.txt": z.object({ name: z.literal("other-sub-file.txt"), type: z.literal("file") }),
|
|
335
|
+
}),
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
export const MyDirectoryTreeContentsSchema = MyDirectoryTreeSchema.shape.contents
|
|
339
|
+
export type MyDirectoryTreeContentsSchemaType = z.infer<typeof MyDirectoryTreeSchema>
|
|
340
|
+
|
|
341
|
+
export type MyDirectoryTree = MyDirectoryTreeContentsSchemaType["contents"]
|
|
342
|
+
|
|
343
|
+
export const testDirectoryFiles = z.enum([
|
|
344
|
+
"other-sub-file.txt",
|
|
345
|
+
"."
|
|
346
|
+
])
|
|
347
|
+
export type MyTestDirectoryFile = z.infer<typeof testDirectoryFiles>
|
|
348
|
+
export type MyNeovimAppName = "nvim" | "nvim_alt""
|
|
349
|
+
`)
|
|
350
|
+
})
|
|
351
|
+
})
|
|
240
352
|
})
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import assert from "assert"
|
|
1
2
|
import type { Dree } from "dree"
|
|
2
3
|
import { scan, Type } from "dree"
|
|
3
4
|
import { readlinkSync } from "fs"
|
|
4
5
|
import { format, resolveConfig } from "prettier"
|
|
5
6
|
import { fileURLToPath } from "url"
|
|
6
7
|
import { debuglog } from "util"
|
|
8
|
+
import type { TestServerConfig } from "../updateTestdirectorySchemaFile.js"
|
|
7
9
|
import { jsonToZod } from "./json-to-zod.js"
|
|
8
10
|
|
|
9
11
|
const log = debuglog("tui-sandbox.dirtree")
|
|
@@ -83,7 +85,11 @@ export function convertDree(root: Dree | undefined): TreeNode {
|
|
|
83
85
|
return node
|
|
84
86
|
}
|
|
85
87
|
|
|
86
|
-
export async function buildSchemaForDirectoryTree(
|
|
88
|
+
export async function buildSchemaForDirectoryTree(
|
|
89
|
+
result: TreeResult,
|
|
90
|
+
name: string,
|
|
91
|
+
config: TestServerConfig
|
|
92
|
+
): Promise<string> {
|
|
87
93
|
const root = convertDree(result.dree)
|
|
88
94
|
|
|
89
95
|
const schema = (await jsonToZod(root, `${name}Schema`)).split("\n")
|
|
@@ -103,6 +109,13 @@ export async function buildSchemaForDirectoryTree(result: TreeResult, name: stri
|
|
|
103
109
|
const allFilePaths = result.allFiles.map(f => f.relativePath)
|
|
104
110
|
const ContentsSchema = `${name}ContentsSchema`
|
|
105
111
|
const ContentsSchemaType = `${name}ContentsSchemaType`
|
|
112
|
+
|
|
113
|
+
assert(config.integrations.neovim.NVIM_APPNAMEs.length > 0, "At least one NVIM_APPNAME must be configured")
|
|
114
|
+
const NVIM_APPNAMEsUnion =
|
|
115
|
+
config.integrations.neovim.NVIM_APPNAMEs.length > 1
|
|
116
|
+
? config.integrations.neovim.NVIM_APPNAMEs.map(a => `"${a}"`).join(" | ")
|
|
117
|
+
: `"${config.integrations.neovim.NVIM_APPNAMEs[0]}"`
|
|
118
|
+
|
|
106
119
|
return [
|
|
107
120
|
...lines,
|
|
108
121
|
...schema,
|
|
@@ -113,15 +126,16 @@ export async function buildSchemaForDirectoryTree(result: TreeResult, name: stri
|
|
|
113
126
|
"",
|
|
114
127
|
`export const testDirectoryFiles = z.enum(${JSON.stringify(allFilePaths, null, 2)})`,
|
|
115
128
|
`export type MyTestDirectoryFile = z.infer<typeof testDirectoryFiles>`,
|
|
129
|
+
`export type MyNeovimAppName = ${NVIM_APPNAMEsUnion}`,
|
|
116
130
|
].join("\n")
|
|
117
131
|
}
|
|
118
132
|
|
|
119
133
|
const __filename = fileURLToPath(import.meta.url)
|
|
120
134
|
|
|
121
|
-
export async function buildTestDirectorySchema(
|
|
122
|
-
log("Building schema for test directory",
|
|
123
|
-
const dree = getDirectoryTree(
|
|
124
|
-
let text = await buildSchemaForDirectoryTree(dree, "MyTestDirectory")
|
|
135
|
+
export async function buildTestDirectorySchema(config: TestServerConfig): Promise<string> {
|
|
136
|
+
log("Building schema for test directory", config.directories.testEnvironmentPath)
|
|
137
|
+
const dree = getDirectoryTree(config.directories.testEnvironmentPath)
|
|
138
|
+
let text = await buildSchemaForDirectoryTree(dree, "MyTestDirectory", config)
|
|
125
139
|
|
|
126
140
|
const options = await resolveConfig(__filename)
|
|
127
141
|
text = await format(text, { ...options, parser: "typescript" })
|
package/src/server/server.ts
CHANGED
|
@@ -3,14 +3,13 @@ import { createNeovimRouter } from "./applications/neovim/neovimRouter.js"
|
|
|
3
3
|
import { createTerminalRouter } from "./applications/terminal/terminalRouter.js"
|
|
4
4
|
import { trpc } from "./connection/trpc.js"
|
|
5
5
|
import { TestServer } from "./TestServer.js"
|
|
6
|
-
import type {
|
|
6
|
+
import type { TestServerConfig } from "./updateTestdirectorySchemaFile.js"
|
|
7
7
|
|
|
8
8
|
/** @private */
|
|
9
9
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
10
|
-
export async function createAppRouter(config:
|
|
10
|
+
export async function createAppRouter(config: TestServerConfig) {
|
|
11
11
|
const appRouter = trpc.router({
|
|
12
12
|
terminal: createTerminalRouter(config),
|
|
13
|
-
|
|
14
13
|
neovim: createNeovimRouter(config),
|
|
15
14
|
})
|
|
16
15
|
|
|
@@ -25,7 +24,7 @@ export async function startTestServer(config: TestServerConfig): Promise<void> {
|
|
|
25
24
|
const testServer = new TestServer({
|
|
26
25
|
port: config.port,
|
|
27
26
|
})
|
|
28
|
-
const appRouter = await createAppRouter(config
|
|
27
|
+
const appRouter = await createAppRouter(config)
|
|
29
28
|
|
|
30
29
|
await testServer.startAndRun(appRouter)
|
|
31
30
|
} catch (err: unknown) {
|