@nifrajs/web 3.3.0 → 4.0.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 (407) hide show
  1. package/dist/backend-only.d.ts +15 -0
  2. package/dist/backend-only.d.ts.map +1 -0
  3. package/dist/backend-only.js +16 -0
  4. package/dist/backend-only.js.map +1 -0
  5. package/dist/boundary.d.ts +5 -0
  6. package/dist/boundary.d.ts.map +1 -1
  7. package/dist/boundary.js +11 -2
  8. package/dist/boundary.js.map +1 -1
  9. package/dist/build-plan.d.ts +35 -6
  10. package/dist/build-plan.d.ts.map +1 -1
  11. package/dist/build-plan.js +89 -35
  12. package/dist/build-plan.js.map +1 -1
  13. package/dist/build-vite.d.ts +18 -0
  14. package/dist/build-vite.d.ts.map +1 -1
  15. package/dist/build-vite.js +97 -17
  16. package/dist/build-vite.js.map +1 -1
  17. package/dist/build.d.ts +72 -23
  18. package/dist/build.d.ts.map +1 -1
  19. package/dist/build.js +411 -98
  20. package/dist/build.js.map +1 -1
  21. package/dist/bun-dev-entry.d.ts +1 -1
  22. package/dist/bun-dev-entry.js +1 -1
  23. package/dist/cdn.d.ts +74 -0
  24. package/dist/cdn.d.ts.map +1 -0
  25. package/dist/cdn.js +132 -0
  26. package/dist/cdn.js.map +1 -0
  27. package/dist/client.d.ts +21 -1
  28. package/dist/client.d.ts.map +1 -1
  29. package/dist/client.js +226 -15
  30. package/dist/client.js.map +1 -1
  31. package/dist/conformance.d.ts +4 -3
  32. package/dist/conformance.d.ts.map +1 -1
  33. package/dist/conformance.js +12 -3
  34. package/dist/conformance.js.map +1 -1
  35. package/dist/csp.d.ts +93 -0
  36. package/dist/csp.d.ts.map +1 -0
  37. package/dist/csp.js +122 -0
  38. package/dist/csp.js.map +1 -0
  39. package/dist/css-contract.d.ts +21 -0
  40. package/dist/css-contract.d.ts.map +1 -0
  41. package/dist/css-contract.js +28 -0
  42. package/dist/css-contract.js.map +1 -0
  43. package/dist/dev-client.d.ts +76 -0
  44. package/dist/dev-client.d.ts.map +1 -0
  45. package/dist/dev-client.js +280 -0
  46. package/dist/dev-client.js.map +1 -0
  47. package/dist/dev-diagnostics.d.ts +26 -2
  48. package/dist/dev-diagnostics.d.ts.map +1 -1
  49. package/dist/dev-diagnostics.js +38 -7
  50. package/dist/dev-diagnostics.js.map +1 -1
  51. package/dist/dev-error.d.ts +4 -13
  52. package/dist/dev-error.d.ts.map +1 -1
  53. package/dist/dev-error.js +46 -4
  54. package/dist/dev-error.js.map +1 -1
  55. package/dist/dev-feed.d.ts +298 -0
  56. package/dist/dev-feed.d.ts.map +1 -0
  57. package/dist/dev-feed.js +797 -0
  58. package/dist/dev-feed.js.map +1 -0
  59. package/dist/dev-indicator.d.ts +38 -0
  60. package/dist/dev-indicator.d.ts.map +1 -0
  61. package/dist/dev-indicator.js +93 -0
  62. package/dist/dev-indicator.js.map +1 -0
  63. package/dist/dev-session.d.ts +77 -0
  64. package/dist/dev-session.d.ts.map +1 -0
  65. package/dist/dev-session.js +580 -0
  66. package/dist/dev-session.js.map +1 -0
  67. package/dist/dev-sourcemap.d.ts +27 -0
  68. package/dist/dev-sourcemap.d.ts.map +1 -0
  69. package/dist/dev-sourcemap.js +235 -0
  70. package/dist/dev-sourcemap.js.map +1 -0
  71. package/dist/dev-ssr-graph.d.ts.map +1 -1
  72. package/dist/dev-ssr-graph.js +13 -5
  73. package/dist/dev-ssr-graph.js.map +1 -1
  74. package/dist/dev.d.ts +15 -2
  75. package/dist/dev.d.ts.map +1 -1
  76. package/dist/dev.js +69 -44
  77. package/dist/dev.js.map +1 -1
  78. package/dist/diagnostic-catalog.d.ts +35 -0
  79. package/dist/diagnostic-catalog.d.ts.map +1 -0
  80. package/dist/diagnostic-catalog.js +203 -0
  81. package/dist/diagnostic-catalog.js.map +1 -0
  82. package/dist/diagnostic-prompt.d.ts +49 -0
  83. package/dist/diagnostic-prompt.d.ts.map +1 -0
  84. package/dist/diagnostic-prompt.js +303 -0
  85. package/dist/diagnostic-prompt.js.map +1 -0
  86. package/dist/diagnostic.d.ts +17 -23
  87. package/dist/diagnostic.d.ts.map +1 -1
  88. package/dist/diagnostic.js +31 -39
  89. package/dist/diagnostic.js.map +1 -1
  90. package/dist/draft.d.ts.map +1 -1
  91. package/dist/draft.js +4 -1
  92. package/dist/draft.js.map +1 -1
  93. package/dist/fn.d.ts +5 -0
  94. package/dist/fn.d.ts.map +1 -1
  95. package/dist/fn.js +13 -3
  96. package/dist/fn.js.map +1 -1
  97. package/dist/fs.d.ts.map +1 -1
  98. package/dist/fs.js +4 -2
  99. package/dist/fs.js.map +1 -1
  100. package/dist/index.d.ts +15 -15
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +13 -12
  103. package/dist/index.js.map +1 -1
  104. package/dist/internal/cdn/cloudflare.d.ts +48 -0
  105. package/dist/internal/cdn/cloudflare.d.ts.map +1 -0
  106. package/dist/internal/cdn/cloudflare.js +94 -0
  107. package/dist/internal/cdn/cloudflare.js.map +1 -0
  108. package/dist/internal/cdn/core.d.ts +91 -0
  109. package/dist/internal/cdn/core.d.ts.map +1 -0
  110. package/dist/internal/cdn/core.js +220 -0
  111. package/dist/internal/cdn/core.js.map +1 -0
  112. package/dist/internal/cdn/fastly.d.ts +17 -0
  113. package/dist/internal/cdn/fastly.d.ts.map +1 -0
  114. package/dist/internal/cdn/fastly.js +43 -0
  115. package/dist/internal/cdn/fastly.js.map +1 -0
  116. package/dist/internal/cdn/vercel.d.ts +31 -0
  117. package/dist/internal/cdn/vercel.d.ts.map +1 -0
  118. package/dist/internal/cdn/vercel.js +56 -0
  119. package/dist/internal/cdn/vercel.js.map +1 -0
  120. package/dist/internal/code-unit-order.d.ts +4 -0
  121. package/dist/internal/code-unit-order.d.ts.map +1 -0
  122. package/dist/internal/code-unit-order.js +6 -0
  123. package/dist/internal/code-unit-order.js.map +1 -0
  124. package/dist/internal/codegen.d.ts +3 -0
  125. package/dist/internal/codegen.d.ts.map +1 -1
  126. package/dist/internal/codegen.js +151 -30
  127. package/dist/internal/codegen.js.map +1 -1
  128. package/dist/internal/dev-csp.d.ts +24 -0
  129. package/dist/internal/dev-csp.d.ts.map +1 -0
  130. package/dist/internal/dev-csp.js +160 -0
  131. package/dist/internal/dev-csp.js.map +1 -0
  132. package/dist/internal/dev-reserved.d.ts +25 -0
  133. package/dist/internal/dev-reserved.d.ts.map +1 -0
  134. package/dist/internal/dev-reserved.js +39 -0
  135. package/dist/internal/dev-reserved.js.map +1 -0
  136. package/dist/internal/html-spans.d.ts +10 -0
  137. package/dist/internal/html-spans.d.ts.map +1 -0
  138. package/dist/internal/html-spans.js +46 -0
  139. package/dist/internal/html-spans.js.map +1 -0
  140. package/dist/internal/loading-runtime.d.ts +44 -0
  141. package/dist/internal/loading-runtime.d.ts.map +1 -0
  142. package/dist/internal/loading-runtime.js +206 -0
  143. package/dist/internal/loading-runtime.js.map +1 -0
  144. package/dist/internal/matches-runtime.d.ts +8 -0
  145. package/dist/internal/matches-runtime.d.ts.map +1 -0
  146. package/dist/internal/matches-runtime.js +61 -0
  147. package/dist/internal/matches-runtime.js.map +1 -0
  148. package/dist/internal/mount-shadow.d.ts +36 -0
  149. package/dist/internal/mount-shadow.d.ts.map +1 -0
  150. package/dist/internal/mount-shadow.js +65 -0
  151. package/dist/internal/mount-shadow.js.map +1 -0
  152. package/dist/internal/node-builtins.d.ts +3 -0
  153. package/dist/internal/node-builtins.d.ts.map +1 -0
  154. package/dist/internal/node-builtins.js +79 -0
  155. package/dist/internal/node-builtins.js.map +1 -0
  156. package/dist/internal/output-guard.d.ts +65 -0
  157. package/dist/internal/output-guard.d.ts.map +1 -0
  158. package/dist/internal/output-guard.js +630 -0
  159. package/dist/internal/output-guard.js.map +1 -0
  160. package/dist/internal/page-execution.d.ts +69 -0
  161. package/dist/internal/page-execution.d.ts.map +1 -0
  162. package/dist/internal/page-execution.js +1021 -0
  163. package/dist/internal/page-execution.js.map +1 -0
  164. package/dist/internal/parity.d.ts +21 -0
  165. package/dist/internal/parity.d.ts.map +1 -1
  166. package/dist/internal/parity.js +104 -22
  167. package/dist/internal/parity.js.map +1 -1
  168. package/dist/internal/private-env.d.ts +12 -0
  169. package/dist/internal/private-env.d.ts.map +1 -0
  170. package/dist/internal/private-env.js +335 -0
  171. package/dist/internal/private-env.js.map +1 -0
  172. package/dist/internal/public-url.d.ts +3 -0
  173. package/dist/internal/public-url.d.ts.map +1 -0
  174. package/dist/internal/public-url.js +18 -0
  175. package/dist/internal/public-url.js.map +1 -0
  176. package/dist/internal/render-document.d.ts +37 -21
  177. package/dist/internal/render-document.d.ts.map +1 -1
  178. package/dist/internal/render-document.js +104 -65
  179. package/dist/internal/render-document.js.map +1 -1
  180. package/dist/internal/request-url.d.ts +3 -0
  181. package/dist/internal/request-url.d.ts.map +1 -0
  182. package/dist/internal/request-url.js +14 -0
  183. package/dist/internal/request-url.js.map +1 -0
  184. package/dist/internal/response-controls.d.ts +75 -0
  185. package/dist/internal/response-controls.d.ts.map +1 -0
  186. package/dist/internal/response-controls.js +256 -0
  187. package/dist/internal/response-controls.js.map +1 -0
  188. package/dist/internal/runtime-contract.d.ts +11 -16
  189. package/dist/internal/runtime-contract.d.ts.map +1 -1
  190. package/dist/internal/runtime-contract.js.map +1 -1
  191. package/dist/internal/secret-scan.d.ts +104 -0
  192. package/dist/internal/secret-scan.d.ts.map +1 -0
  193. package/dist/internal/secret-scan.js +485 -0
  194. package/dist/internal/secret-scan.js.map +1 -0
  195. package/dist/internal/server-boundary.d.ts +6 -29
  196. package/dist/internal/server-boundary.d.ts.map +1 -1
  197. package/dist/internal/server-boundary.js +6 -66
  198. package/dist/internal/server-boundary.js.map +1 -1
  199. package/dist/internal/source-map.d.ts +47 -0
  200. package/dist/internal/source-map.d.ts.map +1 -0
  201. package/dist/internal/source-map.js +225 -0
  202. package/dist/internal/source-map.js.map +1 -0
  203. package/dist/internal/target-compat.d.ts +27 -0
  204. package/dist/internal/target-compat.d.ts.map +1 -0
  205. package/dist/internal/target-compat.js +77 -0
  206. package/dist/internal/target-compat.js.map +1 -0
  207. package/dist/internal/timing-safe-equal.d.ts +6 -0
  208. package/dist/internal/timing-safe-equal.d.ts.map +1 -1
  209. package/dist/internal/timing-safe-equal.js +10 -0
  210. package/dist/internal/timing-safe-equal.js.map +1 -1
  211. package/dist/internal/vitals-runtime.d.ts +18 -0
  212. package/dist/internal/vitals-runtime.d.ts.map +1 -0
  213. package/dist/internal/vitals-runtime.js +38 -0
  214. package/dist/internal/vitals-runtime.js.map +1 -0
  215. package/dist/internal/web-app.d.ts +56 -8
  216. package/dist/internal/web-app.d.ts.map +1 -1
  217. package/dist/internal/web-app.js +215 -772
  218. package/dist/internal/web-app.js.map +1 -1
  219. package/dist/internal/zone-graph.d.ts +89 -0
  220. package/dist/internal/zone-graph.d.ts.map +1 -0
  221. package/dist/internal/zone-graph.js +492 -0
  222. package/dist/internal/zone-graph.js.map +1 -0
  223. package/dist/isr.d.ts +83 -6
  224. package/dist/isr.d.ts.map +1 -1
  225. package/dist/isr.js +301 -39
  226. package/dist/isr.js.map +1 -1
  227. package/dist/llms-txt.d.ts +3 -0
  228. package/dist/llms-txt.d.ts.map +1 -1
  229. package/dist/llms-txt.js +37 -9
  230. package/dist/llms-txt.js.map +1 -1
  231. package/dist/manifest.d.ts +221 -14
  232. package/dist/manifest.d.ts.map +1 -1
  233. package/dist/manifest.js +386 -9
  234. package/dist/manifest.js.map +1 -1
  235. package/dist/module-graph.d.ts +26 -5
  236. package/dist/module-graph.d.ts.map +1 -1
  237. package/dist/module-graph.js +17 -7
  238. package/dist/module-graph.js.map +1 -1
  239. package/dist/navigation.d.ts +17 -3
  240. package/dist/navigation.d.ts.map +1 -1
  241. package/dist/navigation.js +11 -5
  242. package/dist/navigation.js.map +1 -1
  243. package/dist/nonce.d.ts +47 -0
  244. package/dist/nonce.d.ts.map +1 -0
  245. package/dist/nonce.js +63 -0
  246. package/dist/nonce.js.map +1 -0
  247. package/dist/plugins/css-modules.d.ts.map +1 -1
  248. package/dist/plugins/css-modules.js +4 -3
  249. package/dist/plugins/css-modules.js.map +1 -1
  250. package/dist/plugins/kit.d.ts +9 -0
  251. package/dist/plugins/kit.d.ts.map +1 -1
  252. package/dist/plugins/kit.js +18 -0
  253. package/dist/plugins/kit.js.map +1 -1
  254. package/dist/plugins/svg.d.ts +22 -3
  255. package/dist/plugins/svg.d.ts.map +1 -1
  256. package/dist/plugins/svg.js +112 -1
  257. package/dist/plugins/svg.js.map +1 -1
  258. package/dist/plugins/vite-leak-guard.d.ts +107 -3
  259. package/dist/plugins/vite-leak-guard.d.ts.map +1 -1
  260. package/dist/plugins/vite-leak-guard.js +378 -17
  261. package/dist/plugins/vite-leak-guard.js.map +1 -1
  262. package/dist/plugins/vite-zone-guard.d.ts +61 -0
  263. package/dist/plugins/vite-zone-guard.d.ts.map +1 -0
  264. package/dist/plugins/vite-zone-guard.js +208 -0
  265. package/dist/plugins/vite-zone-guard.js.map +1 -0
  266. package/dist/plugins/zone-guard.d.ts +27 -0
  267. package/dist/plugins/zone-guard.d.ts.map +1 -0
  268. package/dist/plugins/zone-guard.js +72 -0
  269. package/dist/plugins/zone-guard.js.map +1 -0
  270. package/dist/prerender.d.ts +10 -0
  271. package/dist/prerender.d.ts.map +1 -1
  272. package/dist/prerender.js +35 -3
  273. package/dist/prerender.js.map +1 -1
  274. package/dist/public-dir.d.ts +9 -0
  275. package/dist/public-dir.d.ts.map +1 -1
  276. package/dist/public-dir.js +131 -48
  277. package/dist/public-dir.js.map +1 -1
  278. package/dist/pwa-manifest.d.ts +68 -0
  279. package/dist/pwa-manifest.d.ts.map +1 -0
  280. package/dist/pwa-manifest.js +178 -0
  281. package/dist/pwa-manifest.js.map +1 -0
  282. package/dist/query.js +4 -4
  283. package/dist/query.js.map +1 -1
  284. package/dist/render-seam.d.ts +42 -2
  285. package/dist/render-seam.d.ts.map +1 -1
  286. package/dist/render-seam.js +6 -0
  287. package/dist/render-seam.js.map +1 -1
  288. package/dist/route-manifest.d.ts +3 -0
  289. package/dist/route-manifest.d.ts.map +1 -1
  290. package/dist/route-manifest.js +26 -3
  291. package/dist/route-manifest.js.map +1 -1
  292. package/dist/route-types.d.ts +24 -0
  293. package/dist/route-types.d.ts.map +1 -0
  294. package/dist/route-types.js +195 -0
  295. package/dist/route-types.js.map +1 -0
  296. package/dist/router.d.ts +28 -6
  297. package/dist/router.d.ts.map +1 -1
  298. package/dist/router.js +129 -40
  299. package/dist/router.js.map +1 -1
  300. package/dist/trusted-html.d.ts +34 -0
  301. package/dist/trusted-html.d.ts.map +1 -0
  302. package/dist/trusted-html.js +35 -0
  303. package/dist/trusted-html.js.map +1 -0
  304. package/dist/vitals.d.ts +33 -0
  305. package/dist/vitals.d.ts.map +1 -0
  306. package/dist/vitals.js +16 -0
  307. package/dist/vitals.js.map +1 -0
  308. package/dist/vite.d.ts +16 -1
  309. package/dist/vite.d.ts.map +1 -1
  310. package/dist/vite.js +187 -36
  311. package/dist/vite.js.map +1 -1
  312. package/dist/zones.d.ts +70 -0
  313. package/dist/zones.d.ts.map +1 -0
  314. package/dist/zones.js +365 -0
  315. package/dist/zones.js.map +1 -0
  316. package/package.json +67 -14
  317. package/src/backend-only.ts +16 -0
  318. package/src/boundary.ts +18 -5
  319. package/src/build-plan.ts +113 -36
  320. package/src/build-vite.ts +124 -15
  321. package/src/build.ts +535 -102
  322. package/src/bun-dev-entry.ts +1 -1
  323. package/src/cdn.ts +216 -0
  324. package/src/client.ts +251 -18
  325. package/src/conformance.ts +16 -3
  326. package/src/csp.ts +194 -0
  327. package/src/css-contract.ts +44 -0
  328. package/src/dev-client.ts +349 -0
  329. package/src/dev-diagnostics.ts +60 -7
  330. package/src/dev-error.ts +49 -5
  331. package/src/dev-feed.ts +1140 -0
  332. package/src/dev-indicator.ts +113 -0
  333. package/src/dev-session.ts +729 -0
  334. package/src/dev-sourcemap.ts +281 -0
  335. package/src/dev-ssr-graph.ts +16 -5
  336. package/src/dev.ts +86 -43
  337. package/src/diagnostic-catalog.ts +243 -0
  338. package/src/diagnostic-prompt.ts +355 -0
  339. package/src/diagnostic.ts +63 -66
  340. package/src/draft.ts +4 -1
  341. package/src/fn.ts +19 -3
  342. package/src/fs.ts +13 -2
  343. package/src/index.ts +57 -10
  344. package/src/internal/cdn/cloudflare.ts +146 -0
  345. package/src/internal/cdn/core.ts +316 -0
  346. package/src/internal/cdn/fastly.ts +62 -0
  347. package/src/internal/cdn/vercel.ts +95 -0
  348. package/src/internal/code-unit-order.ts +5 -0
  349. package/src/internal/codegen.ts +180 -29
  350. package/src/internal/dev-csp.ts +176 -0
  351. package/src/internal/dev-reserved.ts +52 -0
  352. package/src/internal/html-spans.ts +50 -0
  353. package/src/internal/loading-runtime.ts +244 -0
  354. package/src/internal/matches-runtime.ts +62 -0
  355. package/src/internal/mount-shadow.ts +88 -0
  356. package/src/internal/node-builtins.ts +79 -0
  357. package/src/internal/output-guard.ts +701 -0
  358. package/src/internal/page-execution.ts +1371 -0
  359. package/src/internal/parity.ts +150 -36
  360. package/src/internal/private-env.ts +334 -0
  361. package/src/internal/public-url.ts +22 -0
  362. package/src/internal/render-document.ts +153 -73
  363. package/src/internal/request-url.ts +14 -0
  364. package/src/internal/response-controls.ts +284 -0
  365. package/src/internal/runtime-contract.ts +10 -15
  366. package/src/internal/secret-scan.ts +623 -0
  367. package/src/internal/server-boundary.ts +6 -69
  368. package/src/internal/source-map.ts +256 -0
  369. package/src/internal/target-compat.ts +92 -0
  370. package/src/internal/timing-safe-equal.ts +13 -0
  371. package/src/internal/vitals-runtime.ts +53 -0
  372. package/src/internal/web-app.ts +290 -879
  373. package/src/internal/zone-graph.ts +593 -0
  374. package/src/isr.ts +366 -39
  375. package/src/llms-txt.ts +44 -8
  376. package/src/manifest.ts +671 -17
  377. package/src/module-graph.ts +53 -9
  378. package/src/navigation.ts +29 -6
  379. package/src/nonce.ts +104 -0
  380. package/src/plugins/css-modules.ts +5 -3
  381. package/src/plugins/kit.ts +24 -0
  382. package/src/plugins/svg.ts +135 -4
  383. package/src/plugins/vite-leak-guard.ts +529 -16
  384. package/src/plugins/vite-zone-guard.ts +263 -0
  385. package/src/plugins/zone-guard.ts +110 -0
  386. package/src/prerender.ts +49 -3
  387. package/src/public-dir.ts +135 -49
  388. package/src/pwa-manifest.ts +226 -0
  389. package/src/query.ts +4 -4
  390. package/src/render-seam.ts +46 -1
  391. package/src/route-manifest.ts +15 -3
  392. package/src/route-types.ts +264 -0
  393. package/src/router.ts +163 -63
  394. package/src/trusted-html.ts +44 -0
  395. package/src/vitals.ts +44 -0
  396. package/src/vite.ts +207 -36
  397. package/src/zones.ts +430 -0
  398. package/dist/plugins/vite-server-only.d.ts +0 -49
  399. package/dist/plugins/vite-server-only.d.ts.map +0 -1
  400. package/dist/plugins/vite-server-only.js +0 -57
  401. package/dist/plugins/vite-server-only.js.map +0 -1
  402. package/dist/server-only.d.ts +0 -21
  403. package/dist/server-only.d.ts.map +0 -1
  404. package/dist/server-only.js +0 -25
  405. package/dist/server-only.js.map +0 -1
  406. package/src/plugins/vite-server-only.ts +0 -75
  407. package/src/server-only.ts +0 -25
package/dist/csp.js ADDED
@@ -0,0 +1,122 @@
1
+ import { PRE_HYDRATION_GUARD } from "./internal/runtime-contract.js";
2
+ import { createNonceResolver } from "./nonce.js";
3
+ const CSP_POLICY = Symbol.for("nifra.web.cspPolicy");
4
+ /** How a `createWebApp` app's documents meet a CSP: `"nonce"` (every document carries one, so none is
5
+ * cacheable) or `"hash"` (a {@link CspPolicy}). Read by wrappers that cache documents. */
6
+ export const DOCUMENT_POLICY = Symbol.for("nifra.web.documentPolicy");
7
+ /**
8
+ * Create a hash-based Content-Security-Policy for nifra documents, so a page can carry a strict CSP
9
+ * and still be cached.
10
+ *
11
+ * A per-request nonce makes every document unique: nifra marks a nonce-bearing document
12
+ * `private, no-store`, so no shared cache (ISR, a CDN) may store it. Under this policy a document
13
+ * gets a nonce only when it carries a script specific to this request: a page that `defer()`s streams
14
+ * one per settled value, and `unsafeInlineScript` names the nonce. Every other document is nonce-free.
15
+ * Its inline scripts are the constant ones nifra writes, listed by hash, so the CSP header is the
16
+ * same on every request and the page stays cacheable. Page data rides in an inert JSON script, which
17
+ * a CSP does not govern.
18
+ *
19
+ * ```ts
20
+ * const csp = createCspPolicy({
21
+ * header: ({ sources }) => `default-src 'self'; script-src 'self' ${sources}; object-src 'none'`,
22
+ * })
23
+ * const app = createWebApp({ adapter, manifest, clientEntry, csp })
24
+ * ```
25
+ */
26
+ export function createCspPolicy(options) {
27
+ if (typeof options?.header !== "function") {
28
+ throw new TypeError("[nifra/web] createCspPolicy requires a header function");
29
+ }
30
+ return {
31
+ [CSP_POLICY]: {
32
+ header: options.header,
33
+ // A UUID's hyphens are outside the CSP base64-value grammar; the remaining 122 random bits are
34
+ // plenty for a per-response nonce, on every fetch runtime.
35
+ generate: options.generate ?? (() => crypto.randomUUID().replaceAll("-", "")),
36
+ adapters: new WeakMap(),
37
+ },
38
+ };
39
+ }
40
+ /** True for a value made by {@link createCspPolicy}. */
41
+ export const isCspPolicy = (value) => typeof value === "object" && value !== null && CSP_POLICY in value;
42
+ // A closing tag ends at any space, slash or `>` after its name, as a browser reads it.
43
+ const INLINE_SCRIPT = /<script\b([^>]*)>([\s\S]*?)<\/script(?=[\s/>])[^>]*>/gi;
44
+ /** The bodies of the executable inline scripts in a fragment of markup (no `src`, no inert type). */
45
+ const inlineScriptBodies = (html) => {
46
+ const bodies = [];
47
+ for (const match of html.matchAll(INLINE_SCRIPT)) {
48
+ const attrs = match[1] ?? "";
49
+ if (/\bsrc\s*=/i.test(attrs) || /\btype\s*=\s*["']?application\/(ld\+)?json/i.test(attrs))
50
+ continue;
51
+ bodies.push(match[2] ?? "");
52
+ }
53
+ return bodies;
54
+ };
55
+ const ENCODER = new TextEncoder();
56
+ /** A CSP hash source for one inline script body: `'sha256-<base64 of the UTF-8 bytes>'`. */
57
+ async function hashSource(body) {
58
+ const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", ENCODER.encode(body)));
59
+ let binary = "";
60
+ for (const byte of digest)
61
+ binary += String.fromCharCode(byte);
62
+ return `'sha256-${btoa(binary)}'`;
63
+ }
64
+ /**
65
+ * The `'sha256-…'` sources for the constant inline scripts nifra writes into a document rendered
66
+ * with `adapter`: the pre-hydration form guard and the adapter's hydration head. For a CSP set outside
67
+ * the app (a proxy, a CDN rule); {@link createCspPolicy} computes the same list itself.
68
+ */
69
+ export async function nifraScriptHashes(adapter) {
70
+ const bodies = [PRE_HYDRATION_GUARD, ...inlineScriptBodies(adapter.hydrationHead())];
71
+ return Promise.all([...new Set(bodies)].map(hashSource));
72
+ }
73
+ /**
74
+ * Compute (once per adapter) the policy's hash sources. Returns `undefined` once they are ready, so
75
+ * the renderer stays synchronous after the first document.
76
+ */
77
+ export function prepareCspPolicy(policy, adapter) {
78
+ const state = policy[CSP_POLICY];
79
+ const known = state.adapters.get(adapter);
80
+ if (known !== undefined)
81
+ return known instanceof Promise ? known.then(() => undefined) : undefined;
82
+ const head = adapter.hydrationHead();
83
+ const pending = nifraScriptHashes(adapter).then((hashes) => {
84
+ const sources = { head, sources: hashes.join(" ") };
85
+ state.adapters.set(adapter, sources);
86
+ return sources;
87
+ });
88
+ state.adapters.set(adapter, pending);
89
+ // A failed digest must not pin a rejected promise: the next document retries.
90
+ pending.catch(() => state.adapters.delete(adapter));
91
+ return pending.then(() => undefined);
92
+ }
93
+ const preparedSources = (policy, adapter) => {
94
+ const known = policy[CSP_POLICY].adapters.get(adapter);
95
+ if (known === undefined || known instanceof Promise) {
96
+ throw new Error("[nifra/web] CSP policy used before prepareCspPolicy resolved");
97
+ }
98
+ return known;
99
+ };
100
+ /**
101
+ * The nonce one document carries under `policy`: `undefined` unless the document needs one -
102
+ * `needsNonce` (a deferred value or a head tag naming the nonce), or an adapter whose hydration head
103
+ * no longer matches the one the policy hashed. A needed nonce reuses the caller's, else is generated.
104
+ */
105
+ export function cspDocumentNonce(policy, adapter, hydrate, needsNonce, requested) {
106
+ const varies = hydrate && adapter.hydrationHead() !== preparedSources(policy, adapter).head;
107
+ if (!needsNonce && !varies)
108
+ return undefined;
109
+ return requested ?? policy[CSP_POLICY].generate();
110
+ }
111
+ /** The Content-Security-Policy value for one document, or `undefined` when the policy sends none. */
112
+ export function cspHeaderValue(policy, adapter, nonce) {
113
+ const { sources } = preparedSources(policy, adapter);
114
+ const state = policy[CSP_POLICY];
115
+ return nonce === undefined
116
+ ? state.header({ sources })
117
+ : state.header({ sources: `${sources} 'nonce-${nonce}'`, nonce });
118
+ }
119
+ /** The per-request nonce source for a page executor under `policy`: generated eagerly so `meta` can
120
+ * name it in `unsafeInlineScript`, and dropped by the renderer from documents that do not need it. */
121
+ export const cspNonceResolver = (policy) => createNonceResolver({ generate: () => policy[CSP_POLICY].generate() });
122
+ //# sourceMappingURL=csp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csp.js","sourceRoot":"","sources":["../src/csp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * How framework-owned stylesheets are made active during the first document load.
3
+ *
4
+ * `blocking` is the backwards-compatible default. `deferred` is intended for an aggregate
5
+ * stylesheet: the document fetches it with `media="print"`, then the generated client promotes it
6
+ * to `media="all"` after the resource settles and before mounting the app.
7
+ */
8
+ export type CssLoadingMode = "blocking" | "deferred";
9
+ /** The default remains the ordinary render-blocking stylesheet link. */
10
+ export declare const DEFAULT_CSS_LOADING: CssLoadingMode;
11
+ /** Runtime validation for the Vite CSS output switch. `undefined` means Vite's default (`true`). */
12
+ export declare function normalizeCssCodeSplit(value: unknown): boolean;
13
+ /** Runtime validation for JavaScript callers, generated manifests, and hand-authored integrations. */
14
+ export declare function normalizeCssLoading(value: unknown): CssLoadingMode;
15
+ /**
16
+ * Guard the only Vite combination that would claim to solve the stylesheet-insertion regression while
17
+ * leaving the cause in place. A deferred split build can still attach CSS when a prefetched lazy chunk
18
+ * evaluates, so it must fail closed instead of producing a misleadingly healthy deployment.
19
+ */
20
+ export declare function assertCssLoadingCompatible(cssCodeSplit: boolean, cssLoading: CssLoadingMode): void;
21
+ //# sourceMappingURL=css-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-contract.d.ts","sourceRoot":"","sources":["../src/css-contract.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,UAAU,CAAA;AAEpD,wEAAwE;AACxE,eAAO,MAAM,mBAAmB,EAAE,cAA2B,CAAA;AAE7D,oGAAoG;AACpG,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAM7D;AAED,sGAAsG;AACtG,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAKlE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,OAAO,EACrB,UAAU,EAAE,cAAc,GACzB,IAAI,CAMN"}
@@ -0,0 +1,28 @@
1
+ /** The default remains the ordinary render-blocking stylesheet link. */
2
+ export const DEFAULT_CSS_LOADING = "blocking";
3
+ /** Runtime validation for the Vite CSS output switch. `undefined` means Vite's default (`true`). */
4
+ export function normalizeCssCodeSplit(value) {
5
+ if (value === undefined)
6
+ return true;
7
+ if (typeof value === "boolean")
8
+ return value;
9
+ throw new TypeError(`[nifra/web] cssCodeSplit must be a boolean when provided, received ${JSON.stringify(value)}`);
10
+ }
11
+ /** Runtime validation for JavaScript callers, generated manifests, and hand-authored integrations. */
12
+ export function normalizeCssLoading(value) {
13
+ if (value === "blocking" || value === "deferred")
14
+ return value;
15
+ throw new TypeError(`[nifra/web] cssLoading must be "blocking" or "deferred", received ${JSON.stringify(value)}`);
16
+ }
17
+ /**
18
+ * Guard the only Vite combination that would claim to solve the stylesheet-insertion regression while
19
+ * leaving the cause in place. A deferred split build can still attach CSS when a prefetched lazy chunk
20
+ * evaluates, so it must fail closed instead of producing a misleadingly healthy deployment.
21
+ */
22
+ export function assertCssLoadingCompatible(cssCodeSplit, cssLoading) {
23
+ if (cssLoading !== "deferred" || !cssCodeSplit)
24
+ return;
25
+ throw new Error('[nifra/web] cssLoading: "deferred" requires cssCodeSplit: false. Vite can otherwise inject ' +
26
+ "stylesheets when prefetched lazy chunks evaluate, reintroducing page-wide style/layout work.");
27
+ }
28
+ //# sourceMappingURL=css-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-contract.js","sourceRoot":"","sources":["../src/css-contract.ts"],"names":[],"mappings":"AASA,wEAAwE;AACxE,MAAM,CAAC,MAAM,mBAAmB,GAAmB,UAAU,CAAA;AAE7D,oGAAoG;AACpG,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACpC,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IAC5C,MAAM,IAAI,SAAS,CACjB,sEAAsE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAC9F,CAAA;AACH,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,KAAK,CAAA;IAC9D,MAAM,IAAI,SAAS,CACjB,qEAAqE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAC7F,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACxC,YAAqB,EACrB,UAA0B;IAE1B,IAAI,UAAU,KAAK,UAAU,IAAI,CAAC,YAAY;QAAE,OAAM;IACtD,MAAM,IAAI,KAAK,CACb,6FAA6F;QAC3F,8FAA8F,CACjG,CAAA;AACH,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * The browser half of the dev feed: a small inline script a dev server puts first in each page's
3
+ * `<head>`, so the agent sees what the page did after it left the server - uncaught errors, unhandled
4
+ * rejections, failed script/stylesheet loads, hydration mismatches and console output.
5
+ *
6
+ * Inline and first, rather than a module, so it is listening before any module (the framework, the
7
+ * HMR client, the app) runs. Dev only: nothing here is reachable from a production build.
8
+ */
9
+ import { type DevLogLevel } from "./dev-feed.js";
10
+ export interface DevClientConfig {
11
+ /** Where the batches go (same origin). */
12
+ readonly ingestPath: string;
13
+ /** Proves a batch came from a page this server served. */
14
+ readonly pageToken: string;
15
+ /** The request that rendered this document: browser entries from it carry the same id. */
16
+ readonly requestId?: string | undefined;
17
+ /** The document's path + search, so a client-side navigation away stops claiming that request. */
18
+ readonly documentPath?: string | undefined;
19
+ /** The issues indicator module, loaded on the first error the server answers for; none when off. */
20
+ readonly indicatorPath?: string | undefined;
21
+ }
22
+ /** The script's text (without the `<script>` element). */
23
+ export declare function devClientSource(config: DevClientConfig): string;
24
+ /** The CSP source that admits exactly `source`. */
25
+ export declare function scriptHash(source: string): string;
26
+ /** Whether a response is a page the script belongs in: HTML, with a body nobody has encoded yet. */
27
+ export declare function isInjectablePage(response: Response, method: string): boolean;
28
+ /**
29
+ * Prepare `headers` for the script: admit it in the page's CSP, by hash unless `nonced` (the caller
30
+ * puts a nonce on every script afterwards). Returns the `<script>` element to insert, or undefined
31
+ * when the page's CSP forbids scripts and nothing should be inserted.
32
+ */
33
+ export declare function devClientTag(config: DevClientConfig, headers: Headers, origin: string, nonced?: boolean): string | undefined;
34
+ /** `html` with `tag` inserted into its head; unchanged when there is no `<head>`. */
35
+ export declare function injectIntoHtml(html: string, tag: string): string;
36
+ /**
37
+ * Stream `body` with `tag` inserted into its head. Only the prefix up to the insertion point is held
38
+ * back; the rest streams through untouched, so a streamed SSR page keeps its first-byte time.
39
+ */
40
+ export declare function injectIntoStream(body: ReadableStream<Uint8Array>, tag: string): ReadableStream<Uint8Array>;
41
+ /** One batch is bounded by what `fetch(keepalive)` may carry. */
42
+ export declare const CLIENT_BATCH_MAX_BYTES: number;
43
+ export declare const CLIENT_BATCH_MAX_EVENTS = 50;
44
+ interface EventContext {
45
+ readonly page: string;
46
+ readonly requestId?: string | undefined;
47
+ }
48
+ export interface BrowserError {
49
+ readonly name: string;
50
+ readonly message: string;
51
+ readonly stack: string;
52
+ }
53
+ export type ClientEvent = EventContext & ({
54
+ readonly kind: "error" | "rejection";
55
+ readonly name: string;
56
+ readonly message: string;
57
+ readonly stack: string;
58
+ } | {
59
+ readonly kind: "resource";
60
+ readonly tag: string;
61
+ readonly url: string;
62
+ } | {
63
+ readonly kind: "console";
64
+ readonly level: DevLogLevel;
65
+ readonly message: string;
66
+ /** The first Error a `console.error` call was given: frameworks report caught errors so. */
67
+ readonly error?: BrowserError | undefined;
68
+ });
69
+ export interface ClientBatch {
70
+ readonly token: string;
71
+ readonly events: readonly ClientEvent[];
72
+ }
73
+ /** A batch the script could have sent, or undefined. Malformed events are dropped, not fatal. */
74
+ export declare function parseClientBatch(value: unknown): ClientBatch | undefined;
75
+ export {};
76
+ //# sourceMappingURL=dev-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-client.d.ts","sourceRoot":"","sources":["../src/dev-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,KAAK,WAAW,EAAiB,MAAM,eAAe,CAAA;AAG/D,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,0FAA0F;IAC1F,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,kGAAkG;IAClG,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1C,oGAAoG;IACpG,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC5C;AA0FD,0DAA0D;AAC1D,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAQ/D;AAED,mDAAmD;AACnD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,oGAAoG;AACpG,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAK5E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,UAAQ,GACb,MAAM,GAAG,SAAS,CASpB;AA2BD,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhE;AAYD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAChC,GAAG,EAAE,MAAM,GACV,cAAc,CAAC,UAAU,CAAC,CAuC5B;AAMD,iEAAiE;AACjE,eAAO,MAAM,sBAAsB,QAAY,CAAA;AAC/C,eAAO,MAAM,uBAAuB,KAAK,CAAA;AAEzC,UAAU,YAAY;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACxC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,MAAM,WAAW,GAAG,YAAY,GACpC,CACI;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,CAAA;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACzE;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,4FAA4F;IAC5F,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CAC1C,CACJ,CAAA;AAEH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAA;CACxC;AAiDD,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,CAUxE"}
@@ -0,0 +1,280 @@
1
+ /**
2
+ * The browser half of the dev feed: a small inline script a dev server puts first in each page's
3
+ * `<head>`, so the agent sees what the page did after it left the server - uncaught errors, unhandled
4
+ * rejections, failed script/stylesheet loads, hydration mismatches and console output.
5
+ *
6
+ * Inline and first, rather than a module, so it is listening before any module (the framework, the
7
+ * HMR client, the app) runs. Dev only: nothing here is reachable from a production build.
8
+ */
9
+ import { createHash } from "node:crypto";
10
+ import { isDevLogLevel } from "./dev-feed.js";
11
+ import { admitInlineScript } from "./internal/dev-csp.js";
12
+ // ES2017, no dependencies, one global: `__nifraDevClient`, the idempotence flag that also queues issues
13
+ // for the indicator module. Keep it small: it ships in every dev page, and its hash goes into every CSP
14
+ // that needs one.
15
+ const CLIENT_SOURCE = String.raw `(function(C){
16
+ if(window.__nifraDevClient)return;var S=window.__nifraDevClient={issues:[]};
17
+ var nonce=document.currentScript&&document.currentScript.nonce,loading=0;
18
+ var q=[],timer=0,inside=0,MSG=8000,STACK=16000;
19
+ function cap(s,n){s=String(s);return s.length>n?s.slice(0,n)+"...":s}
20
+ function where(){return location.pathname+location.search}
21
+ function ser(v,d){
22
+ if(typeof v==="string")return v;
23
+ if(v instanceof Error)return v.stack||v.name+": "+v.message;
24
+ if(typeof v==="function")return"[Function "+(v.name||"anonymous")+"]";
25
+ if(typeof v!=="object"||v===null)return String(v);
26
+ if(typeof Element!=="undefined"&&v instanceof Element)return"<"+v.tagName.toLowerCase()+(v.id?"#"+v.id:"")+">";
27
+ if(d>2)return Array.isArray(v)?"[Array]":"[Object]";
28
+ var seen=[];
29
+ try{return JSON.stringify(v,function(k,x){
30
+ if(typeof x==="object"&&x!==null){if(seen.indexOf(x)!==-1)return"[Circular]";seen.push(x)}
31
+ if(typeof x==="bigint")return x+"n";
32
+ if(x instanceof Error)return x.name+": "+x.message;
33
+ return x})}catch(e){return Object.prototype.toString.call(v)}}
34
+ function fmt(a){
35
+ var args=Array.prototype.slice.call(a),out=[];
36
+ if(typeof args[0]==="string"&&args[0].indexOf("%")!==-1){
37
+ var rest=args.slice(1);
38
+ out.push(args[0].replace(/%([sdifoOjc%])/g,function(m,k){
39
+ if(k==="%")return"%";
40
+ if(!rest.length)return m;
41
+ var v=rest.shift();
42
+ if(k==="c")return"";
43
+ if(k==="d"||k==="i")return String(parseInt(v,10));
44
+ if(k==="f")return String(parseFloat(v));
45
+ return ser(v,0)}));
46
+ args=rest}
47
+ for(var i=0;i<args.length;i++)out.push(ser(args[i],0));
48
+ return out.join(" ")}
49
+ function send(keep){
50
+ clearTimeout(timer);timer=0;
51
+ while(q.length){
52
+ var body=JSON.stringify({token:C.t,events:q.splice(0,50)});
53
+ try{fetch(C.u,{method:"POST",body:body,keepalive:!!keep&&body.length<60000,headers:{"content-type":"application/json"},credentials:"same-origin"}).then(function(r){if(r.status===200&&C.i)return r.json().then(issues)}).catch(function(){})}catch(e){}}}
54
+ function issues(j){
55
+ var list=j&&j.issues;if(!list||!list.length)return;
56
+ if(S.indicator){S.indicator.add(list);return}
57
+ S.issues=S.issues.concat(list);if(loading)return;loading=1;
58
+ var s=document.createElement("script");s.type="module";s.src=C.i;if(nonce)s.nonce=nonce;
59
+ (document.head||document.documentElement).appendChild(s)}
60
+ function push(e){
61
+ e.page=cap(where(),2000);
62
+ if(C.r&&e.page===C.p)e.requestId=C.r;
63
+ q.push(e);
64
+ if(q.length>=50)send(false);else if(!timer)timer=setTimeout(send,100)}
65
+ ["debug","info","log","warn","error"].forEach(function(level){
66
+ var orig=console[level];if(typeof orig!=="function")return;
67
+ console[level]=function(){
68
+ if(!inside){inside=1;try{
69
+ var ev={kind:"console",level:level,message:cap(fmt(arguments),MSG)};
70
+ if(level==="error")for(var i=0;i<arguments.length;i++){var x=arguments[i];
71
+ if(x instanceof Error){ev.error={name:cap(x.name,200),message:cap(x.message,MSG),stack:cap(x.stack||"",STACK)};break}}
72
+ push(ev)}catch(e){}inside=0}
73
+ return orig.apply(this,arguments)}});
74
+ addEventListener("error",function(ev){
75
+ var t=ev.target;
76
+ if(t&&t!==window&&t.tagName){
77
+ var tag=t.tagName.toLowerCase(),rel=(t.rel||"").toLowerCase();
78
+ if(tag==="script"||(tag==="link"&&/stylesheet|modulepreload|preload/.test(rel)))push({kind:"resource",tag:tag,url:cap(t.src||t.href||"",2000)});
79
+ return}
80
+ var e=ev.error;
81
+ if(!e&&ev.message==="Script error.")return;
82
+ push({kind:"error",name:cap(e&&e.name?e.name:"Error",200),message:cap(e&&e.message!=null?e.message:ev.message,MSG),
83
+ stack:cap(e&&e.stack?e.stack:(ev.filename?" at "+ev.filename+":"+ev.lineno+":"+ev.colno:""),STACK)})},true);
84
+ addEventListener("unhandledrejection",function(ev){
85
+ var r=ev.reason;
86
+ if(r instanceof Error)push({kind:"rejection",name:cap(r.name,200),message:cap(r.message,MSG),stack:cap(r.stack||"",STACK)});
87
+ else push({kind:"rejection",name:"UnhandledRejection",message:cap(ser(r,0),MSG)})});
88
+ addEventListener("pagehide",function(){send(true)});
89
+ document.addEventListener("visibilitychange",function(){if(document.visibilityState==="hidden")send(true)});
90
+ })`;
91
+ // `</script` inside a JSON value would end the element early; `<!--` can start a script-data escape.
92
+ const scriptSafe = (json) => json
93
+ .replaceAll("<", "\\u003c")
94
+ .replaceAll(">", "\\u003e")
95
+ .replaceAll("\u2028", "\\u2028")
96
+ .replaceAll("\u2029", "\\u2029");
97
+ /** The script's text (without the `<script>` element). */
98
+ export function devClientSource(config) {
99
+ const settings = { u: config.ingestPath, t: config.pageToken };
100
+ if (config.indicatorPath !== undefined)
101
+ settings.i = config.indicatorPath;
102
+ if (config.requestId !== undefined && config.documentPath !== undefined) {
103
+ settings.r = config.requestId;
104
+ settings.p = config.documentPath;
105
+ }
106
+ return `${CLIENT_SOURCE}(${scriptSafe(JSON.stringify(settings))})`;
107
+ }
108
+ /** The CSP source that admits exactly `source`. */
109
+ export function scriptHash(source) {
110
+ return `'sha256-${createHash("sha256").update(source).digest("base64")}'`;
111
+ }
112
+ /** Whether a response is a page the script belongs in: HTML, with a body nobody has encoded yet. */
113
+ export function isInjectablePage(response, method) {
114
+ if (method === "HEAD" || response.body === null)
115
+ return false;
116
+ if (response.status === 204 || response.status === 304)
117
+ return false;
118
+ if (response.headers.has("content-encoding"))
119
+ return false;
120
+ return (response.headers.get("content-type") ?? "").toLowerCase().includes("text/html");
121
+ }
122
+ /**
123
+ * Prepare `headers` for the script: admit it in the page's CSP, by hash unless `nonced` (the caller
124
+ * puts a nonce on every script afterwards). Returns the `<script>` element to insert, or undefined
125
+ * when the page's CSP forbids scripts and nothing should be inserted.
126
+ */
127
+ export function devClientTag(config, headers, origin, nonced = false) {
128
+ const source = devClientSource(config);
129
+ const hash = nonced ? undefined : scriptHash(source);
130
+ // A nonced client hands its nonce to the module it loads, so only a hashed one needs the URL admitted.
131
+ const indicator = nonced || config.indicatorPath === undefined ? undefined : new URL(config.indicatorPath, origin);
132
+ if (!admitInlineScript(headers, hash, new URL(config.ingestPath, origin), indicator))
133
+ return undefined;
134
+ return `<script data-nifra-dev>${source}</script>`;
135
+ }
136
+ // Latin-1 views keep string offsets equal to byte offsets, so a match position is a splice point.
137
+ const latin1 = new TextDecoder("latin1");
138
+ const HEAD_OPEN = /<head(?:\s[^>]*)?>/i;
139
+ const META_CHARSET = /^\s*<meta\s[^>]*charset\s*=[^>]*>/i;
140
+ // Past this, a page without `<head>` is a fragment: stop looking and stream it as it is.
141
+ const HEAD_SEARCH_LIMIT = 64 * 1024;
142
+ // Enough to see a `<meta charset>` that immediately follows `<head>`.
143
+ const META_LOOKAHEAD = 256;
144
+ /** Where the script goes in `text`: after `<head>`, and after a `<meta charset>` that leads it. */
145
+ function insertionPoint(text, final) {
146
+ const head = HEAD_OPEN.exec(text);
147
+ if (head === null) {
148
+ const body = /<body[\s>]/i.test(text);
149
+ return final || body || text.length > HEAD_SEARCH_LIMIT ? "none" : "wait";
150
+ }
151
+ const afterHead = head.index + head[0].length;
152
+ const rest = text.slice(afterHead);
153
+ const meta = META_CHARSET.exec(rest);
154
+ if (meta !== null)
155
+ return afterHead + meta[0].length;
156
+ if (!final && rest.length < META_LOOKAHEAD && !/<(?!meta)/i.test(rest.replace(/^\s+/, "")))
157
+ return "wait";
158
+ return afterHead;
159
+ }
160
+ /** `html` with `tag` inserted into its head; unchanged when there is no `<head>`. */
161
+ export function injectIntoHtml(html, tag) {
162
+ const at = insertionPoint(html, true);
163
+ return typeof at === "number" ? html.slice(0, at) + tag + html.slice(at) : html;
164
+ }
165
+ function concat(chunks, length) {
166
+ const out = new Uint8Array(length);
167
+ let offset = 0;
168
+ for (const chunk of chunks) {
169
+ out.set(chunk, offset);
170
+ offset += chunk.byteLength;
171
+ }
172
+ return out;
173
+ }
174
+ /**
175
+ * Stream `body` with `tag` inserted into its head. Only the prefix up to the insertion point is held
176
+ * back; the rest streams through untouched, so a streamed SSR page keeps its first-byte time.
177
+ */
178
+ export function injectIntoStream(body, tag) {
179
+ const insert = new TextEncoder().encode(tag);
180
+ const held = [];
181
+ let heldBytes = 0;
182
+ let done = false;
183
+ const release = (controller, final) => {
184
+ const bytes = concat(held, heldBytes);
185
+ const at = insertionPoint(latin1.decode(bytes), final);
186
+ if (at === "wait")
187
+ return;
188
+ held.length = 0;
189
+ heldBytes = 0;
190
+ done = true;
191
+ if (at === "none") {
192
+ controller.enqueue(bytes);
193
+ return;
194
+ }
195
+ controller.enqueue(bytes.subarray(0, at));
196
+ controller.enqueue(insert);
197
+ controller.enqueue(bytes.subarray(at));
198
+ };
199
+ return body.pipeThrough(new TransformStream({
200
+ transform(chunk, controller) {
201
+ if (done) {
202
+ controller.enqueue(chunk);
203
+ return;
204
+ }
205
+ held.push(chunk);
206
+ heldBytes += chunk.byteLength;
207
+ release(controller, false);
208
+ },
209
+ flush(controller) {
210
+ if (!done && heldBytes > 0)
211
+ release(controller, true);
212
+ },
213
+ }));
214
+ }
215
+ // ---------------------------------------------------------------------------------------------------
216
+ // What the script sends
217
+ // ---------------------------------------------------------------------------------------------------
218
+ /** One batch is bounded by what `fetch(keepalive)` may carry. */
219
+ export const CLIENT_BATCH_MAX_BYTES = 64 * 1024;
220
+ export const CLIENT_BATCH_MAX_EVENTS = 50;
221
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
222
+ const text = (value, max) => typeof value === "string" ? value.slice(0, max) : undefined;
223
+ // The script only ever tags an event with the id the server put in it; anything else is dropped.
224
+ const REQUEST_ID = /^r\d{1,12}$/;
225
+ function parseBrowserError(value) {
226
+ if (!isRecord(value))
227
+ return undefined;
228
+ const message = text(value.message, 8 * 1024);
229
+ if (message === undefined)
230
+ return undefined;
231
+ return {
232
+ name: text(value.name, 200) || "Error",
233
+ message,
234
+ stack: text(value.stack, 16 * 1024) ?? "",
235
+ };
236
+ }
237
+ function parseEvent(value) {
238
+ if (!isRecord(value))
239
+ return undefined;
240
+ const page = text(value.page, 2048);
241
+ if (page === undefined || !page.startsWith("/"))
242
+ return undefined;
243
+ const requestId = typeof value.requestId === "string" && REQUEST_ID.test(value.requestId)
244
+ ? value.requestId
245
+ : undefined;
246
+ if (value.kind === "error" || value.kind === "rejection") {
247
+ const error = parseBrowserError(value);
248
+ return error === undefined ? undefined : { kind: value.kind, ...error, page, requestId };
249
+ }
250
+ if (value.kind === "resource") {
251
+ const tag = text(value.tag, 20);
252
+ const url = text(value.url, 2048);
253
+ if (tag === undefined || url === undefined)
254
+ return undefined;
255
+ return { kind: "resource", tag, url, page, requestId };
256
+ }
257
+ if (value.kind === "console") {
258
+ const message = text(value.message, 8 * 1024);
259
+ if (message === undefined || !isDevLogLevel(value.level))
260
+ return undefined;
261
+ const error = parseBrowserError(value.error);
262
+ return { kind: "console", level: value.level, message, error, page, requestId };
263
+ }
264
+ return undefined;
265
+ }
266
+ /** A batch the script could have sent, or undefined. Malformed events are dropped, not fatal. */
267
+ export function parseClientBatch(value) {
268
+ if (!isRecord(value) || typeof value.token !== "string" || !Array.isArray(value.events))
269
+ return undefined;
270
+ if (value.events.length > CLIENT_BATCH_MAX_EVENTS)
271
+ return undefined;
272
+ const events = [];
273
+ for (const raw of value.events) {
274
+ const event = parseEvent(raw);
275
+ if (event !== undefined)
276
+ events.push(event);
277
+ }
278
+ return { token: value.token, events };
279
+ }
280
+ //# sourceMappingURL=dev-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-client.js","sourceRoot":"","sources":["../src/dev-client.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,20 @@
1
+ import { type Diagnostic } from "./diagnostic.js";
2
+ /**
3
+ * Whether a codeframe may show `file` (the canonical path it would read) to a browser: source in a
4
+ * browser zone. A page reports its own stack frames, so it can name any path: data files and the dev
5
+ * server's own `.nifra/` files (the discovery record holds the agent token) never qualify.
6
+ */
7
+ export declare function createSourceGate(root: string): (file: string) => boolean;
8
+ /** A failure as the dev feed recorded it: the entry and request let its agent prompt name a check. */
9
+ export interface CapturedFailure {
10
+ readonly diagnostic: Diagnostic;
11
+ readonly entry?: {
12
+ readonly id: string;
13
+ readonly seq: number;
14
+ } | undefined;
15
+ readonly requestId?: string | undefined;
16
+ readonly category?: string | undefined;
17
+ }
1
18
  export interface DevDiagnostics {
2
19
  /** True when a request path targets the structured last-error endpoint. */
3
20
  isLastErrorPath(pathname: string): boolean;
@@ -13,8 +30,15 @@ export interface DevDiagnostics {
13
30
  readonly method: string;
14
31
  readonly url: string;
15
32
  }): string;
33
+ /** The overlay HTML for a failure the feed already recorded, which also becomes the last error. */
34
+ show(captured: CapturedFailure): string;
16
35
  }
17
36
  /** One diagnostics surface per dev server. `root` is the resolved project root; it scopes the codeframe
18
- * to the project (see buildDiagnostic). Both dev servers resolve a concrete root before calling this. */
19
- export declare function createDevDiagnostics(root: string): DevDiagnostics;
37
+ * to the project (see buildDiagnostic). Both dev servers resolve a concrete root before calling this.
38
+ * `build` replaces the default Diagnostic builder: the dev session passes one that also records the
39
+ * failure in its feed (redacted), so the overlay, this endpoint and the feed show the same object. */
40
+ export declare function createDevDiagnostics(root: string, build?: (err: unknown, request: {
41
+ readonly method: string;
42
+ readonly url: string;
43
+ }) => CapturedFailure): DevDiagnostics;
20
44
  //# sourceMappingURL=dev-diagnostics.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dev-diagnostics.d.ts","sourceRoot":"","sources":["../src/dev-diagnostics.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IAC1C;wGACoG;IACpG,SAAS,IAAI;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,CAAA;IAC1F;4GACwG;IACxG,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAA;CAC1F;AAED;yGACyG;AACzG,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAoBjE"}
1
+ {"version":3,"file":"dev-diagnostics.d.ts","sourceRoot":"","sources":["../src/dev-diagnostics.ts"],"names":[],"mappings":"AAYA,OAAO,EAAmB,KAAK,UAAU,EAA+B,MAAM,iBAAiB,CAAA;AAK/F;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAOxE;AAED,sGAAsG;AACtG,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IAC1C;wGACoG;IACpG,SAAS,IAAI;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,CAAA;IAC1F;4GACwG;IACxG,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAA;IACzF,mGAAmG;IACnG,IAAI,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAAA;CACxC;AAED;;;sGAGsG;AACtG,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,CACN,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,KACvD,eAAe,GACnB,cAAc,CAqChB"}