@kasperpeulen/vitest-plugin-nextjs 0.0.0-alpha.0 → 0.1.0-alpha.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 (250) hide show
  1. package/README.md +249 -2
  2. package/dist/_virtual/_rolldown/runtime.js +14 -0
  3. package/dist/action-ids.d.ts +18 -0
  4. package/dist/action-ids.js +44 -0
  5. package/dist/adapter.d.ts +8 -0
  6. package/dist/adapter.js +12 -0
  7. package/dist/app-requests.d.ts +63 -0
  8. package/dist/app-requests.js +253 -0
  9. package/dist/browser-context.d.ts +24 -0
  10. package/dist/browser-context.js +157 -0
  11. package/dist/build-output.d.ts +68 -0
  12. package/dist/build-output.js +216 -0
  13. package/dist/build.d.ts +26 -0
  14. package/dist/build.js +39 -0
  15. package/dist/built-files.d.ts +9 -0
  16. package/dist/built-files.js +22 -0
  17. package/dist/cache.d.ts +44 -0
  18. package/dist/cache.js +99 -0
  19. package/dist/client-components.d.ts +3 -0
  20. package/dist/client-components.js +4 -0
  21. package/dist/client-file-key.d.ts +5 -0
  22. package/dist/client-file-key.js +5 -0
  23. package/dist/client-files.d.ts +83 -0
  24. package/dist/client-files.js +186 -0
  25. package/dist/client-graph.d.ts +94 -0
  26. package/dist/client-graph.js +266 -0
  27. package/dist/client-modules.d.ts +10 -0
  28. package/dist/client-modules.js +43 -0
  29. package/dist/client.d.ts +42 -0
  30. package/dist/client.js +263 -0
  31. package/dist/commonjs.d.ts +44 -0
  32. package/dist/commonjs.js +111 -0
  33. package/dist/compat/browser/client.d.ts +19 -0
  34. package/dist/compat/browser/client.js +13 -0
  35. package/dist/compat/build.d.ts +145 -0
  36. package/dist/compat/build.js +149 -0
  37. package/dist/compat/checks.d.ts +16 -0
  38. package/dist/compat/checks.js +148 -0
  39. package/dist/compat/patches.d.ts +13 -0
  40. package/dist/compat/patches.js +30 -0
  41. package/dist/compat/paths.d.ts +74 -0
  42. package/dist/compat/paths.js +160 -0
  43. package/dist/compat/rsc/handlers.d.ts +2 -0
  44. package/dist/compat/rsc/handlers.js +2 -0
  45. package/dist/compat/rsc/prerender.d.ts +10 -0
  46. package/dist/compat/rsc/prerender.js +9 -0
  47. package/dist/compat/server/headers.d.ts +3 -0
  48. package/dist/compat/server/headers.js +3 -0
  49. package/dist/compat/ssr/build-output.d.ts +4 -0
  50. package/dist/compat/ssr/build-output.js +3 -0
  51. package/dist/compat/ssr/cache.d.ts +6 -0
  52. package/dist/compat/ssr/cache.js +6 -0
  53. package/dist/compat/ssr/handler.d.ts +8 -0
  54. package/dist/compat/ssr/handler.js +8 -0
  55. package/dist/compat/ssr/node-server.d.ts +5 -0
  56. package/dist/compat/ssr/node-server.js +4 -0
  57. package/dist/compat/ssr/render-errors.d.ts +4 -0
  58. package/dist/compat/ssr/render-errors.js +4 -0
  59. package/dist/compat/ssr/senders.d.ts +6 -0
  60. package/dist/compat/ssr/senders.js +6 -0
  61. package/dist/compat/types.d.ts +8 -0
  62. package/dist/compat/types.js +1 -0
  63. package/dist/compile.d.ts +31 -0
  64. package/dist/compile.js +140 -0
  65. package/dist/disk.d.ts +16 -0
  66. package/dist/disk.js +13 -0
  67. package/dist/document-loads.d.ts +15 -0
  68. package/dist/document-loads.js +53 -0
  69. package/dist/document.d.ts +79 -0
  70. package/dist/document.js +328 -0
  71. package/dist/downloads.d.ts +15 -0
  72. package/dist/downloads.js +71 -0
  73. package/dist/esm-require.d.ts +11 -0
  74. package/dist/esm-require.js +32 -0
  75. package/dist/fast-crypto/index.js +1093 -0
  76. package/dist/fast-crypto.d.ts +20 -0
  77. package/dist/fast-crypto.js +151 -0
  78. package/dist/flight.d.ts +19 -0
  79. package/dist/flight.js +42 -0
  80. package/dist/form-submission.d.ts +15 -0
  81. package/dist/form-submission.js +27 -0
  82. package/dist/from-page.d.ts +5 -0
  83. package/dist/from-page.js +44 -0
  84. package/dist/globals.d.ts +1 -0
  85. package/dist/globals.js +197 -0
  86. package/dist/host-document.d.ts +26 -0
  87. package/dist/host-document.js +34 -0
  88. package/dist/index.d.ts +280 -0
  89. package/dist/index.js +281 -0
  90. package/dist/internal.d.ts +2 -0
  91. package/dist/internal.js +3 -0
  92. package/dist/leftovers.d.ts +11 -0
  93. package/dist/leftovers.js +55 -0
  94. package/dist/mode.d.ts +169 -0
  95. package/dist/mode.js +31 -0
  96. package/dist/node/LICENSES.md +3540 -0
  97. package/dist/node/assert/strict.js +29 -0
  98. package/dist/node/assert.js +3044 -0
  99. package/dist/node/buffer.js +1499 -0
  100. package/dist/node/child_process.js +45 -0
  101. package/dist/node/cluster.js +85 -0
  102. package/dist/node/console.js +96 -0
  103. package/dist/node/constants.js +495 -0
  104. package/dist/node/crypto.js +1388 -0
  105. package/dist/node/dgram.js +78 -0
  106. package/dist/node/diagnostics_channel.js +122 -0
  107. package/dist/node/dns/promises.js +129 -0
  108. package/dist/node/dns.js +137 -0
  109. package/dist/node/domain.js +43 -0
  110. package/dist/node/events.js +1155 -0
  111. package/dist/node/fs/promises.js +40 -0
  112. package/dist/node/fs.js +10375 -0
  113. package/dist/node/http.js +326 -0
  114. package/dist/node/http2.js +305 -0
  115. package/dist/node/https.js +57 -0
  116. package/dist/node/inspector/promises.js +66 -0
  117. package/dist/node/inspector.js +76 -0
  118. package/dist/node/module.js +205 -0
  119. package/dist/node/net.js +392 -0
  120. package/dist/node/os.js +259 -0
  121. package/dist/node/path/posix.js +25 -0
  122. package/dist/node/path/win32.js +25 -0
  123. package/dist/node/path.js +384 -0
  124. package/dist/node/perf_hooks.js +313 -0
  125. package/dist/node/process.js +452 -0
  126. package/dist/node/punycode.js +178 -0
  127. package/dist/node/querystring.js +934 -0
  128. package/dist/node/readline/promises.js +71 -0
  129. package/dist/node/readline.js +56 -0
  130. package/dist/node/repl.js +44 -0
  131. package/dist/node/sqlite.js +22 -0
  132. package/dist/node/stream/consumers.js +47 -0
  133. package/dist/node/stream/promises.js +6 -0
  134. package/dist/node/stream/web.js +52 -0
  135. package/dist/node/stream.js +4323 -0
  136. package/dist/node/string_decoder.js +276 -0
  137. package/dist/node/sys.js +6 -0
  138. package/dist/node/timers/promises.js +71 -0
  139. package/dist/node/timers.js +133 -0
  140. package/dist/node/tls.js +122 -0
  141. package/dist/node/trace_events.js +23 -0
  142. package/dist/node/tty.js +69 -0
  143. package/dist/node/url.js +1426 -0
  144. package/dist/node/util/types.js +1456 -0
  145. package/dist/node/util.js +4807 -0
  146. package/dist/node/v8.js +160 -0
  147. package/dist/node/vm.js +88 -0
  148. package/dist/node/wasi.js +16 -0
  149. package/dist/node/worker_threads.js +123 -0
  150. package/dist/node/zlib.js +1396 -0
  151. package/dist/node-builtins.d.ts +40 -0
  152. package/dist/node-builtins.js +74 -0
  153. package/dist/node-on-page.d.ts +46 -0
  154. package/dist/node-on-page.js +101 -0
  155. package/dist/node-platform.d.ts +36 -0
  156. package/dist/node-platform.js +152 -0
  157. package/dist/node-rendered.d.ts +21 -0
  158. package/dist/node-rendered.js +26 -0
  159. package/dist/node-server.d.ts +46 -0
  160. package/dist/node-server.js +193 -0
  161. package/dist/optimizer-cache-key.d.ts +26 -0
  162. package/dist/optimizer-cache-key.js +73 -0
  163. package/dist/own-package.d.ts +1 -0
  164. package/dist/own-package.js +6 -0
  165. package/dist/page-store.d.ts +33 -0
  166. package/dist/page-store.js +80 -0
  167. package/dist/page-timers.d.ts +22 -0
  168. package/dist/page-timers.js +47 -0
  169. package/dist/page.d.ts +112 -0
  170. package/dist/page.js +549 -0
  171. package/dist/paths.d.ts +13 -0
  172. package/dist/paths.js +47 -0
  173. package/dist/plugin.d.ts +22 -0
  174. package/dist/plugin.js +995 -0
  175. package/dist/prerender-verdict.d.ts +8 -0
  176. package/dist/prerender-verdict.js +67 -0
  177. package/dist/project/context.d.ts +546 -0
  178. package/dist/project/context.js +111 -0
  179. package/dist/project/entries.d.ts +42 -0
  180. package/dist/project/entries.js +189 -0
  181. package/dist/project/env-worker.d.ts +1 -0
  182. package/dist/project/env-worker.js +9 -0
  183. package/dist/project/env.d.ts +36 -0
  184. package/dist/project/env.js +82 -0
  185. package/dist/project/layers.d.ts +31 -0
  186. package/dist/project/layers.js +150 -0
  187. package/dist/project/loaders.d.ts +71 -0
  188. package/dist/project/loaders.js +300 -0
  189. package/dist/project/metadata.d.ts +8 -0
  190. package/dist/project/metadata.js +34 -0
  191. package/dist/project/module-exports.d.ts +29 -0
  192. package/dist/project/module-exports.js +77 -0
  193. package/dist/project/routes.d.ts +19 -0
  194. package/dist/project/routes.js +92 -0
  195. package/dist/project/routing.d.ts +46 -0
  196. package/dist/project/routing.js +280 -0
  197. package/dist/project/transform.d.ts +8 -0
  198. package/dist/project/transform.js +110 -0
  199. package/dist/project/webpack.d.ts +46 -0
  200. package/dist/project/webpack.js +160 -0
  201. package/dist/project.d.ts +264 -0
  202. package/dist/project.js +58 -0
  203. package/dist/registry-global.d.ts +5 -0
  204. package/dist/registry-global.js +5 -0
  205. package/dist/registry.d.ts +241 -0
  206. package/dist/registry.js +30 -0
  207. package/dist/route-chunks.d.ts +13 -0
  208. package/dist/route-chunks.js +32 -0
  209. package/dist/route-lookup.d.ts +34 -0
  210. package/dist/route-lookup.js +207 -0
  211. package/dist/routes-ahead-shared.d.ts +17 -0
  212. package/dist/routes-ahead-shared.js +9 -0
  213. package/dist/routes-ahead.d.ts +10 -0
  214. package/dist/routes-ahead.js +54 -0
  215. package/dist/rsc.d.ts +19 -0
  216. package/dist/rsc.js +171 -0
  217. package/dist/server-action.d.ts +9 -0
  218. package/dist/server-action.js +15 -0
  219. package/dist/server-code.d.ts +176 -0
  220. package/dist/server-code.js +357 -0
  221. package/dist/server-in-front.d.ts +37 -0
  222. package/dist/server-in-front.js +90 -0
  223. package/dist/server-layers.d.ts +22 -0
  224. package/dist/server-layers.js +33 -0
  225. package/dist/setup-browser.d.ts +1 -0
  226. package/dist/setup-browser.js +8 -0
  227. package/dist/setup-node.d.ts +1 -0
  228. package/dist/setup-node.js +6 -0
  229. package/dist/setup.d.ts +8 -0
  230. package/dist/setup.js +62 -0
  231. package/dist/speed-features.d.ts +13 -0
  232. package/dist/speed-features.js +95 -0
  233. package/dist/ssr.d.ts +70 -0
  234. package/dist/ssr.js +480 -0
  235. package/dist/static-build.d.ts +36 -0
  236. package/dist/static-build.js +92 -0
  237. package/dist/storage.d.ts +31 -0
  238. package/dist/storage.js +94 -0
  239. package/dist/styles-shared.d.ts +137 -0
  240. package/dist/styles-shared.js +124 -0
  241. package/dist/styles.d.ts +102 -0
  242. package/dist/styles.js +730 -0
  243. package/dist/stylesheet-versions.d.ts +17 -0
  244. package/dist/stylesheet-versions.js +43 -0
  245. package/dist/tester.html +10 -0
  246. package/dist/use-cache.d.ts +15 -0
  247. package/dist/use-cache.js +93 -0
  248. package/dist/vitest-version.d.ts +6 -0
  249. package/dist/vitest-version.js +12 -0
  250. package/package.json +125 -4
@@ -0,0 +1,253 @@
1
+ import { registry } from "./registry.js";
2
+ import "./globals.js";
3
+ import { speedFeature } from "./speed-features.js";
4
+ import { PageStore } from "./page-store.js";
5
+ import { takesRequest } from "./server-in-front.js";
6
+ import { loadedSsrLayer, ssrLayer } from "./server-layers.js";
7
+ //#region src/app-requests.ts
8
+ const { Headers, Request: ServerNativeRequest } = globalThis;
9
+ const isRequest = (value) => value instanceof ServerNativeRequest;
10
+ async function handledByServer(...[request, options]) {
11
+ const layer = loadedSsrLayer() ?? await ssrLayer();
12
+ request.signal?.throwIfAborted();
13
+ return layer.handleRequest(request, options);
14
+ }
15
+ const nativeFetch = registry.network;
16
+ async function networkFetch(input, init) {
17
+ if (!init?.body && !(isRequest(input) && input.body)) return nativeFetch(input, init);
18
+ const request = new ServerNativeRequest(input, init);
19
+ return nativeFetch(new ServerNativeRequest(request, { body: await request.arrayBuffer() }));
20
+ }
21
+ function sameOriginRequest(input, init) {
22
+ const request = isRequest(input) ? input : void 0;
23
+ const url = new URL(request ? request.url : String(input), window.location.href);
24
+ if (url.origin !== window.location.origin || url.protocol === "blob:") return;
25
+ const headers = new Headers(init?.headers ?? request?.headers);
26
+ return {
27
+ url,
28
+ method: (init?.method ?? request?.method ?? "GET").toUpperCase(),
29
+ headers,
30
+ marked: headers.has("rsc") || headers.has("next-action")
31
+ };
32
+ }
33
+ let page;
34
+ let routerOutlivesPage = false;
35
+ /** Says which page of the app is open, by its signal, which aborts as it is left. */
36
+ function setOpenPage(signal) {
37
+ page = signal;
38
+ }
39
+ /** Says whether the router of the pages outlives them, from now on. */
40
+ function setRouterOutlivesPage(outlives) {
41
+ routerOutlivesPage = outlives;
42
+ }
43
+ const pageLeft = () => new DOMException("The page was left.", "AbortError");
44
+ const failsAsPageLeft = (action) => routerOutlivesPage && !action;
45
+ function ofLeftPage(action) {
46
+ return failsAsPageLeft(action) ? Promise.reject(pageLeft()) : never();
47
+ }
48
+ function browserHeaders(headers, url, method, from, credentials = true) {
49
+ headers.set("host", url.host);
50
+ from.headers.forEach((value, name) => {
51
+ if (!headers.has(name)) headers.set(name, value);
52
+ });
53
+ if (!headers.has("user-agent")) headers.set("user-agent", navigator.userAgent);
54
+ if (method !== "GET" && method !== "HEAD" && !headers.has("origin")) headers.set("origin", url.origin);
55
+ if (credentials && !headers.has("cookie")) {
56
+ const cookie = from.cookieHeader();
57
+ if (cookie) headers.set("cookie", cookie);
58
+ }
59
+ return headers;
60
+ }
61
+ function leftTheApp(url) {
62
+ return /* @__PURE__ */ new Error(`vitest-plugin-rsc: the app navigated to another origin: ${url.href}. A browser would leave the app for it, which a test cannot do.`);
63
+ }
64
+ function unlessAborted(answer, signal, abandon) {
65
+ return new Promise((resolve, reject) => {
66
+ const abort = () => {
67
+ reject(signal.reason);
68
+ answer.catch(() => {});
69
+ abandon(answer);
70
+ };
71
+ if (signal.aborted) return abort();
72
+ signal.addEventListener("abort", abort, { once: true });
73
+ answer.then((response) => {
74
+ signal.removeEventListener("abort", abort);
75
+ resolve(response);
76
+ }, (error) => {
77
+ signal.removeEventListener("abort", abort);
78
+ reject(error);
79
+ });
80
+ });
81
+ }
82
+ async function sendRequest(request, { from, credentials = true, navigation, network, opened }) {
83
+ let url = new URL(request.url);
84
+ let method = request.method;
85
+ let sent = request.headers;
86
+ const own = from && credentials && sent.has("cookie") ? new PageStore() : void 0;
87
+ own?.seed(sent.get("cookie"));
88
+ let body = request.body ? new Uint8Array(await request.arrayBuffer()) : null;
89
+ let redirected = false;
90
+ let redirects = 0;
91
+ for (;;) {
92
+ const headers = from ? browserHeaders(new Headers(sent), url, method, from, credentials) : new Headers(sent);
93
+ const appOpened = opened ? {
94
+ ...opened,
95
+ pathname: url.pathname
96
+ } : null;
97
+ const response = await unlessAborted(handledByServer({
98
+ url: url.href,
99
+ method,
100
+ headers,
101
+ body,
102
+ signal: request.signal
103
+ }, {
104
+ nested: !from,
105
+ unrouted: network ? "pass" : "not-found",
106
+ opened: navigation === "app" ? appOpened : redirected ? void 0 : opened,
107
+ pageLoad: navigation === "test"
108
+ }), request.signal, (answer) => void answer.then((late) => late?.body?.cancel()).catch(() => {}));
109
+ if (!response) return redirected ? nativeFetch(url, {
110
+ method,
111
+ headers: sent,
112
+ body,
113
+ signal: request.signal
114
+ }) : network();
115
+ if (credentials) from?.receive(response.headers.getSetCookie());
116
+ const location = response.headers.get("location");
117
+ if (response.status >= 300 && response.status < 400 && location) {
118
+ if (request.redirect === "manual") {
119
+ Object.defineProperties(response, { url: { value: url.href } });
120
+ return response;
121
+ }
122
+ if (request.redirect === "error") throw new TypeError("fetch failed", { cause: /* @__PURE__ */ new Error(`unexpected redirect of ${url.href} to ${location}`) });
123
+ if (!redirected) sent = new Headers(sent);
124
+ url = new URL(location, url);
125
+ const { status } = response;
126
+ if ((status === 301 || status === 302) && method === "POST" || status === 303 && method !== "GET" && method !== "HEAD") {
127
+ method = "GET";
128
+ body = null;
129
+ for (const name of [
130
+ "encoding",
131
+ "language",
132
+ "location",
133
+ "type"
134
+ ]) sent.delete(`content-${name}`);
135
+ }
136
+ redirected = true;
137
+ if (++redirects > 20) throw new Error(`vitest-plugin-rsc: too many redirects for ${request.url}. The last one was to ${url.href}.`);
138
+ if (url.origin !== window.location.origin) {
139
+ if (navigation) throw leftTheApp(url);
140
+ sent.delete("authorization");
141
+ return nativeFetch(url, {
142
+ method,
143
+ headers: sent,
144
+ body,
145
+ signal: request.signal
146
+ });
147
+ }
148
+ if (own) {
149
+ own.receive(response.headers.getSetCookie());
150
+ sent.set("cookie", own.cookieHeader());
151
+ }
152
+ continue;
153
+ }
154
+ Object.defineProperties(response, {
155
+ url: { value: url.href },
156
+ redirected: { value: redirected }
157
+ });
158
+ return response;
159
+ }
160
+ }
161
+ function pageResponse(response) {
162
+ const { Response: PageResponse } = window;
163
+ if (response instanceof PageResponse && !response.headers.has("set-cookie")) return response;
164
+ const headers = [...response.headers].filter(([name]) => name !== "set-cookie");
165
+ const { status, statusText, url, redirected } = response;
166
+ const page = new PageResponse(response.body, {
167
+ status,
168
+ statusText,
169
+ headers
170
+ });
171
+ return Object.defineProperties(page, {
172
+ url: { value: url },
173
+ redirected: { value: redirected }
174
+ });
175
+ }
176
+ const appFetch = (store, network) => async (input, init, sent) => {
177
+ const server = !store;
178
+ const from = store?.();
179
+ if (!sent) return network()(input, init);
180
+ const credentials = (init?.credentials ?? (isRequest(input) ? input.credentials : void 0)) !== "omit";
181
+ if (!sent.marked) {
182
+ if (from) sent.headers.delete("cookie");
183
+ const headers = from ? browserHeaders(sent.headers, sent.url, sent.method, from, credentials) : sent.headers;
184
+ if (!await takesRequest({
185
+ url: sent.url.href,
186
+ headers
187
+ })) return network()(input, init);
188
+ }
189
+ if (server && sent.method === "GET" && sent.headers.get("rsc") === "1" && sent.headers.has("x-action-redirect") && registry.openedByRequest.getStore()?.rendersRedirect === false) return new registry.Response(null, { status: 204 });
190
+ const spare = isRequest(input) && input.body ? input.clone() : input;
191
+ const response = await sendRequest(server ? new registry.Request(input, init) : new Request(input, init), {
192
+ from,
193
+ credentials,
194
+ network: sent.marked ? void 0 : () => network()(spare, init)
195
+ });
196
+ return from && response ? pageResponse(response) : response;
197
+ };
198
+ const never = () => new Promise(() => {});
199
+ function isPrefetch(sent, init) {
200
+ return sent.headers.has("rsc") && (sent.headers.has("next-router-prefetch") || init?.priority === "low");
201
+ }
202
+ const noPrefetch = () => new Response(null, { status: 204 });
203
+ async function heardBy(sender, response, action) {
204
+ if (failsAsPageLeft(action)) return failsAsLeft(sender, response);
205
+ const answered = await response.catch(() => void 0);
206
+ if (!sender.aborted) return response;
207
+ answered?.body?.cancel().catch(() => {});
208
+ return ofLeftPage(action);
209
+ }
210
+ function failsAsLeft(sender, response) {
211
+ const left = new Promise((_, reject) => sender.addEventListener("abort", () => reject(pageLeft()), { once: true }));
212
+ left.catch(() => {});
213
+ response.then((answered) => {
214
+ if (sender.aborted) answered?.body?.cancel().catch(() => {});
215
+ }, () => {});
216
+ return Promise.race([response, left]);
217
+ }
218
+ /**
219
+ * The browser's `fetch` while a browser context of the app is open: what
220
+ * Next's client router and Client Components call. `store()` is the store of
221
+ * the context, and `network()` the `fetch` the document had before it, which
222
+ * gets every request that is not the app's, or, where the DOM hands over the
223
+ * page's requests, one that answers none, for the DOM to send. Without a
224
+ * context, `network()` gets every request: code that took this `fetch` in a
225
+ * context has the document's own after it.
226
+ *
227
+ * Next marks the requests it sends for a page, with an `rsc` or a
228
+ * `next-action` header. They belong to the page that is open as they are
229
+ * sent. Its router is there only once its page is, so without a page that
230
+ * page was left, and it sends nothing more. A test asks with
231
+ * `handleRequest()`.
232
+ */
233
+ function pageFetch(store, network) {
234
+ const browserFetch = appFetch(() => store(), network);
235
+ return async (input, init) => {
236
+ if (!store()) return network()(input, init);
237
+ const sent = sameOriginRequest(input, init);
238
+ if (!sent?.marked) return browserFetch(input, init, sent);
239
+ const action = sent.headers.has("next-action");
240
+ const sender = page;
241
+ if (!sender || sender.aborted) return ofLeftPage(action);
242
+ if (speedFeature("skipPrefetch") && isPrefetch(sent, init)) return noPrefetch();
243
+ return heardBy(sender, browserFetch(input, init, sent), action);
244
+ };
245
+ }
246
+ const serverFetch = appFetch(void 0, () => networkFetch);
247
+ registry.fetch = async (input, init) => {
248
+ if (!isRequest(input) && !URL.canParse(String(input))) throw new TypeError(`Failed to parse URL from ${String(input)}`, { cause: /* @__PURE__ */ new TypeError("Invalid URL") });
249
+ return serverFetch(input, init, sameOriginRequest(input, init));
250
+ };
251
+ process.env.__NEXT_PRIVATE_ORIGIN = window.location.origin;
252
+ //#endregion
253
+ export { leftTheApp, pageFetch, sendRequest, setOpenPage, setRouterOutlivesPage, unlessAborted };
@@ -0,0 +1,24 @@
1
+ import { PageStore } from "./page-store.js";
2
+ import { PageStorage } from "./storage.js";
3
+
4
+ //#region src/browser-context.d.ts
5
+ /** A browser context of the app: its cookie jar, the headers of its requests, and its storage. */
6
+ declare class BrowserContext {
7
+ readonly store: PageStore;
8
+ readonly storage: PageStorage;
9
+ }
10
+ /**
11
+ * Opens a browser context of the app, empty, unless one is open: the
12
+ * document has its cookies, storage, requests and navigations until
13
+ * `closeContext()`.
14
+ */
15
+ declare function openContext(): BrowserContext;
16
+ /**
17
+ * Closes the browser context that is open, and puts back what the document
18
+ * had wherever the context's own are in place. Also with none open: a patch
19
+ * over them that has gone since, like a spy that a test restored after
20
+ * `cleanup()`, put them back.
21
+ */
22
+ declare function closeContext(): void;
23
+ //#endregion
24
+ export { BrowserContext, closeContext, openContext };
@@ -0,0 +1,157 @@
1
+ import { registry } from "./registry.js";
2
+ import { PageStore } from "./page-store.js";
3
+ import { pageFetch } from "./app-requests.js";
4
+ import { streamedContentQueue } from "./document.js";
5
+ import { fromPage } from "./from-page.js";
6
+ import { followNavigation } from "./document-loads.js";
7
+ import { appHasNavigations } from "./host-document.js";
8
+ import { PageStorage, itemsOfStorage, storageOf } from "./storage.js";
9
+ import pageHost from "virtual:vitest-plugin-rsc/page-host";
10
+ //#region src/browser-context.ts
11
+ /** A browser context of the app: its cookie jar, the headers of its requests, and its storage. */
12
+ var BrowserContext = class {
13
+ store = new PageStore();
14
+ storage = new PageStorage();
15
+ };
16
+ let opened;
17
+ const saved = /* @__PURE__ */ new Map();
18
+ const patched = /* @__PURE__ */ new Set();
19
+ const savedOf = (binding) => saved.get(binding) ?? descriptorOf(Object.getPrototypeOf(binding.target), binding.name);
20
+ function savedValue(binding) {
21
+ const descriptor = savedOf(binding);
22
+ return descriptor?.get ? descriptor.get.call(binding.target) : descriptor?.value;
23
+ }
24
+ function descriptorOf(target, name) {
25
+ for (; target; target = Object.getPrototypeOf(target)) {
26
+ const descriptor = Object.getOwnPropertyDescriptor(target, name);
27
+ if (descriptor) return descriptor;
28
+ }
29
+ }
30
+ const leftToDocument = /* @__PURE__ */ new WeakSet();
31
+ const interceptedFetch = pageFetch(() => opened?.store, () => async () => void 0);
32
+ const handsOver = pageHost.interceptRequests(async (request) => leftToDocument.has(request) ? void 0 : interceptedFetch(...fromPage(request)));
33
+ const toDocument = (input, init) => () => {
34
+ const documentFetch = savedValue(fetchBinding) ?? registry.network;
35
+ if (!handsOver) return documentFetch;
36
+ return () => {
37
+ const request = new window.Request(input, init);
38
+ leftToDocument.add(request);
39
+ return documentFetch(request);
40
+ };
41
+ };
42
+ const fetchBinding = {
43
+ target: window,
44
+ name: "fetch",
45
+ own: {
46
+ configurable: true,
47
+ enumerable: true,
48
+ writable: true,
49
+ value: (input, init) => pageFetch(() => opened?.store, toDocument(input, init))(...fromPage(input, init))
50
+ }
51
+ };
52
+ const cookieBinding = {
53
+ target: document,
54
+ name: "cookie",
55
+ own: {
56
+ configurable: true,
57
+ get: () => opened ? opened.store.documentCookie() : savedValue(cookieBinding),
58
+ set(cookie) {
59
+ if (opened) opened.store.write(String(cookie));
60
+ else savedOf(cookieBinding)?.set?.call(document, cookie);
61
+ }
62
+ }
63
+ };
64
+ const storageBindings = ["localStorage", "sessionStorage"].map((name) => {
65
+ const binding = {
66
+ target: window,
67
+ name,
68
+ own: void 0
69
+ };
70
+ const items = () => opened ? opened.storage[name] : itemsOfStorage(savedValue(binding));
71
+ const storage = storageOf(items);
72
+ binding.own = {
73
+ configurable: true,
74
+ enumerable: true,
75
+ get: () => storage
76
+ };
77
+ return binding;
78
+ });
79
+ const bindings = [
80
+ fetchBinding,
81
+ cookieBinding,
82
+ ...[
83
+ "cookieStore",
84
+ "CookieStore",
85
+ "CookieChangeEvent"
86
+ ].map((name) => ({
87
+ target: window,
88
+ name,
89
+ own: void 0
90
+ })),
91
+ ...storageBindings,
92
+ {
93
+ target: self,
94
+ name: "$RC",
95
+ own: streamedContentQueue
96
+ }
97
+ ];
98
+ function same(one, other) {
99
+ if (!one || !other) return one === other;
100
+ return one.get === other.get && one.set === other.set && one.value === other.value;
101
+ }
102
+ const ownOf = ({ target, name }) => Object.getOwnPropertyDescriptor(target, name);
103
+ const original = new Map(bindings.map((binding) => [binding, ownOf(binding)]));
104
+ const isDocuments = (binding, descriptor) => saved.has(binding) && same(descriptor, saved.get(binding)) || same(descriptor, original.get(binding));
105
+ const { navigation } = pageHost;
106
+ const followed = (event) => {
107
+ if (opened) followNavigation(event, opened.store);
108
+ };
109
+ /**
110
+ * Opens a browser context of the app, empty, unless one is open: the
111
+ * document has its cookies, storage, requests and navigations until
112
+ * `closeContext()`.
113
+ */
114
+ function openContext() {
115
+ if (opened) return opened;
116
+ for (const binding of bindings) {
117
+ const { target, name, own } = binding;
118
+ const descriptor = ownOf(binding);
119
+ if (same(descriptor, own)) continue;
120
+ if (patched.has(binding) && !isDocuments(binding, descriptor)) continue;
121
+ patched.delete(binding);
122
+ saved.set(binding, descriptor);
123
+ if (own) Object.defineProperty(target, name, own);
124
+ else Reflect.deleteProperty(target, name);
125
+ }
126
+ navigation?.addEventListener("navigate", followed);
127
+ appHasNavigations(true);
128
+ return opened = new BrowserContext();
129
+ }
130
+ /**
131
+ * Closes the browser context that is open, and puts back what the document
132
+ * had wherever the context's own are in place. Also with none open: a patch
133
+ * over them that has gone since, like a spy that a test restored after
134
+ * `cleanup()`, put them back.
135
+ */
136
+ function closeContext() {
137
+ const closing = opened !== void 0;
138
+ opened = void 0;
139
+ navigation?.removeEventListener("navigate", followed);
140
+ appHasNavigations(false);
141
+ for (const binding of bindings) {
142
+ const { target, name, own } = binding;
143
+ const descriptor = ownOf(binding);
144
+ if (!same(descriptor, own)) {
145
+ if (isDocuments(binding, descriptor)) patched.delete(binding);
146
+ else if (closing) patched.add(binding);
147
+ continue;
148
+ }
149
+ patched.delete(binding);
150
+ if (!saved.has(binding)) continue;
151
+ const put = saved.get(binding);
152
+ if (put) Object.defineProperty(target, name, put);
153
+ else Reflect.deleteProperty(target, name);
154
+ }
155
+ }
156
+ //#endregion
157
+ export { BrowserContext, closeContext, openContext };
@@ -0,0 +1,68 @@
1
+ import { Stylesheets } from "./styles-shared.js";
2
+ import { PrerenderVerdict } from "./registry.js";
3
+ import { PrerenderManifest } from "./compat/ssr/build-output.js";
4
+
5
+ //#region src/build-output.d.ts
6
+ declare function setStylesheets(of: Stylesheets): void;
7
+ declare function setServerActions(ids: Iterable<string>): void;
8
+ declare let prerenderManifest: PrerenderManifest;
9
+ type Route = {
10
+ kind: "page" | "route";
11
+ page: string;
12
+ pathname: string;
13
+ };
14
+ /**
15
+ * Lists what Next's build prerenders of a route, by its verdict: the entries
16
+ * of the prerender manifest that Next's handler reads. With them the handler
17
+ * prerenders a pathname at its first request, keeps it, and serves it from
18
+ * then on, as `next start` serves what the build prerendered. Without the
19
+ * `revalidate` the build writes: Next's cache reads it for a page the build
20
+ * prerendered, and here every page is first prerendered by the handler,
21
+ * which keeps the `revalidate` of the render with it.
22
+ */
23
+ declare function recordRoute(route: Route, verdict: PrerenderVerdict | undefined): void;
24
+ /** Forgets what the build kept, as the server's cache forgets its entries. */
25
+ declare function forgetBuilt(): void;
26
+ /**
27
+ * A page as the build keeps it, which Next's handler is about to keep for
28
+ * `pathname`, at the first prerender of that pathname in this `generation`
29
+ * of the cache. The build keeps a page of a parallel route's slot without a
30
+ * status (`export/routes/app-page.js:126-141`), which `next start` serves
31
+ * with 200: a page whose other slots have no page for its path renders the
32
+ * not-found page there, which a page load shows, and a navigation, which
33
+ * keeps the other slots as they are, does not. Next's handler would keep
34
+ * the status of its render, 404, and Next's router takes a navigation that
35
+ * answers 404 for a page load. So the entry gets 200, in place: the handler
36
+ * answers the request of its prerender with the status of the entry it
37
+ * keeps, and otherwise with the one its render set. `route` is the source
38
+ * of the entry, the page, as Next's response cache hands it to the cache.
39
+ */
40
+ declare function keptAsBuilt(pathname: string, value: {
41
+ kind: string;
42
+ status?: number;
43
+ } | null, {
44
+ route
45
+ }: {
46
+ route?: {
47
+ sourceRoute?: string;
48
+ };
49
+ }, generation: number): void;
50
+ /**
51
+ * Hands Next's handler a manifest without `route` for `respond()`, the
52
+ * response of a prefetch: Next reads the manifest as it starts a request.
53
+ */
54
+ declare function withoutRoute<T>(route: Route, respond: () => Promise<T>): Promise<T>;
55
+ /** Whether the build prerenders a route, or a pathname of it. */
56
+ declare function isPrerendered(route: Route): boolean;
57
+ /**
58
+ * Takes a route out of what the build prerenders: for a render that read the
59
+ * request, which the build would have found as it prerendered the route.
60
+ * All of its pathnames: of a route with `generateStaticParams`, the build
61
+ * keeps those that did not read it, and here the others are not rendered yet.
62
+ */
63
+ declare function demoteRoute(route: Route): void;
64
+ /** A file of `.next/`, by its path, as Next's `loadManifest()` reads it. */
65
+ declare function loadManifest(file: string): unknown;
66
+ declare const nodeRouteDistDir = ".next/vitest-plugin-rsc-node";
67
+ //#endregion
68
+ export { demoteRoute, forgetBuilt, isPrerendered, keptAsBuilt, loadManifest, nodeRouteDistDir, prerenderManifest, recordRoute, setServerActions, setStylesheets, withoutRoute };