Skip to content

Commit f0ff34a

Browse files
committed
Restore clack prompts and migrate tern-cli build to ESM
1 parent ec172a2 commit f0ff34a

11 files changed

Lines changed: 117 additions & 108 deletions

File tree

packages/tern-cli/package-lock.json

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/tern-cli/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
"typecheck": "tsc --noEmit -p tsconfig.json"
1818
},
1919
"dependencies": {
20-
"@hookflo/tern-dev": "latest"
20+
"@hookflo/tern-dev": "latest",
21+
"@clack/prompts": "latest"
22+
},
23+
"type": "module",
24+
"engines": {
25+
"node": ">=18"
2126
}
2227
}

packages/tern-cli/src/files.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as fs from "node:fs";
22
import * as path from "node:path";
3-
import { confirm } from "./prompts";
3+
import * as clack from "@clack/prompts";
44

55
/** Returns the target handler file path for a framework/platform pair. */
66
export function getFilePath(framework: string, platform: string): string {
@@ -48,10 +48,10 @@ export async function createHandlerFile(
4848
const fullPath = path.join(process.cwd(), filePath);
4949

5050
if (fs.existsSync(fullPath)) {
51-
const overwrite = await confirm(
52-
`${path.basename(fullPath)} already exists. overwrite?`,
53-
);
54-
if (!overwrite) {
51+
const overwrite = await clack.confirm({
52+
message: `${path.basename(fullPath)} already exists. overwrite?`,
53+
});
54+
if (clack.isCancel(overwrite) || !overwrite) {
5555
return false;
5656
}
5757
}

packages/tern-cli/src/index.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
#!/usr/bin/env node
2-
import { GRAY, RESET } from "./colors";
3-
import { createConfig } from "./config";
4-
import { createHandlerFile, getFilePath, getWebhookPath } from "./files";
5-
import { installTern } from "./install";
6-
import { printEnvBlock, printLogo, printStep, printStepDone, printStepFile, printSummary } from "./print";
7-
import { getTemplate } from "./templates";
8-
import { startTunnel } from "./tunnel";
9-
import { askQuestions, ENV_VARS, getPlatformLabel } from "./wizard";
2+
import "./patch-clack.js";
3+
import { GRAY, RESET } from "./colors.js";
4+
import { createConfig } from "./config.js";
5+
import { createHandlerFile, getFilePath, getWebhookPath } from "./files.js";
6+
import { installTern } from "./install.js";
7+
import { printEnvBlock, printLogo, printStep, printStepDone, printStepFile, printSummary } from "./print.js";
8+
import { getTemplate } from "./templates.js";
9+
import { startTunnel } from "./tunnel.js";
10+
import { askQuestions, ENV_VARS, getPlatformLabel } from "./wizard.js";
1011

1112
function actionLabel(action: "both" | "handler" | "tunnel"): string {
1213
if (action === "both") return "handler + local testing";

packages/tern-cli/src/install.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { execSync } from "node:child_process";
22
import * as fs from "node:fs";
3-
import { printStep, printStepDone } from "./print";
3+
import { printStep, printStepDone } from "./print.js";
44

55
/** Detects the package manager install command from lockfiles. */
66
export function detectPackageManager(): string {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { GREEN } from "./colors.js";
2+
3+
let clackPatched = false;
4+
5+
export function patchClackColors(): void {
6+
if (clackPatched) return;
7+
clackPatched = true;
8+
9+
process.env.FORCE_COLOR = "3";
10+
11+
const originalWrite = process.stdout.write.bind(process.stdout);
12+
process.stdout.write = ((chunk: string | Uint8Array, ...args: unknown[]) => {
13+
if (typeof chunk === "string") {
14+
chunk = chunk
15+
.replace(/\x1b\[32m/g, GREEN)
16+
.replace(/\x1b\[36m/g, GREEN)
17+
.replace(/\x1b\[2;32m/g, GREEN);
18+
}
19+
20+
return originalWrite(chunk as never, ...(args as never[]));
21+
}) as typeof process.stdout.write;
22+
}
23+
24+
patchClackColors();

packages/tern-cli/src/print.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CYAN, GRAY, GREEN, MUTED, RED, RESET, WHITE, YELLOW } from "./colors";
1+
import { CYAN, GRAY, GREEN, MUTED, RED, RESET, WHITE, YELLOW } from "./colors.js";
22

33
const LABEL_WIDTH = 16;
44

packages/tern-cli/src/prompts.ts

Lines changed: 0 additions & 65 deletions
This file was deleted.

packages/tern-cli/src/tunnel.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { spawn } from "node:child_process";
2-
import { copyToClipboard } from "./clipboard";
3-
import { openBrowser } from "./browser";
2+
import { copyToClipboard } from "./clipboard.js";
3+
import { openBrowser } from "./browser.js";
44
import {
55
printEvent,
66
printExit,
@@ -9,7 +9,7 @@ import {
99
printStepDone,
1010
printUrlBox,
1111
startConnectingAnimation,
12-
} from "./print";
12+
} from "./print.js";
1313

1414
/** Starts tern-dev forwarding and streams connection updates. */
1515
export function startTunnel(

packages/tern-cli/src/wizard.ts

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { select, text } from "./prompts";
1+
import * as clack from "@clack/prompts";
22

33
/** Platform option metadata shown in the setup wizard. */
44
export const PLATFORMS = [
@@ -57,33 +57,51 @@ export interface WizardAnswers {
5757
port: string;
5858
}
5959

60+
function handleCancel(value: unknown): void {
61+
if (!clack.isCancel(value)) return;
62+
clack.cancel("cancelled");
63+
process.exit(0);
64+
}
65+
6066
/** Runs the interactive setup wizard. */
6167
export async function askQuestions(): Promise<WizardAnswers> {
62-
const platform = await select<Platform>(
63-
"which platform are you integrating?",
64-
PLATFORMS,
65-
);
68+
const platform = await clack.select<Platform>({
69+
message: "which platform are you integrating?",
70+
options: [...PLATFORMS],
71+
});
72+
handleCancel(platform);
6673

67-
const framework = await select<Framework>(
68-
"which framework are you using?",
69-
FRAMEWORKS,
70-
);
74+
const framework = await clack.select<Framework>({
75+
message: "which framework are you using?",
76+
options: [...FRAMEWORKS],
77+
});
78+
handleCancel(framework);
7179

72-
const action = await select<Action>("what would you like to do?", [
73-
{ value: "both", label: "set up webhook handler + test locally" },
74-
{ value: "handler", label: "set up webhook handler only" },
75-
{ value: "tunnel", label: "test locally only" },
76-
]);
80+
const action = await clack.select<Action>({
81+
message: "what would you like to do?",
82+
options: [
83+
{ value: "both", label: "set up webhook handler + test locally" },
84+
{ value: "handler", label: "set up webhook handler only" },
85+
{ value: "tunnel", label: "test locally only" },
86+
],
87+
});
88+
handleCancel(action);
7789

7890
let port = "3000";
7991
if (action !== "handler") {
80-
port = await text("which port is your app running on?", "3000", (v: string) => {
81-
const n = Number(v);
82-
if (!Number.isInteger(n) || n < 1 || n > 65535) {
83-
return "enter a valid port number";
84-
}
85-
return undefined;
92+
const entered = await clack.text({
93+
message: "which port is your app running on?",
94+
placeholder: "3000",
95+
defaultValue: "3000",
96+
validate: (v: string) => {
97+
const n = Number(v);
98+
if (!Number.isInteger(n) || n < 1 || n > 65535)
99+
return "enter a valid port number";
100+
return undefined;
101+
},
86102
});
103+
handleCancel(entered);
104+
port = entered;
87105
}
88106

89107
return { platform, framework, action, port };

0 commit comments

Comments
 (0)