v0.0.53
What's Changed
- Request context by @justinvdm in #251
Breaking Changes
- The
appContextprop has been renamed toctxeverywhere - Environment variables must now be imported from
cloudflare:workers - Action handlers (in functions.ts files) must now use
requestInfoto access request data - The
RouteOptionsandHandlerOptionstypes have been replaced by theRequestInfotype - App context types are now configured via
rw.d.tsinstead of type parameters
Migration Guide
1. appContext Renamed to ctx
The shared context object, previously named appContext, has been renamed to ctx throughout the codebase:
// Before
function MyComponent({ appContext }: RouteOptions) {
return <div>Hello {appContext.user?.username}</div>;
}
route("/dashboard", ({ appContext }) => {
if (!appContext.user) {
return redirect("/login");
}
});
const middleware = ({ request, appContext }) => {
appContext.someValue = "test";
};
// After
function MyComponent({ ctx }: RequestInfo) {
return <div>Hello {ctx.user?.username}</div>;
}
route("/dashboard", ({ ctx }) => {
if (!ctx.user) {
return redirect("/login");
}
});
const middleware = ({ request, ctx }) => {
ctx.someValue = "test";
};2. Environment Variables
Environment variables are now accessed through the cloudflare:workers import:
// Before
function MyComponent({ env }: RouteOptions) {
const db = env.DB;
}
// After
import { env } from "cloudflare:workers";
function MyComponent() {
const db = env.DB;
}3. Action Handlers (functions.ts)
Action handlers must now use requestInfo to access request data:
// Before - functions.ts
export async function myAction(input: string, opts?: HandlerOptions) {
const { request, appContext } = opts!;
// ...
}
// After - functions.ts
import { requestInfo } from "@redwoodjs/sdk/worker";
export async function myAction(input: string) {
const { request, headers, ctx } = requestInfo;
// ...
}4. Components and Routes
Components, routes and middleware now use the RequestInfo type instead of RouteOptions as their input type:
// Before
import { RouteOptions } from "@redwoodjs/sdk/worker";
export function Home({ appContext }: RouteOptions) {
return (
<div>
<p>
{appContext.user?.username
? `You are logged in as user ${appContext.user.username}`
: "You are not logged in"}
</p>
</div>
);
}
// After
import { RequestInfo } from "@redwoodjs/sdk/worker";
export function Home({ ctx }: RequestInfo) {
return (
<div>
<p>
{ctx.user?.username
? `You are logged in as user ${ctx.user.username}`
: "You are not logged in"}
</p>
</div>
);
}
// Before - Route
route("/protected", [
({ appContext }: RouteOptions) => {
if (!appContext.user) {
return new Response(null, {
status: 302,
headers: { Location: "/user/login" },
});
}
},
Home,
]);
// After - Route
route("/protected", [
({ ctx }: RequestInfo) => {
if (!ctx.user) {
return new Response(null, {
status: 302,
headers: { Location: "/user/login" },
});
}
},
Home,
]);
// Before - Middleware
import { RouteMiddleware } from "@redwoodjs/sdk/router";
export const authMiddleware =
(): RouteMiddleware =>
async ({ request, appContext }) => {
const session = await sessions.load(request);
if (session?.userId) {
appContext.user = await db.user.findUnique({
where: { id: session.userId },
});
}
};
// After - Middleware
import { RouteMiddleware } from "@redwoodjs/sdk/router";
export const authMiddleware =
(): RouteMiddleware =>
async ({ request, ctx }) => {
const session = await sessions.load(request);
if (session?.userId) {
ctx.user = await db.user.findUnique({
where: { id: session.userId },
});
}
};5. App Context Configuration
The way app context is configured has changed from using type parameters to using declaration merging in a rw.d.ts file:
// Before
// src/worker.tsx
import type { User } from "@prisma/client";
import { Session } from "./session/durableObject";
export type AppContext = {
session: Session | null;
user: User | null;
};
export default defineApp<AppContext>([
// ... app configuration
])
// After
// src/worker.tsx
import type { User } from "@prisma/client";
import { Session } from "./session/durableObject";
export type AppContext = {
session: Session | null;
user: User | null;
};
// types/rw.d.ts - New file
import { AppContext } from "../src/worker";
declare module "@redwoodjs/sdk/worker" {
export interface DefaultAppContext extends AppContext {}
}
// tsconfig.json
{
"compilerOptions": {
// ... other options
"types": [..., "./types/rw.d.ts"]
}
}
// src/worker.tsx
export default defineApp([
// ... app configuration
])The rw.d.ts file is a TypeScript declaration file that allows you to extend existing types from the SDK. By placing it in a types directory in your tsconfig.json, you can ensure TypeScript picks up your custom type definitions.
Full Changelog: v0.0.52...v0.0.53