Skip to content

Commit 972eb3b

Browse files
authored
feat: added zero 0.25 (#54)
1 parent 351e8ef commit 972eb3b

11 files changed

Lines changed: 317 additions & 145 deletions

File tree

.env

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
VITE_PUBLIC_SERVER='http://localhost:4848'
1+
AUTH_SECRET="abcd"
22
ZERO_UPSTREAM_DB="postgresql://user:password@127.0.0.1:5430/postgres"
3-
ZERO_AUTH_SECRET="secretkey"
4-
ZERO_REPLICA_FILE="/tmp/hello_zero_replica.db"
5-
ZERO_LOG_LEVEL="debug"
3+
VITE_PUBLIC_ZERO_CACHE_URL="http://localhost:4848"
4+
ZERO_QUERY_URL="http://localhost:5173/api/zero/query"
5+
ZERO_MUTATE_URL="http://localhost:5173/api/zero/mutate"
6+
ZERO_QUERY_FORWARD_COOKIES="true"
7+
ZERO_MUTATE_FORWARD_COOKIES="true"
8+
ZERO_SCHEMA_FILE="schema.ts"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ dist-ssr
2929
# zero
3030
zero-schema.json
3131
.vercel
32+
zero.db*
3233

3334
# sst
3435
.sst

api/index.ts

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
import { Hono } from "hono";
2-
import { setCookie } from "hono/cookie";
2+
import type { Context } from "hono";
3+
import { getCookie, setCookie } from "hono/cookie";
34
import { 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

614
export const config = {
7-
runtime: "edge",
15+
runtime: "nodejs",
816
};
917

1018
export 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+
3059
app.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+
48100
export default handle(app);
49101

50102
function must<T>(val: T) {

0 commit comments

Comments
 (0)