@tui-sandbox/library 11.6.6 → 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.
- package/CHANGELOG.md +14 -0
- package/dist/browser/assets/{index-BanBEC6y.js → index-CQ6TDc4S.js} +7 -7
- package/dist/browser/index.html +1 -1
- package/dist/src/scripts/commands/commandTuiNeovimExec.d.ts +2 -1
- package/dist/src/scripts/commands/commandTuiNeovimExec.js +1 -2
- package/dist/src/scripts/commands/commandTuiNeovimExec.js.map +1 -1
- package/dist/src/scripts/commands/commandTuiNeovimPrepare.d.ts +2 -1
- package/dist/src/scripts/commands/commandTuiNeovimPrepare.js +1 -2
- package/dist/src/scripts/commands/commandTuiNeovimPrepare.js.map +1 -1
- package/dist/src/scripts/commands/commandTuiStart.d.ts +2 -1
- package/dist/src/scripts/commands/commandTuiStart.js +2 -2
- package/dist/src/scripts/commands/commandTuiStart.js.map +1 -1
- package/dist/src/scripts/resolveConfig.test.d.ts +1 -0
- package/dist/src/scripts/resolveConfig.test.js +144 -0
- package/dist/src/scripts/resolveConfig.test.js.map +1 -0
- package/dist/src/scripts/resolveTuiConfig.d.ts +13 -0
- package/dist/src/scripts/resolveTuiConfig.js +43 -0
- package/dist/src/scripts/resolveTuiConfig.js.map +1 -0
- package/dist/src/scripts/tui.d.ts +0 -7
- package/dist/src/scripts/tui.js +11 -13
- package/dist/src/scripts/tui.js.map +1 -1
- package/dist/src/server/applications/neovim/environment/TempDirectory.d.ts +7 -0
- package/dist/src/server/applications/neovim/environment/TempDirectory.js +17 -0
- package/dist/src/server/applications/neovim/environment/TempDirectory.js.map +1 -0
- package/dist/src/server/applications/neovim/environment/createTempDir.test.js +1 -15
- package/dist/src/server/applications/neovim/environment/createTempDir.test.js.map +1 -1
- package/dist/src/server/config.d.ts +2 -0
- package/dist/src/server/config.js +9 -0
- package/dist/src/server/config.js.map +1 -0
- package/dist/src/server/updateTestdirectorySchemaFile.d.ts +10 -8
- package/dist/src/server/updateTestdirectorySchemaFile.js +8 -0
- package/dist/src/server/updateTestdirectorySchemaFile.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/scripts/commands/commandTuiNeovimExec.ts +2 -2
- package/src/scripts/commands/commandTuiNeovimPrepare.ts +2 -2
- package/src/scripts/commands/commandTuiStart.ts +3 -2
- package/src/scripts/resolveConfig.test.ts +73 -0
- package/src/scripts/resolveTuiConfig.ts +59 -0
- package/src/scripts/tui.ts +11 -15
- package/src/server/applications/neovim/environment/TempDirectory.ts +18 -0
- package/src/server/applications/neovim/environment/createTempDir.test.ts +2 -17
- package/src/server/config.ts +11 -0
- 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.
|
|
3
|
+
"version": "11.7.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/mikavilpas/tui-sandbox"
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"@xterm/addon-fit": "0.10.0",
|
|
18
18
|
"@xterm/addon-unicode11": "0.8.0",
|
|
19
19
|
"@xterm/xterm": "5.5.0",
|
|
20
|
-
"concurrently": "9.2.
|
|
20
|
+
"concurrently": "9.2.1",
|
|
21
21
|
"cors": "2.8.5",
|
|
22
22
|
"cypress": "15.0.0",
|
|
23
23
|
"dree": "5.1.5",
|
|
@@ -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.
|
|
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.4",
|
|
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 {
|
|
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 {
|
|
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
|
+
}
|
package/src/scripts/tui.ts
CHANGED
|
@@ -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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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": {
|
|
@@ -57,7 +52,8 @@ switch (command?.action) {
|
|
|
57
52
|
// important:
|
|
58
53
|
//
|
|
59
54
|
// This is what determines if the test run was successful or not.
|
|
60
|
-
process.
|
|
55
|
+
process.exitCode = typeof result === "number" ? result : 1
|
|
56
|
+
break
|
|
61
57
|
}
|
|
62
58
|
default: {
|
|
63
59
|
command satisfies undefined
|
|
@@ -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
|
-
|
|
14
|
-
|
|
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
|
|