Skip to content

Commit 419c971

Browse files
c-tsx
1 parent 6978e6d commit 419c971

2 files changed

Lines changed: 102 additions & 22 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"test:update": "pnpm -r test:update",
3333
"test:update:subset": "pnpm -r test:update:subset",
3434
"generate-grammar": "pnpm -r generate-grammar",
35-
"transform-recorded-tests": "c-tsx ./packages/cursorless-engine/src/scripts/transformRecordedTests/index.ts"
35+
"transform-recorded-tests": "pnpm exec ./packages/common/scripts/c-tsx.js ./packages/cursorless-engine/src/scripts/transformRecordedTests/index.ts"
3636
},
3737
"devDependencies": {
3838
"@eslint/config-helpers": "^0.5.3",

packages/common/scripts/c-tsx.js

Lines changed: 101 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,113 @@
11
#!/usr/bin/env node
22
/* global process, console */
33

4-
import { spawn } from "node:child_process";
5-
import { dirname, join } from "node:path";
4+
// This script runs a TypeScript file using Node.js by first bundling it with
5+
// esbuild.
6+
7+
import { spawn } from "cross-spawn";
8+
import { build } from "esbuild";
9+
import { existsSync, mkdirSync, rmSync } from "node:fs";
610
import { fileURLToPath } from "node:url";
11+
import { dirname, join } from "node:path";
12+
import { randomBytes } from "node:crypto";
13+
14+
/**
15+
* Run a command with arguments and return a child process
16+
* @param {string} command
17+
* @param {string[]} args
18+
* @param {Partial<NodeJS.ProcessEnv>?} extraEnv
19+
*/
20+
function runCommand(command, args, extraEnv = {}) {
21+
return spawn(command, args, {
22+
stdio: "inherit",
23+
env: {
24+
...process.env,
25+
...extraEnv,
26+
},
27+
});
28+
}
729

8-
const [fileToRun, ...childArgs] = process.argv.slice(2);
30+
/**
31+
* Create a temporary directory and return its path
32+
* @param {string} baseDir
33+
*/
34+
function createTempDirectory(baseDir) {
35+
const tempDir = join(
36+
baseDir,
37+
"out",
38+
"c-tsx-tmp",
39+
randomBytes(16).toString("hex"),
40+
);
941

10-
if (fileToRun == null) {
11-
console.error("Error: No input file specified.");
12-
console.error("Usage: c-tsx <file.ts> [script args...]");
13-
process.exit(1);
42+
mkdirSync(tempDir, { recursive: true });
43+
44+
return tempDir;
45+
}
46+
47+
/**
48+
* Clean up the temporary directory
49+
* @param {import("fs").PathLike} tempDir
50+
*/
51+
function cleanupTempDirectory(tempDir) {
52+
if (existsSync(tempDir)) {
53+
rmSync(tempDir, { recursive: true });
54+
}
1455
}
1556

16-
const scriptDirectory = dirname(fileURLToPath(import.meta.url));
17-
const repoRoot = join(scriptDirectory, "../../..");
57+
// Main function to execute the script
58+
async function main() {
59+
const args = process.argv.slice(2);
1860

19-
const child = spawn(
20-
process.platform === "win32" ? "tsx.cmd" : "tsx",
21-
[fileToRun, ...childArgs],
22-
{
23-
stdio: "inherit",
24-
env: {
25-
...process.env,
26-
CURSORLESS_REPO_ROOT: repoRoot,
61+
// Check if the input file is specified
62+
if (args.length === 0) {
63+
console.error("Error: No input file specified.");
64+
console.error("Usage: c-tsx <file.ts> [script args...]");
65+
process.exit(1);
66+
}
67+
68+
const [fileToRun, ...childArgs] = args;
69+
70+
// Note that the temporary directory must be in the workspace root, otherwise
71+
// VSCode will ignore the source maps, and breakpoints will not work.
72+
const tempDir = createTempDirectory(process.cwd());
73+
const outFile = join(tempDir, "out.cjs");
74+
75+
// Set up cleanup for when the script exits
76+
process.on("exit", () => cleanupTempDirectory(tempDir));
77+
process.on("SIGINT", () => cleanupTempDirectory(tempDir));
78+
process.on("SIGTERM", () => cleanupTempDirectory(tempDir));
79+
80+
// Run esbuild to bundle the TypeScript file
81+
await build({
82+
entryPoints: [fileToRun],
83+
sourcemap: true,
84+
conditions: ["cursorless:bundler"],
85+
logLevel: "warning",
86+
platform: "node",
87+
bundle: true,
88+
format: "cjs",
89+
outfile: outFile,
90+
external: ["./reporters/parallel-buffered", "./worker.js"],
91+
});
92+
93+
const scriptDirectory = dirname(fileURLToPath(import.meta.url));
94+
const repoRoot = join(scriptDirectory, "..", "..", "..");
95+
96+
const nodeProcess = runCommand(
97+
process.execPath,
98+
["--enable-source-maps", outFile, ...childArgs],
99+
{
100+
["CURSORLESS_REPO_ROOT"]: repoRoot,
27101
},
28-
},
29-
);
102+
);
103+
nodeProcess.on("error", (error) => {
104+
console.error(error);
105+
process.exit(1);
106+
});
107+
nodeProcess.on("close", (code) => process.exit(code ?? undefined));
108+
}
30109

31-
child.on("close", (code) => {
32-
process.exit(code ?? undefined);
110+
main().catch((error) => {
111+
console.error(error);
112+
process.exit(1);
33113
});

0 commit comments

Comments
 (0)