feat(tern-cli): migrate scaffolding UX to Ink and normalize framework templates#11
feat(tern-cli): migrate scaffolding UX to Ink and normalize framework templates#11Prateek32177 wants to merge 4 commits intomainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1338015ef6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
packages/tern-cli/src/files.ts
Outdated
| return | ||
| } | ||
| const current = fs.readFileSync(fullPath, 'utf8') | ||
| if (current !== content) fs.writeFileSync(fullPath, content, 'utf8') |
There was a problem hiding this comment.
Prevent silent overwrite of existing scaffold targets
createHandlerFile now overwrites any existing file whenever the generated content differs, with no confirmation or --force gate. Since run() invokes this for primary handlers and support files (src/index.ts, src/routes/webhooks/index.ts, src/env.ts), rerunning scaffold in an existing Express/Hono/Cloudflare codebase can silently replace user-maintained entrypoints and routes, which is a destructive regression from the previous confirm-before-overwrite behavior.
Useful? React with 👍 / 👎.
packages/tern-cli/src/templates.ts
Outdated
| { status: 200 } | ||
| ) | ||
| function cloudflareTemplate(p: string): string { | ||
| return `import { createWebhookHandler } from '@hookflo/tern/cloudflare'\n\n// ─── Reliability ─────────────────────────────────────────────────────────────\n// queue: false → direct execution\n// queue: true → not supported on Workers — use Cloudflare Queues for guaranteed delivery\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface Env {\n WEBHOOK_SECRET: string\n // QSTASH_TOKEN: string\n // QSTASH_CURRENT_SIGNING_KEY: string\n // QSTASH_NEXT_SIGNING_KEY: string\n // SLACK_WEBHOOK_URL: string\n // DISCORD_WEBHOOK_URL: string\n [key: string]: unknown\n}\n\nexport default {\n async fetch(request: Request, env: Env): Promise<Response> {\n const url = new URL(request.url)\n\n if (url.pathname === '/') {\n return Response.json({ status: 'ok', framework: 'cloudflare-workers' })\n }\n\n if (url.pathname === '/webhooks/${p}' && request.method === 'POST') {\n const handler = createWebhookHandler({\n platform: '${p}',\n secret: env.WEBHOOK_SECRET,\n handler: async (payload) => {\n console.log('✅ ${p} webhook verified. Event:', payload?.type)\n return { received: true }\n },\n })\n\n return handler(request, env)\n }\n\n return Response.json({ error: 'Not found' }, { status: 404 })\n },\n}\n` |
There was a problem hiding this comment.
Use selected secret env var in Cloudflare template
The Cloudflare scaffold hardcodes secret: env.WEBHOOK_SECRET, but the generator computes and documents a platform-specific secret key (for example STRIPE_WEBHOOK_SECRET) via ENV_VARS and .env creation. For non-other platforms this produces a mismatched configuration: users fill the generated variable, while runtime verification reads a different one, causing webhook validation to fail unless they add an undocumented WEBHOOK_SECRET.
Useful? React with 👍 / 👎.
packages/tern-cli/src/wizard.ts
Outdated
| const platform = (args.platform ?? 'stripe') as Platform | ||
| const framework = (args.framework ?? 'nextjs') as Framework | ||
| const action = (args.action ?? 'both') as Action | ||
| const port = String(args.port ?? '3000') |
There was a problem hiding this comment.
Validate --port input before accepting CLI args
askQuestions() now accepts --port verbatim with no numeric/range checks, so invalid values (e.g. --port abc or out-of-range numbers) flow into config and tunnel startup. This leads to invalid tern.config.json output ("port": NaN) and runtime failures when launching the tunnel. The previous wizard guarded this with 1–65535 validation, so the CLI-arg path should enforce equivalent checks.
Useful? React with 👍 / 👎.
Motivation
.env,src/env.ts, framework entry points, router index files, and package scripts automatically.Description
Banner,Step,EnvBlock, andDoneunderpackages/tern-cli/src/ui/, and wired them viapackages/tern-cli/src/cli.tsx.packages/tern-cli/src/commands/scaffold.tsto centralize generator flow and produce support artifacts.packages/tern-cli/src/templates.tsto include reliability comment blocks (queue: falsedefault + QStash guidance), alerting examples (Slack/Discord), and canonical handlers for Next.js, Express, Hono, and Cloudflare Workers.packages/tern-cli/src/files.tsto: createsrc/routes/webhooks/index.ts,src/index.ts,src/env.ts, generate/merge.envand.gitignoreentries, and set framework-appropriatepackage.jsonscripts and a Nodetsconfig.jsonwhen needed.@clack/promptsruntime dependency from the scaffolding flow and moved wizard input collection to argument-based parsing inpackages/tern-cli/src/wizard.ts(usingminimist), simplifying automation and testability.packages/tern-cli/package.jsonandtsconfig.jsonto support Ink/React usage (ink,react,@types/react) and JSX compilation (jsx: react-jsx, include.tsx).Testing
npx tsx -eto validate output ofgetTemplate,getFilePath, andgetWebhookPath; these checks succeeded and confirmed presence ofqueue: false, QStash vars and correct target paths.clackreferences to confirm migration away from clack prompts; the grep checks succeeded.npm installinpackages/tern-clibut the install failed due to environment registry policy (403 Forbidden), so dependencies (react,ink, types) could not be fetched and installed.npm run typecheckinpackages/tern-cli; it failed becausereact/inktypings are unavailable in this environment untilnpm installsucceeds.Codex Task