@farcaster/snap-hono 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +6 -4
- package/dist/payloadToResponse.d.ts +8 -0
- package/dist/payloadToResponse.js +29 -0
- package/package.json +2 -3
- package/src/index.ts +6 -10
- package/src/payloadToResponse.ts +39 -0
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { cors } from "hono/cors";
|
|
2
|
-
import {
|
|
2
|
+
import { MEDIA_TYPE } from "@farcaster/snap";
|
|
3
|
+
import { parseRequest } from "@farcaster/snap/server";
|
|
4
|
+
import { payloadToResponse } from "./payloadToResponse";
|
|
3
5
|
/**
|
|
4
6
|
* Register GET and POST snap handlers on `app` at `options.path` (default `/`).
|
|
5
7
|
*
|
|
@@ -19,13 +21,13 @@ export function registerSnapHandler(app, snapFn, options = {}) {
|
|
|
19
21
|
app.get(path, async (c) => {
|
|
20
22
|
const accept = c.req.header("Accept");
|
|
21
23
|
if (!clientWantsSnapResponse(accept)) {
|
|
22
|
-
return c.text(fallbackText, 200);
|
|
24
|
+
return c.text(fallbackText, 200, { Vary: "Accept" });
|
|
23
25
|
}
|
|
24
26
|
const response = await snapFn({
|
|
25
27
|
action: { type: "get" },
|
|
26
28
|
request: c.req.raw,
|
|
27
29
|
});
|
|
28
|
-
return
|
|
30
|
+
return payloadToResponse(response);
|
|
29
31
|
});
|
|
30
32
|
app.post(path, async (c) => {
|
|
31
33
|
const raw = c.req.raw;
|
|
@@ -53,7 +55,7 @@ export function registerSnapHandler(app, snapFn, options = {}) {
|
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
const response = await snapFn({ action: parsed.action, request: raw });
|
|
56
|
-
return
|
|
58
|
+
return payloadToResponse(response);
|
|
57
59
|
});
|
|
58
60
|
}
|
|
59
61
|
function clientWantsSnapResponse(accept) {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type SnapResponse } from "@farcaster/snap";
|
|
2
|
+
/**
|
|
3
|
+
* Validate a snap root object, then return a JSON Response for the client.
|
|
4
|
+
* Sets `Content-Type: application/vnd.farcaster.snap+json` and `Vary: Accept`.
|
|
5
|
+
*
|
|
6
|
+
* On validation failure returns JSON `{ "error": "...", "issues": [...] }` with status 400.
|
|
7
|
+
*/
|
|
8
|
+
export declare function payloadToResponse(payload: SnapResponse): Response;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MEDIA_TYPE, rootSchema, validatePage, } from "@farcaster/snap";
|
|
2
|
+
/**
|
|
3
|
+
* Validate a snap root object, then return a JSON Response for the client.
|
|
4
|
+
* Sets `Content-Type: application/vnd.farcaster.snap+json` and `Vary: Accept`.
|
|
5
|
+
*
|
|
6
|
+
* On validation failure returns JSON `{ "error": "...", "issues": [...] }` with status 400.
|
|
7
|
+
*/
|
|
8
|
+
export function payloadToResponse(payload) {
|
|
9
|
+
const validation = validatePage(payload);
|
|
10
|
+
if (!validation.valid) {
|
|
11
|
+
return new Response(JSON.stringify({
|
|
12
|
+
error: "invalid snap page",
|
|
13
|
+
issues: validation.issues,
|
|
14
|
+
}), {
|
|
15
|
+
status: 400,
|
|
16
|
+
headers: {
|
|
17
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const finalized = rootSchema.parse(payload);
|
|
22
|
+
return new Response(JSON.stringify(finalized), {
|
|
23
|
+
status: 200,
|
|
24
|
+
headers: {
|
|
25
|
+
"Content-Type": `${MEDIA_TYPE}; charset=utf-8`,
|
|
26
|
+
Vary: "Accept",
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farcaster/snap-hono",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Hono integration for Farcaster Snap servers",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,10 +26,9 @@
|
|
|
26
26
|
},
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@farcaster/snap": "1.
|
|
29
|
+
"@farcaster/snap": "1.2.0"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@farcaster/snap": "^1.0.0",
|
|
33
32
|
"hono": ">=4.0.0"
|
|
34
33
|
},
|
|
35
34
|
"devDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import type { Hono } from "hono";
|
|
2
2
|
import { cors } from "hono/cors";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
MEDIA_TYPE,
|
|
7
|
-
type ParseRequestOptions,
|
|
8
|
-
type SnapFunction,
|
|
9
|
-
} from "@farcaster/snap";
|
|
3
|
+
import { MEDIA_TYPE, type SnapFunction } from "@farcaster/snap";
|
|
4
|
+
import { parseRequest } from "@farcaster/snap/server";
|
|
5
|
+
import { payloadToResponse } from "./payloadToResponse";
|
|
10
6
|
|
|
11
7
|
export type SnapHandlerOptions = {
|
|
12
8
|
/**
|
|
@@ -54,14 +50,14 @@ export function registerSnapHandler(
|
|
|
54
50
|
app.get(path, async (c) => {
|
|
55
51
|
const accept = c.req.header("Accept");
|
|
56
52
|
if (!clientWantsSnapResponse(accept)) {
|
|
57
|
-
return c.text(fallbackText, 200);
|
|
53
|
+
return c.text(fallbackText, 200, { Vary: "Accept" });
|
|
58
54
|
}
|
|
59
55
|
|
|
60
56
|
const response = await snapFn({
|
|
61
57
|
action: { type: "get" },
|
|
62
58
|
request: c.req.raw,
|
|
63
59
|
});
|
|
64
|
-
return
|
|
60
|
+
return payloadToResponse(response);
|
|
65
61
|
});
|
|
66
62
|
|
|
67
63
|
app.post(path, async (c) => {
|
|
@@ -98,7 +94,7 @@ export function registerSnapHandler(
|
|
|
98
94
|
|
|
99
95
|
const response = await snapFn({ action: parsed.action, request: raw });
|
|
100
96
|
|
|
101
|
-
return
|
|
97
|
+
return payloadToResponse(response);
|
|
102
98
|
});
|
|
103
99
|
}
|
|
104
100
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MEDIA_TYPE,
|
|
3
|
+
rootSchema,
|
|
4
|
+
type SnapResponse,
|
|
5
|
+
validatePage,
|
|
6
|
+
} from "@farcaster/snap";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Validate a snap root object, then return a JSON Response for the client.
|
|
10
|
+
* Sets `Content-Type: application/vnd.farcaster.snap+json` and `Vary: Accept`.
|
|
11
|
+
*
|
|
12
|
+
* On validation failure returns JSON `{ "error": "...", "issues": [...] }` with status 400.
|
|
13
|
+
*/
|
|
14
|
+
export function payloadToResponse(payload: SnapResponse): Response {
|
|
15
|
+
const validation = validatePage(payload);
|
|
16
|
+
if (!validation.valid) {
|
|
17
|
+
return new Response(
|
|
18
|
+
JSON.stringify({
|
|
19
|
+
error: "invalid snap page",
|
|
20
|
+
issues: validation.issues,
|
|
21
|
+
}),
|
|
22
|
+
{
|
|
23
|
+
status: 400,
|
|
24
|
+
headers: {
|
|
25
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const finalized = rootSchema.parse(payload);
|
|
32
|
+
return new Response(JSON.stringify(finalized), {
|
|
33
|
+
status: 200,
|
|
34
|
+
headers: {
|
|
35
|
+
"Content-Type": `${MEDIA_TYPE}; charset=utf-8`,
|
|
36
|
+
Vary: "Accept",
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|