11import { Hono } from "hono" ;
2- import { setCookie } from "hono/cookie" ;
2+ import type { Context } from "hono" ;
3+ import { getCookie , setCookie } from "hono/cookie" ;
34import { handle } from "hono/vercel" ;
4- import { SignJWT } from "jose" ;
5+ import { SignJWT , jwtVerify } from "jose" ;
6+ import { Pool } from "pg" ;
7+ import { mustGetMutator , mustGetQuery } from "@rocicorp/zero" ;
8+ import { handleMutateRequest , handleQueryRequest } from "@rocicorp/zero/server" ;
9+ import { zeroNodePg } from "@rocicorp/zero/server/adapters/pg" ;
10+ import { mutators } from "../src/mutators" ;
11+ import { queries } from "../src/queries" ;
12+ import { schema , type AuthData } from "../src/schema" ;
513
614export const config = {
7- runtime : "edge " ,
15+ runtime : "nodejs " ,
816} ;
917
1018export const app = new Hono ( ) . basePath ( "/api" ) ;
@@ -27,6 +35,27 @@ function randomInt(max: number) {
2735 return Math . floor ( Math . random ( ) * max ) ;
2836}
2937
38+ const authSecret = new TextEncoder ( ) . encode ( must ( process . env . AUTH_SECRET ) ) ;
39+ const pool = new Pool ( {
40+ connectionString : must ( process . env . ZERO_UPSTREAM_DB ) ,
41+ } ) ;
42+ const dbProvider = zeroNodePg ( schema , pool ) ;
43+
44+ const getContext = async ( c : Context ) : Promise < AuthData > => {
45+ const token = getCookie ( c , "jwt" ) ;
46+ if ( ! token ) {
47+ return { userID : null } ;
48+ }
49+
50+ try {
51+ const verified = await jwtVerify ( token , authSecret ) ;
52+ const sub = verified . payload . sub ;
53+ return { userID : typeof sub === "string" ? sub : null } ;
54+ } catch {
55+ return { userID : null } ;
56+ }
57+ } ;
58+
3059app . get ( "/login" , async ( c ) => {
3160 const jwtPayload = {
3261 sub : userIDs [ randomInt ( userIDs . length ) ] ,
@@ -36,7 +65,7 @@ app.get("/login", async (c) => {
3665 const jwt = await new SignJWT ( jwtPayload )
3766 . setProtectedHeader ( { alg : "HS256" } )
3867 . setExpirationTime ( "30days" )
39- . sign ( new TextEncoder ( ) . encode ( must ( process . env . ZERO_AUTH_SECRET ) ) ) ;
68+ . sign ( new TextEncoder ( ) . encode ( must ( process . env . AUTH_SECRET ) ) ) ;
4069
4170 setCookie ( c , "jwt" , jwt , {
4271 expires : new Date ( Date . now ( ) + 30 * 24 * 60 * 60 * 1000 ) ,
@@ -45,6 +74,29 @@ app.get("/login", async (c) => {
4574 return c . text ( "ok" ) ;
4675} ) ;
4776
77+ app . post ( "/zero/query" , async ( c ) => {
78+ const ctx = await getContext ( c ) ;
79+ const result = await handleQueryRequest (
80+ ( name , args ) => mustGetQuery ( queries , name ) . fn ( { args, ctx } ) ,
81+ schema ,
82+ c . req . raw
83+ ) ;
84+ return c . json ( result ) ;
85+ } ) ;
86+
87+ app . post ( "/zero/mutate" , async ( c ) => {
88+ const ctx = await getContext ( c ) ;
89+ const result = await handleMutateRequest (
90+ dbProvider ,
91+ ( transact ) =>
92+ transact ( ( tx , name , args ) =>
93+ mustGetMutator ( mutators , name ) . fn ( { tx, args, ctx } )
94+ ) ,
95+ c . req . raw
96+ ) ;
97+ return c . json ( result ) ;
98+ } ) ;
99+
48100export default handle ( app ) ;
49101
50102function must < T > ( val : T ) {
0 commit comments