rwsdk 1.0.0-beta.48 → 1.0.0-beta.49-test.20260121220325

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.
@@ -16,12 +16,16 @@ export { initClientNavigation, navigate } from "./navigation.js";
16
16
  import { getCachedNavigationResponse } from "./navigationCache.js";
17
17
  import { isActionResponse } from "./types";
18
18
  export const fetchTransport = (transportContext) => {
19
- const fetchCallServer = async (id, args, source = "action") => {
19
+ const fetchCallServer = async (id, args, source = "action", method = "POST") => {
20
20
  const url = new URL(window.location.href);
21
21
  url.searchParams.set("__rsc", "");
22
22
  const isAction = id != null;
23
23
  if (isAction) {
24
24
  url.searchParams.set("__rsc_action_id", id);
25
+ // If args are provided and method is GET, serialize them into the query string
26
+ if (args != null && method === "GET") {
27
+ url.searchParams.set("args", JSON.stringify(args));
28
+ }
25
29
  }
26
30
  let fetchPromise;
27
31
  if (!isAction && source === "navigation") {
@@ -39,11 +43,26 @@ export const fetchTransport = (transportContext) => {
39
43
  }
40
44
  }
41
45
  else {
42
- fetchPromise = fetch(url, {
43
- method: "POST",
44
- redirect: "manual",
45
- body: args != null ? await encodeReply(args) : null,
46
- });
46
+ const headers = new Headers();
47
+ // Add x-rsc-data-only header if we want to skip the React tree render on the server
48
+ if (source === "query") {
49
+ headers.set("x-rsc-data-only", "true");
50
+ }
51
+ if (method === "GET") {
52
+ fetchPromise = fetch(url, {
53
+ method: "GET",
54
+ headers,
55
+ redirect: "manual",
56
+ });
57
+ }
58
+ else {
59
+ fetchPromise = fetch(url, {
60
+ method: "POST",
61
+ headers,
62
+ redirect: "manual",
63
+ body: args != null ? await encodeReply(args) : null,
64
+ });
65
+ }
47
66
  }
48
67
  // If there's a response handler, check the response first
49
68
  if (transportContext.handleResponse) {
@@ -56,7 +75,9 @@ export const fetchTransport = (transportContext) => {
56
75
  const streamData = createFromFetch(Promise.resolve(response), {
57
76
  callServer: fetchCallServer,
58
77
  });
59
- transportContext.setRscPayload(streamData);
78
+ if (source === "navigation" || source === "action") {
79
+ transportContext.setRscPayload(streamData);
80
+ }
60
81
  const result = await streamData;
61
82
  const rawActionResult = result.actionResult;
62
83
  if (isActionResponse(rawActionResult)) {
@@ -78,7 +99,9 @@ export const fetchTransport = (transportContext) => {
78
99
  const streamData = createFromFetch(fetchPromise, {
79
100
  callServer: fetchCallServer,
80
101
  });
81
- transportContext.setRscPayload(streamData);
102
+ if (source === "navigation" || source === "action") {
103
+ transportContext.setRscPayload(streamData);
104
+ }
82
105
  const result = await streamData;
83
106
  const rawActionResult = result.actionResult;
84
107
  if (isActionResponse(rawActionResult)) {
@@ -164,8 +187,8 @@ export const initClient = async ({ transport = fetchTransport, hydrateRootOption
164
187
  onActionResponse,
165
188
  };
166
189
  let transportCallServer = transport(transportContext);
167
- const callServer = (id, args, source) => {
168
- return transportCallServer(id, args, source);
190
+ const callServer = (id, args, source, method) => {
191
+ return transportCallServer(id, args, source, method);
169
192
  };
170
193
  const upgradeToRealtime = async ({ key } = {}) => {
171
194
  const { realtimeTransport } = await import("../lib/realtime/client");
@@ -1,6 +1,5 @@
1
- import type { CallServerCallback } from "react-server-dom-webpack/client.browser";
2
1
  export type { HydrationOptions } from "react-dom/client";
3
- export type { CallServerCallback } from "react-server-dom-webpack/client.browser";
2
+ export type CallServerCallback = <Result>(id: null | string, args: null | unknown[], source?: "action" | "navigation" | "query", method?: "GET" | "POST") => Promise<Result | undefined>;
4
3
  export type RscActionResponse<Result> = {
5
4
  node: React.ReactNode;
6
5
  actionResult: Result;
@@ -32,4 +31,4 @@ export type TransportContext = {
32
31
  onActionResponse?: (actionResponse: ActionResponseData) => boolean | void;
33
32
  };
34
33
  export type Transport = (context: TransportContext) => CallServerCallback;
35
- export type CreateCallServer = (context: TransportContext) => <Result>(id: null | string, args: null | unknown[], source?: "action" | "navigation") => Promise<Result>;
34
+ export type CreateCallServer = (context: TransportContext) => <Result>(id: null | string, args: null | unknown[], source?: "action" | "navigation" | "query", method?: "GET" | "POST") => Promise<Result | undefined>;
@@ -1,3 +1,4 @@
1
+ // import type { CallServerCallback } from "react-server-dom-webpack/client.browser";
1
2
  export function isActionResponse(value) {
2
3
  return (typeof value === "object" &&
3
4
  value !== null &&
@@ -10,4 +10,5 @@ export * from "../requestInfo/types";
10
10
  export * from "../requestInfo/utils";
11
11
  export * from "../requestInfo/worker";
12
12
  export * from "../script";
13
+ export * from "../server";
13
14
  export * from "../worker";
@@ -10,4 +10,5 @@ export * from "../requestInfo/types";
10
10
  export * from "../requestInfo/utils";
11
11
  export * from "../requestInfo/worker";
12
12
  export * from "../script";
13
+ export * from "../server";
13
14
  export * from "../worker";
@@ -58,7 +58,7 @@ export const realtimeTransport = ({ key = DEFAULT_KEY, handleResponse, }) => (tr
58
58
  }
59
59
  return ws;
60
60
  };
61
- const realtimeCallServer = async (id, args) => {
61
+ const realtimeCallServer = async (id, args, _source, _method) => {
62
62
  try {
63
63
  const socket = ensureWs();
64
64
  const { encodeReply } = await import("react-server-dom-webpack/client.browser");
@@ -82,7 +82,7 @@ export const realtimeTransport = ({ key = DEFAULT_KEY, handleResponse, }) => (tr
82
82
  }
83
83
  catch (e) {
84
84
  console.error("[Realtime] Error calling server", e);
85
- return null;
85
+ return undefined;
86
86
  }
87
87
  };
88
88
  const processResponse = async (response) => {
@@ -99,7 +99,7 @@ export const realtimeTransport = ({ key = DEFAULT_KEY, handleResponse, }) => (tr
99
99
  streamForRsc = response.body;
100
100
  }
101
101
  if (!shouldContinue) {
102
- return null;
102
+ return undefined;
103
103
  }
104
104
  const rscPayload = createFromReadableStream(streamForRsc, {
105
105
  callServer: realtimeCallServer,
@@ -114,7 +114,7 @@ export const realtimeTransport = ({ key = DEFAULT_KEY, handleResponse, }) => (tr
114
114
  const isRedirect = actionResponse.status >= 300 && actionResponse.status < 400;
115
115
  if (location && isRedirect) {
116
116
  window.location.href = location;
117
- return null;
117
+ return undefined;
118
118
  }
119
119
  }
120
120
  return rawActionResult;
@@ -314,7 +314,7 @@ export function defineRoutes(routes) {
314
314
  if (isRouteComponent(componentHandler)) {
315
315
  const requestInfo = getRequestInfo();
316
316
  const WrappedComponent = wrapWithLayouts(wrapHandlerToThrowResponses(componentHandler), route.layouts || [], requestInfo);
317
- if (!isClientReference(componentHandler)) {
317
+ if (!isClientReference(componentHandler) && !requestInfo.rw.pageRouteResolved) {
318
318
  requestInfo.rw.pageRouteResolved = Promise.withResolvers();
319
319
  }
320
320
  return await renderPage(requestInfo, WrappedComponent, onError);
@@ -1 +1 @@
1
- export declare const createServerReference: (id: string, name: string) => Function;
1
+ export declare const createServerReference: (id: string, name: string, method?: "GET" | "POST", source?: "action" | "query") => Function;
@@ -1,5 +1,12 @@
1
1
  import { createServerReference as baseCreateServerReference } from "react-server-dom-webpack/client.browser";
2
- export const createServerReference = (id, name) => {
3
- id = id + "#" + name;
4
- return baseCreateServerReference(id, globalThis.__rsc_callServer);
2
+ export const createServerReference = (id, name, method, source = "action") => {
3
+ const fullId = id + "#" + name;
4
+ const proxy = baseCreateServerReference(fullId, (id, args) => {
5
+ return globalThis.__rsc_callServer(id, args, source, method);
6
+ });
7
+ // Attach metadata that hooks like useQuery can use
8
+ proxy.id = fullId;
9
+ proxy.method = method;
10
+ proxy.source = source;
11
+ return proxy;
5
12
  };
@@ -50,10 +50,19 @@ export async function __smokeTestActionHandler(timestamp) {
50
50
  export async function rscActionHandler(req) {
51
51
  const url = new URL(req.url);
52
52
  const contentType = req.headers.get("content-type");
53
- const data = contentType?.startsWith("multipart/form-data")
54
- ? await req.formData()
55
- : await req.text();
56
- const args = (await decodeReply(data, null));
53
+ let args = [];
54
+ if (req.method === "GET") {
55
+ const argsParam = url.searchParams.get("args");
56
+ if (argsParam) {
57
+ args = JSON.parse(argsParam);
58
+ }
59
+ }
60
+ else {
61
+ const data = contentType?.startsWith("multipart/form-data")
62
+ ? await req.formData()
63
+ : await req.text();
64
+ args = (await decodeReply(data, null));
65
+ }
57
66
  const actionId = url.searchParams.get("__rsc_action_id");
58
67
  if (import.meta.env.VITE_IS_DEV_SERVER && actionId === "__rsc_hot_update") {
59
68
  return null;
@@ -0,0 +1,52 @@
1
+ type Interruptor<TArgs extends any[] = any[], TResult = any> = (context: {
2
+ request: Request;
3
+ ctx: Record<string, any>;
4
+ args: TArgs;
5
+ }) => Promise<Response | void | TResult> | Response | void | TResult;
6
+ type ServerFunction<TArgs extends any[] = any[], TResult = any> = (...args: TArgs) => Promise<TResult>;
7
+ type ServerFunctionOptions = {
8
+ method?: "GET" | "POST";
9
+ };
10
+ type WrappedServerFunction<TArgs extends any[] = any[], TResult = any> = {
11
+ (...args: TArgs): Promise<TResult>;
12
+ method?: "GET" | "POST";
13
+ };
14
+ /**
15
+ * Wrap a function to be used as a server query.
16
+ *
17
+ * - **Method**: Defaults to `GET`. can be changed via `options`.
18
+ * - **Behavior**: When called from the client, it returns data-only and does **not** rehydrate or re-render the React page.
19
+ * - **Location**: Must be defined in a file with `"use server"`. We recommend `queries.ts` colocated with components.
20
+ * - **Middleware**: You can pass an array of functions as the first argument to act as interruptors (e.g. for auth).
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * // getters.ts
25
+ * "use server"
26
+ *
27
+ * export const getUser = serverQuery(async (id: string) => {
28
+ * return db.user.findUnique({ where: { id } })
29
+ * })
30
+ * ```
31
+ */
32
+ export declare function serverQuery<TArgs extends any[] = any[], TResult = any>(fnsOrFn: ServerFunction<TArgs, TResult> | [...Interruptor<TArgs, TResult>[], ServerFunction<TArgs, TResult>], options?: ServerFunctionOptions): WrappedServerFunction<TArgs, TResult>;
33
+ /**
34
+ * Wrap a function to be used as a server action.
35
+ *
36
+ * - **Method**: Defaults to `POST`. can be changed via `options`.
37
+ * - **Behavior**: When called from the client, it **will** rehydrate and re-render the React page with the new server state.
38
+ * - **Location**: Must be defined in a file with `"use server"`. We recommend `actions.ts` colocated with components.
39
+ * - **Middleware**: You can pass an array of functions as the first argument to act as interruptors (e.g. for auth).
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * // actions.ts
44
+ * "use server"
45
+ *
46
+ * export const updateUser = serverAction(async (id: string, data: any) => {
47
+ * return db.user.update({ where: { id }, data })
48
+ * })
49
+ * ```
50
+ */
51
+ export declare function serverAction<TArgs extends any[] = any[], TResult = any>(fnsOrFn: ServerFunction<TArgs, TResult> | [...Interruptor<TArgs, TResult>[], ServerFunction<TArgs, TResult>], options?: ServerFunctionOptions): WrappedServerFunction<TArgs, TResult>;
52
+ export {};
@@ -0,0 +1,88 @@
1
+ import { requestInfo } from "./requestInfo/worker";
2
+ function createServerFunction(fns, mainFn, options) {
3
+ const wrapped = async (...args) => {
4
+ const { request, ctx } = requestInfo;
5
+ // Execute interruptors
6
+ for (const fn of fns) {
7
+ const result = await fn({ request, ctx, args });
8
+ if (result instanceof Response) {
9
+ // We can't easily return a Response from a server action function
10
+ // because the return type is expected to be TResult.
11
+ // However, if the interruptor returns a Response, it usually means "stop and return this HTTP response".
12
+ // In the RSC context, throwing a Response is a common pattern to short-circuit.
13
+ throw result;
14
+ }
15
+ }
16
+ return mainFn(...args);
17
+ };
18
+ wrapped.method = options?.method ?? "POST"; // Default to POST if not specified, though user said serverQuery defaults to GET?
19
+ // User said: "export const getProject = serverQuery(...) // Defaults to GET"
20
+ // So serverQuery defaults to GET, serverAction defaults to POST?
21
+ return wrapped;
22
+ }
23
+ /**
24
+ * Wrap a function to be used as a server query.
25
+ *
26
+ * - **Method**: Defaults to `GET`. can be changed via `options`.
27
+ * - **Behavior**: When called from the client, it returns data-only and does **not** rehydrate or re-render the React page.
28
+ * - **Location**: Must be defined in a file with `"use server"`. We recommend `queries.ts` colocated with components.
29
+ * - **Middleware**: You can pass an array of functions as the first argument to act as interruptors (e.g. for auth).
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * // getters.ts
34
+ * "use server"
35
+ *
36
+ * export const getUser = serverQuery(async (id: string) => {
37
+ * return db.user.findUnique({ where: { id } })
38
+ * })
39
+ * ```
40
+ */
41
+ export function serverQuery(fnsOrFn, options) {
42
+ let fns = [];
43
+ let mainFn;
44
+ if (Array.isArray(fnsOrFn)) {
45
+ fns = fnsOrFn.slice(0, -1);
46
+ mainFn = fnsOrFn[fnsOrFn.length - 1];
47
+ }
48
+ else {
49
+ mainFn = fnsOrFn;
50
+ }
51
+ const method = options?.method ?? "GET"; // Default to GET for query
52
+ const wrapped = createServerFunction(fns, mainFn, { ...options, method });
53
+ wrapped.method = method;
54
+ return wrapped;
55
+ }
56
+ /**
57
+ * Wrap a function to be used as a server action.
58
+ *
59
+ * - **Method**: Defaults to `POST`. can be changed via `options`.
60
+ * - **Behavior**: When called from the client, it **will** rehydrate and re-render the React page with the new server state.
61
+ * - **Location**: Must be defined in a file with `"use server"`. We recommend `actions.ts` colocated with components.
62
+ * - **Middleware**: You can pass an array of functions as the first argument to act as interruptors (e.g. for auth).
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * // actions.ts
67
+ * "use server"
68
+ *
69
+ * export const updateUser = serverAction(async (id: string, data: any) => {
70
+ * return db.user.update({ where: { id }, data })
71
+ * })
72
+ * ```
73
+ */
74
+ export function serverAction(fnsOrFn, options) {
75
+ let fns = [];
76
+ let mainFn;
77
+ if (Array.isArray(fnsOrFn)) {
78
+ fns = fnsOrFn.slice(0, -1);
79
+ mainFn = fnsOrFn[fnsOrFn.length - 1];
80
+ }
81
+ else {
82
+ mainFn = fnsOrFn;
83
+ }
84
+ const method = options?.method ?? "POST"; // Default to POST for action
85
+ const wrapped = createServerFunction(fns, mainFn, { ...options, method });
86
+ wrapped.method = method;
87
+ return wrapped;
88
+ }
@@ -117,7 +117,13 @@ export const defineApp = (routes) => {
117
117
  });
118
118
  }
119
119
  const actionResult = normalizeActionResult(requestInfo.rw.actionResult);
120
- const pageElement = createPageElement(requestInfo, Page);
120
+ const isDataOnly = request.headers.get("x-rsc-data-only") === "true";
121
+ const pageElement = isDataOnly && actionResult !== undefined
122
+ ? null
123
+ : createPageElement(requestInfo, Page);
124
+ if (pageElement === null) {
125
+ rw.pageRouteResolved?.resolve();
126
+ }
121
127
  const { rscPayload: shouldInjectRSCPayload } = rw;
122
128
  let rscPayloadStream = renderToRscStream({
123
129
  input: {
@@ -111,16 +111,78 @@ export const transformServerFunctions = (code, normalizedId, environment, server
111
111
  else {
112
112
  s.append('import { createServerReference } from "rwsdk/client";\n\n');
113
113
  }
114
+ const ext = path.extname(normalizedId).toLowerCase();
115
+ const lang = ext === ".tsx" || ext === ".jsx" ? Lang.Tsx : SgLang.TypeScript;
116
+ const root = sgParse(lang, code);
114
117
  for (const name of allExports) {
115
118
  if (name !== "default" && name !== defaultFunctionName) {
116
- s.append(`export let ${name} = createServerReference(${JSON.stringify(normalizedId)}, ${JSON.stringify(name)});\n`);
117
- log(`Added ${environment} server reference for function: %s in normalizedId=%s`, name, normalizedId);
119
+ let method;
120
+ let source = "action";
121
+ // Try to find if this export is a serverQuery or serverAction call to extract the method
122
+ const patterns = [
123
+ `export const ${name} = serverQuery($$$, { method: "$METHOD" })`,
124
+ `export const ${name} = serverQuery($$$)`,
125
+ `export const ${name} = serverAction($$$)`,
126
+ ];
127
+ for (const pattern of patterns) {
128
+ const matches = root.root().findAll(pattern);
129
+ if (matches.length > 0) {
130
+ if (pattern.includes("serverQuery")) {
131
+ const methodMatch = matches[0].getMatch("METHOD");
132
+ method = methodMatch ? methodMatch.text() : "GET";
133
+ source = "query";
134
+ }
135
+ else if (pattern.includes("serverAction")) {
136
+ method = "POST";
137
+ source = "action";
138
+ }
139
+ break;
140
+ }
141
+ }
142
+ let extraArgs = "";
143
+ if (source === "query") {
144
+ extraArgs = `, ${JSON.stringify(method ?? "GET")}, "query"`;
145
+ }
146
+ else if (method !== undefined) {
147
+ extraArgs = `, ${JSON.stringify(method)}`;
148
+ }
149
+ s.append(`export let ${name} = createServerReference(${JSON.stringify(normalizedId)}, ${JSON.stringify(name)}${extraArgs});\n`);
150
+ log(`Added ${environment} server reference for function: %s (method: %s, source: %s) in normalizedId=%s`, name, method || "default", source, normalizedId);
118
151
  }
119
152
  }
120
153
  // Check for default export in the actual module (not re-exports)
121
154
  if (hasDefaultExport(code, normalizedId)) {
122
- s.append(`\nexport default createServerReference(${JSON.stringify(normalizedId)}, "default");\n`);
123
- log(`Added ${environment} server reference for default export in normalizedId=%s`, normalizedId);
155
+ let method;
156
+ let source = "action";
157
+ const patterns = [
158
+ `export default serverQuery($$$, { method: "$METHOD" })`,
159
+ `export default serverQuery($$$)`,
160
+ `export default serverAction($$$)`,
161
+ ];
162
+ for (const pattern of patterns) {
163
+ const matches = root.root().findAll(pattern);
164
+ if (matches.length > 0) {
165
+ if (pattern.includes("serverQuery")) {
166
+ const methodMatch = matches[0].getMatch("METHOD");
167
+ method = methodMatch ? methodMatch.text() : "GET";
168
+ source = "query";
169
+ }
170
+ else if (pattern.includes("serverAction")) {
171
+ method = "POST";
172
+ source = "action";
173
+ }
174
+ break;
175
+ }
176
+ }
177
+ let extraArgs = "";
178
+ if (source === "query") {
179
+ extraArgs = `, ${JSON.stringify(method ?? "GET")}, "query"`;
180
+ }
181
+ else if (method !== undefined) {
182
+ extraArgs = `, ${JSON.stringify(method)}`;
183
+ }
184
+ s.append(`\nexport default createServerReference(${JSON.stringify(normalizedId)}, "default"${extraArgs});\n`);
185
+ log(`Added ${environment} server reference for default export (method: %s, source: %s) in normalizedId=%s`, method || "default", source, normalizedId);
124
186
  }
125
187
  process.env.VERBOSE &&
126
188
  log(`${environment} transformation complete for normalizedId=%s`, normalizedId);
@@ -89,6 +89,36 @@ export async function sum() {
89
89
  export { sum } from './math';
90
90
  export { default as multiply } from './multiply';
91
91
  export * from './utils';
92
+ `;
93
+ let SERVER_QUERY_GET_CODE = `
94
+ "use server";
95
+ export const getProject = serverQuery(async (id) => {
96
+ return { id, name: "Project X" };
97
+ });
98
+ `;
99
+ let SERVER_QUERY_POST_CODE = `
100
+ "use server";
101
+ export const getProject = serverQuery(async (id) => {
102
+ return { id, name: "Project X" };
103
+ }, { method: "POST" });
104
+ `;
105
+ let SERVER_ACTION_CODE = `
106
+ "use server";
107
+ export const upvote = serverAction(async (id) => {
108
+ return { id, count: 1 };
109
+ });
110
+ `;
111
+ let SERVER_QUERY_DEFAULT_CODE = `
112
+ "use server";
113
+ export default serverQuery(async (id) => {
114
+ return { id, name: "Project X" };
115
+ });
116
+ `;
117
+ let SERVER_ACTION_DEFAULT_CODE = `
118
+ "use server";
119
+ export default serverAction(async (id) => {
120
+ return { id, name: "Project X" };
121
+ });
92
122
  `;
93
123
  const TEST_CASES = {
94
124
  COMMENT_CODE,
@@ -102,6 +132,11 @@ export * from './utils';
102
132
  RE_EXPORT_CODE,
103
133
  PREDEFINED_DEFAULT_EXPORT_CODE,
104
134
  EXPORT_DEFAULT_FUNCTION_CODE,
135
+ SERVER_QUERY_GET_CODE,
136
+ SERVER_QUERY_POST_CODE,
137
+ SERVER_ACTION_CODE,
138
+ SERVER_QUERY_DEFAULT_CODE,
139
+ SERVER_ACTION_DEFAULT_CODE,
105
140
  };
106
141
  describe("TRANSFORMS", () => {
107
142
  for (const [key, CODE] of Object.entries(TEST_CASES)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rwsdk",
3
- "version": "1.0.0-beta.48",
3
+ "version": "1.0.0-beta.49-test.20260121220325",
4
4
  "description": "Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime",
5
5
  "type": "module",
6
6
  "bin": {
@@ -151,7 +151,7 @@
151
151
  "license": "MIT",
152
152
  "dependencies": {
153
153
  "@ast-grep/napi": "~0.39.0",
154
- "@cloudflare/workers-types": "~4.20260111.0",
154
+ "@cloudflare/workers-types": "~4.20260120.0",
155
155
  "@mdx-js/mdx": "~3.1.1",
156
156
  "@puppeteer/browsers": "~2.10.0",
157
157
  "@types/decompress": "~4.2.7",
@@ -200,7 +200,7 @@
200
200
  },
201
201
  "packageManager": "pnpm@10.0.0+sha512.b8fef5494bd3fe4cbd4edabd0745df2ee5be3e4b0b8b08fa643aa3e4c6702ccc0f00d68fa8a8c9858a735a0032485a44990ed2810526c875e416f001b17df12b",
202
202
  "devDependencies": {
203
- "@cloudflare/vite-plugin": "1.20.1",
203
+ "@cloudflare/vite-plugin": "1.21.1",
204
204
  "capnweb": "~0.2.0",
205
205
  "@types/debug": "~4.1.12",
206
206
  "@types/js-beautify": "~1.14.3",