@rangojs/router 0.10.1 → 0.12.0

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.
Files changed (62) hide show
  1. package/dist/testing/vitest.js +1 -1
  2. package/dist/types/browser/partial-update.d.ts +1 -0
  3. package/dist/types/client-urls/navigation.d.ts +11 -0
  4. package/dist/types/client-urls/revalidate-chain.d.ts +33 -0
  5. package/dist/types/client-urls/types.d.ts +41 -14
  6. package/dist/types/client.d.ts +2 -0
  7. package/dist/types/deps/rsc-client.d.ts +1 -0
  8. package/dist/types/deps/rsc.d.ts +1 -1
  9. package/dist/types/deps/ssr.d.ts +1 -1
  10. package/dist/types/index.d.ts +1 -1
  11. package/dist/types/index.rsc.d.ts +1 -1
  12. package/dist/types/router/is-action.d.ts +34 -0
  13. package/dist/types/rsc/types.d.ts +9 -9
  14. package/dist/types/ssr/index.d.ts +27 -4
  15. package/dist/types/testing/flight.d.ts +4 -3
  16. package/dist/types/testing/index.d.ts +3 -1
  17. package/dist/types/testing/run-client-revalidate.d.ts +43 -0
  18. package/dist/types/testing/to-url.d.ts +2 -0
  19. package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +2 -0
  20. package/dist/types/testing/vitest.d.ts +2 -1
  21. package/dist/types/types/handler-context.d.ts +12 -5
  22. package/dist/types/types/index.d.ts +1 -1
  23. package/dist/types/vite/plugins/expose-action-id.d.ts +14 -0
  24. package/dist/types/vite/plugins/virtual-entries.d.ts +3 -2
  25. package/dist/vite/index.js +66 -13
  26. package/package.json +8 -3
  27. package/skills/client-urls/SKILL.md +26 -4
  28. package/skills/loader/SKILL.md +1 -0
  29. package/skills/testing/SKILL.md +1 -0
  30. package/skills/testing/setup.md +6 -6
  31. package/skills/typesafety/route-types.md +1 -0
  32. package/src/browser/partial-update.ts +11 -2
  33. package/src/browser/server-action-bridge.ts +9 -2
  34. package/src/cache/cache-runtime.ts +1 -1
  35. package/src/cache/segment-codec.ts +2 -2
  36. package/src/client-urls/navigation.ts +40 -42
  37. package/src/client-urls/revalidate-chain.ts +83 -0
  38. package/src/client-urls/types.ts +41 -13
  39. package/src/client.tsx +5 -0
  40. package/src/deps/rsc-client.ts +8 -0
  41. package/src/deps/rsc.ts +4 -2
  42. package/src/deps/ssr.ts +1 -0
  43. package/src/index.rsc.ts +1 -0
  44. package/src/index.ts +1 -0
  45. package/src/router/is-action.ts +100 -0
  46. package/src/router/revalidation.ts +5 -48
  47. package/src/rsc/handler.ts +3 -3
  48. package/src/rsc/server-action.ts +2 -4
  49. package/src/rsc/types.ts +9 -9
  50. package/src/ssr/index.tsx +132 -51
  51. package/src/testing/flight.ts +4 -3
  52. package/src/testing/index.ts +4 -1
  53. package/src/testing/run-client-revalidate.ts +108 -0
  54. package/src/testing/run-transition-when.ts +1 -3
  55. package/src/testing/to-url.ts +5 -0
  56. package/src/testing/vitest-stubs/plugin-rsc.ts +13 -5
  57. package/src/testing/vitest.ts +3 -2
  58. package/src/types/handler-context.ts +13 -5
  59. package/src/types/index.ts +1 -0
  60. package/src/vite/plugins/expose-action-id.ts +29 -1
  61. package/src/vite/plugins/use-cache-transform.ts +65 -1
  62. package/src/vite/plugins/virtual-entries.ts +14 -11
@@ -1,5 +1,6 @@
1
1
  import type { ComponentType, ReactNode } from "react";
2
2
  import type {
3
+ IsActionFn,
3
4
  LoaderDefinition,
4
5
  LoaderOptions,
5
6
  TransitionConfig,
@@ -54,7 +55,8 @@ export type ClientLayoutFn = <const TItems extends ClientUrlItems>(
54
55
  * subset of the server ShouldRevalidateFn args — the predicate RUNS IN THE
55
56
  * BROWSER (it is declared in a "use client" module and never crosses the
56
57
  * projection boundary); only its decision is sent to the server. There is no
57
- * `context` — no server handler context exists where this executes.
58
+ * `context` — no server handler context exists where this executes. `isAction`
59
+ * is the same callable matcher as on the server, not a boolean.
58
60
  */
59
61
  export interface ClientRevalidateArgs {
60
62
  /** Full URL of the page being navigated away from (current location). */
@@ -66,21 +68,46 @@ export interface ClientRevalidateArgs {
66
68
  /** Route params for the navigation target (definition-local match). */
67
69
  readonly nextParams: Record<string, string>;
68
70
  /**
69
- * The locked default decision for this loader, computed client-side with
70
- * the same rules the server would apply: `true` on actions and when
71
- * params/search changed, `false` otherwise. Return it for default behavior
72
- * plus your own conditions.
71
+ * The current default decision for this loader, computed client-side with
72
+ * the same rules the server applies to the request the decisions ride on:
73
+ * `true` when they ride the action POST itself, otherwise `true` when
74
+ * params/search changed. (An action-triggered refetch GET gets navigation
75
+ * defaults — matching the server — even though `isAction()` is true.)
76
+ * Earlier predicates' `{ defaultShouldRevalidate }` verdicts thread into
77
+ * this value, exactly like the server chain. Return it for default
78
+ * behavior plus your own conditions.
73
79
  */
74
80
  readonly defaultShouldRevalidate: boolean;
75
81
  /** True when this is a stale history-entry background revalidation. */
76
82
  readonly stale: boolean;
77
- /** True when revalidation is triggered by a server action. */
78
- readonly isAction: boolean;
79
- /** The triggering server action's id, when isAction. */
83
+ /**
84
+ * Same {@link IsActionFn} the server `revalidate()` predicate receives.
85
+ * In the browser the match is against the action stub's hashed `$$id`
86
+ * (the id the action request carries) — not the RSC file-path `$id`.
87
+ */
88
+ readonly isAction: IsActionFn;
89
+ /**
90
+ * The triggering server action's id, when this is an action. In the
91
+ * browser this is the hashed `hash#export` form (`$$id`), not the RSC
92
+ * file-path `src/...#export`. Prefer `isAction(ref)` — a substring of
93
+ * `path#export` will not match here in production.
94
+ */
80
95
  readonly actionId?: string;
81
96
  }
82
97
 
83
- export type ClientRevalidateFn = (args: ClientRevalidateArgs) => boolean;
98
+ /**
99
+ * Client-run per-loader predicate, with the same chain semantics as the
100
+ * server's `revalidate()` (src/router/revalidation.ts): a boolean is a HARD
101
+ * decision that short-circuits the rest of the chain; a
102
+ * `{ defaultShouldRevalidate }` object updates the running suggestion, which
103
+ * later predicates receive as their `defaultShouldRevalidate`; `void` /
104
+ * `null` / `undefined` defers to the current suggestion — so
105
+ * `isAction(CartActions) || undefined` defers to the locked default.
106
+ * Predicates must be synchronous; the object form requires a boolean value.
107
+ */
108
+ export type ClientRevalidateFn = (
109
+ args: ClientRevalidateArgs,
110
+ ) => boolean | { defaultShouldRevalidate: boolean } | null | void;
84
111
 
85
112
  export interface ClientUrlLoaderRecord {
86
113
  readonly loader: LoaderDefinition<any, any>;
@@ -158,10 +185,11 @@ export interface ClientUrlHelpers {
158
185
  readonly loading: (component: ReactNode) => ClientUrlItem;
159
186
  /**
160
187
  * Per-loader revalidation predicate, valid inside a loader() use callback
161
- * only. Runs IN THE BROWSER with client-computable args; return true to
162
- * re-run the loader, false to keep held data. Absent predicates (and
163
- * requests that carry no decisions: no-JS, PE, prefetch, document loads)
164
- * follow the locked server defaults.
188
+ * only. Runs IN THE BROWSER with client-computable args (including the
189
+ * callable `isAction(...refs)` matcher); return true to re-run the loader,
190
+ * false to keep held data. Absent predicates (and requests that carry no
191
+ * decisions: no-JS, PE, prefetch, document loads) follow the locked server
192
+ * defaults.
165
193
  */
166
194
  readonly revalidate: (fn: ClientRevalidateFn) => ClientUrlItem;
167
195
  /**
package/src/client.tsx CHANGED
@@ -470,3 +470,8 @@ export { useReverse } from "./browser/react/use-reverse.js";
470
470
  export type { ScopedReverseFunction, LocalReverseFunction } from "./reverse.js";
471
471
 
472
472
  export type { LoaderDefinition } from "./types.js";
473
+ export type { ActionRef, IsActionFn } from "./types.js";
474
+ export type {
475
+ ClientRevalidateArgs,
476
+ ClientRevalidateFn,
477
+ } from "./client-urls/types.js";
@@ -0,0 +1,8 @@
1
+ /// <reference types="@vitejs/plugin-rsc/types" />
2
+ // RSC-environment *client* protocol (deserialize / encodeReply). Kept as its
3
+ // own module so a server-only importer of `./rsc.ts` does not pull this side.
4
+ export {
5
+ createFromReadableStream,
6
+ encodeReply,
7
+ createClientTemporaryReferenceSet,
8
+ } from "@vitejs/plugin-rsc/rsc/client";
package/src/deps/rsc.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  /// <reference types="@vitejs/plugin-rsc/types" />
2
- // Re-export @vitejs/plugin-rsc/rsc for internal use by virtual entries
2
+ // Re-export the RSC-environment *server* runtime for virtual entries.
3
+ // Prefer `@vitejs/plugin-rsc/rsc/server` over the combined `/rsc` barrel so
4
+ // Vite can skip bundling the unused `react-server-dom` client protocol.
3
5
  export {
4
6
  renderToReadableStream,
5
7
  decodeReply,
@@ -7,4 +9,4 @@ export {
7
9
  loadServerAction,
8
10
  decodeAction,
9
11
  decodeFormState,
10
- } from "@vitejs/plugin-rsc/rsc";
12
+ } from "@vitejs/plugin-rsc/rsc/server";
package/src/deps/ssr.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export {
2
2
  createFromReadableStream,
3
3
  setOnClientReference,
4
+ getClientEntryUrl,
4
5
  } from "@vitejs/plugin-rsc/ssr";
package/src/index.rsc.ts CHANGED
@@ -45,6 +45,7 @@ export type {
45
45
  RevalidateParams,
46
46
  Revalidate,
47
47
  ActionRef,
48
+ IsActionFn,
48
49
  RouteKeys,
49
50
  // Loader types
50
51
  LoaderDefinition,
package/src/index.ts CHANGED
@@ -45,6 +45,7 @@ export type {
45
45
  RevalidateParams,
46
46
  Revalidate,
47
47
  ActionRef,
48
+ IsActionFn,
48
49
  RouteKeys,
49
50
  // Loader types
50
51
  LoaderDefinition,
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Shared `isAction()` matcher for revalidate predicates (server + clientUrls).
3
+ *
4
+ * Action identity is `actionId`. The helper resolves an imported reference the
5
+ * same way the action boundary derives that id (`$id ?? $$id`), so a
6
+ * rename-safe `isAction(fn)` / `isAction(namespace)` match works in both the
7
+ * RSC environment (file-path `$id`) and the browser (hashed `$$id`).
8
+ */
9
+
10
+ import type { ActionRef, IsActionFn } from "../types.js";
11
+
12
+ // Bind preservation is per-reference, in expose-action-id.ts. Do not patch
13
+ // Function.prototype.bind here (rsc+ssr share a realm; global wrap stacks).
14
+
15
+ /**
16
+ * Resolve a server-action reference's stable id, mirroring how the action
17
+ * boundary derives `actionContext.actionId` in `rsc/server-action.ts`
18
+ * (`$id ?? $$id`): the file-path `$id` set by the expose-action-id plugin in a
19
+ * production RSC build when present, otherwise React's `$$id`. Resolving both
20
+ * the incoming `actionId` and the reference with the same precedence makes
21
+ * `isAction()` form-agnostic across dev and production.
22
+ */
23
+ export function resolveActionRefId(ref: unknown): string | undefined {
24
+ if (ref == null) return undefined;
25
+ const r = ref as { $id?: unknown; $$id?: unknown };
26
+ if (typeof r.$id === "string") return r.$id;
27
+ if (typeof r.$$id === "string") return r.$$id;
28
+ return undefined;
29
+ }
30
+
31
+ /**
32
+ * Depth cap for the object walk. The supported shapes need at most two
33
+ * object levels — a namespace (values are functions) and a grouped-namespace
34
+ * literal (`{ Cart: CartActions }`, values are namespaces). The cap keeps an
35
+ * accidentally passed arbitrary object (a ctx, a data blob — it type-checks
36
+ * as Record<string, unknown>) from triggering a full deep traversal on every
37
+ * predicate call.
38
+ */
39
+ const MAX_ACTION_REF_DEPTH = 3;
40
+
41
+ function matchesActionRef(
42
+ ref: unknown,
43
+ currentActionId: string,
44
+ seen: Set<object>,
45
+ depth: number,
46
+ ): boolean {
47
+ if (ref == null) return false;
48
+ if (typeof ref === "function") {
49
+ return resolveActionRefId(ref) === currentActionId;
50
+ }
51
+ if (typeof ref !== "object") return false;
52
+ if (depth >= MAX_ACTION_REF_DEPTH) return false;
53
+ if (seen.has(ref)) return false;
54
+ seen.add(ref);
55
+ // Namespace, object literal, or grouped namespaces
56
+ // (`{ Cart: CartActions, Order: OrderActions }`): walk every value.
57
+ // Object.values invokes getters; a throwing getter must not abort the
58
+ // predicate into the fail-open path, so treat it as "no match here".
59
+ let values: unknown[];
60
+ try {
61
+ values = Object.values(ref);
62
+ } catch {
63
+ return false;
64
+ }
65
+ for (const value of values) {
66
+ if (matchesActionRef(value, currentActionId, seen, depth + 1)) return true;
67
+ }
68
+ return false;
69
+ }
70
+
71
+ /**
72
+ * Build the `isAction()` helper bound to the current action. Called with no
73
+ * arguments it answers "is this request an action at all?" — `true` during
74
+ * action handling (including action-triggered refetches that carry no id
75
+ * yet), `false` on plain navigation. Called with one or more action
76
+ * references it narrows to those: a single imported action, several
77
+ * (variadic), a namespace import (`import * as Mod`), an object literal of
78
+ * actions (`{ addToCart, removeFromCart }`), or a grouped namespace object.
79
+ * Returns `false` when there is no action or nothing matches.
80
+ *
81
+ * `inAction` is the request kind. It defaults to "an id is present" so
82
+ * existing server call sites stay a single argument. The client passes the
83
+ * explicit flag so a refetch terminal with `isAction: true` still answers
84
+ * bare `isAction()` even if `actionId` was not threaded.
85
+ */
86
+ export function makeIsAction(
87
+ currentActionId: string | undefined,
88
+ inAction: boolean = currentActionId !== undefined,
89
+ ): IsActionFn {
90
+ return (...actions: ActionRef[]): boolean => {
91
+ if (!inAction) return false;
92
+ if (actions.length === 0) return true;
93
+ if (!currentActionId) return false;
94
+ const seen = new Set<object>();
95
+ for (const action of actions) {
96
+ if (matchesActionRef(action, currentActionId, seen, 0)) return true;
97
+ }
98
+ return false;
99
+ };
100
+ }
@@ -4,7 +4,7 @@
4
4
  * Evaluates whether segments should revalidate based on params, actions, and custom functions.
5
5
  */
6
6
 
7
- import type { ResolvedSegment, HandlerContext, ActionRef } from "../types";
7
+ import type { ResolvedSegment, HandlerContext } from "../types";
8
8
  import type { ActionContext } from "./types";
9
9
  import {
10
10
  debugLog,
@@ -15,52 +15,7 @@ import type { RevalidationTraceEntry } from "./logging.js";
15
15
  import { _getRequestContext } from "../server/request-context.js";
16
16
  import { isAutoGeneratedRouteName } from "../route-name.js";
17
17
  import { paramsEqual } from "./params-util.js";
18
-
19
- /**
20
- * Resolve a server-action reference's stable id, mirroring how the action
21
- * boundary derives `actionContext.actionId` in `rsc/server-action.ts`
22
- * (`$id ?? $$id`): the file-path `$id` set by the expose-action-id plugin in a
23
- * production RSC build when present, otherwise React's `$$id`. Resolving both
24
- * the incoming `actionId` and the reference with the same precedence makes
25
- * `isAction()` form-agnostic across dev and production.
26
- */
27
- function resolveActionRefId(ref: unknown): string | undefined {
28
- if (ref == null) return undefined;
29
- const r = ref as { $id?: unknown; $$id?: unknown };
30
- if (typeof r.$id === "string") return r.$id;
31
- if (typeof r.$$id === "string") return r.$$id;
32
- return undefined;
33
- }
34
-
35
- /**
36
- * Build the `isAction()` helper bound to the current action's id. Called with no
37
- * arguments it answers "is this request an action at all?" (any action) — `true`
38
- * during action handling, `false` on plain navigation. Called with one or more
39
- * action references it narrows to those: a single imported action, several
40
- * (variadic), or any export of a namespace import (`import * as Mod`). Returns
41
- * `false` when there is no action (plain navigation) or nothing matches.
42
- */
43
- function makeIsAction(
44
- currentActionId: string | undefined,
45
- ): (...actions: ActionRef[]) => boolean {
46
- return (...actions: ActionRef[]): boolean => {
47
- if (!currentActionId) return false;
48
- // Bare isAction(): an action is in flight (currentActionId is set) and the
49
- // caller did not narrow to a specific action, so this is "any action".
50
- if (actions.length === 0) return true;
51
- for (const action of actions) {
52
- if (typeof action === "function") {
53
- if (resolveActionRefId(action) === currentActionId) return true;
54
- } else if (action && typeof action === "object") {
55
- // Namespace import: match any export of the module.
56
- for (const value of Object.values(action)) {
57
- if (resolveActionRefId(value) === currentActionId) return true;
58
- }
59
- }
60
- }
61
- return false;
62
- };
63
- }
18
+ import { makeIsAction } from "./is-action.js";
64
19
 
65
20
  /**
66
21
  * Options for revalidation evaluation
@@ -249,6 +204,8 @@ export async function evaluateRevalidation<TEnv>(
249
204
  ? prevRouteKey
250
205
  : undefined;
251
206
 
207
+ const isActionFn = makeIsAction(actionContext?.actionId);
208
+
252
209
  for (const { name, fn } of revalidations) {
253
210
  let result: any;
254
211
  try {
@@ -265,7 +222,7 @@ export async function evaluateRevalidation<TEnv>(
265
222
  slotName: segment.slot,
266
223
  // Action context (only populated when triggered by server action)
267
224
  actionId: actionContext?.actionId,
268
- isAction: makeIsAction(actionContext?.actionId),
225
+ isAction: isActionFn,
269
226
  actionUrl: actionContext?.actionUrl,
270
227
  actionResult: actionContext?.actionResult,
271
228
  formData: actionContext?.formData,
@@ -16,7 +16,7 @@ import {
16
16
  _getRequestContext,
17
17
  createRequestContext,
18
18
  } from "../server/request-context.js";
19
- import * as rscDeps from "@vitejs/plugin-rsc/rsc";
19
+ import * as rscDeps from "@vitejs/plugin-rsc/rsc/server";
20
20
  import type {
21
21
  RscPayload,
22
22
  CreateRSCHandlerOptions,
@@ -137,7 +137,7 @@ import { INTERNAL_RANGO_DEBUG } from "../internal-debug.js";
137
137
  * @example With custom deps (advanced)
138
138
  * ```tsx
139
139
  * import { createRSCHandler } from "@rangojs/router/rsc";
140
- * import * as rsc from "@vitejs/plugin-rsc/rsc";
140
+ * import * as rsc from "@vitejs/plugin-rsc/rsc/server";
141
141
  * import { router } from "./router.js";
142
142
  *
143
143
  * export default createRSCHandler({
@@ -176,7 +176,7 @@ export function createRSCHandler<
176
176
  // stores not covered by the app-level ctx._cacheStore.
177
177
  const explicitTaggedStores = new Set<SegmentCacheStore>();
178
178
 
179
- // Use provided deps or default to @vitejs/plugin-rsc/rsc exports
179
+ // Use provided deps or default to @vitejs/plugin-rsc/rsc/server exports
180
180
  const deps = options.deps ?? rscDeps;
181
181
  const {
182
182
  renderToReadableStream,
@@ -20,6 +20,7 @@ import {
20
20
  setRequestContextParams,
21
21
  } from "../server/request-context.js";
22
22
  import { observePhase, PHASES } from "../router/instrument.js";
23
+ import { resolveActionRefId } from "../router/is-action.js";
23
24
  import type { TraceSpan } from "../router/tracing.js";
24
25
  import { gateTransitions } from "./transition-gate.js";
25
26
  import type { RscPayload } from "./types.js";
@@ -302,10 +303,7 @@ export async function executeServerAction<TEnv>(
302
303
  }
303
304
 
304
305
  // Build continuation for the revalidation phase
305
- const actionMeta = loadedAction as
306
- | { $id?: string; $$id?: string }
307
- | undefined;
308
- const resolvedActionId = actionMeta?.$id ?? actionMeta?.$$id ?? actionId;
306
+ const resolvedActionId = resolveActionRefId(loadedAction) ?? actionId;
309
307
 
310
308
  return {
311
309
  returnValue,
package/src/rsc/types.ts CHANGED
@@ -103,11 +103,11 @@ export interface RscPayload {
103
103
  export type ReactFormState = unknown;
104
104
 
105
105
  /**
106
- * RSC dependencies from @vitejs/plugin-rsc/rsc
106
+ * RSC dependencies from @vitejs/plugin-rsc/rsc/server
107
107
  */
108
108
  export interface RSCDependencies {
109
109
  /**
110
- * renderToReadableStream from @vitejs/plugin-rsc/rsc
110
+ * renderToReadableStream from @vitejs/plugin-rsc/rsc/server
111
111
  */
112
112
  renderToReadableStream: <T>(
113
113
  payload: T,
@@ -118,7 +118,7 @@ export interface RSCDependencies {
118
118
  ) => ReadableStream<Uint8Array>;
119
119
 
120
120
  /**
121
- * decodeReply from @vitejs/plugin-rsc/rsc
121
+ * decodeReply from @vitejs/plugin-rsc/rsc/server
122
122
  */
123
123
  decodeReply: (
124
124
  body: FormData | string,
@@ -126,23 +126,23 @@ export interface RSCDependencies {
126
126
  ) => Promise<unknown[]>;
127
127
 
128
128
  /**
129
- * createTemporaryReferenceSet from @vitejs/plugin-rsc/rsc
129
+ * createTemporaryReferenceSet from @vitejs/plugin-rsc/rsc/server
130
130
  */
131
131
  createTemporaryReferenceSet: () => unknown;
132
132
 
133
133
  /**
134
- * loadServerAction from @vitejs/plugin-rsc/rsc
134
+ * loadServerAction from @vitejs/plugin-rsc/rsc/server
135
135
  */
136
136
  loadServerAction: (actionId: string) => Promise<Function>;
137
137
 
138
138
  /**
139
- * decodeAction from @vitejs/plugin-rsc/rsc
139
+ * decodeAction from @vitejs/plugin-rsc/rsc/server
140
140
  * Decodes a FormData into a bound action function (for useActionState forms)
141
141
  */
142
142
  decodeAction: (body: FormData) => Promise<() => Promise<unknown>>;
143
143
 
144
144
  /**
145
- * decodeFormState from @vitejs/plugin-rsc/rsc
145
+ * decodeFormState from @vitejs/plugin-rsc/rsc/server
146
146
  * Decodes the action result into a ReactFormState for useActionState progressive enhancement
147
147
  */
148
148
  decodeFormState: (
@@ -300,8 +300,8 @@ export interface CreateRSCHandlerOptions<
300
300
  router: RangoInternal<TEnv, TRoutes>;
301
301
 
302
302
  /**
303
- * RSC dependencies from @vitejs/plugin-rsc/rsc.
304
- * Defaults to the exports from @vitejs/plugin-rsc/rsc.
303
+ * RSC dependencies from @vitejs/plugin-rsc/rsc/server.
304
+ * Defaults to the exports from @vitejs/plugin-rsc/rsc/server.
305
305
  */
306
306
  deps?: RSCDependencies;
307
307