Skip to content

Commit 0b2b917

Browse files
authored
feat: pass hono's context in getLoadContext (#24)
* feat: pass hono's context in `getLoadContext` * update README * update README
1 parent 4f91c7e commit 0b2b917

File tree

6 files changed

+122
-12
lines changed

6 files changed

+122
-12
lines changed

README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,88 @@ export const onRequest = handle(build, server, { getLoadContext })
217217

218218
This way is almost the same as [Remix](https://remix.run/docs/en/main/guides/vite#augmenting-load-context).
219219

220+
### Getting Hono context
221+
222+
You can get the Hono context in Remix routes. For example, you can pass the value with `c.set()` from your Hono instance in the `server/index.ts`:
223+
224+
```ts
225+
// server/index.ts
226+
import { Hono } from 'hono'
227+
228+
const app = new Hono<{
229+
Variables: {
230+
message: string
231+
}
232+
}>()
233+
234+
app.use(async (c, next) => {
235+
c.set('message', 'Hi from Hono')
236+
await next()
237+
})
238+
239+
export default app
240+
```
241+
242+
In the Remix route, you can get the context from `args.context.hono.context`:
243+
244+
```ts
245+
// app/routes/_index.tsx
246+
import type { LoaderFunctionArgs } from '@remix-run/cloudflare'
247+
import { useLoaderData } from '@remix-run/react'
248+
249+
export const loader = ({ context }) => {
250+
const message = args.context.hono.context.get('message')
251+
return { message }
252+
}
253+
254+
export default function Index() {
255+
const { message } = useLoaderData<typeof loader>()
256+
return <h1>Message is {message}</h1>
257+
}
258+
```
259+
260+
To enable type inference, config the `load-context.ts` like follows:
261+
262+
```ts
263+
// load-context.ts
264+
import type { AppLoadContext } from '@remix-run/cloudflare'
265+
import type { Context } from 'hono'
266+
import type { PlatformProxy } from 'wrangler'
267+
268+
type Env = {
269+
Variables: {
270+
message: string
271+
}
272+
}
273+
274+
type Cloudflare = Omit<PlatformProxy, 'dispose'>
275+
276+
declare module '@remix-run/cloudflare' {
277+
interface AppLoadContext {
278+
cloudflare: Cloudflare
279+
hono: {
280+
context: Context<Env>
281+
}
282+
extra: string
283+
}
284+
}
285+
286+
type GetLoadContext = (args: {
287+
request: Request
288+
context: {
289+
cloudflare: Cloudflare
290+
hono: { context: Context<Env> }
291+
}
292+
}) => AppLoadContext
293+
294+
export const getLoadContext: GetLoadContext = ({ context }) => {
295+
return {
296+
...context,
297+
extra: 'stuff',
298+
}
299+
}
300+
```
301+
220302
## Auth middleware for Remix routes
221303

222304
If you want to add Auth Middleware, e.g. Basic Auth middleware, please be careful that users can access the protected pages with SPA tradition. To prevent this, add a `loader` to the page:

examples/cloudflare-pages/app/routes/_index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import { useLoaderData } from '@remix-run/react'
44
export const loader = (args: LoaderFunctionArgs) => {
55
const extra = args.context.extra
66
const cloudflare = args.context.cloudflare
7-
return { cloudflare, extra }
7+
const myVarInVariables = args.context.hono.context.get('MY_VAR_IN_VARIABLES')
8+
return { cloudflare, extra, myVarInVariables }
89
}
910

1011
export default function Index() {
11-
const { cloudflare, extra } = useLoaderData<typeof loader>()
12+
const { cloudflare, extra, myVarInVariables } = useLoaderData<typeof loader>()
1213
return (
1314
<div>
1415
<h1>Remix and Hono</h1>
@@ -19,6 +20,7 @@ export default function Index() {
1920
{cloudflare.caches ? 'caches are available' : ''}
2021
</h3>
2122
<h4>Extra is {extra}</h4>
23+
<h5>Var in Variables is {myVarInVariables}</h5>
2224
</div>
2325
)
2426
}

examples/cloudflare-pages/e2e.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ test('Should return 200 response - /', async ({ page }) => {
1818

1919
const contentH4 = await page.textContent('h4')
2020
expect(contentH4).toBe('Extra is stuff')
21+
22+
const contentH5 = await page.textContent('h5')
23+
expect(contentH5).toBe('Var in Variables is My variable set in c.set')
2124
})
2225

2326
test('Should return 200 response - /api', async ({ page }) => {

examples/cloudflare-pages/load-context.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,34 @@
11
import type { AppLoadContext } from '@remix-run/cloudflare'
2+
import type { Context } from 'hono'
23
import type { PlatformProxy } from 'wrangler'
34

4-
interface Env {
5-
MY_VAR: string
5+
type Env = {
6+
Bindings: {
7+
MY_VAR: string
8+
}
9+
Variables: {
10+
MY_VAR_IN_VARIABLES: string
11+
}
612
}
713

8-
type Cloudflare = Omit<PlatformProxy<Env>, 'dispose'>
14+
type Cloudflare = Omit<PlatformProxy<Env['Bindings']>, 'dispose'>
915

1016
declare module '@remix-run/cloudflare' {
1117
interface AppLoadContext {
1218
cloudflare: Cloudflare
1319
extra: string
20+
hono: {
21+
context: Context<Env>
22+
}
1423
}
1524
}
1625

1726
type GetLoadContext = (args: {
1827
request: Request
19-
context: { cloudflare: Cloudflare }
28+
context: {
29+
cloudflare: Cloudflare
30+
hono: { context: Context<Env> }
31+
}
2032
}) => AppLoadContext
2133

2234
// Shared implementation compatible with Vite, Wrangler, and Cloudflare Pages

examples/cloudflare-pages/server/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,22 @@ const app = new Hono<{
55
Bindings: {
66
MY_VAR: string
77
}
8+
Variables: {
9+
MY_VAR_IN_VARIABLES: string
10+
}
811
}>()
912

10-
app.use(async(c, next) => {
13+
app.use(async (c, next) => {
14+
c.set('MY_VAR_IN_VARIABLES', 'My variable set in c.set')
1115
await next()
1216
c.header('X-Powered-By', 'Remix and Hono')
1317
})
1418

1519
app.get('/api', (c) => {
1620
return c.json({
1721
message: 'Hello',
18-
var: c.env.MY_VAR
22+
var: c.env.MY_VAR,
1923
})
2024
})
2125

22-
2326
export default app

src/remix.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
import type { AppLoadContext } from '@remix-run/cloudflare'
22
import type { Context } from 'hono'
33

4-
export type GetLoadContext = (args: {
4+
type GetLoadContextArgs = {
55
request: Request
66
context: {
77
// Relaxing the type definition
88
// eslint-disable-next-line @typescript-eslint/no-explicit-any
99
cloudflare: any
10+
hono: {
11+
context: Context
12+
}
1013
}
11-
}) => AppLoadContext | Promise<AppLoadContext>
14+
}
15+
16+
export type GetLoadContext = (args: GetLoadContextArgs) => AppLoadContext | Promise<AppLoadContext>
1217

1318
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1419
export const defaultGetLoadContext = ({ context }: any): AppLoadContext => {
@@ -17,7 +22,7 @@ export const defaultGetLoadContext = ({ context }: any): AppLoadContext => {
1722
}
1823
}
1924

20-
export const createGetLoadContextArgs = (c: Context) => {
25+
export const createGetLoadContextArgs = (c: Context): GetLoadContextArgs => {
2126
return {
2227
context: {
2328
cloudflare: {
@@ -29,6 +34,9 @@ export const createGetLoadContextArgs = (c: Context) => {
2934
// @ts-expect-error globalThis.caches is not typed
3035
caches: globalThis.caches ? caches : undefined,
3136
},
37+
hono: {
38+
context: c,
39+
},
3240
},
3341
request: c.req.raw,
3442
}

0 commit comments

Comments
 (0)