@tui-sandbox/library 11.6.7 → 11.7.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/browser/assets/{index-B9YWhyKg.js → index-CQ6TDc4S.js} +1 -1
  3. package/dist/browser/index.html +1 -1
  4. package/dist/src/scripts/commands/commandTuiNeovimExec.d.ts +2 -1
  5. package/dist/src/scripts/commands/commandTuiNeovimExec.js +1 -2
  6. package/dist/src/scripts/commands/commandTuiNeovimExec.js.map +1 -1
  7. package/dist/src/scripts/commands/commandTuiNeovimPrepare.d.ts +2 -1
  8. package/dist/src/scripts/commands/commandTuiNeovimPrepare.js +1 -2
  9. package/dist/src/scripts/commands/commandTuiNeovimPrepare.js.map +1 -1
  10. package/dist/src/scripts/commands/commandTuiStart.d.ts +2 -1
  11. package/dist/src/scripts/commands/commandTuiStart.js +2 -2
  12. package/dist/src/scripts/commands/commandTuiStart.js.map +1 -1
  13. package/dist/src/scripts/resolveConfig.test.d.ts +1 -0
  14. package/dist/src/scripts/resolveConfig.test.js +144 -0
  15. package/dist/src/scripts/resolveConfig.test.js.map +1 -0
  16. package/dist/src/scripts/resolveTuiConfig.d.ts +13 -0
  17. package/dist/src/scripts/resolveTuiConfig.js +43 -0
  18. package/dist/src/scripts/resolveTuiConfig.js.map +1 -0
  19. package/dist/src/scripts/tui.d.ts +0 -7
  20. package/dist/src/scripts/tui.js +9 -12
  21. package/dist/src/scripts/tui.js.map +1 -1
  22. package/dist/src/server/applications/neovim/environment/TempDirectory.d.ts +7 -0
  23. package/dist/src/server/applications/neovim/environment/TempDirectory.js +17 -0
  24. package/dist/src/server/applications/neovim/environment/TempDirectory.js.map +1 -0
  25. package/dist/src/server/applications/neovim/environment/createTempDir.test.js +1 -15
  26. package/dist/src/server/applications/neovim/environment/createTempDir.test.js.map +1 -1
  27. package/dist/src/server/config.d.ts +2 -0
  28. package/dist/src/server/config.js +9 -0
  29. package/dist/src/server/config.js.map +1 -0
  30. package/dist/src/server/updateTestdirectorySchemaFile.d.ts +10 -8
  31. package/dist/src/server/updateTestdirectorySchemaFile.js +8 -0
  32. package/dist/src/server/updateTestdirectorySchemaFile.js.map +1 -1
  33. package/dist/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +3 -3
  35. package/src/scripts/commands/commandTuiNeovimExec.ts +2 -2
  36. package/src/scripts/commands/commandTuiNeovimPrepare.ts +2 -2
  37. package/src/scripts/commands/commandTuiStart.ts +3 -2
  38. package/src/scripts/resolveConfig.test.ts +73 -0
  39. package/src/scripts/resolveTuiConfig.ts +59 -0
  40. package/src/scripts/tui.ts +9 -14
  41. package/src/server/applications/neovim/environment/TempDirectory.ts +18 -0
  42. package/src/server/applications/neovim/environment/createTempDir.test.ts +2 -17
  43. package/src/server/config.ts +11 -0
  44. package/src/server/updateTestdirectorySchemaFile.ts +10 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tui-sandbox/library",
3
- "version": "11.6.7",
3
+ "version": "11.7.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/mikavilpas/tui-sandbox"
@@ -25,9 +25,10 @@
25
25
  "neovim": "5.3.0",
26
26
  "node-pty": "1.0.0",
27
27
  "prettier": "3.6.2",
28
+ "tsx": "4.20.5",
28
29
  "type-fest": "4.41.0",
29
30
  "winston": "3.17.0",
30
- "zod": "4.1.4"
31
+ "zod": "4.1.5"
31
32
  },
32
33
  "devDependencies": {
33
34
  "@types/command-exists": "1.2.3",
@@ -35,7 +36,6 @@
35
36
  "@types/express": "5.0.3",
36
37
  "@types/node": "24.3.0",
37
38
  "nodemon": "3.1.10",
38
- "tsx": "4.20.5",
39
39
  "vite": "7.1.3",
40
40
  "vitest": "3.2.4"
41
41
  },
@@ -1,9 +1,9 @@
1
1
  import { NeovimApplication, type StdoutOrStderrMessage } from "../../server/applications/neovim/NeovimApplication.js"
2
2
  import { prepareNewTestDirectory } from "../../server/applications/neovim/prepareNewTestDirectory.js"
3
+ import type { TestServerConfig } from "../../server/updateTestdirectorySchemaFile.js"
3
4
  import type { NeovimExec } from "../parseArguments.js"
4
- import { config } from "../tui.js"
5
5
 
6
- export async function commandTuiNeovimExec(command: NeovimExec): Promise<void> {
6
+ export async function commandTuiNeovimExec(command: NeovimExec, config: TestServerConfig): Promise<void> {
7
7
  // automatically dispose of the neovim instance when done
8
8
  await using app = new NeovimApplication(config.directories.testEnvironmentPath)
9
9
  app.events.on("stdout" satisfies StdoutOrStderrMessage, data => {
@@ -1,7 +1,7 @@
1
1
  import { installDependencies } from "../../server/applications/neovim/api.js"
2
- import { config } from "../tui.js"
2
+ import type { TestServerConfig } from "../../server/updateTestdirectorySchemaFile.js"
3
3
 
4
- export async function commandTuiNeovimPrepare(): Promise<void> {
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
7
  await installDependencies(
@@ -1,10 +1,11 @@
1
1
  import path from "path"
2
2
  import { createCypressSupportFile } from "../../server/cypress-support/createCypressSupportFile.js"
3
3
  import { startTestServer } from "../../server/server.js"
4
+ import type { TestServerConfig } from "../../server/updateTestdirectorySchemaFile.js"
4
5
  import { updateTestdirectorySchemaFile } from "../../server/updateTestdirectorySchemaFile.js"
5
- import { config, cwd } from "../tui.js"
6
+ import { cwd } from "../tui.js"
6
7
 
7
- export async function commandTuiStart(): Promise<void> {
8
+ export async function commandTuiStart(config: TestServerConfig): Promise<void> {
8
9
  try {
9
10
  await createCypressSupportFile({
10
11
  cypressSupportDirectoryPath: path.join(cwd, "cypress", "support"),
@@ -0,0 +1,73 @@
1
+ import assert from "assert"
2
+ import { writeFile } from "fs/promises"
3
+ import { expect } from "vitest"
4
+ import { TempDirectory } from "../server/applications/neovim/environment/TempDirectory.js"
5
+ import type { TestServerConfig } from "../server/updateTestdirectorySchemaFile.js"
6
+ import { testServerConfigSchema } from "../server/updateTestdirectorySchemaFile.js"
7
+ import type { ResolveTuiConfigResult, ResolveTuiConfigResultSuccess } from "./resolveTuiConfig.js"
8
+ import { resolveTuiConfig } from "./resolveTuiConfig.js"
9
+
10
+ it("defaults to the default configuration if no config file is found", async () => {
11
+ const config = await resolveTuiConfig(__dirname)
12
+ assert(!config.error)
13
+ expect(config.id).toBe("no-config-found" satisfies ResolveTuiConfigResultSuccess["id"])
14
+ expect(testServerConfigSchema.safeParse(config.result).success).toBe(true)
15
+ })
16
+
17
+ it("loads a custom configuration file if it exists", async () => {
18
+ using dir = TempDirectory.create()
19
+
20
+ const customConfig: TestServerConfig = {
21
+ directories: {
22
+ testEnvironmentPath: "./test-environment2/",
23
+ outputFilePath: "./output.ts",
24
+ },
25
+ port: 12345,
26
+ }
27
+ {
28
+ const filename = `${dir.path}/tui-sandbox.config.ts`
29
+ const contents = `export const config = ${JSON.stringify(customConfig)}`
30
+ await writeFile(filename, contents)
31
+ }
32
+
33
+ const config = await resolveTuiConfig(dir.path)
34
+ expect(config).toStrictEqual({
35
+ id: "custom-config",
36
+ result: customConfig,
37
+ } satisfies ResolveTuiConfigResult)
38
+ })
39
+
40
+ it("uses the default configuration file if the config has invalid contents", async () => {
41
+ using dir = TempDirectory.create()
42
+
43
+ {
44
+ const customConfig: TestServerConfig = {
45
+ // @ts-expect-error testing an invalid config on purpose
46
+ directories: undefined,
47
+ port: 12345,
48
+ }
49
+ const filename = `${dir.path}/tui-sandbox.config.ts`
50
+ const contents = `export const config = ${JSON.stringify(customConfig)}`
51
+ await writeFile(filename, contents)
52
+ }
53
+
54
+ const result = await resolveTuiConfig(dir.path)
55
+ assert(result.error)
56
+ expect(result.configFilePath).contains(dir.path)
57
+ expect(result.message).match(/Issues found in the config file/)
58
+ })
59
+
60
+ it("fails if the config has not been exported from the config file", async () => {
61
+ using dir = TempDirectory.create()
62
+
63
+ {
64
+ const filename = `${dir.path}/tui-sandbox.config.ts`
65
+ const contents = ``
66
+ await writeFile(filename, contents)
67
+ }
68
+
69
+ const result = await resolveTuiConfig(dir.path)
70
+ assert(result.error)
71
+ expect(result.configFilePath).contains(dir.path)
72
+ expect(result.message).match(/Issues found in the config file/)
73
+ })
@@ -0,0 +1,59 @@
1
+ import assert from "assert"
2
+ import { resolve } from "path/posix"
3
+ import { pathToFileURL } from "url"
4
+ import { debuglog } from "util"
5
+ import * as z from "zod"
6
+ import { createDefaultConfig } from "../server/config.js"
7
+ import { type TestServerConfig, testServerConfigSchema } from "../server/updateTestdirectorySchemaFile.js"
8
+
9
+ const log = debuglog("tui-sandbox.resolveConfig")
10
+
11
+ export type ResolveTuiConfigResultSuccess = {
12
+ id: "default-config" | "custom-config" | "no-config-found"
13
+ result: TestServerConfig
14
+ error?: never
15
+ }
16
+ export type ResolveTuiConfigResultError = {
17
+ error: object
18
+ configFilePath: string
19
+ message: string
20
+ }
21
+
22
+ export type ResolveTuiConfigResult = ResolveTuiConfigResultSuccess | ResolveTuiConfigResultError
23
+
24
+ export const resolveTuiConfig = async (cwd: string): Promise<ResolveTuiConfigResult> => {
25
+ const defaultConfig = createDefaultConfig(cwd, process.env)
26
+
27
+ const url = pathToFileURL(resolve(cwd, "tui-sandbox.config.ts"))
28
+
29
+ let file: unknown
30
+ try {
31
+ // loading typescript files works when using https://tsx.is/
32
+ file = await import(url.href)
33
+ log(`Found configuration file in ${url.pathname}:`, JSON.stringify(file, null, 2))
34
+ } catch (e) {
35
+ console.log("Using the default configuration.")
36
+ log("Config load error:", e)
37
+
38
+ return {
39
+ id: "no-config-found",
40
+ result: defaultConfig,
41
+ }
42
+ }
43
+
44
+ assert(file)
45
+ const customConfigSchema = z.strictObject({ config: testServerConfigSchema })
46
+ const customConfig = customConfigSchema.safeParse(file)
47
+ if (customConfig.success) {
48
+ return {
49
+ id: "custom-config",
50
+ result: customConfig.data.config,
51
+ }
52
+ } else {
53
+ return {
54
+ error: z.treeifyError(customConfig.error),
55
+ configFilePath: url.pathname,
56
+ message: `Issues found in the config file`,
57
+ }
58
+ }
59
+ }
@@ -1,12 +1,11 @@
1
1
  import assert from "node:assert"
2
- import path from "node:path"
3
- import type { TestServerConfig } from "../server/index.js"
4
2
  import type { TestResultExitCode } from "./commands/commandRun.js"
5
3
  import { commandRun } from "./commands/commandRun.js"
6
4
  import { commandTuiNeovimExec } from "./commands/commandTuiNeovimExec.js"
7
5
  import { commandTuiNeovimPrepare } from "./commands/commandTuiNeovimPrepare.js"
8
6
  import { commandTuiStart } from "./commands/commandTuiStart.js"
9
7
  import { parseArguments } from "./parseArguments.js"
8
+ import { resolveTuiConfig } from "./resolveTuiConfig.js"
10
9
 
11
10
  //
12
11
  // This is the main entrypoint to tui-sandbox
@@ -21,18 +20,14 @@ if (major < 24) {
21
20
  process.exit(1)
22
21
  }
23
22
 
24
- const outputFileName = "MyTestDirectory.ts"
25
-
26
23
  /** The cwd in the user's directory when they are running this script. Not the
27
24
  * cwd of the script itself. */
28
25
  export const cwd = process.cwd()
29
- export const config = {
30
- directories: {
31
- testEnvironmentPath: path.join(cwd, "test-environment/"),
32
- outputFilePath: path.join(cwd, outputFileName),
33
- },
34
- port: process.env["PORT"] ? parseInt(process.env["PORT"]) : 3000,
35
- } satisfies TestServerConfig
26
+ const configResult = await resolveTuiConfig(cwd)
27
+ if (configResult.error) {
28
+ console.error(configResult.message, configResult.error)
29
+ process.exit(1)
30
+ }
36
31
 
37
32
  // the arguments passed to this script start at index 2
38
33
  const args = process.argv.slice(2)
@@ -41,15 +36,15 @@ const command = await parseArguments(args)
41
36
 
42
37
  switch (command?.action) {
43
38
  case "neovim prepare": {
44
- await commandTuiNeovimPrepare()
39
+ await commandTuiNeovimPrepare(configResult.result)
45
40
  break
46
41
  }
47
42
  case "neovim exec": {
48
- await commandTuiNeovimExec(command)
43
+ await commandTuiNeovimExec(command, configResult.result)
49
44
  break
50
45
  }
51
46
  case "start": {
52
- await commandTuiStart()
47
+ await commandTuiStart(configResult.result)
53
48
  break
54
49
  }
55
50
  case "run": {
@@ -0,0 +1,18 @@
1
+ import fs from "fs"
2
+ import nodePath from "path"
3
+
4
+ export type TestTempDirPrefix = "test-temp-dir-"
5
+
6
+ export class TempDirectory implements Disposable {
7
+ private constructor(public readonly path: string) {}
8
+
9
+ public static create(): TempDirectory {
10
+ const tmp = fs.mkdtempSync("test-temp-dir-" satisfies TestTempDirPrefix)
11
+ const absolutePath = nodePath.resolve(tmp)
12
+ return new TempDirectory(absolutePath)
13
+ }
14
+
15
+ [Symbol.dispose](): void {
16
+ fs.rmdirSync(this.path, { recursive: true, maxRetries: 5 })
17
+ }
18
+ }
@@ -1,27 +1,12 @@
1
- import fs from "fs"
2
1
  import nodePath from "path"
3
2
  import { expect, it, vi } from "vitest"
4
3
  import type { TestDirsPath } from "./createTempDir.js"
5
4
  import { createTempDir } from "./createTempDir.js"
5
+ import type { TestTempDirPrefix } from "./TempDirectory.js"
6
+ import { TempDirectory } from "./TempDirectory.js"
6
7
 
7
8
  vi.spyOn(console, "log").mockImplementation(vi.fn())
8
9
 
9
- type TestTempDirPrefix = "test-temp-dir-"
10
-
11
- class TempDirectory implements Disposable {
12
- constructor(public readonly path: string) {}
13
-
14
- public static create(): TempDirectory {
15
- const tmp = fs.mkdtempSync("test-temp-dir-" satisfies TestTempDirPrefix)
16
- const absolutePath = nodePath.resolve(tmp)
17
- return new TempDirectory(absolutePath)
18
- }
19
-
20
- [Symbol.dispose](): void {
21
- fs.rmdirSync(this.path, { recursive: true, maxRetries: 5 })
22
- }
23
- }
24
-
25
10
  it("should create a temp dir with no contents", async () => {
26
11
  // typically the user will want to have contents, but this should not be an error
27
12
  using dir = TempDirectory.create()
@@ -0,0 +1,11 @@
1
+ import path from "path"
2
+ import type { TestServerConfig } from "./updateTestdirectorySchemaFile.js"
3
+
4
+ export const createDefaultConfig = (cwd: string, environment: NodeJS.ProcessEnv): TestServerConfig =>
5
+ ({
6
+ directories: {
7
+ testEnvironmentPath: path.join(cwd, "test-environment/"),
8
+ outputFilePath: path.join(cwd, "MyTestDirectory.ts"),
9
+ },
10
+ port: environment["PORT"] ? parseInt(environment["PORT"]) : 3000,
11
+ }) satisfies TestServerConfig
@@ -1,18 +1,20 @@
1
1
  import { readFileSync, writeFileSync } from "fs"
2
2
  import { debuglog } from "util"
3
+ import * as z from "zod"
3
4
  import { buildTestDirectorySchema } from "./dirtree/index.js"
4
5
 
5
6
  const log = debuglog("tui-sandbox.updateTestdirectorySchemaFile")
6
7
 
7
- export type DirectoriesConfig = {
8
- testEnvironmentPath: string
9
- outputFilePath: string
10
- }
8
+ export type DirectoriesConfig = TestServerConfig["directories"]
11
9
 
12
- export type TestServerConfig = {
13
- directories: DirectoriesConfig
14
- port: number
15
- }
10
+ export type TestServerConfig = z.output<typeof testServerConfigSchema>
11
+ export const testServerConfigSchema = z.strictObject({
12
+ directories: z.object({
13
+ testEnvironmentPath: z.string(),
14
+ outputFilePath: z.string(),
15
+ }),
16
+ port: z.number().int().min(1).max(65535),
17
+ })
16
18
 
17
19
  export type UpdateTestdirectorySchemaFileResult = "updated" | "did-nothing"
18
20