diff --git a/.changeset/perfect-geckos-tell.md b/.changeset/perfect-geckos-tell.md new file mode 100644 index 0000000000000..e2434a16ae5eb --- /dev/null +++ b/.changeset/perfect-geckos-tell.md @@ -0,0 +1,5 @@ +--- +"create-cloudflare": minor +--- + +Update openapi C3 template to include better ts types and lint command diff --git a/packages/create-cloudflare/templates/openapi/ts/.gitignore b/packages/create-cloudflare/templates/openapi/ts/.gitignore index 42387803be0c4..3b0fe33c47f10 100644 --- a/packages/create-cloudflare/templates/openapi/ts/.gitignore +++ b/packages/create-cloudflare/templates/openapi/ts/.gitignore @@ -169,3 +169,4 @@ dist # wrangler project .dev.vars +.wrangler/ diff --git a/packages/create-cloudflare/templates/openapi/ts/biome.json b/packages/create-cloudflare/templates/openapi/ts/biome.json new file mode 100644 index 0000000000000..2eb07517c0dab --- /dev/null +++ b/packages/create-cloudflare/templates/openapi/ts/biome.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": false, + "ignore": [] + }, + "formatter": { + "enabled": true, + "indentStyle": "tab" + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double" + } + } +} diff --git a/packages/create-cloudflare/templates/openapi/ts/package.json b/packages/create-cloudflare/templates/openapi/ts/package.json index 31663ce043a55..6e625a5cf3116 100644 --- a/packages/create-cloudflare/templates/openapi/ts/package.json +++ b/packages/create-cloudflare/templates/openapi/ts/package.json @@ -6,16 +6,19 @@ "deploy": "wrangler deploy", "dev": "wrangler dev", "start": "wrangler dev", + "lint": "npx @biomejs/biome check src/ || (npx @biomejs/biome check --write src/; exit 1)", "cf-typegen": "wrangler types" }, "dependencies": { - "chanfana": "^2.0.2", - "zod": "^3.23.8", - "hono": "^4.4.7" + "chanfana": "^2.6.1", + "hono": "^4.6.16", + "zod": "^3.24.1" }, "devDependencies": { - "@types/node": "20.8.3", - "@types/service-worker-mock": "^2.0.1", - "wrangler": "^3.101.0" + "@biomejs/biome": "1.9.4", + "@cloudflare/workers-types": "^4.20250109.0", + "@types/node": "22.10.7", + "@types/service-worker-mock": "^2.0.4", + "wrangler": "^3.103.0" } } diff --git a/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskCreate.ts b/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskCreate.ts index 798aa82ceddbb..f9d91d58e3fd0 100644 --- a/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskCreate.ts +++ b/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskCreate.ts @@ -1,6 +1,6 @@ import { Bool, OpenAPIRoute } from "chanfana"; import { z } from "zod"; -import { Task } from "../types"; +import { type AppContext, Task } from "../types"; export class TaskCreate extends OpenAPIRoute { schema = { @@ -34,7 +34,7 @@ export class TaskCreate extends OpenAPIRoute { }, }; - async handle(c) { + async handle(c: AppContext) { // Get validated data const data = await this.getValidatedData(); diff --git a/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskDelete.ts b/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskDelete.ts index ed6f691e78eb2..cc0570ca1d357 100644 --- a/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskDelete.ts +++ b/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskDelete.ts @@ -1,6 +1,6 @@ import { Bool, OpenAPIRoute, Str } from "chanfana"; import { z } from "zod"; -import { Task } from "../types"; +import { type AppContext, Task } from "../types"; export class TaskDelete extends OpenAPIRoute { schema = { @@ -30,7 +30,7 @@ export class TaskDelete extends OpenAPIRoute { }, }; - async handle(c) { + async handle(c: AppContext) { // Get validated data const data = await this.getValidatedData(); diff --git a/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskFetch.ts b/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskFetch.ts index 07cf324e856e4..c7e384f569dff 100644 --- a/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskFetch.ts +++ b/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskFetch.ts @@ -1,6 +1,6 @@ import { Bool, OpenAPIRoute, Str } from "chanfana"; import { z } from "zod"; -import { Task } from "../types"; +import { type AppContext, Task } from "../types"; export class TaskFetch extends OpenAPIRoute { schema = { @@ -43,7 +43,7 @@ export class TaskFetch extends OpenAPIRoute { }, }; - async handle(c) { + async handle(c: AppContext) { // Get validated data const data = await this.getValidatedData(); diff --git a/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskList.ts b/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskList.ts index 8f50506e085d2..df17deb187bd7 100644 --- a/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskList.ts +++ b/packages/create-cloudflare/templates/openapi/ts/src/endpoints/taskList.ts @@ -1,6 +1,6 @@ import { Bool, Num, OpenAPIRoute } from "chanfana"; import { z } from "zod"; -import { Task } from "../types"; +import { type AppContext, Task } from "../types"; export class TaskList extends OpenAPIRoute { schema = { @@ -37,7 +37,7 @@ export class TaskList extends OpenAPIRoute { }, }; - async handle(c) { + async handle(c: AppContext) { // Get validated data const data = await this.getValidatedData(); diff --git a/packages/create-cloudflare/templates/openapi/ts/src/index.ts b/packages/create-cloudflare/templates/openapi/ts/src/index.ts index 46aee732be236..1a7e696256bd2 100644 --- a/packages/create-cloudflare/templates/openapi/ts/src/index.ts +++ b/packages/create-cloudflare/templates/openapi/ts/src/index.ts @@ -6,7 +6,7 @@ import { TaskFetch } from "./endpoints/taskFetch"; import { TaskList } from "./endpoints/taskList"; // Start a Hono app -const app = new Hono(); +const app = new Hono<{ Bindings: Env }>(); // Setup OpenAPI registry const openapi = fromHono(app, { @@ -19,5 +19,8 @@ openapi.post("/api/tasks", TaskCreate); openapi.get("/api/tasks/:taskSlug", TaskFetch); openapi.delete("/api/tasks/:taskSlug", TaskDelete); +// You may also register routes for non OpenAPI directly on Hono +// app.get('/test', (c) => c.text('Hono!')) + // Export the Hono app export default app; diff --git a/packages/create-cloudflare/templates/openapi/ts/src/types.ts b/packages/create-cloudflare/templates/openapi/ts/src/types.ts index f91817f6c44ad..a1a4731dfe83c 100644 --- a/packages/create-cloudflare/templates/openapi/ts/src/types.ts +++ b/packages/create-cloudflare/templates/openapi/ts/src/types.ts @@ -1,6 +1,9 @@ import { DateTime, Str } from "chanfana"; +import type { Context } from "hono"; import { z } from "zod"; +export type AppContext = Context<{ Bindings: Env }>; + export const Task = z.object({ name: Str({ example: "lorem" }), slug: Str(), diff --git a/packages/create-cloudflare/templates/openapi/ts/tsconfig.json b/packages/create-cloudflare/templates/openapi/ts/tsconfig.json index 196166eb6db16..b285336e633ac 100644 --- a/packages/create-cloudflare/templates/openapi/ts/tsconfig.json +++ b/packages/create-cloudflare/templates/openapi/ts/tsconfig.json @@ -1,32 +1,30 @@ { "compilerOptions": { - "allowJs": true, - "allowSyntheticDefaultImports": true, - "baseUrl": "src", - "declaration": true, - "sourceMap": true, + /* Base Options: */ "esModuleInterop": true, - "inlineSourceMap": false, - "lib": ["esnext"], - "listEmittedFiles": false, - "listFiles": false, - "moduleResolution": "node", - "noFallthroughCasesInSwitch": true, - "pretty": true, - "resolveJsonModule": true, - "rootDir": ".", "skipLibCheck": true, - "strict": false, - "traceResolution": false, - "outDir": "", - "target": "esnext", - "module": "esnext", + "target": "es2022", + "verbatimModuleSyntax": false, + "allowJs": true, + "resolveJsonModule": true, + "moduleDetection": "force", + /* Strictness */ + "noImplicitAny": false, + "noImplicitThis": true, + "strictNullChecks": false, + "strict": true, + "noUncheckedIndexedAccess": true, + /* If NOT transpiling with TypeScript: */ + "moduleResolution": "Bundler", + "module": "es2022", + "noEmit": true, + /* If your code runs in the DOM: */ + "lib": ["es2022"], "types": [ "@types/node", "@types/service-worker-mock", "@cloudflare/workers-types" ] }, - "exclude": ["node_modules", "dist", "tests"], - "include": ["src", "scripts"] + "include": ["src", "worker-configuration.d.ts"] }