@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,6 @@
1
+ import { NEXT_CACHE_IMPLICIT_TAG_ID } from "next/dist/lib/constants.js";
2
+ import { IncrementalCache } from "next/dist/server/lib/incremental-cache/index.js";
3
+ import { tagsManifest } from "next/dist/server/lib/incremental-cache/tags-manifest.external";
4
+ import { nodeFs } from "next/dist/server/lib/node-fs-methods.js";
5
+ import { initializeCacheHandlers, registerCustomCacheHandlers, setCacheHandler } from "next/dist/server/use-cache/handlers.js";
6
+ export { IncrementalCache, NEXT_CACHE_IMPLICIT_TAG_ID, initializeCacheHandlers, nodeFs, registerCustomCacheHandlers, setCacheHandler, tagsManifest };
@@ -0,0 +1,6 @@
1
+ import { NEXT_CACHE_IMPLICIT_TAG_ID } from "next/dist/lib/constants.js";
2
+ import { IncrementalCache } from "next/dist/server/lib/incremental-cache/index.js";
3
+ import { tagsManifest } from "next/dist/server/lib/incremental-cache/tags-manifest.external";
4
+ import { nodeFs } from "next/dist/server/lib/node-fs-methods.js";
5
+ import { initializeCacheHandlers, registerCustomCacheHandlers, setCacheHandler } from "next/dist/server/use-cache/handlers.js";
6
+ export { IncrementalCache, NEXT_CACHE_IMPLICIT_TAG_ID, initializeCacheHandlers, nodeFs, registerCustomCacheHandlers, setCacheHandler, tagsManifest };
@@ -0,0 +1,8 @@
1
+ import { normalizeNextQueryParam } from "next/dist/server/web/utils.js";
2
+ import { NEXT_REWRITTEN_PATH_HEADER, NEXT_REWRITTEN_QUERY_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_RSC_UNION_QUERY, RSC_HEADER } from "next/dist/client/components/app-router-headers.js";
3
+ import { isRSCRequestHeader } from "next/dist/server/lib/is-rsc-request.js";
4
+ import * as appPageModule from "next/dist/server/route-modules/app-page/module.js";
5
+ import { getIsPossibleServerAction } from "next/dist/server/lib/server-action-request-meta.js";
6
+ import { getRouteMatcher } from "next/dist/shared/lib/router/utils/route-matcher.js";
7
+ import { getRouteRegex } from "next/dist/shared/lib/router/utils/route-regex.js";
8
+ export { NEXT_REWRITTEN_PATH_HEADER, NEXT_REWRITTEN_QUERY_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_RSC_UNION_QUERY, RSC_HEADER, appPageModule, getIsPossibleServerAction, getRouteMatcher, getRouteRegex, isRSCRequestHeader, normalizeNextQueryParam };
@@ -0,0 +1,8 @@
1
+ import { normalizeNextQueryParam } from "next/dist/server/web/utils.js";
2
+ import { NEXT_REWRITTEN_PATH_HEADER, NEXT_REWRITTEN_QUERY_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_RSC_UNION_QUERY, RSC_HEADER } from "next/dist/client/components/app-router-headers.js";
3
+ import { isRSCRequestHeader } from "next/dist/server/lib/is-rsc-request.js";
4
+ import * as appPageModule from "next/dist/server/route-modules/app-page/module.js";
5
+ import { getIsPossibleServerAction } from "next/dist/server/lib/server-action-request-meta.js";
6
+ import { getRouteMatcher } from "next/dist/shared/lib/router/utils/route-matcher.js";
7
+ import { getRouteRegex } from "next/dist/shared/lib/router/utils/route-regex.js";
8
+ export { NEXT_REWRITTEN_PATH_HEADER, NEXT_REWRITTEN_QUERY_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_RSC_UNION_QUERY, RSC_HEADER, appPageModule, getIsPossibleServerAction, getRouteMatcher, getRouteRegex, isRSCRequestHeader, normalizeNextQueryParam };
@@ -0,0 +1,5 @@
1
+ import { fromNodeOutgoingHttpHeaders, toNodeOutgoingHttpHeaders } from "next/dist/server/web/utils.js";
2
+ import { isDynamicServerError } from "next/dist/client/components/hooks-server-context.js";
3
+ import { MockedResponse } from "next/dist/server/lib/mock-request.js";
4
+ import { RequestMeta } from "next/dist/server/request-meta.js";
5
+ export { MockedResponse, type RequestMeta, fromNodeOutgoingHttpHeaders, isDynamicServerError, toNodeOutgoingHttpHeaders };
@@ -0,0 +1,4 @@
1
+ import { fromNodeOutgoingHttpHeaders, toNodeOutgoingHttpHeaders } from "next/dist/server/web/utils.js";
2
+ import { isDynamicServerError } from "next/dist/client/components/hooks-server-context.js";
3
+ import { MockedResponse } from "next/dist/server/lib/mock-request.js";
4
+ export { MockedResponse, fromNodeOutgoingHttpHeaders, isDynamicServerError, toNodeOutgoingHttpHeaders };
@@ -0,0 +1,4 @@
1
+ import { getAccessFallbackHTTPStatus, isHTTPAccessFallbackError } from "next/dist/client/components/http-access-fallback/http-access-fallback.js";
2
+ import { getRedirectStatusCodeFromError, getURLFromRedirectError } from "next/dist/client/components/redirect.js";
3
+ import { isRedirectError } from "next/dist/client/components/redirect-error.js";
4
+ export { getAccessFallbackHTTPStatus, getRedirectStatusCodeFromError, getURLFromRedirectError, isHTTPAccessFallbackError, isRedirectError };
@@ -0,0 +1,4 @@
1
+ import { getAccessFallbackHTTPStatus, isHTTPAccessFallbackError } from "next/dist/client/components/http-access-fallback/http-access-fallback.js";
2
+ import { getRedirectStatusCodeFromError, getURLFromRedirectError } from "next/dist/client/components/redirect.js";
3
+ import { isRedirectError } from "next/dist/client/components/redirect-error.js";
4
+ export { getAccessFallbackHTTPStatus, getRedirectStatusCodeFromError, getURLFromRedirectError, isHTTPAccessFallbackError, isRedirectError };
@@ -0,0 +1,6 @@
1
+ import { NodeNextResponse } from "next/dist/server/base-http/node.js";
2
+ import { generateETag } from "next/dist/server/lib/etag.js";
3
+ import RenderResult from "next/dist/server/render-result.js";
4
+ import { sendRenderResult } from "next/dist/server/send-payload.js";
5
+ import { sendResponse } from "next/dist/server/send-response.js";
6
+ export { NodeNextResponse, RenderResult, generateETag, sendRenderResult, sendResponse };
@@ -0,0 +1,6 @@
1
+ import { NodeNextResponse } from "next/dist/server/base-http/node.js";
2
+ import { generateETag } from "next/dist/server/lib/etag.js";
3
+ import RenderResult from "next/dist/server/render-result.js";
4
+ import { sendRenderResult } from "next/dist/server/send-payload.js";
5
+ import { sendResponse } from "next/dist/server/send-response.js";
6
+ export { NodeNextResponse, RenderResult, generateETag, sendRenderResult, sendResponse };
@@ -0,0 +1,8 @@
1
+ import { RoutesManifest } from "next/dist/build/index.js";
2
+ import { AdapterOutputs } from "next/dist/build/adapter/build-complete.js";
3
+ import { ProxyMatcher } from "next/dist/build/analysis/get-page-static-info.js";
4
+ import { AppLoaderOptions } from "next/dist/build/webpack/loaders/next-app-loader/index.js";
5
+ import { EdgeFunctionDefinition, MiddlewareManifest } from "next/dist/build/webpack/plugins/middleware-plugin.js";
6
+ import { Header } from "next/dist/lib/load-custom-routes.js";
7
+ import { NextConfigComplete } from "next/dist/server/config-shared.js";
8
+ export { type AdapterOutputs, type AppLoaderOptions, type EdgeFunctionDefinition, type Header, type MiddlewareManifest, type NextConfigComplete, type ProxyMatcher, type RoutesManifest };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ import { NextLayer, NextProject } from "./project.js";
2
+ import { Plugin } from "vite";
3
+
4
+ //#region src/compile.d.ts
5
+ /**
6
+ * The call of a `next/font` function whose CSS a module is, by the module's
7
+ * id: the import the SWC transform turns the call into. Nothing for any other
8
+ * module.
9
+ */
10
+ declare function fontRequestOf(id: string): string | undefined;
11
+ declare function createDependencyCompilePlugin(getProject: () => NextProject, layer: NextLayer, isAppCode: (file: string, layer: NextLayer) => boolean): {
12
+ name: string;
13
+ resolveId(source: string): {
14
+ id: string;
15
+ external: boolean;
16
+ } | undefined;
17
+ transform(code: string, id: string): Promise<{
18
+ code: string;
19
+ map: string | null;
20
+ } | undefined>;
21
+ };
22
+ declare function createScanCompilePlugin(getProject: () => NextProject, layer: NextLayer, isAppCode: (file: string, layer: NextLayer) => boolean): {
23
+ name: string;
24
+ transform(code: string, id: string): Promise<{
25
+ code: string;
26
+ map: string | null;
27
+ } | undefined>;
28
+ };
29
+ declare function createCompilePlugin(getProject: () => NextProject, layerOf: (environment: string) => NextLayer | undefined, isAppCode: (file: string, layer: NextLayer) => boolean): Plugin;
30
+ //#endregion
31
+ export { createCompilePlugin, createDependencyCompilePlugin, createScanCompilePlugin, fontRequestOf };
@@ -0,0 +1,140 @@
1
+ import { linked } from "./styles.js";
2
+ import { normalizePath } from "vite";
3
+ import path from "node:path";
4
+ import fs from "node:fs";
5
+ import { withBuiltFiles } from "@kasperpeulen/vitest-plugin-rsc/internal/static-build";
6
+ //#region src/compile.ts
7
+ const fontPrefix = "\0vitest-plugin-rsc/next-font/";
8
+ const fontRequest = /^next\/font\/(?:google|local)\/target\.css\?/;
9
+ /**
10
+ * The call of a `next/font` function whose CSS a module is, by the module's
11
+ * id: the import the SWC transform turns the call into. Nothing for any other
12
+ * module.
13
+ */
14
+ function fontRequestOf(id) {
15
+ if (!id.startsWith(fontPrefix)) return void 0;
16
+ const name = id.slice(29).split("?")[0];
17
+ if (!name.endsWith(".css")) return void 0;
18
+ return Buffer.from(name.slice(0, -4), "base64url").toString();
19
+ }
20
+ const sourceFile = /\.(?:tsx|ts|jsx|js|mjs)$/;
21
+ function createDependencyCompilePlugin(getProject, layer, isAppCode) {
22
+ return {
23
+ name: "vitest-plugin-rsc:next-compile-dependency",
24
+ resolveId(source) {
25
+ if (fontRequest.test(source)) return {
26
+ id: source,
27
+ external: true
28
+ };
29
+ },
30
+ async transform(code, id) {
31
+ if (!/\.[cm]?js$/.test(id) || !/\bnext\/font\b/.test(code) || isAppCode(id, layer)) return;
32
+ if (!path.relative(getProject().nextDir, id).startsWith("..")) return;
33
+ const compiled = await getProject().compile(code, id, layer);
34
+ return compiled && {
35
+ code: compiled.code,
36
+ map: compiled.map ?? null
37
+ };
38
+ }
39
+ };
40
+ }
41
+ function createScanCompilePlugin(getProject, layer, isAppCode) {
42
+ return {
43
+ name: `vitest-plugin-rsc:next-compile-scan:${layer}`,
44
+ async transform(code, id) {
45
+ if (id.includes("?") || !sourceFile.test(id) || !isAppCode(id, layer)) return;
46
+ const compiled = await getProject().compile(code, id, layer).catch(() => void 0);
47
+ if (!compiled || compiled.refused) return;
48
+ return {
49
+ code: compiled.code,
50
+ map: compiled.map ?? null
51
+ };
52
+ }
53
+ };
54
+ }
55
+ function createCompilePlugin(getProject, layerOf, isAppCode) {
56
+ return {
57
+ name: "vitest-plugin-rsc:next-compile",
58
+ enforce: "pre",
59
+ configureServer(server) {
60
+ const serveFile = async (request, response) => {
61
+ server.middlewares.handle(request, response, (error) => {
62
+ response.statusCode = error ? 500 : 404;
63
+ response.end();
64
+ });
65
+ };
66
+ const serve = async (request, response) => {
67
+ const project = getProject();
68
+ if (await project.optimizeImage(request, response, serveFile)) return true;
69
+ const file = project.readEmittedFile(new URL(request.url, "http://n").pathname);
70
+ if (!file) return false;
71
+ response.setHeader("content-type", file.contentType);
72
+ response.end(file.body);
73
+ return true;
74
+ };
75
+ server.middlewares.use(async (request, response, next) => {
76
+ let served;
77
+ try {
78
+ served = await serve(request, response);
79
+ } catch (error) {
80
+ server.config.logger.error(`vitest-plugin-rsc: ${request.url} failed. ${String(error)}`);
81
+ response.statusCode = 500;
82
+ response.end("Internal Server Error");
83
+ return;
84
+ }
85
+ if (!served) next();
86
+ });
87
+ },
88
+ async resolveId(source, importer, options) {
89
+ if (source.startsWith(fontPrefix)) return source;
90
+ if (fontRequest.test(source)) return `${fontPrefix}${Buffer.from(source).toString("base64url")}.js`;
91
+ const layer = layerOf(this.environment.name);
92
+ const candidates = layer && getProject().webpackAliasOf(source, layer);
93
+ for (const candidate of candidates ?? []) {
94
+ const resolved = await this.resolve(candidate, importer, {
95
+ ...options,
96
+ skipSelf: true
97
+ });
98
+ if (resolved) return resolved;
99
+ }
100
+ },
101
+ async load(id) {
102
+ const built = (code, language) => {
103
+ if (this.environment.mode !== "build") return code;
104
+ const pathnames = getProject().emittedFiles().map((file) => file.pathname);
105
+ return withBuiltFiles(code, pathnames, language);
106
+ };
107
+ if (id.startsWith(fontPrefix)) {
108
+ const name = id.slice(29).split("?")[0];
109
+ const key = name.replace(/\.(?:js|css)$/, "");
110
+ const request = Buffer.from(key, "base64url").toString();
111
+ const { css, exports } = await getProject().loadFont(request);
112
+ if (name.endsWith(".css")) return built(css, "css");
113
+ const stylesheet = linked(`${fontPrefix}${key}.css`, this.environment.mode === "build");
114
+ return `import ${JSON.stringify(stylesheet)};\nexport default ${JSON.stringify(exports)};\n`;
115
+ }
116
+ const layer = layerOf(this.environment.name);
117
+ if (!layer || id.includes("?")) return;
118
+ if (getProject().webpackRuleOf(id, layer) && fs.existsSync(id)) return {
119
+ code: await getProject().loadWithWebpackRule(id, layer),
120
+ moduleType: "js"
121
+ };
122
+ if (!getProject().isImage(id) || !fs.existsSync(id)) return;
123
+ return built(await getProject().loadImage(id), "js");
124
+ },
125
+ async transform(code, id) {
126
+ const layer = layerOf(this.environment.name);
127
+ if (!layer || id.includes("?")) return;
128
+ if (!sourceFile.test(id) && !getProject().webpackRuleOf(id, layer)?.compile) return;
129
+ if (!isAppCode(id, layer) || !fs.existsSync(id)) return;
130
+ if (id.startsWith(`${normalizePath(this.environment.config.cacheDir)}/`)) return;
131
+ const compiled = await getProject().compile(code, id, layer);
132
+ return compiled && {
133
+ code: compiled.code,
134
+ map: compiled.map ?? null
135
+ };
136
+ }
137
+ };
138
+ }
139
+ //#endregion
140
+ export { createCompilePlugin, createDependencyCompilePlugin, createScanCompilePlugin, fontRequestOf };
package/dist/disk.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ //#region src/disk.d.ts
2
+ /** The global the disk is on. */
3
+ declare const diskGlobal = "__vitest_plugin_rsc_disk__";
4
+ /** The disk: the `fs` of memfs, and what empties it. */
5
+ type Disk = {
6
+ fs: Record<string, any>;
7
+ reset(): void;
8
+ };
9
+ /**
10
+ * Empties the disk, as it is before any test: nothing but `/tmp`, which
11
+ * `os.tmpdir()` names. Closes what watches a file of it, which would see the
12
+ * next test's files otherwise. Nothing to do while no module imports `fs`.
13
+ */
14
+ declare function resetDisk(): void;
15
+ //#endregion
16
+ export { Disk, diskGlobal, resetDisk };
package/dist/disk.js ADDED
@@ -0,0 +1,13 @@
1
+ //#region src/disk.ts
2
+ /** The global the disk is on. */
3
+ const diskGlobal = "__vitest_plugin_rsc_disk__";
4
+ /**
5
+ * Empties the disk, as it is before any test: nothing but `/tmp`, which
6
+ * `os.tmpdir()` names. Closes what watches a file of it, which would see the
7
+ * next test's files otherwise. Nothing to do while no module imports `fs`.
8
+ */
9
+ function resetDisk() {
10
+ globalThis[diskGlobal]?.reset();
11
+ }
12
+ //#endregion
13
+ export { diskGlobal, resetDisk };
@@ -0,0 +1,15 @@
1
+ import { PageStore } from "./page-store.js";
2
+
3
+ //#region src/document-loads.d.ts
4
+ /**
5
+ * What a navigation does in a browser context of the app, whose store is
6
+ * `from`. The app can leave its page without its router:
7
+ * `location.assign()`, a `<form>` or an `<a>` that React does not handle,
8
+ * Next's own fallback when a client-side navigation is not possible. For a
9
+ * browser that is a page load. Here it would replace the test with the app,
10
+ * so `navigate()` loads the page the way `renderServer()` does instead, or
11
+ * downloads what a browser would.
12
+ */
13
+ declare function followNavigation(event: Event, from: PageStore): void;
14
+ //#endregion
15
+ export { followNavigation };
@@ -0,0 +1,53 @@
1
+ import { openedAt } from "./registry.js";
2
+ import { leftTheApp } from "./app-requests.js";
3
+ import { documentUrl } from "./document.js";
4
+ import { enctypeOf, formBody } from "./form-submission.js";
5
+ import { fromPage } from "./from-page.js";
6
+ import { currentPage, leavePage, navigate, noRouter } from "./page.js";
7
+ //#region src/document-loads.ts
8
+ import.meta.hot?.on("vite:beforeFullReload", ({ path }) => {
9
+ if (reloadsDocument(path)) return leavePage("a reload of the page");
10
+ });
11
+ import.meta.hot?.on("vite:ws:disconnect", () => leavePage("a lost connection to the dev server"));
12
+ function reloadsDocument(path) {
13
+ if (!path?.endsWith(".html") || path === "/index.html") return true;
14
+ const pagePath = decodeURI(new URL(documentUrl()).pathname);
15
+ const payloadPath = (import.meta.env?.BASE_URL ?? "/") + path.slice(1);
16
+ return pagePath === payloadPath || pagePath.endsWith("/") && `${pagePath}index.html` === payloadPath;
17
+ }
18
+ /**
19
+ * What a navigation does in a browser context of the app, whose store is
20
+ * `from`. The app can leave its page without its router:
21
+ * `location.assign()`, a `<form>` or an `<a>` that React does not handle,
22
+ * Next's own fallback when a client-side navigation is not possible. For a
23
+ * browser that is a page load. Here it would replace the test with the app,
24
+ * so `navigate()` loads the page the way `renderServer()` does instead, or
25
+ * downloads what a browser would.
26
+ */
27
+ function followNavigation(event, from) {
28
+ const { destination, hashChange, formData, downloadRequest, navigationType, sourceElement } = event;
29
+ if (destination.sameDocument) currentPage()?.nodeOnPage?.at(new URL(destination.url).pathname);
30
+ if (destination.sameDocument || hashChange || !event.cancelable) return;
31
+ const url = new URL(destination.url);
32
+ if (downloadRequest !== null && (url.protocol === "blob:" || url.protocol === "data:")) return;
33
+ if (destination.url === documentUrl()) return;
34
+ if (url.origin === window.location.origin && openedAt(url)?.node) {
35
+ event.preventDefault();
36
+ leavePage("a navigation to the host's document").catch(() => {}).then(() => window.location.reload());
37
+ return;
38
+ }
39
+ event.preventDefault();
40
+ if (url.origin !== window.location.origin) {
41
+ reportError(currentPage() ? leftTheApp(url) : noRouter(url));
42
+ return;
43
+ }
44
+ navigate(url, fromPage(url, {
45
+ method: formData ? "POST" : "GET",
46
+ headers: { accept: "text/html" },
47
+ body: formData && formBody(formData, enctypeOf(sourceElement))
48
+ })[1], downloadRequest, from, navigationType === "push").catch((error) => {
49
+ if (!(error instanceof DOMException && error.name === "AbortError")) reportError(error);
50
+ });
51
+ }
52
+ //#endregion
53
+ export { followNavigation };
@@ -0,0 +1,79 @@
1
+ //#region src/document.d.ts
2
+ /** An entry of the history: its URL and its state. */
3
+ type HistoryEntry = {
4
+ url: string;
5
+ state: unknown;
6
+ };
7
+ /**
8
+ * Keeps the properties `keys` of `target`, the document or one of its
9
+ * elements, as the pages are left, until it is called again: the marks of
10
+ * React DOM on the root of an app that renders the pages after its first
11
+ * (`renderAgain()` in client.tsx). Without `keys` they are no longer kept,
12
+ * and the app that kept them removes them.
13
+ */
14
+ declare function keepProperties(target: object, keys?: Iterable<PropertyKey>): void;
15
+ /**
16
+ * The URL of the document without the page that is open: the runner's, which
17
+ * the page shows as its own while it is open.
18
+ */
19
+ declare function documentUrl(): string;
20
+ /**
21
+ * Starts the files of the route of the page that loads next, as the server
22
+ * renders it: `stylesheets` as Next links them, in the CORS mode of
23
+ * `crossOrigin`, and `modules`. By their URLs. They go with that page.
24
+ */
25
+ declare function preloadPage({
26
+ stylesheets,
27
+ crossOrigin,
28
+ modules
29
+ }: {
30
+ stylesheets: string[];
31
+ crossOrigin: string | undefined;
32
+ modules: string[];
33
+ }): void;
34
+ /**
35
+ * Replaces the page in this document with the one the server sent as `html`:
36
+ * its `<head>` first, the rest once the stylesheets of the `<head>` have
37
+ * loaded, and runs its inline scripts in document order once the stylesheets
38
+ * of the rest have too. Resolves then, and without running them for a page
39
+ * that was left in the meantime.
40
+ *
41
+ * The page is there in full before the app starts, so the document has loaded
42
+ * by the time Next's client looks: it reads the Flight payload that Next's
43
+ * inline scripts left in `self.__next_f`, and hydrates.
44
+ *
45
+ * With a `container`, the page is the one of a node, which renders no
46
+ * `<html>` or `<body>`, and what is in the document stays the test's. What
47
+ * the HTML parser puts in `<body>` goes in the container: the node, with the
48
+ * scripts it renders, and after it the scripts of Next and React.
49
+ *
50
+ * The page takes the entry of the history that the document is at, or with
51
+ * `after` gets one of its own, after that entry. With `inKeptApp`, leaving
52
+ * the page leaves what the app added to the `<head>`: see `unloadKeptApp()`.
53
+ * React's inline scripts get timers of the page's own, which leaving the
54
+ * page clears.
55
+ *
56
+ * Returns what takes React DOM's properties off the nodes of this page,
57
+ * before its root unmounts: React takes the nodes out of the document as it
58
+ * does, and leaves its fiber on a text node. A node that outlives the page
59
+ * then keeps no fiber of it: the one that an assertion of the test holds
60
+ * until it ends, or the one under the pointer. Once the page is left, it
61
+ * does nothing: leaving took them off already. Nothing for a page of a kept
62
+ * app, whose root outlives the page.
63
+ */
64
+ declare function loadDocument(html: string, url: string, container?: Element, after?: HistoryEntry, inKeptApp?: boolean): Promise<() => void>;
65
+ /** `self.$RC` of a page. */
66
+ declare const streamedContentQueue: PropertyDescriptor;
67
+ /**
68
+ * Takes back what the code of the kept app added to the `<head>` as its pages
69
+ * were open, once the app is left: see `loadDocument()`. With `withGlobals`,
70
+ * also the globals of Next and React on `window` that point into it.
71
+ */
72
+ declare function unloadKeptApp(withGlobals?: boolean): void;
73
+ /**
74
+ * Leaves the page, and the one that was loading: the document is as it was
75
+ * before the page, but for what a kept app keeps (`unloadKeptApp()`).
76
+ */
77
+ declare function unloadDocument(): void;
78
+ //#endregion
79
+ export { HistoryEntry, documentUrl, keepProperties, loadDocument, preloadPage, streamedContentQueue, unloadDocument, unloadKeptApp };