@tui-sandbox/library 11.11.2 → 12.0.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 (92) hide show
  1. package/dist/browser/assets/index-CYUPHpRk.css +1 -0
  2. package/dist/browser/assets/index-DPQpUaDL.js +9 -0
  3. package/dist/browser/index.html +2 -2
  4. package/dist/src/browser/neovim-client.d.ts +2 -0
  5. package/dist/src/browser/neovim-client.js +2 -0
  6. package/dist/src/browser/neovim-client.js.map +1 -1
  7. package/dist/src/client/index.d.ts +1 -0
  8. package/dist/src/client/neovim-terminal-client.d.ts +0 -2
  9. package/dist/src/client/neovim-terminal-client.js +0 -2
  10. package/dist/src/client/neovim-terminal-client.js.map +1 -1
  11. package/dist/src/client/startTerminal.d.ts +0 -2
  12. package/dist/src/client/startTerminal.js +0 -2
  13. package/dist/src/client/startTerminal.js.map +1 -1
  14. package/dist/src/client/terminal-terminal-client.d.ts +0 -1
  15. package/dist/src/client/terminal-terminal-client.js +0 -1
  16. package/dist/src/client/terminal-terminal-client.js.map +1 -1
  17. package/dist/src/server/cypress-support/contents.js +9 -11
  18. package/dist/src/server/cypress-support/contents.js.map +1 -1
  19. package/dist/src/server/index.d.ts +4 -0
  20. package/dist/src/server/index.js.map +1 -1
  21. package/dist/tsconfig.tsbuildinfo +1 -1
  22. package/package.json +34 -8
  23. package/CHANGELOG.md +0 -941
  24. package/dist/browser/assets/index-BQzArJW3.js +0 -9
  25. package/dist/browser/assets/index-hkmOP7rU.css +0 -1
  26. package/index.html +0 -11
  27. package/src/browser/neovim-client.ts +0 -126
  28. package/src/client/MyNeovimConfigModification.test.ts +0 -25
  29. package/src/client/MyNeovimConfigModification.ts +0 -8
  30. package/src/client/color-utilities.test.ts +0 -10
  31. package/src/client/color-utilities.ts +0 -9
  32. package/src/client/cypress-assertions.ts +0 -35
  33. package/src/client/index.ts +0 -4
  34. package/src/client/neovim-terminal-client.ts +0 -130
  35. package/src/client/public/DejaVuSansMNerdFontMono-Regular.ttf +0 -0
  36. package/src/client/startTerminal.ts +0 -97
  37. package/src/client/style.css +0 -32
  38. package/src/client/terminal-config.ts +0 -25
  39. package/src/client/terminal-terminal-client.ts +0 -106
  40. package/src/client/validateMouseEvent.ts +0 -22
  41. package/src/scripts/commands/commandRun.ts +0 -68
  42. package/src/scripts/commands/commandTuiNeovimExec.ts +0 -36
  43. package/src/scripts/commands/commandTuiNeovimPrepare.ts +0 -12
  44. package/src/scripts/commands/commandTuiStart.ts +0 -36
  45. package/src/scripts/parseArguments.test.ts +0 -28
  46. package/src/scripts/parseArguments.ts +0 -66
  47. package/src/scripts/resolveConfig.test.ts +0 -78
  48. package/src/scripts/resolveTuiConfig.ts +0 -65
  49. package/src/scripts/tui.ts +0 -77
  50. package/src/server/TestServer.ts +0 -73
  51. package/src/server/applications/neovim/NeovimApplication.ts +0 -236
  52. package/src/server/applications/neovim/NeovimJavascriptApiClient.test.ts +0 -48
  53. package/src/server/applications/neovim/NeovimJavascriptApiClient.ts +0 -68
  54. package/src/server/applications/neovim/api.ts +0 -257
  55. package/src/server/applications/neovim/environment/TempDirectory.ts +0 -18
  56. package/src/server/applications/neovim/environment/createTempDir.test.ts +0 -29
  57. package/src/server/applications/neovim/environment/createTempDir.ts +0 -91
  58. package/src/server/applications/neovim/neovimRouter.ts +0 -100
  59. package/src/server/applications/neovim/prepareNewTestDirectory.test.ts +0 -32
  60. package/src/server/applications/neovim/prepareNewTestDirectory.ts +0 -21
  61. package/src/server/applications/terminal/TerminalTestApplication.ts +0 -101
  62. package/src/server/applications/terminal/api.ts +0 -89
  63. package/src/server/applications/terminal/runBlockingShellCommand.test.ts +0 -41
  64. package/src/server/applications/terminal/runBlockingShellCommand.ts +0 -64
  65. package/src/server/applications/terminal/terminalRouter.ts +0 -47
  66. package/src/server/blockingCommandInputSchema.test.ts +0 -24
  67. package/src/server/blockingCommandInputSchema.ts +0 -27
  68. package/src/server/config.test.ts +0 -7
  69. package/src/server/config.ts +0 -18
  70. package/src/server/connection/trpc.ts +0 -3
  71. package/src/server/cypress-support/contents.ts +0 -245
  72. package/src/server/cypress-support/createCypressSupportFile.test.ts +0 -69
  73. package/src/server/cypress-support/createCypressSupportFile.ts +0 -56
  74. package/src/server/dirtree/index.test.ts +0 -352
  75. package/src/server/dirtree/index.ts +0 -144
  76. package/src/server/dirtree/json-to-zod.ts +0 -60
  77. package/src/server/index.ts +0 -6
  78. package/src/server/server.ts +0 -34
  79. package/src/server/types.ts +0 -98
  80. package/src/server/updateTestdirectorySchemaFile.test.ts +0 -49
  81. package/src/server/updateTestdirectorySchemaFile.ts +0 -71
  82. package/src/server/utilities/DisposableSingleApplication.test.ts +0 -92
  83. package/src/server/utilities/DisposableSingleApplication.ts +0 -49
  84. package/src/server/utilities/Lazy.ts +0 -16
  85. package/src/server/utilities/TerminalApplication.ts +0 -100
  86. package/src/server/utilities/generator.test.ts +0 -50
  87. package/src/server/utilities/generator.ts +0 -12
  88. package/src/server/utilities/tabId.ts +0 -4
  89. package/src/server/utilities/timeout.ts +0 -3
  90. package/src/server/utilities/timeoutable.ts +0 -19
  91. package/tsconfig.json +0 -31
  92. package/vite.config.js +0 -27
@@ -1,68 +0,0 @@
1
- import assert from "assert"
2
- import type { CloseEvent } from "concurrently"
3
- import concurrently from "concurrently"
4
- import type { PartialDeep } from "type-fest"
5
- import { debuglog } from "util"
6
- import * as z from "zod"
7
- import type { AllKeys } from "../../server/types.js"
8
-
9
- const log = debuglog("tui-sandbox.commandRun")
10
-
11
- export type TestResultExitCode = string | number
12
-
13
- const cypressName = "cypress"
14
- export async function commandRun(): Promise<TestResultExitCode> {
15
- const job = concurrently(
16
- [
17
- {
18
- name: "server",
19
- command: "tui start",
20
- prefixColor: "blue",
21
- },
22
- {
23
- name: cypressName,
24
- command: `'wait-on --timeout 60000 http-get://127.0.0.1:3000/ping && cypress run --config baseUrl=http://127.0.0.1:3000 --quiet'`,
25
- prefixColor: "yellow",
26
- },
27
- ],
28
- {
29
- killOthersOn: ["failure", "success"],
30
- padPrefix: true, // makes all the prefixes the same length
31
- successCondition: "command-cypress", // the test run that determines success/failure
32
- }
33
- )
34
-
35
- await job.result.then(
36
- _ => {
37
- log("All commands completed successfully")
38
- },
39
- (err: unknown) => {
40
- log("One or more commands failed. Debug info follows.", err)
41
- }
42
- )
43
-
44
- try {
45
- const result = await job.result
46
- const cypressCommand = result.find(cmd => cmd.command.name === "cypress")
47
- assert(cypressCommand, "Cypress command not found in the result")
48
- return cypressCommand.exitCode
49
- } catch (e) {
50
- // an array of [`CloseEvent`](#CloseEvent), in the order that the commands terminated.
51
- // https://github.com/open-cli-tools/concurrently/blob/37212b7d925d8ece22d3afa68a77eef36bb833cc/README.md?plain=1#L125
52
- const infos = z
53
- .array(
54
- z.object({
55
- command: z.object({
56
- name: z.string(),
57
- } satisfies PartialDeep<AllKeys<CloseEvent["command"]>>),
58
- exitCode: z.number().or(z.string()),
59
- } satisfies PartialDeep<AllKeys<CloseEvent>>)
60
- )
61
- .parse(e)
62
-
63
- const cypressCommand = infos.find(cmd => cmd.command.name === cypressName)
64
- assert(cypressCommand, "Cypress command not found in the result")
65
-
66
- return cypressCommand.exitCode
67
- }
68
- }
@@ -1,36 +0,0 @@
1
- import { NeovimApplication, type StdoutOrStderrMessage } from "../../server/applications/neovim/NeovimApplication.js"
2
- import { prepareNewTestDirectory } from "../../server/applications/neovim/prepareNewTestDirectory.js"
3
- import type { TestServerConfigMetadata } from "../../server/updateTestdirectorySchemaFile.js"
4
- import type { NeovimExec } from "../parseArguments.js"
5
-
6
- export async function commandTuiNeovimExec(command: NeovimExec, config: TestServerConfigMetadata): Promise<void> {
7
- // automatically dispose of the neovim instance when done
8
- await using app = new NeovimApplication(config.config.directories.testEnvironmentPath)
9
- app.events.on("stdout" satisfies StdoutOrStderrMessage, data => {
10
- console.log(` neovim output: ${data}`)
11
- })
12
- const testDirectory = await prepareNewTestDirectory(config.config)
13
- const NVIM_APPNAME = process.env["NVIM_APPNAME"]
14
-
15
- if (NVIM_APPNAME && !config.config.integrations.neovim.NVIM_APPNAMEs.find(n => n === NVIM_APPNAME)) {
16
- process.exitCode = 1
17
- const message = `The NVIM_APPNAME environment variable is set to "${NVIM_APPNAME}", but only the following neovim configurations are known in the configuration file: ${JSON.stringify(
18
- config.config.integrations.neovim.NVIM_APPNAMEs
19
- )}. Please set NVIM_APPNAME to one of the configured names or unset it to use the default ("nvim"). Config file path: ${config.configFilePath}`
20
-
21
- console.error(message)
22
-
23
- return
24
- }
25
-
26
- await app.startNextAndKillCurrent(
27
- testDirectory,
28
- {
29
- filename: "empty.txt",
30
- headlessCmd: command.command,
31
- NVIM_APPNAME,
32
- },
33
- { cols: 80, rows: 24 }
34
- )
35
- await app.application.untilExit()
36
- }
@@ -1,12 +0,0 @@
1
- import { installDependencies } from "../../server/applications/neovim/api.js"
2
- import type { TestServerConfigMetadata } from "../../server/updateTestdirectorySchemaFile.js"
3
-
4
- export async function commandTuiNeovimPrepare(config: TestServerConfigMetadata): Promise<void> {
5
- const NVIM_APPNAME = process.env["NVIM_APPNAME"]
6
- console.log(`🚀 Installing neovim dependencies${NVIM_APPNAME ? ` for NVIM_APPNAME=${NVIM_APPNAME}` : ""}...`)
7
- await installDependencies(process.env["NVIM_APPNAME"], config.config).catch((err: unknown) => {
8
- console.error("Error installing neovim dependencies", err)
9
- process.exit(1)
10
- })
11
- process.exit(0)
12
- }
@@ -1,36 +0,0 @@
1
- import path from "path"
2
- import { createCypressSupportFile } from "../../server/cypress-support/createCypressSupportFile.js"
3
- import { startTestServer } from "../../server/server.js"
4
- import type { TestServerConfig, TestServerConfigMetadata } from "../../server/updateTestdirectorySchemaFile.js"
5
- import { updateTestdirectorySchemaFile } from "../../server/updateTestdirectorySchemaFile.js"
6
- import { cwd } from "../tui.js"
7
-
8
- export async function commandTuiStart(config: TestServerConfigMetadata): Promise<void> {
9
- await Promise.allSettled([updateSchemaFile(config.config), createSupportFile()])
10
-
11
- try {
12
- console.log(`🚀 Starting test server in ${cwd} - this should be the root of your integration-tests directory 🤞🏻`)
13
- await startTestServer(config.config)
14
- } catch (e) {
15
- console.error("Failed to startTestServer", e)
16
- }
17
- }
18
-
19
- async function updateSchemaFile(config: TestServerConfig): Promise<void> {
20
- try {
21
- await updateTestdirectorySchemaFile(config)
22
- } catch (e) {
23
- console.error("Failed to updateTestdirectorySchemaFile", e)
24
- }
25
- }
26
-
27
- async function createSupportFile(): Promise<void> {
28
- try {
29
- await createCypressSupportFile({
30
- cypressSupportDirectoryPath: path.join(cwd, "cypress", "support"),
31
- supportFileName: "tui-sandbox.ts",
32
- })
33
- } catch (e) {
34
- console.error("Failed to createCypressSupportFile", e)
35
- }
36
- }
@@ -1,28 +0,0 @@
1
- import { describe, expect, it } from "vitest"
2
- import { parseArguments } from "./parseArguments.js"
3
-
4
- it(`can parse "neovim prepare"`, async () => {
5
- expect(await parseArguments(["neovim", "prepare"])).toEqual({ action: "neovim prepare" })
6
- expect(await parseArguments(["neovim", "prepare", "foo"])).toBeUndefined()
7
- })
8
-
9
- describe("neovim exec", () => {
10
- it(`can parse "neovim exec <command>"`, async () => {
11
- expect(await parseArguments(["neovim", "exec", "foo"])).toEqual({ action: "neovim exec", command: "foo" })
12
- })
13
-
14
- it(`only allows one argument`, async () => {
15
- expect(await parseArguments(["neovim", "exec"])).toBeUndefined()
16
- expect(await parseArguments(["neovim", "exec", "foo", "bar"])).toBeUndefined()
17
- })
18
- })
19
-
20
- it(`can parse "start"`, async () => {
21
- expect(await parseArguments(["start"])).toEqual({ action: "start" })
22
- expect(await parseArguments(["start", "foo"])).toBeUndefined()
23
- })
24
-
25
- it(`can parse "run"`, async () => {
26
- expect(await parseArguments(["run"])).toEqual({ action: "run" })
27
- expect(await parseArguments(["run", "foo"])).toBeUndefined()
28
- })
@@ -1,66 +0,0 @@
1
- import assert from "assert"
2
- import * as z from "zod"
3
-
4
- export const parseArguments = async (args: string[]): Promise<ParseArgumentsResult | undefined> => {
5
- {
6
- const schema = z.tuple([z.literal("neovim"), z.literal("prepare")])
7
- const prepareArguments = schema.safeParse(args)
8
- if (prepareArguments.success) {
9
- return {
10
- action: "neovim prepare",
11
- }
12
- }
13
- }
14
-
15
- {
16
- const schema = z.tuple([z.literal("neovim"), z.literal("exec"), z.string()])
17
- const execArguments = schema.safeParse(args)
18
- if (execArguments.success) {
19
- const command = execArguments.data.at(2)
20
- assert(command, "No command provided for neovim exec")
21
- return {
22
- action: "neovim exec",
23
- command,
24
- }
25
- }
26
- }
27
-
28
- {
29
- const schema = z.tuple([z.literal("start")])
30
- const result = schema.safeParse(args)
31
- if (result.success) {
32
- return {
33
- action: "start",
34
- }
35
- }
36
- }
37
-
38
- {
39
- const schema = z.tuple([z.literal("run")])
40
- const result = schema.safeParse(args)
41
- if (result.success) {
42
- return {
43
- action: "run",
44
- }
45
- }
46
- }
47
- }
48
-
49
- export type ParseArgumentsResult = NeovimPrepare | NeovimExec | TuiStart | TuiRunOnce
50
-
51
- export type NeovimExec = {
52
- action: "neovim exec"
53
- command: string
54
- }
55
-
56
- export type NeovimPrepare = {
57
- action: "neovim prepare"
58
- }
59
-
60
- export type TuiStart = {
61
- action: "start"
62
- }
63
-
64
- export type TuiRunOnce = {
65
- action: "run"
66
- }
@@ -1,78 +0,0 @@
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.config).success).toBe(true)
15
- })
16
-
17
- it("loads a custom configuration file if it exists", async () => {
18
- using dir = TempDirectory.create()
19
-
20
- const filename = `${dir.path}/tui-sandbox.config.ts`
21
- const customConfig: TestServerConfig = {
22
- directories: {
23
- testEnvironmentPath: "./test-environment2/",
24
- outputFilePath: "./output.ts",
25
- latestSymlinkName: "latest",
26
- },
27
- integrations: { neovim: { NVIM_APPNAMEs: ["nvim", "nvim_2"] } },
28
- port: 12345,
29
- }
30
- {
31
- const contents = `export const config = ${JSON.stringify(customConfig)}`
32
- await writeFile(filename, contents)
33
- }
34
-
35
- const config = await resolveTuiConfig(dir.path)
36
- expect(config).toStrictEqual({
37
- id: "custom-config",
38
- result: {
39
- config: customConfig,
40
- configFilePath: filename,
41
- },
42
- } satisfies ResolveTuiConfigResult)
43
- })
44
-
45
- it("uses the default configuration file if the config has invalid contents", async () => {
46
- using dir = TempDirectory.create()
47
-
48
- {
49
- const customConfig: TestServerConfig = {
50
- // @ts-expect-error testing an invalid config on purpose
51
- directories: undefined,
52
- port: 12345,
53
- }
54
- const filename = `${dir.path}/tui-sandbox.config.ts`
55
- const contents = `export const config = ${JSON.stringify(customConfig)}`
56
- await writeFile(filename, contents)
57
- }
58
-
59
- const result = await resolveTuiConfig(dir.path)
60
- assert(result.error)
61
- expect(result.configFilePath).contains(dir.path)
62
- expect(result.message).match(/Issues found in the config file/)
63
- })
64
-
65
- it("fails if the config has not been exported from the config file", async () => {
66
- using dir = TempDirectory.create()
67
-
68
- {
69
- const filename = `${dir.path}/tui-sandbox.config.ts`
70
- const contents = ``
71
- await writeFile(filename, contents)
72
- }
73
-
74
- const result = await resolveTuiConfig(dir.path)
75
- assert(result.error)
76
- expect(result.configFilePath).contains(dir.path)
77
- expect(result.message).match(/Issues found in the config file/)
78
- })
@@ -1,65 +0,0 @@
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 { testServerConfigSchema, type TestServerConfigMetadata } 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: TestServerConfigMetadata
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: {
41
- config: defaultConfig,
42
- configFilePath: url.pathname,
43
- },
44
- }
45
- }
46
-
47
- assert(file)
48
- const customConfigSchema = z.strictObject({ config: testServerConfigSchema })
49
- const customConfig = customConfigSchema.safeParse(file)
50
- if (customConfig.success) {
51
- return {
52
- id: "custom-config",
53
- result: {
54
- config: customConfig.data.config,
55
- configFilePath: url.pathname,
56
- },
57
- }
58
- } else {
59
- return {
60
- error: z.treeifyError(customConfig.error),
61
- configFilePath: url.pathname,
62
- message: `Issues found in the config file`,
63
- }
64
- }
65
- }
@@ -1,77 +0,0 @@
1
- import assert from "node:assert"
2
- import type { TestServerConfigMetadata } from "../server/updateTestdirectorySchemaFile.js"
3
- import type { TestResultExitCode } from "./commands/commandRun.js"
4
- import { commandRun } from "./commands/commandRun.js"
5
- import { commandTuiNeovimExec } from "./commands/commandTuiNeovimExec.js"
6
- import { commandTuiNeovimPrepare } from "./commands/commandTuiNeovimPrepare.js"
7
- import { commandTuiStart } from "./commands/commandTuiStart.js"
8
- import { parseArguments } from "./parseArguments.js"
9
- import { resolveTuiConfig } from "./resolveTuiConfig.js"
10
-
11
- //
12
- // This is the main entrypoint to tui-sandbox
13
- //
14
-
15
- const [major] = process.versions.node.split(".").map(Number)
16
- assert(major)
17
- assert(!isNaN(major))
18
-
19
- if (major < 24) {
20
- console.error(`tui-sandbox error: Node.js >= 24.0.0 is required. You are using ${process.version}.`)
21
- process.exit(1)
22
- }
23
-
24
- /** The cwd in the user's directory when they are running this script. Not the
25
- * cwd of the script itself. */
26
- export const cwd = process.cwd()
27
- const configResult = await resolveTuiConfig(cwd)
28
- if (configResult.error) {
29
- console.error(configResult.message, configResult.error)
30
- process.exit(1)
31
- }
32
-
33
- // the arguments passed to this script start at index 2
34
- const args = process.argv.slice(2)
35
- const config: TestServerConfigMetadata = configResult.result
36
- const command = await parseArguments(args)
37
-
38
- switch (command?.action) {
39
- case "neovim prepare": {
40
- await commandTuiNeovimPrepare(config)
41
- break
42
- }
43
- case "neovim exec": {
44
- await commandTuiNeovimExec(command, config)
45
- break
46
- }
47
- case "start": {
48
- await commandTuiStart(config)
49
- break
50
- }
51
- case "run": {
52
- const result: TestResultExitCode = await commandRun()
53
- // important:
54
- //
55
- // This is what determines if the test run was successful or not.
56
- process.exitCode = typeof result === "number" ? result : 1
57
- break
58
- }
59
- case undefined: {
60
- command satisfies undefined
61
- showUsageAndExit()
62
- }
63
- }
64
-
65
- function showUsageAndExit() {
66
- console.log(
67
- [
68
- //
69
- `Usage (pick one):`,
70
- ` tui start`,
71
- ` tui neovim exec '<ex-command>'`,
72
- ` tui neovim prepare`,
73
- ].join("\n")
74
- )
75
-
76
- process.exit(1)
77
- }
@@ -1,73 +0,0 @@
1
- import type { AnyTRPCRouter } from "@trpc/server"
2
- import * as trpcExpress from "@trpc/server/adapters/express"
3
- import cors from "cors"
4
- import { once } from "events"
5
- import express from "express"
6
- import { accessSync } from "fs"
7
- import path from "path"
8
- import { fileURLToPath } from "url"
9
- import { debuglog } from "util"
10
-
11
- export type TestServerSettings = {
12
- port: number
13
- }
14
-
15
- const __filename = fileURLToPath(import.meta.url)
16
- const __dirname = path.dirname(__filename)
17
- const log = debuglog("tui-sandbox.TestServer")
18
-
19
- export class TestServer {
20
- public constructor(private readonly settings: TestServerSettings) {}
21
-
22
- public async startAndRun(appRouter: AnyTRPCRouter): Promise<void> {
23
- log("🚀 Server starting")
24
-
25
- const app = express()
26
- app.use(
27
- "/trpc",
28
- trpcExpress.createExpressMiddleware({
29
- router: appRouter,
30
- createContext: () => ({}),
31
- middleware: cors({
32
- origin: "*",
33
- }),
34
- })
35
- )
36
-
37
- {
38
- const publicPath = path.resolve(__dirname, "..", "..", "browser")
39
- try {
40
- accessSync(publicPath)
41
- } catch {
42
- // This is normal when developing the tui-sandbox library locally. It
43
- // should always exist when using it as an npm package, however.
44
- console.warn(
45
- `⚠️ Warning: Looks like the tui-sandbox root contents directory is not accessible at: ${publicPath}`
46
- )
47
- }
48
-
49
- // eslint-disable-next-line import-x/no-named-as-default-member
50
- app.use(express.static(publicPath))
51
- }
52
-
53
- app.use("/ping", (_, res) => {
54
- // used by the command-line test runner to see when the server is ready
55
- res.send("pong")
56
- })
57
-
58
- const server = app.listen(this.settings.port, "0.0.0.0")
59
-
60
- console.info(`✅ Server listening on port ${this.settings.port}`)
61
-
62
- await Promise.race([once(process, "SIGTERM"), once(process, "SIGINT")])
63
- log("😴 Shutting down...")
64
- server.close(error => {
65
- if (error) {
66
- console.error("Error closing server", error)
67
- process.exit(1)
68
- }
69
- log("Server closed")
70
- process.exit(0)
71
- })
72
- }
73
- }