-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add cloudflare adapter docs and guide (#254)
- Loading branch information
1 parent
9bbaef3
commit 63b6c6b
Showing
9 changed files
with
294 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"frames.js": minor | ||
"docs": minor | ||
--- | ||
|
||
feat: cloudflare workers adapter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
# Cloudflare Workers integration | ||
|
||
Frames.js can be easily deployed to [Cloudflare Workers](https://workers.cloudflare.com). | ||
|
||
## Create a new project using `wrangler` | ||
|
||
:::code-group | ||
|
||
```bash [npm] | ||
npm create cloudflare -- my-cf-frames --type hello-world --ts && cd ./my-cf-frames | ||
``` | ||
|
||
```bash [yarn] | ||
yarn create cloudflare my-cf-frames --type hello-world --ts && cd ./my-cf-frames | ||
``` | ||
|
||
```bash [pnpm] | ||
pnpm create cloudflare my-cf-frames --type hello-world --ts && cd ./my-cf-frames | ||
``` | ||
|
||
::: | ||
|
||
## Install `frames.js` | ||
|
||
In order for `frames.js` to work properly in [Cloudflare Workers](https://workers.cloudflare.com) you must replace the `@vercel/og` dependency with `workers-og`. Follow following steps to override the dependency. | ||
|
||
::::steps | ||
|
||
### Override `@vercel/og` package with `workers-og` | ||
|
||
Add following to your `package.json`. | ||
|
||
:::code-group | ||
|
||
```json [npm] | ||
{ | ||
"overrides": { | ||
"frames.js": { | ||
"@vercel/og": "npm:workers-og@^0.0.23" | ||
} | ||
} | ||
} | ||
``` | ||
|
||
```json [yarn] | ||
{ | ||
"resolutions": { | ||
"@vercel/og": "npm:workers-og" | ||
} | ||
} | ||
``` | ||
|
||
```json [pnpm] | ||
{ | ||
"pnpm": { | ||
"overrides": { | ||
"@vercel/og": "npm:workers-og@^0.0.23" | ||
} | ||
} | ||
} | ||
``` | ||
|
||
::: | ||
|
||
### Install the dependencies | ||
|
||
After you have overridden the `@vercel/og` package with `workers-og`, you can install the dependencies. | ||
|
||
:::code-group | ||
|
||
```bash [npm] | ||
npm install frames.js | ||
``` | ||
|
||
```bash [yarn] | ||
yarn add frames.js | ||
``` | ||
|
||
```bash [pnpm] | ||
pnpm add frames.js | ||
``` | ||
|
||
::: | ||
:::: | ||
|
||
## Write your Frames handler | ||
|
||
Open the `src/index.ts` file and replace its content with the following code. | ||
|
||
```tsx | ||
import { createFrames, Button } from "frames.js/cloudflare-workers"; | ||
|
||
const frames = createFrames(); | ||
const handleRequest = frames(async (ctx) => { | ||
const hasClicked = !!(ctx.message && ctx.searchParams.clicked); | ||
|
||
return { | ||
image: <span>Clicked: {hasClicked ? "Yes" : "No"}</span>, | ||
buttons: hasClicked | ||
? [ | ||
<Button action="post" target={{ query: { clicked: true } }}> | ||
Click me | ||
</Button>, | ||
] | ||
: [ | ||
<Button action="post" target="/"> | ||
Reset | ||
</Button>, | ||
], | ||
}; | ||
}); | ||
|
||
export default { | ||
fetch: handleRequest, | ||
}; | ||
``` | ||
|
||
## Develop and test locally | ||
|
||
You can test your Cloudflare Worker locally using `wrangler dev` and our [debugger](/guides/debugger#local-debugger-cli). Follow these steps to start developing locally: | ||
|
||
::::steps | ||
|
||
#### Start the local server | ||
|
||
:::code-group | ||
|
||
```bash [npm] | ||
npm run dev | ||
``` | ||
|
||
```bash [yarn] | ||
yarn dev | ||
``` | ||
|
||
```bash [pnpm] | ||
pnpm dev | ||
``` | ||
|
||
::: | ||
|
||
#### Start the debugger | ||
|
||
After you started the local server, you can start the debugger by running the following command where you replace `<local-url>` with a URL on which local server is running (see the output of above command, e.g. `http://localhost:8787`). | ||
|
||
:::code-group | ||
|
||
```bash [npm] | ||
npx @frames.js/debugger --url <local-url> | ||
``` | ||
|
||
```bash [yarn] | ||
# yarn v1 doesn't have an alternative to npx, so you have to install the debugger globally (or use npx) | ||
yarn global add @frames.js/debugger && frames --url <local-url> | ||
|
||
# yarn v2 | ||
yarn dlx @frames.js/debugger --url <local-url> | ||
``` | ||
|
||
```bash [pnpm] | ||
pnpm dlx @frames.js/debugger --url <local-url> | ||
``` | ||
|
||
::: | ||
|
||
:::: | ||
|
||
## Deploy to Cloudflare Workers | ||
|
||
When you tested your Frames app locally and you are ready to deploy it to Cloudflare Workers, run the following command. | ||
|
||
:::code-group | ||
|
||
```bash [npm] | ||
npm run deploy | ||
``` | ||
|
||
```bash [yarn] | ||
yarn deploy | ||
``` | ||
|
||
```bash [pnpm] | ||
pnpm deploy | ||
``` | ||
|
||
::: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import * as lib from "."; | ||
|
||
describe("cloudflare workers adapter", () => { | ||
it.each(["createFrames", "Button"])("exports %s", (exportName) => { | ||
expect(lib).toHaveProperty(exportName); | ||
}); | ||
|
||
it("correctly integrates with Cloudflare Workers", async () => { | ||
const frames = lib.createFrames(); | ||
const handler = frames(async (ctx) => { | ||
expect(ctx.request.url).toBe("http://localhost:3000/"); | ||
|
||
return { | ||
image: <span>Test</span>, | ||
buttons: [<lib.Button action="post">Click me</lib.Button>], | ||
}; | ||
}); | ||
|
||
const request = new Request("http://localhost:3000"); | ||
|
||
// @ts-expect-error - expects fetcher property on request but it is not used by our lib | ||
const response = await handler(request, {}, {}); | ||
|
||
expect(response.status).toBe(200); | ||
expect(response.headers.get("content-type")).toBe("text/html"); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
export { Button, type types } from "../core"; | ||
import { createFrames as coreCreateFrames, types } from "../core"; | ||
import { CoreMiddleware } from "../middleware"; | ||
import { Buffer } from "node:buffer"; | ||
|
||
// make Buffer available on globalThis so it is compatible with cloudflare workers | ||
// eslint-disable-next-line no-undef | ||
globalThis.Buffer = Buffer; | ||
|
||
type CreateFramesForCloudflareWorkers = types.CreateFramesFunctionDefinition< | ||
CoreMiddleware, | ||
(req: Request) => Promise<Response> | ||
>; | ||
|
||
/** | ||
* Creates Frames instance to use with you Hono server | ||
* | ||
* @example | ||
* import { createFrames, Button } from 'frames.js/cloudflare-workers'; | ||
* | ||
* const frames = createFrames(); | ||
* const fetch = frames(async (ctx) => { | ||
* return { | ||
* image: <span>Test</span>, | ||
* buttons: [ | ||
* <Button action="post"> | ||
* Click me | ||
* </Button>, | ||
* ], | ||
* }; | ||
* }); | ||
* | ||
* export default { | ||
* fetch, | ||
* } satisfies ExportedHandler; | ||
*/ | ||
// @ts-expect-error | ||
export const createFrames: CreateFramesForCloudflareWorkers = | ||
function createFramesForCloudflareWorkers( | ||
options?: types.FramesOptions<any, any> | ||
) { | ||
const frames = coreCreateFrames(options); | ||
|
||
return function cloudflareWorkersFramesHandler< | ||
TPerRouteMiddleware extends types.FramesMiddleware<any, any>[], | ||
>( | ||
handler: types.FrameHandlerFunction<any, any>, | ||
handlerOptions?: types.FramesRequestHandlerFunctionOptions<TPerRouteMiddleware> | ||
) { | ||
const framesHandler = frames(handler, handlerOptions); | ||
|
||
return async function handleCloudflareWorkersRequest(req) { | ||
return framesHandler(req); | ||
}; | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters