Skip to content

Commit

Permalink
feat: widen response types
Browse files Browse the repository at this point in the history
  • Loading branch information
jxom committed Mar 5, 2024
1 parent 149d522 commit 00725e7
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changeset/chatty-ears-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"frog": patch
---

Widened handler return types to allow [`Response` objects](https://developer.mozilla.org/en-US/docs/Web/API/Response).
6 changes: 3 additions & 3 deletions playground/src/transaction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Button, Frog } from 'frog'

export const app = new Frog()

app.frame('/', () => {
return {
app.frame('/', (c) => {
return c.res({
image: (
<div style={{ backgroundColor: 'red', width: '100%', height: '100%' }}>
Example
Expand All @@ -14,7 +14,7 @@ app.frame('/', () => {
<Button.Transaction target="/send">Send Transaction</Button.Transaction>,
<Button.Transaction target="/mint">Mint</Button.Transaction>,
],
}
})
})

// Raw transaction
Expand Down
15 changes: 15 additions & 0 deletions site/pages/reference/frog-transaction-response.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ app.transaction('/raw-send', (c) => {
})
```

:::tip
Frog also supports [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) objects as a return value of the `.transaction` handler. Useful for returning error responses.

```tsx twoslash
// @noErrors
import { Frog, parseEther } from 'frog'

export const app = new Frog()

app.transaction('/send-ether', (c) => {
return new Response('dang', { status: 400 }) // [!code focus]
})
```
:::

## Send Transaction (`c.send`)

### chainId
Expand Down
13 changes: 10 additions & 3 deletions src/frog-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
type FrameResponse,
} from './types/frame.js'
import type { Hub } from './types/hub.js'
import type { HandlerResponse } from './types/response.js'
import { type Pretty } from './types/utils.js'
import { fromQuery } from './utils/fromQuery.js'
import { getButtonValues } from './utils/getButtonValues.js'
Expand Down Expand Up @@ -261,7 +262,7 @@ export class FrogBase<
path: path,
handler: (
context: Pretty<FrameContext<path, state>>,
) => FrameResponse | Promise<FrameResponse>,
) => HandlerResponse<FrameResponse>,
options: RouteOptions = {},
) {
const { verify = this.verify } = options
Expand All @@ -287,6 +288,9 @@ export class FrogBase<

if (context.url !== parsePath(c.req.url)) return c.redirect(context.url)

const response = await handler(context)
if (response instanceof Response) return response

const {
action,
browserLocation = this.browserLocation,
Expand All @@ -295,7 +299,7 @@ export class FrogBase<
image,
intents,
title = 'Frog Frame',
} = await handler(context)
} = response.data
const buttonValues = getButtonValues(parseIntents(intents))

if (context.status === 'redirect' && context.buttonIndex) {
Expand Down Expand Up @@ -472,11 +476,14 @@ export class FrogBase<
? await this.imageOptions()
: this.imageOptions

const response = await handler(context)
if (response instanceof Response) return response

const {
image,
headers = this.headers,
imageOptions = defaultImageOptions,
} = await handler(context)
} = response.data
if (typeof image === 'string') return c.redirect(image, 302)
return new ImageResponse(image, {
...imageOptions,
Expand Down
3 changes: 2 additions & 1 deletion src/frog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { routes as devRoutes } from './dev/routes.js'
import { FrogBase, type RouteOptions } from './frog-base.js'
import { type FrameContext } from './types/context.js'
import { type FrameResponse } from './types/frame.js'
import type { HandlerResponse } from './types/response.js'
import { type Pretty } from './types/utils.js'

/**
Expand Down Expand Up @@ -46,7 +47,7 @@ export class Frog<
path: path,
handler: (
context: Pretty<FrameContext<path, state>>,
) => FrameResponse | Promise<FrameResponse>,
) => HandlerResponse<FrameResponse>,
options: RouteOptions = {},
) {
super.frame(path, handler, options)
Expand Down
8 changes: 5 additions & 3 deletions src/routes/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Env } from 'hono'

import type { FrogBase, RouteOptions } from '../frog-base.js'
import type { TransactionContext } from '../types/context.js'
import type { HandlerResponse } from '../types/response.js'
import type { TransactionResponse } from '../types/transaction.js'
import { getTransactionContext } from '../utils/getTransactionContext.js'
import { parsePath } from '../utils/parsePath.js'
Expand All @@ -12,7 +13,7 @@ export function transaction<state, env extends Env>(
path: string,
handler: (
context: TransactionContext,
) => TransactionResponse | Promise<TransactionResponse>,
) => HandlerResponse<TransactionResponse>,
options: RouteOptions = {},
) {
const { verify = this.verify } = options
Expand All @@ -27,7 +28,8 @@ export function transaction<state, env extends Env>(
}),
req: c.req,
})
const transaction = await handler(transactionContext)
return c.json(transaction)
const response = await handler(transactionContext)
if (response instanceof Response) return response
return c.json(response.data)
})
}
5 changes: 4 additions & 1 deletion src/types/frame.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { type ImageResponseOptions } from 'hono-og'
import type { TypedResponse } from './response.js'

export type FrameResponse = {
/**
Expand Down Expand Up @@ -105,7 +106,9 @@ export type FrameResponse = {
title?: string | undefined
}

export type FrameResponseFn = (response: FrameResponse) => FrameResponse
export type FrameResponseFn = (
response: FrameResponse,
) => TypedResponse<FrameResponse>

export type FrameData = {
buttonIndex?: 1 | 2 | 3 | 4 | undefined
Expand Down
10 changes: 10 additions & 0 deletions src/types/response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export type TypedResponse<data> = {
data: data
format: 'frame' | 'transaction'
}

export type HandlerResponse<typedResponse> =
| Response
| TypedResponse<typedResponse>
| Promise<Response>
| Promise<TypedResponse<typedResponse>>
5 changes: 3 additions & 2 deletions src/types/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
GetValue,
Hex,
} from 'viem'
import type { TypedResponse } from './response.js'
import type { UnionWiden, Widen } from './utils.js'

//////////////////////////////////////////////////////
Expand Down Expand Up @@ -38,7 +39,7 @@ export type EthSendTransactionParameters<quantity = string> = {

export type TransactionResponseFn<parameters> = (
parameters: parameters,
) => TransactionResponse
) => TypedResponse<TransactionResponse>

//////////////////////////////////////////////////////
// Send Transaction
Expand Down Expand Up @@ -85,4 +86,4 @@ export type ContractTransactionResponseFn = <
>,
>(
response: ContractTransactionParameters<abi, functionName, args>,
) => TransactionResponse
) => TypedResponse<TransactionResponse>
2 changes: 1 addition & 1 deletion src/utils/getFrameContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function getFrameContext<state>(
previousButtonValues,
previousState: previousState as any,
req,
res: (data) => data,
res: (data) => ({ data, format: 'frame' }),
status,
transactionId: frameData?.transactionId,
url,
Expand Down
2 changes: 1 addition & 1 deletion src/utils/getTransactionContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export function getTransactionContext<state>(
},
}
if (value) response.params.value = value.toString()
return response
return { data: response, format: 'transaction' }
},
send(parameters) {
return this.res({
Expand Down

0 comments on commit 00725e7

Please sign in to comment.