@tui-sandbox/library 7.3.0 → 7.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tui-sandbox/library",
3
- "version": "7.3.0",
3
+ "version": "7.5.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,8 +8,8 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "@catppuccin/palette": "1.7.1",
11
- "@trpc/client": "11.0.0-rc.648",
12
- "@trpc/server": "11.0.0-rc.648",
11
+ "@trpc/client": "11.0.0-rc.666",
12
+ "@trpc/server": "11.0.0-rc.666",
13
13
  "@xterm/addon-attach": "0.11.0",
14
14
  "@xterm/addon-fit": "0.10.0",
15
15
  "@xterm/xterm": "5.5.0",
@@ -17,24 +17,24 @@
17
17
  "core-js": "3.39.0",
18
18
  "cors": "2.8.5",
19
19
  "dree": "5.1.5",
20
- "express": "4.21.1",
20
+ "express": "4.21.2",
21
21
  "neovim": "5.3.0",
22
22
  "node-pty": "1.0.0",
23
- "prettier": "3.4.1",
23
+ "prettier": "3.4.2",
24
24
  "tsx": "4.19.2",
25
- "type-fest": "4.29.0",
25
+ "type-fest": "4.30.2",
26
26
  "winston": "3.17.0",
27
- "zod": "3.23.8"
27
+ "zod": "3.24.1"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@runtyping/zod": "2.1.1",
31
31
  "@types/command-exists": "1.2.3",
32
32
  "@types/cors": "2.8.17",
33
33
  "@types/express": "5.0.0",
34
- "@types/node": "22.10.1",
35
- "nodemon": "3.1.7",
36
- "vite": "6.0.1",
37
- "vitest": "2.1.6"
34
+ "@types/node": "22.10.2",
35
+ "nodemon": "3.1.9",
36
+ "vite": "6.0.5",
37
+ "vitest": "2.1.8"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "cypress": "^13",
@@ -98,25 +98,16 @@ export class TerminalClient {
98
98
 
99
99
  public async runBlockingShellCommand(input: BlockingCommandClientInput): Promise<BlockingShellCommandOutput> {
100
100
  await this.ready
101
- return this.trpc.neovim.runBlockingShellCommand.mutate({
102
- ...input,
103
- tabId: this.tabId,
104
- })
101
+ return this.trpc.neovim.runBlockingShellCommand.mutate({ ...input, tabId: this.tabId })
105
102
  }
106
103
 
107
104
  public async runLuaCode(input: LuaCodeClientInput): Promise<RunLuaCodeOutput> {
108
105
  await this.ready
109
- return this.trpc.neovim.runLuaCode.mutate({
110
- luaCode: input.luaCode,
111
- tabId: this.tabId,
112
- })
106
+ return this.trpc.neovim.runLuaCode.mutate({ ...input, tabId: this.tabId })
113
107
  }
114
108
 
115
109
  public async runExCommand(input: ExCommandClientInput): Promise<RunExCommandOutput> {
116
110
  await this.ready
117
- return this.trpc.neovim.runExCommand.mutate({
118
- command: input.command,
119
- tabId: this.tabId,
120
- })
111
+ return this.trpc.neovim.runExCommand.mutate({ ...input, tabId: this.tabId })
121
112
  }
122
113
  }
@@ -18,8 +18,11 @@ const outputFileName = "MyTestDirectory.ts"
18
18
  * cwd of the script itself. */
19
19
  const cwd = process.cwd()
20
20
  const config = {
21
- testEnvironmentPath: path.join(cwd, "test-environment/"),
22
- outputFilePath: path.join(cwd, outputFileName),
21
+ directories: {
22
+ testEnvironmentPath: path.join(cwd, "test-environment/"),
23
+ outputFilePath: path.join(cwd, outputFileName),
24
+ },
25
+ port: process.env["PORT"] ? parseInt(process.env["PORT"]) : 3000,
23
26
  } satisfies TestServerConfig
24
27
 
25
28
  // the arguments passed to this script start at index 2
@@ -35,11 +38,11 @@ if (args[0] === "neovim") {
35
38
 
36
39
  {
37
40
  // automatically dispose of the neovim instance when done
38
- await using app = new NeovimApplication(config.testEnvironmentPath)
41
+ await using app = new NeovimApplication(config.directories.testEnvironmentPath)
39
42
  app.events.on("stdout" satisfies StdoutOrStderrMessage, data => {
40
43
  console.log(` neovim output: ${data}`)
41
44
  })
42
- const testDirectory = await prepareNewTestDirectory(config)
45
+ const testDirectory = await prepareNewTestDirectory(config.directories)
43
46
  await app.startNextAndKillCurrent(
44
47
  testDirectory,
45
48
  { filename: "empty.txt", headlessCmd: command },
@@ -62,7 +65,7 @@ try {
62
65
  cypressSupportDirectoryPath: path.join(cwd, "cypress", "support"),
63
66
  supportFileName: "tui-sandbox.ts",
64
67
  })
65
- await updateTestdirectorySchemaFile(config)
68
+ await updateTestdirectorySchemaFile(config.directories)
66
69
  await startTestServer(config)
67
70
  } catch (e) {
68
71
  console.error(e)
@@ -17,14 +17,13 @@ it("should return the expected contents", async () => {
17
17
  RunExCommandOutput,
18
18
  RunLuaCodeOutput,
19
19
  StartNeovimGenericArguments,
20
+ TestDirectory,
20
21
  } from "@tui-sandbox/library/dist/src/server/types"
22
+ import assert from "assert"
21
23
  import type { OverrideProperties } from "type-fest"
22
24
  import type { MyTestDirectory, MyTestDirectoryFile } from "../../MyTestDirectory"
23
25
 
24
- export type NeovimContext = {
25
- contents: MyTestDirectory
26
- rootPathAbsolute: string
27
- }
26
+ export type NeovimContext = TestDirectory<MyTestDirectory>
28
27
 
29
28
  declare global {
30
29
  interface Window {
@@ -46,6 +45,7 @@ it("should return the expected contents", async () => {
46
45
 
47
46
  Cypress.Commands.add("startNeovim", (startArguments?: MyStartNeovimServerArguments) => {
48
47
  cy.window().then(async win => {
48
+ testWindow = win
49
49
  return await win.startNeovim(startArguments)
50
50
  })
51
51
  })
@@ -74,6 +74,13 @@ it("should return the expected contents", async () => {
74
74
  })
75
75
  })
76
76
 
77
+ let testWindow: Window | undefined
78
+
79
+ Cypress.on("fail", async () => {
80
+ assert(testWindow, "testWindow is not defined")
81
+ await testWindow.runExCommand({ command: "messages", log: true })
82
+ })
83
+
77
84
  before(function () {
78
85
  // disable Cypress's default behavior of logging all XMLHttpRequests and
79
86
  // fetches to the Command Log
@@ -96,6 +103,9 @@ it("should return the expected contents", async () => {
96
103
 
97
104
  runLuaCode(input: LuaCodeClientInput): Chainable<RunLuaCodeOutput>
98
105
 
106
+ /** Run an ex command in neovim.
107
+ * @example "echo expand('%:.')" current file, relative to the cwd
108
+ */
99
109
  runExCommand(input: ExCommandClientInput): Chainable<RunExCommandOutput>
100
110
  }
101
111
  }
@@ -20,14 +20,13 @@ import type {
20
20
  RunExCommandOutput,
21
21
  RunLuaCodeOutput,
22
22
  StartNeovimGenericArguments,
23
+ TestDirectory,
23
24
  } from "@tui-sandbox/library/dist/src/server/types"
25
+ import assert from "assert"
24
26
  import type { OverrideProperties } from "type-fest"
25
27
  import type { MyTestDirectory, MyTestDirectoryFile } from "../../MyTestDirectory"
26
28
 
27
- export type NeovimContext = {
28
- contents: MyTestDirectory
29
- rootPathAbsolute: string
30
- }
29
+ export type NeovimContext = TestDirectory<MyTestDirectory>
31
30
 
32
31
  declare global {
33
32
  interface Window {
@@ -49,6 +48,7 @@ type MyStartNeovimServerArguments = OverrideProperties<
49
48
 
50
49
  Cypress.Commands.add("startNeovim", (startArguments?: MyStartNeovimServerArguments) => {
51
50
  cy.window().then(async win => {
51
+ testWindow = win
52
52
  return await win.startNeovim(startArguments)
53
53
  })
54
54
  })
@@ -77,6 +77,13 @@ Cypress.Commands.add("runExCommand", (input: ExCommandClientInput) => {
77
77
  })
78
78
  })
79
79
 
80
+ let testWindow: Window | undefined
81
+
82
+ Cypress.on("fail", async () => {
83
+ assert(testWindow, "testWindow is not defined")
84
+ await testWindow.runExCommand({ command: "messages", log: true })
85
+ })
86
+
80
87
  before(function () {
81
88
  // disable Cypress's default behavior of logging all XMLHttpRequests and
82
89
  // fetches to the Command Log
@@ -99,6 +106,9 @@ declare global {
99
106
 
100
107
  runLuaCode(input: LuaCodeClientInput): Chainable<RunLuaCodeOutput>
101
108
 
109
+ /** Run an ex command in neovim.
110
+ * @example "echo expand('%:.')" current file, relative to the cwd
111
+ */
102
112
  runExCommand(input: ExCommandClientInput): Chainable<RunExCommandOutput>
103
113
  }
104
114
  }
@@ -6,10 +6,10 @@ import { access, mkdir, mkdtemp } from "fs/promises"
6
6
  import path from "path"
7
7
  import { convertDree, getDirectoryTree } from "../../dirtree/index.js"
8
8
  import type { TestDirectory } from "../../types.js"
9
- import type { TestServerConfig } from "../../updateTestdirectorySchemaFile.js"
9
+ import type { DirectoriesConfig } from "../../updateTestdirectorySchemaFile.js"
10
10
  import { updateTestdirectorySchemaFile } from "../../updateTestdirectorySchemaFile.js"
11
11
 
12
- export async function createTempDir(config: TestServerConfig): Promise<TestDirectory> {
12
+ export async function createTempDir(config: DirectoriesConfig): Promise<TestDirectory> {
13
13
  try {
14
14
  const dir = await createUniqueDirectory(config.testEnvironmentPath)
15
15
 
@@ -10,7 +10,7 @@ import type {
10
10
  StartNeovimGenericArguments,
11
11
  TestDirectory,
12
12
  } from "../types.js"
13
- import type { TestServerConfig } from "../updateTestdirectorySchemaFile.js"
13
+ import type { DirectoriesConfig } 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"
@@ -53,7 +53,7 @@ export async function start(
53
53
  options: StartNeovimGenericArguments,
54
54
  terminalDimensions: TerminalDimensions,
55
55
  tabId: TabId,
56
- config: TestServerConfig
56
+ config: DirectoriesConfig
57
57
  ): Promise<TestDirectory> {
58
58
  const neovim = neovims.get(tabId.tabId)
59
59
  assert(neovim, `Neovim instance not found for client id ${tabId.tabId}`)
@@ -64,7 +64,7 @@ export async function start(
64
64
  return testDirectory
65
65
  }
66
66
 
67
- export async function prepareNewTestDirectory(config: TestServerConfig): Promise<TestDirectory> {
67
+ export async function prepareNewTestDirectory(config: DirectoriesConfig): Promise<TestDirectory> {
68
68
  await removeTestDirectories(config.testEnvironmentPath)
69
69
  const testDirectory = await createTempDir(config)
70
70
  return testDirectory
@@ -174,6 +174,9 @@ export async function runExCommand(options: ExCommandInput): Promise<RunExComman
174
174
  console.log(`Neovim ${neovim.application.processId()} running Ex command: ${options.command}`)
175
175
  try {
176
176
  const output = await api.commandOutput(options.command)
177
+ if (options.log) {
178
+ console.log(`Ex command output: ${output}`)
179
+ }
177
180
  return { value: output }
178
181
  } catch (e) {
179
182
  console.warn(`Error running Ex command: ${options.command}`, e)
@@ -5,7 +5,7 @@ import { z } from "zod"
5
5
  import { trpc } from "./connection/trpc.js"
6
6
  import * as neovim from "./neovim/index.js"
7
7
  import { TestServer } from "./TestServer.js"
8
- import type { TestServerConfig } from "./updateTestdirectorySchemaFile.js"
8
+ import type { DirectoriesConfig, TestServerConfig } from "./updateTestdirectorySchemaFile.js"
9
9
  import { applicationAvailable } from "./utilities/applicationAvailable.js"
10
10
  import { tabIdSchema } from "./utilities/tabId.js"
11
11
 
@@ -29,13 +29,17 @@ const luaCodeInputSchema = z.object({ tabId: tabIdSchema, luaCode: z.string() })
29
29
  export type LuaCodeClientInput = Except<LuaCodeInput, "tabId">
30
30
  export type LuaCodeInput = z.infer<typeof luaCodeInputSchema>
31
31
 
32
- const exCommandInputSchema = z.object({ tabId: tabIdSchema, command: z.string() })
32
+ const exCommandInputSchema = z.object({
33
+ tabId: tabIdSchema,
34
+ command: z.string(),
35
+ log: z.boolean().optional(),
36
+ })
33
37
  export type ExCommandClientInput = Except<ExCommandInput, "tabId">
34
38
  export type ExCommandInput = z.infer<typeof exCommandInputSchema>
35
39
 
36
40
  /** @private */
37
41
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
38
- export async function createAppRouter(config: TestServerConfig) {
42
+ export async function createAppRouter(config: DirectoriesConfig) {
39
43
  if (!(await applicationAvailable("nvim"))) {
40
44
  throw new Error("Neovim is not installed. Please install Neovim (nvim).")
41
45
  }
@@ -99,9 +103,9 @@ export type RouterInput = inferRouterInputs<AppRouter>
99
103
 
100
104
  export async function startTestServer(config: TestServerConfig): Promise<TestServer> {
101
105
  const testServer = new TestServer({
102
- port: 3000,
106
+ port: config.port,
103
107
  })
104
- const appRouter = await createAppRouter(config)
108
+ const appRouter = await createAppRouter(config.directories)
105
109
  await testServer.startAndRun(appRouter)
106
110
 
107
111
  return testServer
@@ -8,7 +8,7 @@ import type { VimValue } from "neovim/lib/types/VimValue.js"
8
8
  * be written with confidence that the files and directories they expect are
9
9
  * actually found. Otherwise the tests are brittle and can break easily.
10
10
  */
11
- export type TestDirectory = {
11
+ export type TestDirectory<TContents extends object = object> = {
12
12
  /** The path to the unique test directory (the root).
13
13
  *
14
14
  * @example /Users/mikavilpas/git/tui-sandbox/packages/integration-tests/test-environment/testdirs/dir-0199UZ
@@ -28,7 +28,7 @@ export type TestDirectory = {
28
28
  */
29
29
  testEnvironmentPathRelative: string
30
30
 
31
- contents: object
31
+ contents: TContents
32
32
  }
33
33
 
34
34
  export type { StartNeovimGenericArguments } from "../server/neovim/NeovimApplication.js"
@@ -1,17 +1,22 @@
1
1
  import { readFileSync, writeFileSync } from "fs"
2
2
  import { buildTestDirectorySchema } from "./dirtree/index.js"
3
3
 
4
- export type TestServerConfig = {
4
+ export type DirectoriesConfig = {
5
5
  testEnvironmentPath: string
6
6
  outputFilePath: string
7
7
  }
8
8
 
9
+ export type TestServerConfig = {
10
+ directories: DirectoriesConfig
11
+ port: number
12
+ }
13
+
9
14
  export type UpdateTestdirectorySchemaFileResult = "updated" | "did-nothing"
10
15
 
11
16
  export async function updateTestdirectorySchemaFile({
12
17
  testEnvironmentPath,
13
18
  outputFilePath,
14
- }: TestServerConfig): Promise<UpdateTestdirectorySchemaFileResult> {
19
+ }: DirectoriesConfig): Promise<UpdateTestdirectorySchemaFileResult> {
15
20
  const newSchema: string = await buildTestDirectorySchema(testEnvironmentPath)
16
21
  let oldSchema = ""
17
22