Skip to content

Commit

Permalink
feat: support getLoadContext (#6)
Browse files Browse the repository at this point in the history
* feat: add remaining Cloudflare values to contexts

* support `getLoadContext`

* revert `tsup.config.ts`

* tweak `cloudflare-pages.ts`

* make `getLoadContext` not option for `RemixMiddlewareOptions`
  • Loading branch information
yusukebe authored Sep 23, 2024
1 parent 9b71ca1 commit 3db87a4
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 25 deletions.
19 changes: 12 additions & 7 deletions example/app/routes/_index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import type { LoaderFunctionArgs } from '@remix-run/cloudflare'
import { useLoaderData } from '@remix-run/react'

export const loader = ({ context }: LoaderFunctionArgs) => {
const { env } = context.cloudflare as { env: { MY_VAR: string} }
return {
var: env.MY_VAR
}
export const loader = (args: LoaderFunctionArgs) => {
const extra = args.context.extra
const cloudflare = args.context.cloudflare
return { cloudflare, extra }
}

export default function Index() {
const data = useLoaderData<typeof loader>()
const { cloudflare, extra } = useLoaderData<typeof loader>()
return (
<div>
<h1>Remix and Hono</h1>
<h2>Var is {data.var}</h2>
<h2>Var is {cloudflare.env.MY_VAR}</h2>
<h3>
{cloudflare.cf ? 'cf,' : ''}
{cloudflare.ctx ? 'ctx,' : ''}
{cloudflare.caches ? 'caches are available' : ''}
</h3>
<h4>Extra is {extra}</h4>
</div>
)
}
6 changes: 6 additions & 0 deletions example/e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ test('Should return 200 response - /', async ({ page }) => {

const contentH2 = await page.textContent('h2')
expect(contentH2).toBe('Var is My Value')

const contentH3 = await page.textContent('h3')
expect(contentH3).toBe('cf,ctx,caches are available')

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

test('Should return 200 response - /api', async ({ page }) => {
Expand Down
3 changes: 2 additions & 1 deletion example/functions/[[path]].ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// functions/[[path]].ts
import handle from 'hono-remix-adapter/cloudflare-pages'
import { getLoadContext } from 'load-context'
import * as build from '../build/server'
import server from '../server'

export const onRequest = handle(build, server)
export const onRequest = handle(build, server, { getLoadContext })
28 changes: 28 additions & 0 deletions example/load-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { AppLoadContext } from '@remix-run/cloudflare'
import type { PlatformProxy } from 'wrangler'

interface Env {
MY_VAR: string
}

type Cloudflare = Omit<PlatformProxy<Env>, 'dispose'>

declare module '@remix-run/cloudflare' {
interface AppLoadContext {
cloudflare: Cloudflare
extra: string
}
}

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

// Shared implementation compatible with Vite, Wrangler, and Cloudflare Pages
export const getLoadContext: GetLoadContext = ({ context }) => {
return {
...context,
extra: 'stuff',
}
}
2 changes: 2 additions & 0 deletions example/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import serverAdapter from 'hono-remix-adapter/vite'
import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'
import { getLoadContext } from './load-context'

export default defineConfig({
plugins: [
Expand All @@ -20,6 +21,7 @@ export default defineConfig({
}),
serverAdapter({
adapter,
getLoadContext,
entry: 'server/index.ts',
}),
tsconfigPaths(),
Expand Down
41 changes: 32 additions & 9 deletions src/cloudflare-pages.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,38 @@
import type { ServerBuild } from '@remix-run/cloudflare'
import { createRequestHandler } from '@remix-run/cloudflare'
import { Hono } from 'hono'
import { handle } from 'hono/cloudflare-pages'
import { createMiddleware } from 'hono/factory'
import { staticAssets } from 'remix-hono/cloudflare'
import { remix } from 'remix-hono/handler'
import { createGetLoadContextArgs, defaultGetLoadContext } from './remix'
import type { GetLoadContext } from './remix'

export const handler = (serverBuild: any, userApp?: Hono<any, any, any>) => {
interface RemixMiddlewareOptions {
build: ServerBuild
mode?: 'development' | 'production'
getLoadContext: GetLoadContext
}

function remix({ mode, build, getLoadContext }: RemixMiddlewareOptions) {
return createMiddleware(async (c) => {
const requestHandler = createRequestHandler(build, mode)
const args = createGetLoadContextArgs(c)

const loadContext = getLoadContext(args)
return await requestHandler(
c.req.raw,
loadContext instanceof Promise ? await loadContext : loadContext
)
})
}

type Options = {
getLoadContext: GetLoadContext
}

// Relaxing the type definitions
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const handler = (serverBuild: any, userApp?: Hono<any, any, any>, options?: Options) => {
const app = new Hono()

if (userApp) {
Expand All @@ -18,13 +47,7 @@ export const handler = (serverBuild: any, userApp?: Hono<any, any, any>) => {
return remix({
build: serverBuild,
mode: 'production',
getLoadContext(c) {
return {
cloudflare: {
env: c.env,
},
}
},
getLoadContext: options?.getLoadContext ?? defaultGetLoadContext,
})(c, next)
}
)
Expand Down
20 changes: 13 additions & 7 deletions src/dev.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import type { AppLoadContext } from '@remix-run/cloudflare'
import { Hono } from 'hono'
import { createGetLoadContextArgs, defaultGetLoadContext } from './remix'
import type { GetLoadContext } from './remix'

export const handle = (userApp?: Hono) => {
type Options = {
getLoadContext: GetLoadContext
}

export const handle = (userApp?: Hono, options?: Options) => {
const app = new Hono()

if (userApp) {
Expand All @@ -13,13 +18,14 @@ export const handle = (userApp?: Hono) => {
const build = await import('virtual:remix/server-build')
const { createRequestHandler } = await import('@remix-run/cloudflare')
const handler = createRequestHandler(build, 'development')
const remixContext = {
cloudflare: {
env: c.env,
},
} as unknown as AppLoadContext

const getLoadContext = options?.getLoadContext ?? defaultGetLoadContext
const args = createGetLoadContextArgs(c)

const remixContext = getLoadContext(args)
return handler(c.req.raw, remixContext)
})

return app
}

Expand Down
34 changes: 34 additions & 0 deletions src/remix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { AppLoadContext } from '@remix-run/cloudflare'
import type { Context } from 'hono'

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

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const defaultGetLoadContext = ({ context }: any) => {
return {
...context,
}
}

export const createGetLoadContextArgs = (c: Context) => {
return {
context: {
cloudflare: {
env: c.env,
cf: c.req.raw.cf,
ctx: {
...c.executionCtx,
},
caches,
},
},
request: c.req.raw,
}
}
6 changes: 5 additions & 1 deletion src/vite-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { Plugin } from 'vite'
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import type { GetLoadContext } from './remix'

interface Adapter {
env?: Record<string, unknown> | Promise<Record<string, unknown>>
Expand All @@ -17,6 +18,7 @@ interface Adapter {
interface Options {
entry: string
adapter?: () => Adapter | Promise<Adapter>
getLoadContext?: GetLoadContext
}

export default (options: Options): Plugin => {
Expand Down Expand Up @@ -51,7 +53,9 @@ export default (options: Options): Plugin => {
}

const devModule = await server.ssrLoadModule(devPath)
return devModule['default'](app)
return devModule['default'](app, {
getLoadContext: options.getLoadContext,
})
},
})
}

0 comments on commit 3db87a4

Please sign in to comment.