From 517b2b0cf5779206c035671da29c8a6682ef598d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Xalambr=C3=AD?= Date: Wed, 12 Jul 2023 00:46:18 -0500 Subject: [PATCH] Export new middlewares and document them --- README.md | 116 +++++++++++++++++- package.json | 16 +-- src/middlewares/cookie-session.ts | 17 +-- src/middlewares/session.ts | 8 +- .../{kv-session.ts => worker-kv-session.ts} | 19 +-- 5 files changed, 131 insertions(+), 45 deletions(-) rename src/middlewares/{kv-session.ts => worker-kv-session.ts} (83%) diff --git a/README.md b/README.md index 56d1526..8812cd2 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # Remix adapter for Hono -[Remix](https://remix.run) is a web framework for building web applications, -which can run on the Edge. +> [Remix](https://remix.run) is a web framework for building web applications, +> which can run on the Edge. -[Hono](https://hono.dev) is a small and ultrafast web framework for the Edges. +> [Hono](https://hono.dev) is a small and ultrafast web framework for the Edges. This adapter allows you to use Hono with Remix, so you can use the best of each one. @@ -26,7 +26,7 @@ import { logDevReady } from "@remix-run/cloudflare"; import * as build from "@remix-run/dev/server-build"; import { Hono } from "hono"; import { handle } from "hono/cloudflare-pages"; -import { remix } from "remix-hono"; +import { remix } from "remix-hono/cloudflare"; if (process.env.NODE_ENV === "development") logDevReady(build); @@ -70,6 +70,114 @@ server.use("*", remix(options)); With just that, your app will now have basic auth protection, which can work great of preview applications. +## Session Middleware + +Additionally to the `remix` Hono middleware, there are other three middlewares +to work with Remix sessions. + +Because Remix sessions typically use a secret coming from the environment you +will need access to Hono `ctx.env` to use them. If you're using the Worker KV +session storage you will also need to pass the KV binding to the middleware. + +You can use the different middlewares included in this package to do that: + +```ts +import { session } from "remix-hono/session"; +import { createWorkerKVSessionStorage } from "@remix-run/cloudflare"; + +server.use( + "*", + session({ + autoCommit: true, + createSessionStorage(context) { + return createWorkersKVSessionStorage({ + kv: context.env.MY_KV_BINDING, + cookie: { + name: "session", + httpOnly: true, + secrets: [context.SESSION_SECRET], + }, + }); + }, + }), +); +``` + +Now, setup the Remix middleware after your session middleware and use the +helpers `getSessionStorage` and `getSession` to access the SessionStorage and +Session objects. + +> **Note** The Session object will only be defined if autoCommit was set as true +> in the session middleware options. If you set it to false, you will need to +> call `sessionStorage.getSession()` manually. + +```ts +import { getSessionStorage, getSession } from "remix-hono/session"; +server.use( + "*", + remix({ + build, + mode: process.env.NODE_ENV as "development" | "production", + // getLoadContext is optional, the default function is the same as here + getLoadContext(ctx) { + let sessionStorage = getSessionStorage(ctx); + let session = getSession(ctx); + + // Return them here to access them in your loaders and actions + return { ...ctx.env, sessionStorage, session }; + }, + }), +); +``` + +The `session` middleware is generic and lets you use any session storage +mechanism. If you want to use the Worker KV session storage you can use the +`workerKVSession` middleware instead. + +```ts +import { workerKVSession } from "remix-hono/session/worker-kv"; + +server.use( + "*", + workerKVSession({ + autoCommit: true, // same as in the session middleware + cookie: { + name: "session", // all cookie options as in createWorkerKVSessionStorage + // In this function, you can access context.env to get the session secret + secrets(context) { + return [context.env.SECRET]; + }, + }, + // The name of the binding using for the KVNamespace + binding: "KV_BINDING", + }), +); +``` + +If you want to use the cookie session storage, you can use the `cookieSession` +middleware instead. + +```ts +import { cookieSession } from "remix-hono/session/cookie"; + +server.use( + "*", + cookieSession({ + autoCommit: true, // same as in the session middleware + cookie: { + name: "session", // all cookie options as in createCookieSessionStorage + // In this function, you can access context.env to get the session secret + secrets(context) { + return [context.env.SECRET]; + }, + }, + }), +); +``` + +In both `workerKVSession` and `cookieSession` you use `getSession` and +`getSessionStorage` imported from `remix-hono/session` + ## Author - [Sergio Xalambrí](https://sergiodxa.com) diff --git a/package.json b/package.json index b35c12c..1869028 100644 --- a/package.json +++ b/package.json @@ -30,18 +30,18 @@ "types": "./build/cloudflare.d.ts", "default": "./build/cloudflare.js" }, - "./cookie-session": { - "types": "./build/cookie-session.d.ts", - "default": "./build/cookie-session.js" - }, - "./kv-session": { - "types": "./build/kv-session.d.ts", - "default": "./build/kv-session.js" - }, "./session": { "types": "./build/session.d.ts", "default": "./build/session.js" }, + "./session/cookie": { + "types": "./build/cookie-session.d.ts", + "default": "./build/cookie-session.js" + }, + "./session/worker-kv": { + "types": "./build/worker-kv-session.d.ts", + "default": "./build/worker-kv-session.js" + }, "./package.json": "./package.json" }, "scripts": { diff --git a/src/middlewares/cookie-session.ts b/src/middlewares/cookie-session.ts index 4f5039e..1a28784 100644 --- a/src/middlewares/cookie-session.ts +++ b/src/middlewares/cookie-session.ts @@ -1,9 +1,10 @@ +import type { Context, MiddlewareHandler } from "hono"; + import { CookieOptions, SessionData, createCookieSessionStorage, } from "@remix-run/cloudflare"; -import { Context, Hono, MiddlewareHandler } from "hono"; import { session } from "./session"; @@ -47,17 +48,3 @@ export function kvSession< }, }); } - -new Hono().use( - "*", - kvSession({ - autoCommit: true, - cookie: { - name: "__session", - httpOnly: true, - secrets(context) { - return [context.env.SECRET]; - }, - }, - }), -); diff --git a/src/middlewares/session.ts b/src/middlewares/session.ts index 6dc59fb..7c46df1 100644 --- a/src/middlewares/session.ts +++ b/src/middlewares/session.ts @@ -1,5 +1,9 @@ -import { Session, SessionData, SessionStorage } from "@remix-run/cloudflare"; -import { Context, Env, Input, MiddlewareHandler } from "hono"; +import type { + Session, + SessionData, + SessionStorage, +} from "@remix-run/cloudflare"; +import type { Context, Env, Input, MiddlewareHandler } from "hono"; const sessionStorageSymbol = Symbol(); const sessionSymbol = Symbol(); diff --git a/src/middlewares/kv-session.ts b/src/middlewares/worker-kv-session.ts similarity index 83% rename from src/middlewares/kv-session.ts rename to src/middlewares/worker-kv-session.ts index b5beb02..cfed170 100644 --- a/src/middlewares/kv-session.ts +++ b/src/middlewares/worker-kv-session.ts @@ -1,9 +1,10 @@ +import type { Context, MiddlewareHandler } from "hono"; + import { CookieOptions, SessionData, createWorkersKVSessionStorage, } from "@remix-run/cloudflare"; -import { Context, Hono, MiddlewareHandler } from "hono"; import { session } from "./session"; @@ -15,7 +16,7 @@ type BindingsObject = { [K in KV | Secret]: K extends KV ? KVNamespace : string; }; -export function kvSession< +export function workerKVSession< KVBinding extends string, SecretBinding extends string, Data = SessionData, @@ -54,17 +55,3 @@ export function kvSession< }, }); } - -new Hono().use( - "*", - kvSession({ - autoCommit: true, - cookie: { - name: "session", - secrets(context) { - return [context.env.SECRET]; - }, - }, - binding: "KV_BINDING", - }), -);