@kasperpeulen/vitest-plugin-nextjs 0.0.0-stage → 0.1.0-alpha.1

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 (256) 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 +39 -0
  64. package/dist/compile.js +175 -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 +330 -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/host-return-shared.d.ts +5 -0
  89. package/dist/host-return-shared.js +5 -0
  90. package/dist/host-return.d.ts +5 -0
  91. package/dist/host-return.js +16 -0
  92. package/dist/index.d.ts +280 -0
  93. package/dist/index.js +281 -0
  94. package/dist/internal.d.ts +2 -0
  95. package/dist/internal.js +3 -0
  96. package/dist/leftovers.d.ts +11 -0
  97. package/dist/leftovers.js +55 -0
  98. package/dist/mode.d.ts +169 -0
  99. package/dist/mode.js +31 -0
  100. package/dist/node/LICENSES.md +3540 -0
  101. package/dist/node/assert/strict.js +29 -0
  102. package/dist/node/assert.js +3044 -0
  103. package/dist/node/buffer.js +1499 -0
  104. package/dist/node/child_process.js +45 -0
  105. package/dist/node/cluster.js +85 -0
  106. package/dist/node/console.js +96 -0
  107. package/dist/node/constants.js +495 -0
  108. package/dist/node/crypto.js +1388 -0
  109. package/dist/node/dgram.js +78 -0
  110. package/dist/node/diagnostics_channel.js +122 -0
  111. package/dist/node/dns/promises.js +129 -0
  112. package/dist/node/dns.js +137 -0
  113. package/dist/node/domain.js +43 -0
  114. package/dist/node/events.js +1155 -0
  115. package/dist/node/fs/promises.js +40 -0
  116. package/dist/node/fs.js +10375 -0
  117. package/dist/node/http.js +326 -0
  118. package/dist/node/http2.js +305 -0
  119. package/dist/node/https.js +57 -0
  120. package/dist/node/inspector/promises.js +66 -0
  121. package/dist/node/inspector.js +76 -0
  122. package/dist/node/module.js +205 -0
  123. package/dist/node/net.js +392 -0
  124. package/dist/node/os.js +259 -0
  125. package/dist/node/path/posix.js +25 -0
  126. package/dist/node/path/win32.js +25 -0
  127. package/dist/node/path.js +384 -0
  128. package/dist/node/perf_hooks.js +313 -0
  129. package/dist/node/process.js +452 -0
  130. package/dist/node/punycode.js +178 -0
  131. package/dist/node/querystring.js +934 -0
  132. package/dist/node/readline/promises.js +71 -0
  133. package/dist/node/readline.js +56 -0
  134. package/dist/node/repl.js +44 -0
  135. package/dist/node/sqlite.js +22 -0
  136. package/dist/node/stream/consumers.js +47 -0
  137. package/dist/node/stream/promises.js +6 -0
  138. package/dist/node/stream/web.js +52 -0
  139. package/dist/node/stream.js +4323 -0
  140. package/dist/node/string_decoder.js +276 -0
  141. package/dist/node/sys.js +6 -0
  142. package/dist/node/timers/promises.js +71 -0
  143. package/dist/node/timers.js +133 -0
  144. package/dist/node/tls.js +122 -0
  145. package/dist/node/trace_events.js +23 -0
  146. package/dist/node/tty.js +69 -0
  147. package/dist/node/url.js +1426 -0
  148. package/dist/node/util/types.js +1456 -0
  149. package/dist/node/util.js +4807 -0
  150. package/dist/node/v8.js +160 -0
  151. package/dist/node/vm.js +88 -0
  152. package/dist/node/wasi.js +16 -0
  153. package/dist/node/worker_threads.js +123 -0
  154. package/dist/node/zlib.js +1396 -0
  155. package/dist/node-builtins.d.ts +40 -0
  156. package/dist/node-builtins.js +74 -0
  157. package/dist/node-on-page.d.ts +46 -0
  158. package/dist/node-on-page.js +101 -0
  159. package/dist/node-platform.d.ts +36 -0
  160. package/dist/node-platform.js +152 -0
  161. package/dist/node-rendered.d.ts +21 -0
  162. package/dist/node-rendered.js +26 -0
  163. package/dist/node-server.d.ts +46 -0
  164. package/dist/node-server.js +193 -0
  165. package/dist/not-found-page.d.ts +19 -0
  166. package/dist/not-found-page.js +74 -0
  167. package/dist/optimizer-cache-key.d.ts +26 -0
  168. package/dist/optimizer-cache-key.js +73 -0
  169. package/dist/own-package.d.ts +1 -0
  170. package/dist/own-package.js +6 -0
  171. package/dist/page-store.d.ts +33 -0
  172. package/dist/page-store.js +80 -0
  173. package/dist/page-timers.d.ts +22 -0
  174. package/dist/page-timers.js +47 -0
  175. package/dist/page.d.ts +112 -0
  176. package/dist/page.js +549 -0
  177. package/dist/paths.d.ts +13 -0
  178. package/dist/paths.js +47 -0
  179. package/dist/plugin.d.ts +23 -0
  180. package/dist/plugin.js +1006 -0
  181. package/dist/prerender-verdict.d.ts +8 -0
  182. package/dist/prerender-verdict.js +67 -0
  183. package/dist/project/context.d.ts +546 -0
  184. package/dist/project/context.js +111 -0
  185. package/dist/project/entries.d.ts +42 -0
  186. package/dist/project/entries.js +189 -0
  187. package/dist/project/env-worker.d.ts +1 -0
  188. package/dist/project/env-worker.js +9 -0
  189. package/dist/project/env.d.ts +36 -0
  190. package/dist/project/env.js +82 -0
  191. package/dist/project/layers.d.ts +31 -0
  192. package/dist/project/layers.js +150 -0
  193. package/dist/project/loaders.d.ts +71 -0
  194. package/dist/project/loaders.js +300 -0
  195. package/dist/project/metadata.d.ts +8 -0
  196. package/dist/project/metadata.js +34 -0
  197. package/dist/project/module-exports.d.ts +29 -0
  198. package/dist/project/module-exports.js +77 -0
  199. package/dist/project/routes.d.ts +19 -0
  200. package/dist/project/routes.js +92 -0
  201. package/dist/project/routing.d.ts +46 -0
  202. package/dist/project/routing.js +280 -0
  203. package/dist/project/transform.d.ts +8 -0
  204. package/dist/project/transform.js +110 -0
  205. package/dist/project/webpack.d.ts +65 -0
  206. package/dist/project/webpack.js +191 -0
  207. package/dist/project.d.ts +269 -0
  208. package/dist/project.js +58 -0
  209. package/dist/registry-global.d.ts +5 -0
  210. package/dist/registry-global.js +5 -0
  211. package/dist/registry.d.ts +241 -0
  212. package/dist/registry.js +30 -0
  213. package/dist/route-chunks.d.ts +13 -0
  214. package/dist/route-chunks.js +32 -0
  215. package/dist/route-lookup.d.ts +34 -0
  216. package/dist/route-lookup.js +207 -0
  217. package/dist/routes-ahead-shared.d.ts +17 -0
  218. package/dist/routes-ahead-shared.js +9 -0
  219. package/dist/routes-ahead.d.ts +10 -0
  220. package/dist/routes-ahead.js +54 -0
  221. package/dist/rsc.d.ts +19 -0
  222. package/dist/rsc.js +171 -0
  223. package/dist/server-action.d.ts +9 -0
  224. package/dist/server-action.js +15 -0
  225. package/dist/server-code.d.ts +176 -0
  226. package/dist/server-code.js +357 -0
  227. package/dist/server-in-front.d.ts +37 -0
  228. package/dist/server-in-front.js +90 -0
  229. package/dist/server-layers.d.ts +22 -0
  230. package/dist/server-layers.js +33 -0
  231. package/dist/setup-browser.d.ts +1 -0
  232. package/dist/setup-browser.js +8 -0
  233. package/dist/setup-node.d.ts +1 -0
  234. package/dist/setup-node.js +6 -0
  235. package/dist/setup.d.ts +8 -0
  236. package/dist/setup.js +62 -0
  237. package/dist/speed-features.d.ts +13 -0
  238. package/dist/speed-features.js +95 -0
  239. package/dist/ssr.d.ts +70 -0
  240. package/dist/ssr.js +480 -0
  241. package/dist/static-build.d.ts +36 -0
  242. package/dist/static-build.js +92 -0
  243. package/dist/storage.d.ts +31 -0
  244. package/dist/storage.js +94 -0
  245. package/dist/styles-shared.d.ts +137 -0
  246. package/dist/styles-shared.js +124 -0
  247. package/dist/styles.d.ts +102 -0
  248. package/dist/styles.js +730 -0
  249. package/dist/stylesheet-versions.d.ts +17 -0
  250. package/dist/stylesheet-versions.js +43 -0
  251. package/dist/tester.html +10 -0
  252. package/dist/use-cache.d.ts +15 -0
  253. package/dist/use-cache.js +93 -0
  254. package/dist/vitest-version.d.ts +6 -0
  255. package/dist/vitest-version.js +12 -0
  256. package/package.json +125 -3
@@ -0,0 +1,20 @@
1
+ //#region src/fast-crypto.d.ts
2
+ /** The file of the stand-ins, which the modules below import. */
3
+ declare function fastCryptoFile(): string;
4
+ /**
5
+ * The name of the stand-in module for an import of a server layer, if it has
6
+ * one: a package that hashes passwords, or `node:crypto`, whose module is the
7
+ * layer's own with the stand-ins in it, `nodeCrypto`.
8
+ */
9
+ declare function fastCryptoModuleOf(source: string): string | undefined;
10
+ /**
11
+ * The code of a stand-in module by its name: for `node-crypto`, the layer's
12
+ * `node:crypto`, `nodeCrypto`, with its `pbkdf2`, `scrypt` and `argon2` the
13
+ * stand-ins. That is the file of the package's module in a browser, and
14
+ * Node's own in a worker of Node.js (node-builtins.ts).
15
+ */
16
+ declare function fastCryptoModule(name: string, nodeCrypto: string): string | undefined;
17
+ /** The module of the setup file: Web Crypto's PBKDF2 a stand-in, or nothing. */
18
+ declare function fastCryptoSetup(enabled: boolean): string;
19
+ //#endregion
20
+ export { fastCryptoFile, fastCryptoModule, fastCryptoModuleOf, fastCryptoSetup };
@@ -0,0 +1,151 @@
1
+ import { isBuiltin } from "node:module";
2
+ import { normalizePath } from "vite";
3
+ import path from "node:path";
4
+ import fs from "node:fs";
5
+ import { fileURLToPath } from "node:url";
6
+ //#region src/fast-crypto.ts
7
+ const ownFile = fileURLToPath(import.meta.url);
8
+ const standInsFile = normalizePath(path.join(path.dirname(ownFile), path.extname(ownFile) === ".ts" ? "../dist/fast-crypto/index.js" : "./fast-crypto/index.js"));
9
+ /** The file of the stand-ins, which the modules below import. */
10
+ function fastCryptoFile() {
11
+ if (!fs.existsSync(standInsFile)) throw new Error(`vitest-plugin-rsc: no ${standInsFile}, the package is not built: run \`pnpm build\``);
12
+ return standInsFile;
13
+ }
14
+ const packages = {
15
+ bcryptjs: {
16
+ factory: `bcrypt("bcryptjs")`,
17
+ names: [
18
+ "genSaltSync",
19
+ "genSalt",
20
+ "hashSync",
21
+ "hash",
22
+ "compareSync",
23
+ "compare",
24
+ "getRounds",
25
+ "getSalt",
26
+ "truncates",
27
+ "encodeBase64",
28
+ "decodeBase64",
29
+ "setRandomFallback"
30
+ ],
31
+ specifiers: ["bcryptjs"]
32
+ },
33
+ bcrypt: {
34
+ factory: `bcrypt("bcrypt")`,
35
+ names: [
36
+ "genSaltSync",
37
+ "genSalt",
38
+ "hashSync",
39
+ "hash",
40
+ "compareSync",
41
+ "compare",
42
+ "getRounds"
43
+ ],
44
+ specifiers: ["bcrypt"]
45
+ },
46
+ "node-rs-bcrypt": {
47
+ factory: "nodeRsBcrypt()",
48
+ names: [
49
+ "DEFAULT_COST",
50
+ "genSaltSync",
51
+ "genSalt",
52
+ "hashSync",
53
+ "hash",
54
+ "verifySync",
55
+ "verify",
56
+ "compareSync",
57
+ "compare"
58
+ ],
59
+ specifiers: ["@node-rs/bcrypt"]
60
+ },
61
+ argon2: {
62
+ factory: "argon2()",
63
+ names: [
64
+ "argon2d",
65
+ "argon2i",
66
+ "argon2id",
67
+ "hash",
68
+ "verify",
69
+ "needsRehash"
70
+ ],
71
+ specifiers: ["argon2"]
72
+ },
73
+ "node-rs-argon2": {
74
+ factory: "nodeRsArgon2()",
75
+ names: [
76
+ "Algorithm",
77
+ "Version",
78
+ "hash",
79
+ "hashSync",
80
+ "hashRaw",
81
+ "hashRawSync",
82
+ "verify",
83
+ "verifySync"
84
+ ],
85
+ specifiers: ["@node-rs/argon2"]
86
+ },
87
+ "noble-scrypt": {
88
+ factory: "nobleScrypt()",
89
+ names: ["scrypt", "scryptAsync"],
90
+ specifiers: ["@noble/hashes/scrypt", "@noble/hashes/scrypt.js"]
91
+ },
92
+ "noble-pbkdf2": {
93
+ factory: "noblePbkdf2()",
94
+ names: ["pbkdf2", "pbkdf2Async"],
95
+ specifiers: ["@noble/hashes/pbkdf2", "@noble/hashes/pbkdf2.js"]
96
+ },
97
+ "noble-argon2": {
98
+ factory: "nobleArgon2()",
99
+ names: [
100
+ "argon2d",
101
+ "argon2i",
102
+ "argon2id",
103
+ "argon2dAsync",
104
+ "argon2iAsync",
105
+ "argon2idAsync"
106
+ ],
107
+ specifiers: ["@noble/hashes/argon2", "@noble/hashes/argon2.js"]
108
+ }
109
+ };
110
+ const moduleOfSpecifier = new Map(Object.entries(packages).flatMap(([name, { specifiers }]) => specifiers.map((specifier) => [specifier, name])));
111
+ /**
112
+ * The name of the stand-in module for an import of a server layer, if it has
113
+ * one: a package that hashes passwords, or `node:crypto`, whose module is the
114
+ * layer's own with the stand-ins in it, `nodeCrypto`.
115
+ */
116
+ function fastCryptoModuleOf(source) {
117
+ if (source === "crypto" || source === "node:crypto") return "node-crypto";
118
+ return moduleOfSpecifier.get(source);
119
+ }
120
+ /**
121
+ * The code of a stand-in module by its name: for `node-crypto`, the layer's
122
+ * `node:crypto`, `nodeCrypto`, with its `pbkdf2`, `scrypt` and `argon2` the
123
+ * stand-ins. That is the file of the package's module in a browser, and
124
+ * Node's own in a worker of Node.js (node-builtins.ts).
125
+ */
126
+ function fastCryptoModule(name, nodeCrypto) {
127
+ const from = JSON.stringify(fastCryptoFile());
128
+ if (name === "node-crypto") {
129
+ const own = JSON.stringify(nodeCrypto);
130
+ const names = [
131
+ "pbkdf2",
132
+ "pbkdf2Sync",
133
+ "scrypt",
134
+ "scryptSync",
135
+ "argon2",
136
+ "argon2Sync"
137
+ ];
138
+ const reexports = isBuiltin(nodeCrypto) ? `export const { ${Object.keys(process.getBuiltinModule("node:crypto")).filter((key) => /^[A-Za-z_$][\w$]*$/.test(key) && !names.includes(key)).join(", ")} } = own;\n` : `export * from ${own};\n`;
139
+ return `import own from ${own};\nimport { Buffer } from "node:buffer";\nimport { nodeCrypto } from ${from};\n` + reexports + `const fast = nodeCrypto(Buffer);\nexport const { ${names.join(", ")} } = fast;\nexport default { ...own, ...fast };\n`;
140
+ }
141
+ const standIn = packages[name];
142
+ if (!standIn) return;
143
+ return `import { ${standIn.factory.replace(/\(.*$/, "")} } from ${from};\nconst standIns = ${standIn.factory};\nexport const { ${standIn.names.join(", ")} } = standIns;\nexport default standIns;\n`;
144
+ }
145
+ /** The module of the setup file: Web Crypto's PBKDF2 a stand-in, or nothing. */
146
+ function fastCryptoSetup(enabled) {
147
+ if (!enabled) return "export {};\n";
148
+ return `import { installWebCrypto } from ${JSON.stringify(fastCryptoFile())};\ninstallWebCrypto();\n`;
149
+ }
150
+ //#endregion
151
+ export { fastCryptoFile, fastCryptoModule, fastCryptoModuleOf, fastCryptoSetup };
@@ -0,0 +1,19 @@
1
+ //#region src/flight.d.ts
2
+ declare const rscFlightCodec: {
3
+ readonly server: readonly ["renderToReadableStream", "decodeReply", "decodeReplyFromAsyncIterable", "decodeAction", "decodeFormState", "createTemporaryReferenceSet", "registerServerReference", "registerClientReference", "createClientModuleProxy"];
4
+ readonly static: readonly ["prerender"];
5
+ readonly client: readonly ["createFromReadableStream", "encodeReply", "createTemporaryReferenceSet"];
6
+ };
7
+ type FlightEntry = keyof typeof rscFlightCodec;
8
+ /** The adapters of one entry: a function for each of its exports. */
9
+ type FlightAdapters<Entry extends FlightEntry> = Record<(typeof rscFlightCodec)[Entry][number], (...args: any[]) => unknown>;
10
+ /**
11
+ * The module that the rsc layer gets for an entry of Next's codec. It has
12
+ * every export of the entry, as the installed `next` has it, and forwards it
13
+ * to the adapter that rsc.ts puts in `registry`. The lookup is deferred to
14
+ * the call, so a pre-bundled chunk can load before rsc.ts has. An export
15
+ * without an adapter throws when it is called.
16
+ */
17
+ declare function flightBridge(entry: FlightEntry, exports: string[], nextVersion: string, registry: string): string;
18
+ //#endregion
19
+ export { FlightAdapters, FlightEntry, flightBridge, rscFlightCodec };
package/dist/flight.js ADDED
@@ -0,0 +1,42 @@
1
+ //#region src/flight.ts
2
+ const rscFlightCodec = {
3
+ server: [
4
+ "renderToReadableStream",
5
+ "decodeReply",
6
+ "decodeReplyFromAsyncIterable",
7
+ "decodeAction",
8
+ "decodeFormState",
9
+ "createTemporaryReferenceSet",
10
+ "registerServerReference",
11
+ "registerClientReference",
12
+ "createClientModuleProxy"
13
+ ],
14
+ static: ["prerender"],
15
+ client: [
16
+ "createFromReadableStream",
17
+ "encodeReply",
18
+ "createTemporaryReferenceSet"
19
+ ]
20
+ };
21
+ const owners = {
22
+ server: "flightServer",
23
+ static: "flightStatic",
24
+ client: "flightClient"
25
+ };
26
+ /**
27
+ * The module that the rsc layer gets for an entry of Next's codec. It has
28
+ * every export of the entry, as the installed `next` has it, and forwards it
29
+ * to the adapter that rsc.ts puts in `registry`. The lookup is deferred to
30
+ * the call, so a pre-bundled chunk can load before rsc.ts has. An export
31
+ * without an adapter throws when it is called.
32
+ */
33
+ function flightBridge(entry, exports, nextVersion, registry) {
34
+ const adapted = rscFlightCodec[entry];
35
+ return exports.map((name) => {
36
+ if (adapted.includes(name)) return `export const ${name} = (...args) => ${registry}.${owners[entry]}.${name}(...args);`;
37
+ const message = `vitest-plugin-rsc: \`${name}\` of Next's Flight codec is not supported in the rsc layer (next@${nextVersion}).`;
38
+ return `export const ${name} = () => { throw new Error(${JSON.stringify(message)}); };`;
39
+ }).join("\n");
40
+ }
41
+ //#endregion
42
+ export { flightBridge, rscFlightCodec };
@@ -0,0 +1,15 @@
1
+ //#region src/form-submission.d.ts
2
+ /**
3
+ * The encoding of a submission whose navigation `source` is: the
4
+ * `formenctype` of the button that submits the form, or the `enctype` of the
5
+ * form, which `form.submit()` submits itself.
6
+ */
7
+ declare function enctypeOf(source: Element | null): string;
8
+ /**
9
+ * The body of a form with the entries of `formData`, in the encoding
10
+ * `enctype`. A `Blob` with the type as a browser sends it, without a charset:
11
+ * Next's server tells a form from a Server Action by the exact type.
12
+ */
13
+ declare function formBody(formData: FormData, enctype: string): FormData | Blob;
14
+ //#endregion
15
+ export { enctypeOf, formBody };
@@ -0,0 +1,27 @@
1
+ //#region src/form-submission.ts
2
+ /**
3
+ * The encoding of a submission whose navigation `source` is: the
4
+ * `formenctype` of the button that submits the form, or the `enctype` of the
5
+ * form, which `form.submit()` submits itself.
6
+ */
7
+ function enctypeOf(source) {
8
+ if (source instanceof HTMLFormElement) return source.enctype;
9
+ if (source instanceof HTMLButtonElement || source instanceof HTMLInputElement) {
10
+ if (source.hasAttribute("formenctype")) return source.formEnctype;
11
+ if (source.form) return source.form.enctype;
12
+ }
13
+ return "application/x-www-form-urlencoded";
14
+ }
15
+ /**
16
+ * The body of a form with the entries of `formData`, in the encoding
17
+ * `enctype`. A `Blob` with the type as a browser sends it, without a charset:
18
+ * Next's server tells a form from a Server Action by the exact type.
19
+ */
20
+ function formBody(formData, enctype) {
21
+ if (enctype === "multipart/form-data") return formData;
22
+ const entries = Array.from(formData, ([name, value]) => [name, typeof value === "string" ? value : value.name]);
23
+ if (enctype === "text/plain") return new Blob([entries.map(([name, value]) => `${name}=${value}\r\n`).join("")], { type: "text/plain" });
24
+ return new Blob([String(new URLSearchParams(entries))], { type: "application/x-www-form-urlencoded" });
25
+ }
26
+ //#endregion
27
+ export { enctypeOf, formBody };
@@ -0,0 +1,5 @@
1
+ //#region src/from-page.d.ts
2
+ /** `input` and `init` of a request of the page, as the server's `Request` takes them. */
3
+ declare function fromPage(input: RequestInfo | URL, init?: RequestInit): [RequestInfo | URL, RequestInit | undefined];
4
+ //#endregion
5
+ export { fromPage };
@@ -0,0 +1,44 @@
1
+ //#region src/from-page.ts
2
+ /** `input` and `init` of a request of the page, as the server's `Request` takes them. */
3
+ function fromPage(input, init) {
4
+ if (window.Request === globalThis.Request) return [input, init];
5
+ if (input instanceof window.Request) {
6
+ const { url, method, headers, body, signal, redirect, credentials } = input.body ? input.clone() : input;
7
+ init = {
8
+ method,
9
+ headers,
10
+ body,
11
+ signal,
12
+ redirect,
13
+ credentials,
14
+ ...init
15
+ };
16
+ input = url;
17
+ }
18
+ input = new URL(String(input), window.location.href);
19
+ if (!init) return [input, init];
20
+ const headers = new Headers(init.headers ? [...new window.Headers(init.headers)] : void 0);
21
+ let { body, signal } = init;
22
+ if (body instanceof window.FormData || body instanceof window.Blob) {
23
+ const read = new window.Response(body);
24
+ const type = read.headers.get("content-type");
25
+ if (type && !headers.has("content-type")) headers.set("content-type", type);
26
+ body = read.body;
27
+ }
28
+ if (signal && !(signal instanceof AbortSignal)) {
29
+ const controller = new AbortController();
30
+ const page = signal;
31
+ if (page.aborted) controller.abort(page.reason);
32
+ else page.addEventListener("abort", () => controller.abort(page.reason), { once: true });
33
+ signal = controller.signal;
34
+ }
35
+ return [input, {
36
+ ...init,
37
+ headers,
38
+ body,
39
+ signal,
40
+ ...body ? { duplex: "half" } : {}
41
+ }];
42
+ }
43
+ //#endregion
44
+ export { fromPage };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,197 @@
1
+ import { registry } from "./registry.js";
2
+ import { AsyncLocalStorage } from "node:async_hooks";
3
+ import { Buffer } from "node:buffer";
4
+ import env from "virtual:vitest-plugin-rsc/next-env";
5
+ import pageHost from "virtual:vitest-plugin-rsc/page-host";
6
+ import { SequentialAsyncLocalStorage, asyncFunctionHooks, enterAmbientScope } from "@kasperpeulen/vitest-plugin-rsc/internal/async-local-storage";
7
+ //#region src/globals.ts
8
+ const { Request: NativeRequest, Response: NativeResponse, Headers } = globalThis;
9
+ function headersOf(init, input) {
10
+ if (init?.headers) return new Headers(init.headers);
11
+ return new Headers(input instanceof NativeRequest ? input.headers : void 0);
12
+ }
13
+ var ServerRequest = class ServerRequest extends NativeRequest {
14
+ #headers;
15
+ constructor(input, init) {
16
+ const body = init?.body;
17
+ if (body && typeof body.on === "function" && typeof body.pipe === "function") init = {
18
+ ...init,
19
+ body: new ReadableStream({
20
+ start(controller) {
21
+ body.on("data", (chunk) => controller.enqueue(typeof chunk === "string" ? new TextEncoder().encode(chunk) : new Uint8Array(chunk)));
22
+ body.on("end", () => controller.close());
23
+ body.on("error", (error) => controller.error(error));
24
+ },
25
+ cancel: (reason) => body.destroy?.(reason)
26
+ })
27
+ };
28
+ super(input, init?.body ? {
29
+ duplex: "half",
30
+ ...init
31
+ } : init);
32
+ this.#headers = headersOf(init, input);
33
+ const contentType = super.headers.get("content-type");
34
+ if (contentType && !this.#headers.has("content-type")) this.#headers.set("content-type", contentType);
35
+ }
36
+ get headers() {
37
+ return this.#headers;
38
+ }
39
+ clone() {
40
+ return new ServerRequest(super.clone(), { headers: this.#headers });
41
+ }
42
+ static [Symbol.hasInstance](value) {
43
+ return Function.prototype[Symbol.hasInstance].call(this === ServerRequest ? NativeRequest : this, value);
44
+ }
45
+ };
46
+ var ServerResponse = class ServerResponse extends NativeResponse {
47
+ #headers;
48
+ constructor(body, init) {
49
+ super(body, init);
50
+ this.#headers = headersOf(init);
51
+ const contentType = super.headers.get("content-type");
52
+ if (contentType && !this.#headers.has("content-type")) this.#headers.set("content-type", contentType);
53
+ }
54
+ get headers() {
55
+ return this.#headers;
56
+ }
57
+ clone() {
58
+ const clone = super.clone();
59
+ return new ServerResponse(clone.body, {
60
+ status: clone.status,
61
+ statusText: clone.statusText,
62
+ headers: this.#headers
63
+ });
64
+ }
65
+ static json(data, init) {
66
+ const json = NativeResponse.json(data, init);
67
+ const headers = headersOf(init);
68
+ if (!headers.has("content-type")) headers.set("content-type", "application/json");
69
+ return new ServerResponse(json.body, {
70
+ status: json.status,
71
+ statusText: json.statusText,
72
+ headers
73
+ });
74
+ }
75
+ static [Symbol.hasInstance](value) {
76
+ return Function.prototype[Symbol.hasInstance].call(this === ServerResponse ? NativeResponse : this, value);
77
+ }
78
+ };
79
+ registry.Request = ServerRequest;
80
+ registry.Response = ServerResponse;
81
+ registry.Headers = Headers;
82
+ registry.serverDir = () => pageHost.serverDir;
83
+ registry.enterRequestScope = enterAmbientScope;
84
+ registry.openedByRequest = new SequentialAsyncLocalStorage();
85
+ registry.asyncFunctionHooks = asyncFunctionHooks;
86
+ const nativeQueueMicrotask = globalThis.queueMicrotask;
87
+ registry.queueMicrotask = (callback) => nativeQueueMicrotask(SequentialAsyncLocalStorage.bind(callback));
88
+ const renders = /* @__PURE__ */ new WeakMap();
89
+ registry.performWork = (request, performWork) => {
90
+ let inStores = renders.get(request);
91
+ if (!inStores) renders.set(request, inStores = SequentialAsyncLocalStorage.snapshot());
92
+ inStores(performWork, request);
93
+ };
94
+ registry.fetch = (input, init) => pageHost.serverFetch(input, init);
95
+ registry.network = (input, init) => pageHost.serverFetch(input, init);
96
+ const scope = globalThis;
97
+ scope.process ??= { env: {} };
98
+ scope.process.env ??= {};
99
+ for (const [name, value] of Object.entries(env)) scope.process.env[name] ??= value;
100
+ scope.global ??= scope;
101
+ scope.global.process ??= scope.process;
102
+ scope.Buffer ??= Buffer;
103
+ const takesUint8Array = (() => {
104
+ try {
105
+ return Buffer.from([0, 1]).indexOf(new Uint8Array([1])) === 1;
106
+ } catch {
107
+ return false;
108
+ }
109
+ })();
110
+ for (const method of takesUint8Array ? [] : ["indexOf", "lastIndexOf"]) {
111
+ const original = Buffer.prototype[method];
112
+ Buffer.prototype[method] = function(value, ...rest) {
113
+ if (value instanceof Uint8Array && !Buffer.isBuffer(value)) value = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
114
+ return original.call(this, value, ...rest);
115
+ };
116
+ }
117
+ if (!Buffer.isEncoding("base64url")) {
118
+ const isBase64url = (encoding) => typeof encoding === "string" && encoding.toLowerCase() === "base64url";
119
+ const base64 = (text) => text.replaceAll("-", "+").replaceAll("_", "/");
120
+ const base64url = (text) => text.replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
121
+ const statics = Buffer;
122
+ const { from, byteLength, isEncoding } = statics;
123
+ statics.from = function(value, encoding, ...rest) {
124
+ return isBase64url(encoding) && typeof value === "string" ? from.call(this, base64(value), "base64") : from.call(this, value, encoding, ...rest);
125
+ };
126
+ statics.byteLength = function(value, encoding) {
127
+ return isBase64url(encoding) && typeof value === "string" ? byteLength.call(this, base64(value), "base64") : byteLength.call(this, value, encoding);
128
+ };
129
+ statics.isEncoding = (encoding) => isBase64url(encoding) || isEncoding.call(Buffer, encoding);
130
+ const prototype = Buffer.prototype;
131
+ const toString = prototype.toString;
132
+ const write = prototype.write;
133
+ prototype.toString = function(encoding, ...rest) {
134
+ return isBase64url(encoding) ? base64url(toString.apply(this, ["base64", ...rest])) : toString.apply(this, [encoding, ...rest]);
135
+ };
136
+ prototype.write = function(text, ...rest) {
137
+ const at = rest.findLastIndex((value) => typeof value === "string");
138
+ if (at === -1 || !isBase64url(rest[at])) return write.apply(this, [text, ...rest]);
139
+ const args = [...rest];
140
+ args[at] = "base64";
141
+ return write.apply(this, [base64(text), ...args]);
142
+ };
143
+ }
144
+ scope.AsyncLocalStorage ??= AsyncLocalStorage;
145
+ const immediates = /* @__PURE__ */ new Map();
146
+ function immediate(callback, args) {
147
+ const id = Symbol("immediate");
148
+ const cancel = pageHost.serverImmediate(() => {
149
+ immediates.delete(id);
150
+ callback(...args);
151
+ });
152
+ immediates.set(id, cancel);
153
+ return id;
154
+ }
155
+ function clearImmediateOf(id) {
156
+ immediates.get(id)?.();
157
+ return immediates.delete(id);
158
+ }
159
+ {
160
+ const { process } = scope;
161
+ process.cwd ??= () => "/";
162
+ process.on ??= () => process;
163
+ process.off ??= () => process;
164
+ process.nextTick ??= (callback, ...args) => queueMicrotask(() => callback(...args));
165
+ process.hrtime ??= Object.assign(() => [0, 0], { bigint: () => BigInt(Math.round(performance.now() * 1e6)) });
166
+ const nativeSetTimeout = globalThis.setTimeout;
167
+ const nativeClearTimeout = globalThis.clearTimeout;
168
+ registry.setImmediate = (callback, ...args) => pageHost.immediatesOfRuntime || registry.speedFeatures?.immediates ? immediate(callback, args) : nativeSetTimeout(callback, 0, ...args);
169
+ registry.clearImmediate = (id) => typeof id === "symbol" ? clearImmediateOf(id) : nativeClearTimeout(id);
170
+ registry.setTimeout = (callback, delay, ...args) => registry.speedFeatures?.immediates && !(Number(delay) > 0) && typeof callback === "function" && globalThis.setTimeout === nativeSetTimeout ? immediate(callback, args) : globalThis.setTimeout(callback, delay, ...args);
171
+ registry.clearTimeout = (id) => typeof id === "symbol" ? clearImmediateOf(id) : globalThis.clearTimeout(id);
172
+ const latin1 = (bytes) => {
173
+ let text = "";
174
+ for (let at = 0; at < bytes.length; at += 8192) text += String.fromCharCode(...bytes.subarray(at, at + 8192));
175
+ return text;
176
+ };
177
+ const utf8 = new TextDecoder("utf-8");
178
+ const ucs2 = new TextDecoder("utf-16le");
179
+ const decoders = {
180
+ latin1,
181
+ ascii: latin1,
182
+ utf8: (bytes) => utf8.decode(bytes),
183
+ ucs2: (bytes) => ucs2.decode(bytes)
184
+ };
185
+ for (const [encoding, decode] of Object.entries(decoders)) {
186
+ if (`${encoding}Slice` in Uint8Array.prototype) continue;
187
+ Object.defineProperty(Uint8Array.prototype, `${encoding}Slice`, {
188
+ configurable: true,
189
+ writable: true,
190
+ value(start, end) {
191
+ return decode(this.subarray(start, end));
192
+ }
193
+ });
194
+ }
195
+ }
196
+ //#endregion
197
+ export {};
@@ -0,0 +1,26 @@
1
+ //#region src/host-document.d.ts
2
+ type NavigateEvent = Event & {
3
+ navigationType: "push" | "replace" | "reload" | "traverse";
4
+ destination: {
5
+ url: string;
6
+ sameDocument: boolean;
7
+ };
8
+ hashChange: boolean;
9
+ formData: FormData | null;
10
+ downloadRequest: string | null;
11
+ sourceElement: Element | null;
12
+ };
13
+ /** Says whether a browser context of the app is open: browser-context.ts does. */
14
+ declare function appHasNavigations(open: boolean): void;
15
+ /**
16
+ * Keeps the host's document while the host renders components outside a
17
+ * browser context of the app: a link or a form that would load another
18
+ * document is stopped, and `report` hears of it with the URL it would load.
19
+ * By default `reportError()` gets an error that says why. A declared
20
+ * download, like `<a download>`, is the browser's, and while a context is
21
+ * open, the app has the navigations. Until the function it returns is
22
+ * called.
23
+ */
24
+ declare function keepHostDocument(report?: (url: URL) => void): () => void;
25
+ //#endregion
26
+ export { NavigateEvent, appHasNavigations, keepHostDocument };
@@ -0,0 +1,34 @@
1
+ import pageHost from "virtual:vitest-plugin-rsc/page-host";
2
+ //#region src/host-document.ts
3
+ let inContext = false;
4
+ /** Says whether a browser context of the app is open: browser-context.ts does. */
5
+ function appHasNavigations(open) {
6
+ inContext = open;
7
+ }
8
+ /**
9
+ * Keeps the host's document while the host renders components outside a
10
+ * browser context of the app: a link or a form that would load another
11
+ * document is stopped, and `report` hears of it with the URL it would load.
12
+ * By default `reportError()` gets an error that says why. A declared
13
+ * download, like `<a download>`, is the browser's, and while a context is
14
+ * open, the app has the navigations. Until the function it returns is
15
+ * called.
16
+ */
17
+ function keepHostDocument(report = reportLoad) {
18
+ const { navigation } = pageHost;
19
+ const keep = (event) => {
20
+ if (inContext || event.defaultPrevented) return;
21
+ const { destination, hashChange, downloadRequest } = event;
22
+ if (destination.sameDocument || hashChange || !event.cancelable) return;
23
+ if (downloadRequest !== null || destination.url === window.location.href) return;
24
+ event.preventDefault();
25
+ report(new URL(destination.url));
26
+ };
27
+ navigation?.addEventListener("navigate", keep);
28
+ return () => navigation?.removeEventListener("navigate", keep);
29
+ }
30
+ function reportLoad(url) {
31
+ reportError(/* @__PURE__ */ new Error(`vitest-plugin-rsc: a link or a form navigated to ${url.href}, which would load another document in place of the host's. The host renders it outside a browser context of the app, where there is no router of Next's: the host's document stays.`));
32
+ }
33
+ //#endregion
34
+ export { appHasNavigations, keepHostDocument };
@@ -0,0 +1,5 @@
1
+ //#region src/host-return-shared.d.ts
2
+ declare const hostKey = "vitest-plugin-rsc:host";
3
+ declare const topLevelHostKey = "vitest-plugin-rsc:host-top-level";
4
+ //#endregion
5
+ export { hostKey, topLevelHostKey };
@@ -0,0 +1,5 @@
1
+ //#region src/host-return-shared.ts
2
+ const hostKey = "vitest-plugin-rsc:host";
3
+ const topLevelHostKey = "vitest-plugin-rsc:host-top-level";
4
+ //#endregion
5
+ export { hostKey, topLevelHostKey };
@@ -0,0 +1,5 @@
1
+ //#region src/host-return.d.ts
2
+ /** Keeps `url`, the URL of the host's document, as the one a page that opens now goes back to. */
3
+ declare function rememberHost(url: string): void;
4
+ //#endregion
5
+ export { rememberHost };
@@ -0,0 +1,16 @@
1
+ import { buildDirectory } from "./built-files.js";
2
+ import { hostKey, topLevelHostKey } from "./host-return-shared.js";
3
+ //#region src/host-return.ts
4
+ const ownStorages = ["sessionStorage", "localStorage"].map((name) => Object.getOwnPropertyDescriptor(window, name)?.get);
5
+ /** Keeps `url`, the URL of the host's document, as the one a page that opens now goes back to. */
6
+ function rememberHost(url) {
7
+ if (!buildDirectory) return;
8
+ const [session, local] = ownStorages.map((get) => get?.call(window));
9
+ try {
10
+ session?.setItem(hostKey, url);
11
+ session?.setItem(topLevelHostKey, window.top === window ? "1" : "0");
12
+ local?.setItem(hostKey, url);
13
+ } catch {}
14
+ }
15
+ //#endregion
16
+ export { rememberHost };