rwsdk 1.0.0-alpha.12 → 1.0.0-alpha.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/llms/rules/middleware.d.ts +1 -1
- package/dist/llms/rules/middleware.js +4 -4
- package/dist/runtime/entries/worker.d.ts +0 -1
- package/dist/runtime/entries/worker.js +0 -1
- package/dist/runtime/lib/auth/session.d.ts +2 -2
- package/dist/runtime/lib/auth/session.js +4 -4
- package/dist/runtime/lib/router.test.js +0 -1
- package/dist/runtime/requestInfo/types.d.ts +0 -2
- package/dist/runtime/requestInfo/worker.js +1 -9
- package/dist/runtime/worker.js +0 -8
- package/package.json +44 -44
- package/dist/runtime/imports/resolveSSRValue.d.ts +0 -1
- package/dist/runtime/imports/resolveSSRValue.js +0 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const middleware = "\n\n# RedwoodSDK: Middleware\n\nYou're an expert at Cloudflare, TypeScript, and building web apps with RedwoodSDK. Generate high quality **RedwoodSDK middleware** that adhere to the following best practices:\n\n## Guidelines\n\n1. Create focused, single-responsibility middleware functions\n2. Organize middleware in dedicated files (e.g., `middleware.ts`, `middleware.tsx`)\n3. Use typed parameters and return values\n4. Include clear error handling and logging\n5. Follow the principle of least privilege\n6. Implement proper security headers and CORS policies\n7. Optimize for performance with caching strategies\n\n## What is Middleware?\n\nMiddleware functions in RedwoodSDK are functions that run on every request before your route handlers. They can:\n\n- Add security headers\n- Handle CORS\n- Implement caching strategies\n- Add request/response logging\n- Transform request/response data\n- Implement rate limiting\n- Add performance monitoring\n- Handle error boundaries\n- Setup sessions\n- Authenticate users\n\n## Example Templates\n\n### Basic Middleware Structure\n\n```tsx\nexport default defineApp([\n setCommonHeaders(),\n async ({ ctx, request,
|
|
1
|
+
export declare const middleware = "\n\n# RedwoodSDK: Middleware\n\nYou're an expert at Cloudflare, TypeScript, and building web apps with RedwoodSDK. Generate high quality **RedwoodSDK middleware** that adhere to the following best practices:\n\n## Guidelines\n\n1. Create focused, single-responsibility middleware functions\n2. Organize middleware in dedicated files (e.g., `middleware.ts`, `middleware.tsx`)\n3. Use typed parameters and return values\n4. Include clear error handling and logging\n5. Follow the principle of least privilege\n6. Implement proper security headers and CORS policies\n7. Optimize for performance with caching strategies\n\n## What is Middleware?\n\nMiddleware functions in RedwoodSDK are functions that run on every request before your route handlers. They can:\n\n- Add security headers\n- Handle CORS\n- Implement caching strategies\n- Add request/response logging\n- Transform request/response data\n- Implement rate limiting\n- Add performance monitoring\n- Handle error boundaries\n- Setup sessions\n- Authenticate users\n\n## Example Templates\n\n### Basic Middleware Structure\n\n```tsx\nexport default defineApp([\n setCommonHeaders(),\n async ({ ctx, request, response }) => {\n await setupDb(env);\n setupSessionStore(env);\n try {\n // Grab the session's data.\n ctx.session = await sessions.load(request);\n } catch (error) {\n if (error instanceof ErrorResponse && error.code === 401) {\n await sessions.remove(request, response.headers);\n response.headers.set(\"Location\", \"/user/login\");\n\n return new Response(null, {\n status: 302,\n headers: response.headers,\n });\n }\n\n throw error;\n }\n\n // Populate the ctx with the user's data\n if (ctx.session?.userId) {\n ctx.user = await db.user.findUnique({\n where: {\n id: ctx.session.userId,\n },\n });\n }\n },\n // Route handlers\n]);\n```\n";
|
|
@@ -36,7 +36,7 @@ Middleware functions in RedwoodSDK are functions that run on every request befor
|
|
|
36
36
|
\`\`\`tsx
|
|
37
37
|
export default defineApp([
|
|
38
38
|
setCommonHeaders(),
|
|
39
|
-
async ({ ctx, request,
|
|
39
|
+
async ({ ctx, request, response }) => {
|
|
40
40
|
await setupDb(env);
|
|
41
41
|
setupSessionStore(env);
|
|
42
42
|
try {
|
|
@@ -44,12 +44,12 @@ export default defineApp([
|
|
|
44
44
|
ctx.session = await sessions.load(request);
|
|
45
45
|
} catch (error) {
|
|
46
46
|
if (error instanceof ErrorResponse && error.code === 401) {
|
|
47
|
-
await sessions.remove(request, headers);
|
|
48
|
-
headers.set("Location", "/user/login");
|
|
47
|
+
await sessions.remove(request, response.headers);
|
|
48
|
+
response.headers.set("Location", "/user/login");
|
|
49
49
|
|
|
50
50
|
return new Response(null, {
|
|
51
51
|
status: 302,
|
|
52
|
-
headers,
|
|
52
|
+
headers: response.headers,
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -35,10 +35,10 @@ export declare const defineSessionStore: <Session, SessionInputData>({ cookieNam
|
|
|
35
35
|
unset: (sessionId: string) => Promise<void>;
|
|
36
36
|
}) => {
|
|
37
37
|
load: (request: Request) => Promise<Session | null>;
|
|
38
|
-
save: (
|
|
38
|
+
save: (responseHeaders: Headers, sessionInputData: SessionInputData, { maxAge }?: {
|
|
39
39
|
maxAge?: number | true;
|
|
40
40
|
}) => Promise<void>;
|
|
41
|
-
remove: (request: Request,
|
|
41
|
+
remove: (request: Request, responseHeaders: Headers) => Promise<void>;
|
|
42
42
|
};
|
|
43
43
|
type SessionStoreFromDurableObject<SessionDurableObject> = SessionDurableObject extends DurableObjectMethods<infer Session, infer SessionInputData> ? SessionStore<Session, SessionInputData> : never;
|
|
44
44
|
export declare const defineDurableSession: <SessionDurableObject extends DurableObjectMethods<any, any>>({ cookieName, createCookie, secretKey, sessionDurableObject, }: {
|
|
@@ -89,17 +89,17 @@ export const defineSessionStore = ({ cookieName = "session_id", createCookie = c
|
|
|
89
89
|
throw new ErrorResponse(401, "Invalid session id");
|
|
90
90
|
}
|
|
91
91
|
};
|
|
92
|
-
const save = async (
|
|
92
|
+
const save = async (responseHeaders, sessionInputData, { maxAge } = {}) => {
|
|
93
93
|
const sessionId = await generateSessionId({ secretKey });
|
|
94
94
|
await set(sessionId, sessionInputData);
|
|
95
|
-
|
|
95
|
+
responseHeaders.set("Set-Cookie", createCookie({ name: cookieName, sessionId, maxAge }));
|
|
96
96
|
};
|
|
97
|
-
const remove = async (request,
|
|
97
|
+
const remove = async (request, responseHeaders) => {
|
|
98
98
|
const sessionId = getSessionIdFromCookie(request);
|
|
99
99
|
if (sessionId) {
|
|
100
100
|
await unset(sessionId);
|
|
101
101
|
}
|
|
102
|
-
|
|
102
|
+
responseHeaders.set("Set-Cookie", createCookie({ name: cookieName, sessionId: "", maxAge: 0 }));
|
|
103
103
|
};
|
|
104
104
|
return {
|
|
105
105
|
load,
|
|
@@ -5,8 +5,6 @@ export interface RequestInfo<Params = any, AppContext = DefaultAppContext> {
|
|
|
5
5
|
request: Request;
|
|
6
6
|
params: Params;
|
|
7
7
|
ctx: AppContext;
|
|
8
|
-
/** @deprecated: Use `response.headers` instead */
|
|
9
|
-
headers: Headers;
|
|
10
8
|
rw: RwContext;
|
|
11
9
|
cf: ExecutionContext;
|
|
12
10
|
response: ResponseInit & {
|
|
@@ -2,15 +2,7 @@ import { AsyncLocalStorage } from "async_hooks";
|
|
|
2
2
|
const requestInfoDeferred = Promise.withResolvers();
|
|
3
3
|
const requestInfoStore = new AsyncLocalStorage();
|
|
4
4
|
const requestInfoBase = {};
|
|
5
|
-
const REQUEST_INFO_KEYS = [
|
|
6
|
-
"request",
|
|
7
|
-
"params",
|
|
8
|
-
"ctx",
|
|
9
|
-
"headers",
|
|
10
|
-
"rw",
|
|
11
|
-
"cf",
|
|
12
|
-
"response",
|
|
13
|
-
];
|
|
5
|
+
const REQUEST_INFO_KEYS = ["request", "params", "ctx", "rw", "cf", "response"];
|
|
14
6
|
REQUEST_INFO_KEYS.forEach((key) => {
|
|
15
7
|
Object.defineProperty(requestInfoBase, key, {
|
|
16
8
|
enumerable: true,
|
package/dist/runtime/worker.js
CHANGED
|
@@ -36,7 +36,6 @@ export const defineApp = (routes) => {
|
|
|
36
36
|
const isRSCRequest = url.searchParams.has("__rsc") ||
|
|
37
37
|
request.headers.get("accept")?.includes("text/x-component");
|
|
38
38
|
const isAction = url.searchParams.has("__rsc_action_id");
|
|
39
|
-
const userHeaders = new Headers();
|
|
40
39
|
const rw = {
|
|
41
40
|
Document: DefaultDocument,
|
|
42
41
|
nonce: generateNonce(),
|
|
@@ -52,7 +51,6 @@ export const defineApp = (routes) => {
|
|
|
52
51
|
};
|
|
53
52
|
const outerRequestInfo = {
|
|
54
53
|
request,
|
|
55
|
-
headers: userHeaders,
|
|
56
54
|
cf,
|
|
57
55
|
params: {},
|
|
58
56
|
ctx: {},
|
|
@@ -144,12 +142,6 @@ export const defineApp = (routes) => {
|
|
|
144
142
|
// context(justinvdm, 18 Mar 2025): In some cases, such as a .fetch() call to a durable object instance, or Response.redirect(),
|
|
145
143
|
// we need to return a mutable response object.
|
|
146
144
|
const mutableResponse = new Response(response.body, response);
|
|
147
|
-
// Merge user headers from the legacy headers object
|
|
148
|
-
for (const [key, value] of userHeaders.entries()) {
|
|
149
|
-
if (!response.headers.has(key)) {
|
|
150
|
-
mutableResponse.headers.set(key, value);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
145
|
// Merge headers from user response init (these take precedence)
|
|
154
146
|
if (userResponseInit.headers) {
|
|
155
147
|
const userResponseHeaders = new Headers(userResponseInit.headers);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rwsdk",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.14",
|
|
4
4
|
"description": "Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -132,39 +132,39 @@
|
|
|
132
132
|
"author": "RedwoodSDK <peter@redwoodjs.com>",
|
|
133
133
|
"license": "MIT",
|
|
134
134
|
"dependencies": {
|
|
135
|
-
"@ast-grep/napi": "
|
|
136
|
-
"@cloudflare/workers-types": "
|
|
137
|
-
"@mdx-js/mdx": "
|
|
138
|
-
"@puppeteer/browsers": "
|
|
139
|
-
"@types/fs-extra": "
|
|
140
|
-
"@types/react": "
|
|
141
|
-
"@types/react-dom": "
|
|
142
|
-
"@types/react-is": "
|
|
143
|
-
"@vitejs/plugin-react": "
|
|
144
|
-
"chokidar": "
|
|
145
|
-
"debug": "
|
|
146
|
-
"enhanced-resolve": "
|
|
147
|
-
"eventsource-parser": "
|
|
148
|
-
"execa": "
|
|
149
|
-
"fs-extra": "
|
|
150
|
-
"glob": "
|
|
151
|
-
"ignore": "
|
|
152
|
-
"jsonc-parser": "
|
|
153
|
-
"kysely": "
|
|
154
|
-
"kysely-do": "
|
|
155
|
-
"lodash": "
|
|
156
|
-
"magic-string": "
|
|
157
|
-
"miniflare": "
|
|
158
|
-
"picocolors": "
|
|
159
|
-
"proper-lockfile": "
|
|
160
|
-
"puppeteer-core": "
|
|
161
|
-
"react-is": "
|
|
162
|
-
"rsc-html-stream": "
|
|
163
|
-
"tmp-promise": "
|
|
164
|
-
"ts-morph": "
|
|
165
|
-
"unique-names-generator": "
|
|
166
|
-
"vibe-rules": "
|
|
167
|
-
"vite-tsconfig-paths": "
|
|
135
|
+
"@ast-grep/napi": "~0.38.5",
|
|
136
|
+
"@cloudflare/workers-types": "~4.20250906.0",
|
|
137
|
+
"@mdx-js/mdx": "~3.1.1",
|
|
138
|
+
"@puppeteer/browsers": "~2.8.0",
|
|
139
|
+
"@types/fs-extra": "~11.0.4",
|
|
140
|
+
"@types/react": "~19.1.2",
|
|
141
|
+
"@types/react-dom": "~19.1.2",
|
|
142
|
+
"@types/react-is": "~19.0.0",
|
|
143
|
+
"@vitejs/plugin-react": "~4.3.4",
|
|
144
|
+
"chokidar": "~3.6.0",
|
|
145
|
+
"debug": "~4.4.0",
|
|
146
|
+
"enhanced-resolve": "~5.18.1",
|
|
147
|
+
"eventsource-parser": "~3.0.0",
|
|
148
|
+
"execa": "~9.5.2",
|
|
149
|
+
"fs-extra": "~11.3.0",
|
|
150
|
+
"glob": "~11.0.1",
|
|
151
|
+
"ignore": "~7.0.4",
|
|
152
|
+
"jsonc-parser": "~3.3.1",
|
|
153
|
+
"kysely": "~0.28.2",
|
|
154
|
+
"kysely-do": "~0.0.1-rc.1",
|
|
155
|
+
"lodash": "~4.17.21",
|
|
156
|
+
"magic-string": "~0.30.17",
|
|
157
|
+
"miniflare": "~4.20250405.0",
|
|
158
|
+
"picocolors": "~1.1.1",
|
|
159
|
+
"proper-lockfile": "~4.1.2",
|
|
160
|
+
"puppeteer-core": "~22.8.1",
|
|
161
|
+
"react-is": "~19.0.0",
|
|
162
|
+
"rsc-html-stream": "~0.0.6",
|
|
163
|
+
"tmp-promise": "~3.0.3",
|
|
164
|
+
"ts-morph": "~25.0.1",
|
|
165
|
+
"unique-names-generator": "~4.7.1",
|
|
166
|
+
"vibe-rules": "~0.2.31",
|
|
167
|
+
"vite-tsconfig-paths": "~5.1.4"
|
|
168
168
|
},
|
|
169
169
|
"peerDependencies": {
|
|
170
170
|
"@cloudflare/vite-plugin": "^1.12.4",
|
|
@@ -176,15 +176,15 @@
|
|
|
176
176
|
},
|
|
177
177
|
"packageManager": "pnpm@9.14.4+sha512.c8180b3fbe4e4bca02c94234717896b5529740a6cbadf19fa78254270403ea2f27d4e1d46a08a0f56c89b63dc8ebfd3ee53326da720273794e6200fcf0d184ab",
|
|
178
178
|
"devDependencies": {
|
|
179
|
-
"@types/debug": "
|
|
180
|
-
"@types/js-beautify": "
|
|
181
|
-
"@types/lodash": "
|
|
182
|
-
"@types/node": "
|
|
183
|
-
"@types/proper-lockfile": "
|
|
184
|
-
"js-beautify": "
|
|
185
|
-
"semver": "
|
|
186
|
-
"tsx": "
|
|
187
|
-
"typescript": "
|
|
188
|
-
"vitest": "
|
|
179
|
+
"@types/debug": "~4.1.12",
|
|
180
|
+
"@types/js-beautify": "~1.14.3",
|
|
181
|
+
"@types/lodash": "~4.17.16",
|
|
182
|
+
"@types/node": "~24.5.2",
|
|
183
|
+
"@types/proper-lockfile": "~4.1.4",
|
|
184
|
+
"js-beautify": "~1.15.4",
|
|
185
|
+
"semver": "~7.7.1",
|
|
186
|
+
"tsx": "~4.19.4",
|
|
187
|
+
"typescript": "~5.8.3",
|
|
188
|
+
"vitest": "~3.1.1"
|
|
189
189
|
}
|
|
190
190
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const resolveSSRValue: <Value>(clientReference: Value) => Promise<Value>;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { ssrGetModuleExport } from "rwsdk/__ssr_bridge";
|
|
2
|
-
export const resolveSSRValue = (clientReference) => {
|
|
3
|
-
const id = clientReference.__rwsdk_clientReferenceId;
|
|
4
|
-
if (!id) {
|
|
5
|
-
throw new Error("RWSDK: Client reference is not a client reference");
|
|
6
|
-
}
|
|
7
|
-
return ssrGetModuleExport(id);
|
|
8
|
-
};
|