authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-05 01:54:25-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-05 01:54:25-07:00
log0acf05f4f561b873853587f8629ca691b18a613a
treeec6b55eb8dce9b1c28d7bf3d92d59d78ce601338
parent4db2c542a8c5e6b6756fac08615e30b220b71a2f
signature Signed by PGP key B5690EEEBB952194

test(server): cover CLI runner detection through command suggestions (#10066)


2 files changed, 49 insertions(+), 36 deletions(-)

apps/server/src/cli/invocation.test.ts+47-34
...@@ -1,49 +1,62 @@...@@ -1,49 +1,62 @@
1import { assert, it } from "@effect/vitest";1import { assert, it } from "@effect/vitest";
22
3import { detectCliRunner, formatCliCommand, suggestedPackageSpec } from "./invocation.ts";3import { formatCliCommand } from "./invocation.ts";
44
5it("detects package runners from their cache entry paths", () => {5it("formats package runner commands from their cache entry paths", () => {
6 assert.equal(detectCliRunner("/home/theo/.npm/_npx/abc123/node_modules/t3/dist/bin.mjs"), "npx");6 for (const [entryPath, expected] of [
7 assert.equal(7 ["/home/theo/.npm/_npx/abc123/node_modules/t3/dist/bin.mjs", "npx t3 serve"],
8 detectCliRunner(8 [
9 "C:\\Users\\theo\\AppData\\Local\\npm-cache\\_npx\\abc\\node_modules\\t3\\dist\\bin.mjs",9 "C:\\Users\\theo\\AppData\\Local\\npm-cache\\_npx\\abc\\node_modules\\t3\\dist\\bin.mjs",
10 ),10 "npx t3 serve",
11 "npx",11 ],
12 );12 ["/home/theo/.cache/pnpm/dlx/abc/node_modules/t3/dist/bin.mjs", "pnpm dlx t3 serve"],
13 assert.equal(13 [
14 detectCliRunner("/home/theo/.cache/pnpm/dlx/abc/node_modules/t3/dist/bin.mjs"),14 "/home/theo/.local/share/pnpm/.pnpm/dlx/abc/node_modules/t3/dist/bin.mjs",
15 "pnpm dlx",15 "pnpm dlx t3 serve",
16 );16 ],
17 assert.equal(17 [
18 detectCliRunner("/home/theo/.local/share/pnpm/.pnpm/dlx/abc/node_modules/t3/dist/bin.mjs"),
19 "pnpm dlx",
20 );
21 assert.equal(
22 detectCliRunner(
23 "C:\\Users\\theo\\AppData\\Local\\pnpm-cache\\dlx\\abc\\node_modules\\t3\\dist\\bin.mjs",18 "C:\\Users\\theo\\AppData\\Local\\pnpm-cache\\dlx\\abc\\node_modules\\t3\\dist\\bin.mjs",
24 ),19 "pnpm dlx t3 serve",
25 "pnpm dlx",20 ],
26 );21 ["/home/theo/.bun/install/cache/t3@0.0.31/dist/bin.mjs", "bunx t3 serve"],
27 assert.equal(detectCliRunner("/home/theo/.bun/install/cache/t3@0.0.31/dist/bin.mjs"), "bunx");22 ["/tmp/bunx-1000-t3@latest/node_modules/t3/dist/bin.mjs", "bunx t3 serve"],
28 assert.equal(detectCliRunner("/tmp/bunx-1000-t3@latest/node_modules/t3/dist/bin.mjs"), "bunx");23 [
29 assert.equal(
30 detectCliRunner(
31 "C:\\Users\\theo\\AppData\\Local\\Temp\\bunx-0-t3@latest\\node_modules\\t3\\dist\\bin.mjs",24 "C:\\Users\\theo\\AppData\\Local\\Temp\\bunx-0-t3@latest\\node_modules\\t3\\dist\\bin.mjs",
32 ),25 "bunx t3 serve",
33 "bunx",26 ],
34 );27 ] as const) {
28 assert.equal(formatCliCommand({ subcommand: "serve", entryPath, version: "0.0.31" }), expected);
29 }
35});30});
3631
37it("treats stable installs as direct invocations", () => {32it("treats stable installs as direct invocations", () => {
38 assert.isNull(detectCliRunner("/usr/local/lib/node_modules/t3/dist/bin.mjs"));33 for (const entryPath of [
39 assert.isNull(detectCliRunner("/home/theo/Code/work/t3code/apps/server/dist/bin.mjs"));34 "/usr/local/lib/node_modules/t3/dist/bin.mjs",
40 assert.isNull(detectCliRunner("/home/theo/.t3/runtime/0.0.31/node_modules/t3/dist/bin.mjs"));35 "/home/theo/Code/work/t3code/apps/server/dist/bin.mjs",
41 assert.isNull(detectCliRunner(""));36 "/home/theo/.t3/runtime/0.0.31/node_modules/t3/dist/bin.mjs",
37 "",
38 ]) {
39 assert.equal(
40 formatCliCommand({ subcommand: "serve", entryPath, version: "0.0.31" }),
41 "t3 serve",
42 );
43 }
42});44});
4345
44it("re-suggests the nightly channel only for nightly builds", () => {46it("re-suggests the nightly channel only for nightly builds", () => {
45 assert.equal(suggestedPackageSpec("0.0.31-nightly.20260729"), "t3@nightly");47 for (const [version, expected] of [
46 assert.equal(suggestedPackageSpec("0.0.31"), "t3");48 ["0.0.31-nightly.20260729", "npx t3@nightly serve"],
49 ["0.0.31", "npx t3 serve"],
50 ] as const) {
51 assert.equal(
52 formatCliCommand({
53 subcommand: "serve",
54 entryPath: "/home/theo/.npm/_npx/abc123/node_modules/t3/dist/bin.mjs",
55 version,
56 }),
57 expected,
58 );
59 }
47});60});
4861
49it("formats serve suggestions to match the launching command", () => {62it("formats serve suggestions to match the launching command", () => {
apps/server/src/cli/invocation.ts+2-2
...@@ -18,7 +18,7 @@ export type CliRunner = "npx" | "pnpm dlx" | "bunx";...@@ -18,7 +18,7 @@ export type CliRunner = "npx" | "pnpm dlx" | "bunx";
18 * Global installs and repo checkouts match none of these and return null.18 * Global installs and repo checkouts match none of these and return null.
19 * Detection is best-effort; callers must fail closed to a plain `t3` command.19 * Detection is best-effort; callers must fail closed to a plain `t3` command.
20 */20 */
21export function detectCliRunner(entryPath: string): CliRunner | null {21function detectCliRunner(entryPath: string): CliRunner | null {
22 const path = entryPath.replaceAll("\\", "/");22 const path = entryPath.replaceAll("\\", "/");
23 if (path.includes("/_npx/")) {23 if (path.includes("/_npx/")) {
24 return "npx";24 return "npx";
...@@ -42,7 +42,7 @@ export function detectCliRunner(entryPath: string): CliRunner | null {...@@ -42,7 +42,7 @@ export function detectCliRunner(entryPath: string): CliRunner | null {
42 * from the running version: nightly builds re-suggest the nightly channel,42 * from the running version: nightly builds re-suggest the nightly channel,
43 * anything else suggests the bare package.43 * anything else suggests the bare package.
44 */44 */
45export function suggestedPackageSpec(version: string): string {45function suggestedPackageSpec(version: string): string {
46 return version.includes("-nightly.") ? "t3@nightly" : "t3";46 return version.includes("-nightly.") ? "t3@nightly" : "t3";
47}47}
4848