From 424b0eadd0de67572b495705c3aa83b261dd1b10 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:02:44 +0200 Subject: [PATCH 1/3] feat: cast actions support --- .changeset/brown-walls-thank.md | 5 +++ .changeset/tasty-panthers-protect.md | 5 +++ docs/pages/guides/cast-actions.mdx | 12 +++++++ docs/vocs.config.tsx | 4 +++ .../new-api-cast-actions/frames/frames.ts | 5 +++ .../new-api-cast-actions/frames/route.tsx | 31 +++++++++++++++++ .../examples/new-api-cast-actions/page.tsx | 33 +++++++++++++++++++ .../examples/new-api-cast-actions/utils.ts | 30 +++++++++++++++++ packages/frames.js/src/core/types.ts | 2 +- 9 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 .changeset/brown-walls-thank.md create mode 100644 .changeset/tasty-panthers-protect.md create mode 100644 docs/pages/guides/cast-actions.mdx create mode 100644 examples/framesjs-starter/app/examples/new-api-cast-actions/frames/frames.ts create mode 100644 examples/framesjs-starter/app/examples/new-api-cast-actions/frames/route.tsx create mode 100644 examples/framesjs-starter/app/examples/new-api-cast-actions/page.tsx create mode 100644 examples/framesjs-starter/app/examples/new-api-cast-actions/utils.ts diff --git a/.changeset/brown-walls-thank.md b/.changeset/brown-walls-thank.md new file mode 100644 index 000000000..da0aae82c --- /dev/null +++ b/.changeset/brown-walls-thank.md @@ -0,0 +1,5 @@ +--- +"frames.js": patch +--- + +feat: allow arbitrary response in frames handler diff --git a/.changeset/tasty-panthers-protect.md b/.changeset/tasty-panthers-protect.md new file mode 100644 index 000000000..ac915b809 --- /dev/null +++ b/.changeset/tasty-panthers-protect.md @@ -0,0 +1,5 @@ +--- +"framesjs-starter": patch +--- + +feat: cast actions example diff --git a/docs/pages/guides/cast-actions.mdx b/docs/pages/guides/cast-actions.mdx new file mode 100644 index 000000000..daebe0d2a --- /dev/null +++ b/docs/pages/guides/cast-actions.mdx @@ -0,0 +1,12 @@ +--- +title: "Cast Actions" +description: "A guide to demonstrate how to create cast actions with Frames.js" +--- + +# Cast Actions + +The [Cast Actions](https://warpcast.notion.site/Frames-Cast-Actions-v1-84d5a85d479a43139ea883f6823d8caa) specifiction lets you define actions that can be performed on a cast. This guide will show you how to create cast actions with Frames.js. + +## Example + +[See the example on GitHub](https://github.com/framesjs/frames.js/tree/main/examples/framesjs-starter/app/examples/new-api-cast-actions) diff --git a/docs/vocs.config.tsx b/docs/vocs.config.tsx index 404777612..7f03651c6 100644 --- a/docs/vocs.config.tsx +++ b/docs/vocs.config.tsx @@ -58,6 +58,10 @@ const sidebar = [ text: "Open Frames", link: "/guides/open-frames", }, + { + text: "Cast Actions", + link: "/guides/cast-actions", + }, ], }, { diff --git a/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/frames.ts new file mode 100644 index 000000000..1ccb72618 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/frames.ts @@ -0,0 +1,5 @@ +import { createFrames } from "frames.js/next"; + +export const frames = createFrames({ + basePath: "/examples/new-api-cast-actions/frames", +}); diff --git a/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/route.tsx new file mode 100644 index 000000000..9db3008b3 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-cast-actions/frames/route.tsx @@ -0,0 +1,31 @@ +/* eslint-disable react/jsx-key */ +import { Button } from "frames.js/next"; +import { frames } from "./frames"; +import { constructCastActionUrl } from "../utils"; + +export const GET = frames(async (ctx) => { + const currentUrl = new URL(ctx.url.toString()); + currentUrl.pathname = "/examples/new-api-cast-actions/frames"; + + const installActionUrl = constructCastActionUrl({ + actionType: "post", + icon: "number", + name: "Check FID", + postUrl: currentUrl.toString(), + }); + + return { + image:
FID Action
, + buttons: [ + , + ], + }; +}); + +export const POST = frames(async (ctx) => { + return Response.json({ + message: `The user's FID is ${ctx.message?.castId?.fid}`, + }); +}); diff --git a/examples/framesjs-starter/app/examples/new-api-cast-actions/page.tsx b/examples/framesjs-starter/app/examples/new-api-cast-actions/page.tsx new file mode 100644 index 000000000..82f4048b0 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-cast-actions/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api-cast-actions/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api-cast-actions"); + + return ( +
+ New api cast actions example.{" "} + + Debug + +
+ ); +} diff --git a/examples/framesjs-starter/app/examples/new-api-cast-actions/utils.ts b/examples/framesjs-starter/app/examples/new-api-cast-actions/utils.ts new file mode 100644 index 000000000..2bba8d0f4 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-cast-actions/utils.ts @@ -0,0 +1,30 @@ +type CastActionParams = { + /** The action name. Must be less than 30 characters. */ + name: string; + /** An [Octicons](https://primer.style/foundations/icons) icon name. */ + icon: string; + /** The action type. (Same type options as frame buttons). Only post is accepted in V1. */ + actionType: "post"; + postUrl: string; +}; +export function constructCastActionUrl(params: CastActionParams): string { + // Validate the input parameters + if (params.name.length > 30) { + throw new Error("The action name must be less than 30 characters."); + } + + if (params.actionType.toLowerCase() !== "post") { + throw new Error('The action type must be "post" in V1.'); + } + + // Construct the URL + const baseUrl = "https://warpcast.com/~/add-cast-action"; + const urlParams = new URLSearchParams({ + name: params.name, + icon: params.icon, + actionType: params.actionType, + postUrl: params.postUrl, + }); + + return `${baseUrl}?${urlParams.toString()}`; +} diff --git a/packages/frames.js/src/core/types.ts b/packages/frames.js/src/core/types.ts index 9d4b22e3f..b4c97a026 100644 --- a/packages/frames.js/src/core/types.ts +++ b/packages/frames.js/src/core/types.ts @@ -110,7 +110,7 @@ export type FrameRedirect = { export type FramesHandlerFunctionReturnType< TState extends JsonValue | undefined, -> = FrameDefinition | FrameRedirect; +> = FrameDefinition | FrameRedirect | Response; type FramesMiddlewareNextFunction< TState extends JsonValue | undefined, From b026ebced1fda97c755527bf0591f532f5339368 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Fri, 5 Apr 2024 09:04:39 +0200 Subject: [PATCH 2/3] Update docs/pages/guides/cast-actions.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michal Kvasničák --- docs/pages/guides/cast-actions.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/guides/cast-actions.mdx b/docs/pages/guides/cast-actions.mdx index daebe0d2a..f561fe227 100644 --- a/docs/pages/guides/cast-actions.mdx +++ b/docs/pages/guides/cast-actions.mdx @@ -5,7 +5,7 @@ description: "A guide to demonstrate how to create cast actions with Frames.js" # Cast Actions -The [Cast Actions](https://warpcast.notion.site/Frames-Cast-Actions-v1-84d5a85d479a43139ea883f6823d8caa) specifiction lets you define actions that can be performed on a cast. This guide will show you how to create cast actions with Frames.js. +The [Cast Actions](https://warpcast.notion.site/Frames-Cast-Actions-v1-84d5a85d479a43139ea883f6823d8caa) specification lets you define actions that can be performed on a cast. This guide will show you how to create cast actions with Frames.js. ## Example From 9962b8301d3f4e097b350aa49047c796b881ff3c Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:47:21 +0200 Subject: [PATCH 3/3] fix: changeset minor --- .changeset/brown-walls-thank.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/brown-walls-thank.md b/.changeset/brown-walls-thank.md index da0aae82c..e71364dd9 100644 --- a/.changeset/brown-walls-thank.md +++ b/.changeset/brown-walls-thank.md @@ -1,5 +1,5 @@ --- -"frames.js": patch +"frames.js": minor --- feat: allow arbitrary response in frames handler