diff --git a/.changeset/loud-buckets-prove.md b/.changeset/loud-buckets-prove.md new file mode 100644 index 000000000000..ba335cc3a135 --- /dev/null +++ b/.changeset/loud-buckets-prove.md @@ -0,0 +1,12 @@ +--- +"create-cloudflare": minor +--- + +feat: Improvements to `hono` template. + +The `hono` template has been updated as follows: + +- Bumps `create-hono` to `0.7.0` +- Automatically installs dependencies and specifies the detected package manager to avoid interactive prompts +- Adds a `wrangler.toml` file with commented out examples of all available bindings to match other templates. +- Adds a `cf-typegen` package script to automatically regenerate types for `Bindings` from `wrangler.toml` diff --git a/packages/create-cloudflare/src/frameworks/package.json b/packages/create-cloudflare/src/frameworks/package.json index 371f76be4ac8..3c0a438e2e0a 100644 --- a/packages/create-cloudflare/src/frameworks/package.json +++ b/packages/create-cloudflare/src/frameworks/package.json @@ -10,7 +10,7 @@ "create-analog": "1.2.0", "@angular/create": "17.2.3", "create-docusaurus": "3.1.1", - "create-hono": "0.5.0", + "create-hono": "0.7.0", "create-next-app": "14.1.0", "create-qwik": "1.4.5", "create-react-app": "5.0.1", diff --git a/packages/create-cloudflare/templates/hono/c3.ts b/packages/create-cloudflare/templates/hono/c3.ts index 7df217e3cd84..a4f06e205f46 100644 --- a/packages/create-cloudflare/templates/hono/c3.ts +++ b/packages/create-cloudflare/templates/hono/c3.ts @@ -1,24 +1,77 @@ import { logRaw } from "@cloudflare/cli"; +import { brandColor, dim } from "@cloudflare/cli/colors"; +import { spinner } from "@cloudflare/cli/interactive"; import { runFrameworkGenerator } from "frameworks/index"; +import { loadTemplateSnippets, transformFile } from "helpers/codemod"; +import { detectPackageManager } from "helpers/packageManagers"; import type { TemplateConfig } from "../../src/templates"; +import type * as recast from "recast"; import type { C3Context } from "types"; const generate = async (ctx: C3Context) => { + const { name: pm } = detectPackageManager(); + await runFrameworkGenerator(ctx, [ ctx.project.name, "--template", "cloudflare-workers", + "--install", + "--pm", + pm, ]); logRaw(""); // newline }; +const configure = async (ctx: C3Context) => { + const indexFile = "src/index.ts"; + + const s = spinner(); + s.start(`Updating \`${indexFile}\``); + + const snippets = loadTemplateSnippets(ctx); + + transformFile(indexFile, { + // Insert the env declaration after the last import (but before the rest of the body) + visitProgram: function (n) { + const lastImportIndex = n.node.body.findLastIndex( + (t) => t.type === "ImportDeclaration" + ); + const lastImport = n.get("body", lastImportIndex); + lastImport.insertAfter(...snippets.bindingsTypeTs); + + return this.traverse(n); + }, + visitVariableDeclarator(n) { + if (n.node.id.type === "Identifier" && n.node.id.name === "app") { + n.node.init = snippets + .appDeclarationTs[0] as recast.types.namedTypes.NewExpression; + + return false; + } + }, + }); + + s.stop(`${brandColor("updated")} \`${dim(indexFile)}\``); +}; + const config: TemplateConfig = { configVersion: 1, id: "hono", displayName: "Hono", + copyFiles: { + path: "./templates", + }, platform: "workers", generate, + configure, + transformPackageJson: async () => ({ + scripts: { + dev: "wrangler dev", + deploy: "wrangler deploy --minify", + "cf-typegen": "wrangler types --env-interface CloudflareBindings", + }, + }), devScript: "dev", deployScript: "deploy", }; diff --git a/packages/create-cloudflare/templates/hono/snippets/appDeclaration.ts b/packages/create-cloudflare/templates/hono/snippets/appDeclaration.ts new file mode 100644 index 000000000000..f0edac899c12 --- /dev/null +++ b/packages/create-cloudflare/templates/hono/snippets/appDeclaration.ts @@ -0,0 +1 @@ +new Hono<{ Bindings: Bindings }>() diff --git a/packages/create-cloudflare/templates/hono/snippets/bindingsType.ts b/packages/create-cloudflare/templates/hono/snippets/bindingsType.ts new file mode 100644 index 000000000000..88a8175cb655 --- /dev/null +++ b/packages/create-cloudflare/templates/hono/snippets/bindingsType.ts @@ -0,0 +1 @@ +type Bindings = Record & CloudflareBindings diff --git a/packages/create-cloudflare/templates/hono/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/hono/templates/worker-configuration.d.ts new file mode 100644 index 000000000000..73a9e54e4fd4 --- /dev/null +++ b/packages/create-cloudflare/templates/hono/templates/worker-configuration.d.ts @@ -0,0 +1,4 @@ +// Generated by Wrangler +// After adding bindings to `wrangler.toml`, regenerate this interface via `npm run cf-typegen` +interface CloudflareBindings { +} diff --git a/packages/create-cloudflare/templates/hono/templates/wrangler.toml b/packages/create-cloudflare/templates/hono/templates/wrangler.toml new file mode 100644 index 000000000000..b5a35826d0e6 --- /dev/null +++ b/packages/create-cloudflare/templates/hono/templates/wrangler.toml @@ -0,0 +1,100 @@ +#:schema node_modules/wrangler/config-schema.json +name = "" +main = "src/index.ts" +compatibility_date = "" + +# Variable bindings. These are arbitrary, plaintext strings (similar to environment variables) +# Docs: +# - https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables +# Note: Use secrets to store sensitive data. +# - https://developers.cloudflare.com/workers/configuration/secrets/ +# [vars] +# MY_VARIABLE = "production_value" + +# Bind the Workers AI model catalog. Run machine learning models, powered by serverless GPUs, on Cloudflare’s global network +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#workers-ai +# [ai] +# binding = "AI" + +# Bind an Analytics Engine dataset. Use Analytics Engine to write analytics within your Pages Function. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#analytics-engine-datasets +# [[analytics_engine_datasets]] +# binding = "MY_DATASET" + +# Bind a headless browser instance running on Cloudflare's global network. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#browser-rendering +# [browser] +# binding = "MY_BROWSER" + +# Bind a D1 database. D1 is Cloudflare’s native serverless SQL database. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases +# [[d1_databases]] +# binding = "MY_DB" +# database_name = "my-database" +# database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + +# Bind a dispatch namespace. Use Workers for Platforms to deploy serverless functions programmatically on behalf of your customers. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#dispatch-namespace-bindings-workers-for-platforms +# [[dispatch_namespaces]] +# binding = "MY_DISPATCHER" +# namespace = "my-namespace" + +# Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model. +# Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects +# [[durable_objects.bindings]] +# name = "MY_DURABLE_OBJECT" +# class_name = "MyDurableObject" + +# Durable Object migrations. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#migrations +# [[migrations]] +# tag = "v1" +# new_classes = ["MyDurableObject"] + +# Bind a Hyperdrive configuration. Use to accelerate access to your existing databases from Cloudflare Workers. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#hyperdrive +# [[hyperdrive]] +# binding = "MY_HYPERDRIVE" +# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +# Bind a KV Namespace. Use KV as persistent storage for small key-value pairs. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#kv-namespaces +# [[kv_namespaces]] +# binding = "MY_KV_NAMESPACE" +# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +# Bind an mTLS certificate. Use to present a client certificate when communicating with another service. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#mtls-certificates +# [[mtls_certificates]] +# binding = "MY_CERTIFICATE" +# certificate_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + +# Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#queues +# [[queues.producers]] +# binding = "MY_QUEUE" +# queue = "my-queue" + +# Bind a Queue consumer. Queue Consumers can retrieve tasks scheduled by Producers to act on them. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#queues +# [[queues.consumers]] +# queue = "my-queue" + +# Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#r2-buckets +# [[r2_buckets]] +# binding = "MY_BUCKET" +# bucket_name = "my-bucket" + +# Bind another Worker service. Use this binding to call another Worker without network overhead. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings +# [[services]] +# binding = "MY_SERVICE" +# service = "my-service" + +# Bind a Vectorize index. Use to store and query vector embeddings for semantic search, classification and other vector search use-cases. +# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#vectorize-indexes +# [[vectorize]] +# binding = "MY_INDEX" +# index_name = "my-index"