Skip to content

Commit

Permalink
Merge branch 'main' into feat/node-handler
Browse files Browse the repository at this point in the history
  • Loading branch information
yusukebe committed Nov 20, 2024
2 parents 99c30e0 + 0b2b917 commit 91acc5a
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 12 deletions.
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,88 @@ export const onRequest = handle(build, server, { getLoadContext })

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

### Getting Hono context

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`:

```ts
// server/index.ts
import { Hono } from 'hono'

const app = new Hono<{
Variables: {
message: string
}
}>()

app.use(async (c, next) => {
c.set('message', 'Hi from Hono')
await next()
})

export default app
```

In the Remix route, you can get the context from `args.context.hono.context`:

```ts
// app/routes/_index.tsx
import type { LoaderFunctionArgs } from '@remix-run/cloudflare'
import { useLoaderData } from '@remix-run/react'

export const loader = ({ context }) => {
const message = args.context.hono.context.get('message')
return { message }
}

export default function Index() {
const { message } = useLoaderData<typeof loader>()
return <h1>Message is {message}</h1>
}
```

To enable type inference, config the `load-context.ts` like follows:

```ts
// load-context.ts
import type { AppLoadContext } from '@remix-run/cloudflare'
import type { Context } from 'hono'
import type { PlatformProxy } from 'wrangler'

type Env = {
Variables: {
message: string
}
}

type Cloudflare = Omit<PlatformProxy, 'dispose'>

declare module '@remix-run/cloudflare' {
interface AppLoadContext {
cloudflare: Cloudflare
hono: {
context: Context<Env>
}
extra: string
}
}

type GetLoadContext = (args: {
request: Request
context: {
cloudflare: Cloudflare
hono: { context: Context<Env> }
}
}) => AppLoadContext

export const getLoadContext: GetLoadContext = ({ context }) => {
return {
...context,
extra: 'stuff',
}
}
```

## Auth middleware for Remix routes

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:
Expand Down
6 changes: 4 additions & 2 deletions examples/cloudflare-pages/app/routes/_index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import { useLoaderData } from '@remix-run/react'
export const loader = (args: LoaderFunctionArgs) => {
const extra = args.context.extra
const cloudflare = args.context.cloudflare
return { cloudflare, extra }
const myVarInVariables = args.context.hono.context.get('MY_VAR_IN_VARIABLES')
return { cloudflare, extra, myVarInVariables }
}

export default function Index() {
const { cloudflare, extra } = useLoaderData<typeof loader>()
const { cloudflare, extra, myVarInVariables } = useLoaderData<typeof loader>()
return (
<div>
<h1>Remix and Hono</h1>
Expand All @@ -19,6 +20,7 @@ export default function Index() {
{cloudflare.caches ? 'caches are available' : ''}
</h3>
<h4>Extra is {extra}</h4>
<h5>Var in Variables is {myVarInVariables}</h5>
</div>
)
}
3 changes: 3 additions & 0 deletions examples/cloudflare-pages/e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ test('Should return 200 response - /', async ({ page }) => {

const contentH4 = await page.textContent('h4')
expect(contentH4).toBe('Extra is stuff')

const contentH5 = await page.textContent('h5')
expect(contentH5).toBe('Var in Variables is My variable set in c.set')
})

test('Should return 200 response - /api', async ({ page }) => {
Expand Down
20 changes: 16 additions & 4 deletions examples/cloudflare-pages/load-context.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
import type { AppLoadContext } from '@remix-run/cloudflare'
import type { Context } from 'hono'
import type { PlatformProxy } from 'wrangler'

interface Env {
MY_VAR: string
type Env = {
Bindings: {
MY_VAR: string
}
Variables: {
MY_VAR_IN_VARIABLES: string
}
}

type Cloudflare = Omit<PlatformProxy<Env>, 'dispose'>
type Cloudflare = Omit<PlatformProxy<Env['Bindings']>, 'dispose'>

declare module '@remix-run/cloudflare' {
interface AppLoadContext {
cloudflare: Cloudflare
extra: string
hono: {
context: Context<Env>
}
}
}

type GetLoadContext = (args: {
request: Request
context: { cloudflare: Cloudflare }
context: {
cloudflare: Cloudflare
hono: { context: Context<Env> }
}
}) => AppLoadContext

// Shared implementation compatible with Vite, Wrangler, and Cloudflare Pages
Expand Down
9 changes: 6 additions & 3 deletions examples/cloudflare-pages/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ const app = new Hono<{
Bindings: {
MY_VAR: string
}
Variables: {
MY_VAR_IN_VARIABLES: string
}
}>()

app.use(async(c, next) => {
app.use(async (c, next) => {
c.set('MY_VAR_IN_VARIABLES', 'My variable set in c.set')
await next()
c.header('X-Powered-By', 'Remix and Hono')
})

app.get('/api', (c) => {
return c.json({
message: 'Hello',
var: c.env.MY_VAR
var: c.env.MY_VAR,
})
})


export default app
14 changes: 11 additions & 3 deletions src/remix.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import type { AppLoadContext } from '@remix-run/cloudflare'
import type { Context } from 'hono'

export type GetLoadContext = (args: {
type GetLoadContextArgs = {
request: Request
context: {
// Relaxing the type definition
// eslint-disable-next-line @typescript-eslint/no-explicit-any
cloudflare: any
hono: {
context: Context
}
}
}) => AppLoadContext | Promise<AppLoadContext>
}

export type GetLoadContext = (args: GetLoadContextArgs) => AppLoadContext | Promise<AppLoadContext>

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

export const createGetLoadContextArgs = (c: Context) => {
export const createGetLoadContextArgs = (c: Context): GetLoadContextArgs => {
return {
context: {
cloudflare: {
Expand All @@ -29,6 +34,9 @@ export const createGetLoadContextArgs = (c: Context) => {
// @ts-expect-error globalThis.caches is not typed
caches: globalThis.caches ? caches : undefined,
},
hono: {
context: c,
},
},
request: c.req.raw,
}
Expand Down

0 comments on commit 91acc5a

Please sign in to comment.