@mandujs/core 0.54.32 → 0.55.0-beta.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 (414) hide show
  1. package/README.md +654 -654
  2. package/package.json +106 -210
  3. package/scripts/postinstall-lock.ts +153 -153
  4. package/src/a11y/__tests__/run-audit.test.ts +333 -333
  5. package/src/a11y/fix-hints.ts +76 -76
  6. package/src/a11y/index.ts +18 -18
  7. package/src/a11y/run-audit.ts +15 -15
  8. package/src/a11y/types.ts +125 -125
  9. package/src/agent/__tests__/apply.test.ts +224 -0
  10. package/src/agent/__tests__/context.test.ts +97 -98
  11. package/src/agent/apply.ts +1031 -0
  12. package/src/agent/context.ts +552 -552
  13. package/src/agent/index.ts +4 -3
  14. package/src/agent/plan.ts +161 -243
  15. package/src/agent/repair.ts +239 -162
  16. package/src/agent/sync.ts +197 -198
  17. package/src/agent/types.ts +242 -94
  18. package/src/agent/verify.ts +55 -55
  19. package/src/auth/__tests__/login.test.ts +1 -1
  20. package/src/auth/__tests__/password.test.ts +15 -5
  21. package/src/auth/__tests__/reset.test.ts +2 -2
  22. package/src/auth/__tests__/tokens.test.ts +274 -274
  23. package/src/auth/__tests__/verification.test.ts +274 -274
  24. package/src/auth/index.ts +76 -76
  25. package/src/auth/login.ts +225 -225
  26. package/src/auth/password.ts +14 -2
  27. package/src/auth/reset.ts +243 -243
  28. package/src/auth/tokens.ts +612 -612
  29. package/src/auth/verification.ts +253 -253
  30. package/src/brain/__tests__/redactor.test.ts +94 -94
  31. package/src/brain/adapters/__tests__/_helpers.ts +83 -83
  32. package/src/brain/adapters/__tests__/anthropic-oauth.test.ts +196 -196
  33. package/src/brain/adapters/__tests__/chatgpt-auth.test.ts +193 -193
  34. package/src/brain/adapters/__tests__/openai-oauth.test.ts +209 -209
  35. package/src/brain/adapters/__tests__/resolver.test.ts +143 -143
  36. package/src/brain/adapters/anthropic-oauth.ts +1 -1
  37. package/src/brain/adapters/chatgpt-auth.ts +300 -300
  38. package/src/brain/adapters/index.ts +319 -319
  39. package/src/brain/adapters/oauth-flow.ts +439 -439
  40. package/src/brain/consent.ts +240 -240
  41. package/src/brain/credentials.ts +396 -396
  42. package/src/brain/doctor/analyzer.ts +7 -7
  43. package/src/bundler/__snapshots__/build.test.ts.snap +5 -5
  44. package/src/bundler/__tests__/build-runner.ts +166 -166
  45. package/src/bundler/__tests__/client-boundary-transform.test.ts +524 -524
  46. package/src/bundler/__tests__/cold-start.test.ts +60 -60
  47. package/src/bundler/__tests__/css.test.ts +49 -20
  48. package/src/bundler/__tests__/dev-reliability.test.ts +619 -619
  49. package/src/bundler/__tests__/extended-watch.test.ts +711 -711
  50. package/src/bundler/__tests__/fast-refresh.test.ts +24 -24
  51. package/src/bundler/__tests__/generation.test.ts +447 -0
  52. package/src/bundler/__tests__/hdr.test.ts +24 -18
  53. package/src/bundler/__tests__/hmr-client.test.ts +62 -24
  54. package/src/bundler/__tests__/jsx-runtime-shim.test.ts +179 -140
  55. package/src/bundler/__tests__/manifest-schema.test.ts +305 -266
  56. package/src/bundler/__tests__/prod-smoke.test.ts +138 -138
  57. package/src/bundler/__tests__/reverse-import-graph.test.ts +42 -42
  58. package/src/bundler/__tests__/slot-dispatch.test.ts +573 -573
  59. package/src/bundler/__tests__/url-cap-and-slot-regex.test.ts +286 -286
  60. package/src/bundler/__tests__/vendor-cache.test.ts +455 -455
  61. package/src/bundler/analyzer.ts +15 -15
  62. package/src/bundler/budget.ts +404 -404
  63. package/src/bundler/build.test.ts +898 -915
  64. package/src/bundler/build.ts +113 -24
  65. package/src/bundler/client-boundary-transform.ts +977 -977
  66. package/src/bundler/css.ts +65 -44
  67. package/src/bundler/dev.ts +105 -73
  68. package/src/bundler/fast-refresh-preamble.ts +47 -47
  69. package/src/bundler/generation.ts +602 -0
  70. package/src/bundler/index.ts +3 -3
  71. package/src/bundler/manifest-schema.ts +55 -40
  72. package/src/bundler/plugins/__tests__/block-generated-imports.test.ts +13 -13
  73. package/src/bundler/plugins/__tests__/react-compiler-config.test.ts +83 -83
  74. package/src/bundler/plugins/__tests__/react-compiler-lint.test.ts +110 -110
  75. package/src/bundler/plugins/block-generated-imports.ts +16 -15
  76. package/src/bundler/plugins/index.ts +83 -83
  77. package/src/bundler/plugins/react-compiler-config.ts +108 -108
  78. package/src/bundler/plugins/react-compiler-lint.ts +253 -253
  79. package/src/bundler/plugins/react-compiler.ts +162 -162
  80. package/src/bundler/prerender.ts +29 -9
  81. package/src/bundler/reverse-import-graph.ts +339 -339
  82. package/src/bundler/safe-build.test.ts +1 -1
  83. package/src/bundler/safe-build.ts +103 -103
  84. package/src/bundler/scenario-matrix.ts +229 -229
  85. package/src/bundler/types.ts +58 -56
  86. package/src/bundler/vendor-cache-types.ts +130 -130
  87. package/src/bundler/vendor-cache.ts +526 -526
  88. package/src/change/snapshot.ts +18 -18
  89. package/src/client/Form.tsx +105 -105
  90. package/src/client/Link.tsx +9 -9
  91. package/src/client/__tests__/props-serialization.test.ts +37 -37
  92. package/src/client/__tests__/use-sse.test.ts +153 -153
  93. package/src/client/globals.ts +1 -1
  94. package/src/client/hooks.ts +362 -362
  95. package/src/client/hydrate.ts +2 -2
  96. package/src/client/index.ts +1 -1
  97. package/src/client/island.ts +79 -79
  98. package/src/client/prefetch-helper.ts +55 -55
  99. package/src/client/props-serialization.ts +233 -233
  100. package/src/client/runtime-entry.ts +598 -598
  101. package/src/client/runtime.ts +1 -1
  102. package/src/client/serialize.ts +50 -50
  103. package/src/client/use-fetch.ts +6 -6
  104. package/src/client/use-head.ts +197 -197
  105. package/src/client/use-sse.ts +378 -378
  106. package/src/client/window-state.ts +101 -101
  107. package/src/components/Image-compat.ts +3 -0
  108. package/src/components/Image.tsx +162 -162
  109. package/src/config/validate.ts +1 -1
  110. package/src/config/watcher.ts +311 -311
  111. package/src/constants.ts +40 -40
  112. package/src/content/collection.ts +9 -9
  113. package/src/content/content-layer.ts +7 -7
  114. package/src/content/data-store.ts +245 -245
  115. package/src/content/frontmatter.ts +189 -189
  116. package/src/content/generate-types.ts +1 -1
  117. package/src/content/index.ts +2 -2
  118. package/src/content/loader-context.ts +171 -171
  119. package/src/content/loaders/api.ts +216 -216
  120. package/src/content/loaders/file.ts +172 -172
  121. package/src/content/loaders/glob.ts +253 -253
  122. package/src/content/loaders/index.ts +34 -34
  123. package/src/content/loaders/types.ts +137 -137
  124. package/src/content/meta-store.ts +209 -209
  125. package/src/content/prebuild.test.ts +571 -571
  126. package/src/content/prebuild.ts +636 -636
  127. package/src/content/schema.ts +20 -20
  128. package/src/content/sidebar.ts +630 -630
  129. package/src/content/slug.ts +110 -110
  130. package/src/content/types.ts +282 -282
  131. package/src/content/watcher.ts +135 -135
  132. package/src/contract/client-safe.test.ts +42 -42
  133. package/src/contract/client-safe.ts +114 -114
  134. package/src/contract/define.ts +11 -11
  135. package/src/contract/index.ts +1 -1
  136. package/src/contract/normalize.test.ts +276 -276
  137. package/src/contract/normalize.ts +410 -410
  138. package/src/contract/registry.test.ts +206 -206
  139. package/src/contract/route-helpers.ts +1 -1
  140. package/src/contract/rpc.ts +443 -443
  141. package/src/contract/types.ts +58 -58
  142. package/src/db/__tests__/db.test.ts +9 -9
  143. package/src/db/index.ts +2 -2
  144. package/src/db/migrations/history-table.ts +345 -345
  145. package/src/db/migrations/index.ts +3 -3
  146. package/src/db/migrations/lock.ts +324 -324
  147. package/src/db/migrations/runner.ts +650 -650
  148. package/src/deploy/cache.ts +140 -140
  149. package/src/deploy/compile/vercel.ts +344 -344
  150. package/src/deploy/index.ts +87 -87
  151. package/src/deploy/inference/brain.ts +268 -268
  152. package/src/deploy/inference/context.ts +82 -82
  153. package/src/deploy/inference/filling-extract.ts +245 -245
  154. package/src/deploy/inference/heuristic.ts +182 -182
  155. package/src/deploy/intent.ts +173 -173
  156. package/src/deploy/plan.ts +178 -178
  157. package/src/design/__tests__/agents-link.test.ts +109 -109
  158. package/src/design/__tests__/extract-patch-diff.test.ts +265 -265
  159. package/src/design/__tests__/lint.test.ts +110 -110
  160. package/src/design/__tests__/parser.test.ts +195 -195
  161. package/src/design/__tests__/tailwind-theme.test.ts +229 -229
  162. package/src/design/agents-link.ts +165 -165
  163. package/src/design/diff.ts +138 -138
  164. package/src/design/extract.ts +285 -285
  165. package/src/design/index.ts +102 -102
  166. package/src/design/lint.ts +209 -209
  167. package/src/design/parser.ts +555 -555
  168. package/src/design/patch.ts +241 -241
  169. package/src/design/scaffold.ts +147 -147
  170. package/src/design/tailwind-theme.ts +441 -441
  171. package/src/design/types.ts +210 -210
  172. package/src/desktop/__tests__/smoke.test.ts +2 -2
  173. package/src/desktop/__tests__/webview-fallback.test.ts +12 -32
  174. package/src/desktop/__tests__/window.test.ts +20 -99
  175. package/src/desktop/__tests__/worker.test.ts +266 -266
  176. package/src/desktop/index.ts +43 -43
  177. package/src/desktop/types.ts +158 -158
  178. package/src/desktop/webview-fallback.ts +17 -4
  179. package/src/desktop/window.ts +17 -8
  180. package/src/desktop/worker.ts +180 -180
  181. package/src/dev-error-overlay/__tests__/overlay-injector.test.ts +241 -241
  182. package/src/dev-error-overlay/index.ts +30 -30
  183. package/src/dev-error-overlay/overlay-injector.ts +243 -243
  184. package/src/dev-error-overlay/overlay-styles.ts +52 -52
  185. package/src/dev-error-overlay/types.ts +66 -66
  186. package/src/devtools/ai/context-builder.ts +375 -375
  187. package/src/devtools/ai/index.ts +25 -25
  188. package/src/devtools/ai/mcp-connector.ts +25 -25
  189. package/src/devtools/client/catchers/error-catcher.ts +344 -344
  190. package/src/devtools/client/catchers/index.ts +18 -18
  191. package/src/devtools/client/components/index.ts +39 -39
  192. package/src/devtools/client/components/mandu-character.tsx +331 -331
  193. package/src/devtools/client/components/panel/errors-panel.tsx +259 -259
  194. package/src/devtools/client/components/panel/guard-panel.tsx +30 -30
  195. package/src/devtools/client/components/panel/islands-panel.tsx +16 -16
  196. package/src/devtools/client/components/panel/network-panel.tsx +291 -291
  197. package/src/devtools/client/components/panel/panel-container.tsx +1 -1
  198. package/src/devtools/client/components/panel/preview-panel.tsx +46 -46
  199. package/src/devtools/client/filters/context-filters.ts +282 -282
  200. package/src/devtools/client/filters/index.ts +16 -16
  201. package/src/devtools/client/index.ts +63 -63
  202. package/src/devtools/hook/create-hook.ts +207 -207
  203. package/src/devtools/hook/index.ts +13 -13
  204. package/src/devtools/index.ts +439 -439
  205. package/src/devtools/init.ts +265 -265
  206. package/src/devtools/protocol.ts +237 -237
  207. package/src/devtools/server/index.ts +17 -17
  208. package/src/devtools/types.ts +35 -35
  209. package/src/devtools/worker/index.ts +25 -25
  210. package/src/devtools/worker/redaction-worker.ts +233 -233
  211. package/src/diagnose/__tests__/checks.test.ts +136 -136
  212. package/src/diagnose/checks.ts +185 -185
  213. package/src/diagnose/index.ts +17 -17
  214. package/src/diagnose/run.ts +10 -10
  215. package/src/diagnose/types.ts +53 -53
  216. package/src/email/__tests__/email.test.ts +355 -355
  217. package/src/email/index.ts +282 -282
  218. package/src/email/smtp.ts +64 -64
  219. package/src/error/domains.ts +265 -265
  220. package/src/error/types.ts +6 -6
  221. package/src/errors/extractor.ts +409 -409
  222. package/src/errors/index.ts +19 -19
  223. package/src/filling/__tests__/session-sqlite.test.ts +5 -1
  224. package/src/filling/auth.ts +308 -308
  225. package/src/filling/body-parse.test.ts +60 -60
  226. package/src/filling/cookie-codec.ts +5 -3
  227. package/src/filling/deps.ts +265 -265
  228. package/src/filling/head-method.test.ts +154 -154
  229. package/src/filling/session-sqlite.ts +617 -617
  230. package/src/filling/sse.ts +5 -5
  231. package/src/filling/ws.ts +78 -78
  232. package/src/generator/generate.ts +30 -30
  233. package/src/generator/index.ts +3 -3
  234. package/src/generator/templates.test.ts +48 -48
  235. package/src/generator/templates.ts +219 -219
  236. package/src/guard/__tests__/design-inline-class.test.ts +219 -219
  237. package/src/guard/__tests__/tsgolint-bridge.test.ts +347 -347
  238. package/src/guard/analyzer.ts +360 -360
  239. package/src/guard/auto-correct.ts +1 -1
  240. package/src/guard/check.ts +39 -24
  241. package/src/guard/config-guard.ts +13 -13
  242. package/src/guard/contract-guard.ts +9 -9
  243. package/src/guard/define-rule.ts +243 -243
  244. package/src/guard/design-inline-class.ts +393 -393
  245. package/src/guard/file-type.test.ts +24 -24
  246. package/src/guard/fs-routes-policy.ts +51 -51
  247. package/src/guard/graph.ts +1 -1
  248. package/src/guard/healing.ts +36 -36
  249. package/src/guard/index.ts +11 -11
  250. package/src/guard/presets/atomic.ts +70 -70
  251. package/src/guard/presets/clean.ts +77 -77
  252. package/src/guard/presets/fsd.ts +79 -79
  253. package/src/guard/presets/hexagonal.ts +68 -68
  254. package/src/guard/reporter.ts +442 -442
  255. package/src/guard/rule-presets.ts +379 -379
  256. package/src/guard/semantic-slots.ts +1 -1
  257. package/src/guard/suggestions.ts +358 -358
  258. package/src/guard/tsgolint-bridge.ts +512 -512
  259. package/src/guard/types.ts +348 -348
  260. package/src/guard/watcher.ts +405 -405
  261. package/src/i18n/define.ts +126 -126
  262. package/src/i18n/index.ts +52 -52
  263. package/src/i18n/message-registry.ts +173 -173
  264. package/src/i18n/types.ts +112 -112
  265. package/src/id/__tests__/id.test.ts +3 -3
  266. package/src/id/index.ts +105 -105
  267. package/src/index.ts +9 -48
  268. package/src/internal/client-boundary.ts +266 -266
  269. package/src/internal/index.ts +2 -2
  270. package/src/kitchen/api/agent-devtools-api.ts +779 -779
  271. package/src/kitchen/api/bundle-inspector.ts +179 -0
  272. package/src/kitchen/api/errors-grouping.ts +126 -126
  273. package/src/kitchen/api/file-api.ts +11 -11
  274. package/src/kitchen/kitchen-handler.ts +36 -0
  275. package/src/kitchen/kitchen-ui.ts +456 -0
  276. package/src/logging/index.ts +22 -22
  277. package/src/logging/transports.ts +365 -365
  278. package/src/middleware/bridge.ts +147 -147
  279. package/src/middleware/compose.ts +134 -134
  280. package/src/middleware/compress.ts +62 -62
  281. package/src/middleware/cors.ts +47 -47
  282. package/src/middleware/csrf.ts +328 -328
  283. package/src/middleware/define.ts +132 -132
  284. package/src/middleware/jwt.ts +134 -134
  285. package/src/middleware/logger.ts +58 -58
  286. package/src/middleware/oauth/__tests__/oauth.test.ts +1 -1
  287. package/src/middleware/oauth/index.ts +505 -505
  288. package/src/middleware/oauth/providers.ts +115 -115
  289. package/src/middleware/rate-limit/index.ts +522 -522
  290. package/src/middleware/rate-limit/sqlite-store.ts +382 -382
  291. package/src/middleware/scheduler-cron.ts +96 -96
  292. package/src/middleware/secure/__tests__/secure.test.ts +360 -360
  293. package/src/middleware/secure/csp.ts +193 -193
  294. package/src/middleware/session.ts +174 -174
  295. package/src/middleware/timeout.ts +55 -55
  296. package/src/observability/logger-adapter.ts +36 -36
  297. package/src/observability/sqlite-store.ts +254 -254
  298. package/src/openapi/generator.ts +1 -1
  299. package/src/openapi/openapi.test.ts +43 -43
  300. package/src/perf/__tests__/user-marks.test.ts +354 -354
  301. package/src/perf/index.ts +133 -133
  302. package/src/perf/user-marks.ts +1 -1
  303. package/src/plugins/__tests__/lifecycle-integration.test.ts +272 -272
  304. package/src/plugins/__tests__/runner.test.ts +409 -409
  305. package/src/plugins/define.ts +124 -124
  306. package/src/plugins/examples/dep-check-plugin.ts +80 -80
  307. package/src/plugins/examples/prerender-cache-plugin.ts +111 -111
  308. package/src/plugins/examples/sitemap-plugin.ts +65 -65
  309. package/src/plugins/runner.ts +361 -361
  310. package/src/plugins/types.ts +368 -368
  311. package/src/report/index.ts +1 -1
  312. package/src/resource/__tests__/generator.test.ts +7 -7
  313. package/src/resource/__tests__/schema.test.ts +14 -14
  314. package/src/resource/ddl/__tests__/diff.test.ts +639 -639
  315. package/src/resource/ddl/__tests__/emit.test.ts +165 -165
  316. package/src/resource/ddl/__tests__/snapshot.test.ts +499 -499
  317. package/src/resource/ddl/emit.ts +146 -146
  318. package/src/resource/ddl/persistence-types.ts +218 -218
  319. package/src/resource/ddl/type-map.ts +223 -223
  320. package/src/resource/ddl/types.ts +232 -232
  321. package/src/resource/generator-repo.ts +630 -630
  322. package/src/resource/generator-schema.ts +11 -11
  323. package/src/resource/generators/slot.ts +72 -72
  324. package/src/resource/schema.ts +21 -21
  325. package/src/router/client-entry.test.ts +227 -227
  326. package/src/router/client-entry.ts +218 -218
  327. package/src/router/fs-patterns.test.ts +96 -96
  328. package/src/router/fs-routes.test.ts +532 -532
  329. package/src/router/fs-routes.ts +53 -53
  330. package/src/router/fs-scanner.ts +216 -216
  331. package/src/router/fs-types.ts +19 -19
  332. package/src/router/route-source-analyzer.ts +521 -521
  333. package/src/routes/index.ts +74 -74
  334. package/src/routes/metadata-routes.ts +427 -427
  335. package/src/routes/types.ts +341 -341
  336. package/src/runtime/__tests__/devtools-adapter.test.ts +68 -68
  337. package/src/runtime/__tests__/error-boundary-redaction.test.ts +141 -141
  338. package/src/runtime/__tests__/hdr-client.test.ts +223 -223
  339. package/src/runtime/__tests__/http-errors.test.ts +117 -117
  340. package/src/runtime/__tests__/inline-client-hydration.test.ts +237 -237
  341. package/src/runtime/__tests__/not-found.test.ts +152 -152
  342. package/src/runtime/__tests__/observability-lifecycle.test.ts +103 -103
  343. package/src/runtime/__tests__/page-render-response.test.ts +517 -517
  344. package/src/runtime/__tests__/request-middleware.test.ts +70 -70
  345. package/src/runtime/__tests__/searchparams-page-props.test.ts +81 -81
  346. package/src/runtime/adapter.ts +47 -47
  347. package/src/runtime/boundary.tsx +252 -252
  348. package/src/runtime/cache.ts +494 -494
  349. package/src/runtime/compose.ts +222 -222
  350. package/src/runtime/devtools-adapter.ts +68 -68
  351. package/src/runtime/escape.ts +34 -34
  352. package/src/runtime/fast-refresh-runtime.ts +322 -322
  353. package/src/runtime/fast-refresh-types.ts +1 -1
  354. package/src/runtime/handler.ts +65 -65
  355. package/src/runtime/handlers.ts +30 -11
  356. package/src/runtime/http-errors.ts +113 -113
  357. package/src/runtime/image-handler.ts +1 -1
  358. package/src/runtime/lifecycle.ts +381 -381
  359. package/src/runtime/logger.test.ts +345 -345
  360. package/src/runtime/middleware.ts +264 -264
  361. package/src/runtime/not-found.ts +93 -93
  362. package/src/runtime/observability-lifecycle.ts +290 -290
  363. package/src/runtime/openapi-endpoint.ts +236 -236
  364. package/src/runtime/page-render-response.ts +287 -274
  365. package/src/runtime/ppr.ts +74 -74
  366. package/src/runtime/rate-limit.ts +1 -1
  367. package/src/runtime/redirect.ts +1 -1
  368. package/src/runtime/registry.ts +171 -171
  369. package/src/runtime/request-middleware.ts +31 -31
  370. package/src/runtime/router.test.ts +4 -4
  371. package/src/runtime/router.ts +10 -10
  372. package/src/runtime/server.ts +127 -211
  373. package/src/runtime/shims.ts +48 -48
  374. package/src/runtime/ssr.ts +43 -17
  375. package/src/runtime/static-files.ts +369 -289
  376. package/src/runtime/streaming-ssr.ts +219 -180
  377. package/src/runtime/trace.ts +144 -144
  378. package/src/scheduler/__tests__/scheduler.test.ts +12 -11
  379. package/src/scheduler/index.ts +11 -5
  380. package/src/scheduler/validate.ts +169 -169
  381. package/src/seo/index.ts +219 -219
  382. package/src/seo/integration/ssr.ts +306 -306
  383. package/src/seo/render/basic.ts +435 -435
  384. package/src/seo/render/index.ts +143 -143
  385. package/src/seo/render/jsonld.ts +539 -539
  386. package/src/seo/render/opengraph.ts +197 -197
  387. package/src/seo/render/robots.ts +116 -116
  388. package/src/seo/render/sitemap.ts +137 -137
  389. package/src/seo/render/twitter.ts +127 -127
  390. package/src/seo/resolve/opengraph.ts +143 -143
  391. package/src/seo/resolve/robots.ts +73 -73
  392. package/src/seo/resolve/title.ts +94 -94
  393. package/src/seo/resolve/twitter.ts +73 -73
  394. package/src/seo/resolve/url.ts +104 -104
  395. package/src/seo/routes/index.ts +290 -290
  396. package/src/seo/types.ts +588 -588
  397. package/src/slot/validator.ts +39 -39
  398. package/src/spec/schema.ts +35 -35
  399. package/src/storage/s3/__tests__/s3.test.ts +479 -479
  400. package/src/storage/s3/index.ts +412 -412
  401. package/src/testing/__tests__/assertions.test.ts +632 -632
  402. package/src/testing/__tests__/reporter.test.ts +454 -454
  403. package/src/testing/assertions.ts +986 -986
  404. package/src/testing/db.ts +157 -157
  405. package/src/testing/index.ts +9 -3
  406. package/src/testing/lcov.ts +192 -0
  407. package/src/testing/mocks.ts +203 -203
  408. package/src/testing/session.ts +190 -190
  409. package/src/types/branded.ts +56 -56
  410. package/src/types/index.ts +1 -1
  411. package/src/utils/safe-io.ts +188 -188
  412. package/src/utils/string-safe.ts +298 -298
  413. package/src/watcher/__tests__/watcher.test.ts +59 -59
  414. package/src/watcher/watcher.ts +61 -61
@@ -41,11 +41,16 @@ import {
41
41
  import { createHMRServer, type HMRServer } from "../dev";
42
42
  import { PORTS } from "../../constants";
43
43
 
44
+ const describeCoreIsolated =
45
+ process.env.MANDU_SKIP_CORE_ISOLATED_TESTS === "1"
46
+ ? describe.skip
47
+ : describe;
48
+
44
49
  // ═══════════════════════════════════════════════════════════════════
45
50
  // Section A — `ManduHot` runtime
46
51
  // ═══════════════════════════════════════════════════════════════════
47
52
 
48
- describe("createManduHot — Vite-compat import.meta.hot runtime", () => {
53
+ describeCoreIsolated("createManduHot — Vite-compat import.meta.hot runtime", () => {
49
54
  beforeEach(() => {
50
55
  _resetRegistryForTests();
51
56
  });
@@ -172,22 +177,22 @@ describe("createManduHot — Vite-compat import.meta.hot runtime", () => {
172
177
  * Utility: spin up an HMR server and return it plus the public port the
173
178
  * client should dial. The caller owns teardown via `afterEach`.
174
179
  *
175
- * We pass `port: 0` ... almost. `createHMRServer` computes
176
- * `port + PORTS.HMR_OFFSET` internally, so if we want an ephemeral
177
- * listener we'd need to bind ahead of time. These tests instead use a
178
- * process-local monotonic port allocator to avoid random collisions
179
- * during the full parallel core suite.
180
- */
181
- const HMR_TEST_PORT_STATE = "__MANDU_HMR_TEST_PORT_STATE__";
182
-
183
- function pickPort(): number {
184
- const stateGlobal = globalThis as typeof globalThis & {
185
- __MANDU_HMR_TEST_PORT_STATE__?: { next: number };
186
- };
187
- stateGlobal.__MANDU_HMR_TEST_PORT_STATE__ ??= { next: 0 };
188
- const index = stateGlobal.__MANDU_HMR_TEST_PORT_STATE__.next++;
189
- return 41000 + (((process.pid % 3500) * 2 + index * 2) % 7000);
190
- }
180
+ * We pass `port: 0` ... almost. `createHMRServer` computes
181
+ * `port + PORTS.HMR_OFFSET` internally, so if we want an ephemeral
182
+ * listener we'd need to bind ahead of time. These tests instead use a
183
+ * process-local monotonic port allocator to avoid random collisions
184
+ * during the full parallel core suite.
185
+ */
186
+ const HMR_TEST_PORT_STATE = "__MANDU_HMR_TEST_PORT_STATE__";
187
+
188
+ function pickPort(): number {
189
+ const stateGlobal = globalThis as typeof globalThis & {
190
+ __MANDU_HMR_TEST_PORT_STATE__?: { next: number };
191
+ };
192
+ stateGlobal.__MANDU_HMR_TEST_PORT_STATE__ ??= { next: 0 };
193
+ const index = stateGlobal.__MANDU_HMR_TEST_PORT_STATE__.next++;
194
+ return 41000 + (((process.pid % 3500) * 2 + index * 2) % 7000);
195
+ }
191
196
 
192
197
  /**
193
198
  * A wrapper around WebSocket that stashes every incoming message in an
@@ -206,7 +211,7 @@ interface MessageClient {
206
211
 
207
212
  async function connectWS(hmrPort: number, since?: number): Promise<MessageClient> {
208
213
  const qs = since !== undefined ? `?since=${since}` : "";
209
- const ws = new WebSocket(`ws://localhost:${hmrPort}${qs ? "/" + qs : ""}`);
214
+ const ws = new WebSocket(`ws://127.0.0.1:${hmrPort}${qs ? "/" + qs : ""}`);
210
215
  const messages: unknown[] = [];
211
216
  const waiters: Array<{ idx: number; resolve: (v: unknown) => void; reject: (e: Error) => void; timer: ReturnType<typeof setTimeout> }> = [];
212
217
 
@@ -262,14 +267,14 @@ function waitFor(ms: number): Promise<void> {
262
267
  return new Promise((r) => setTimeout(r, ms));
263
268
  }
264
269
 
265
- describe("createHMRServer — replay buffer semantics", () => {
270
+ describeCoreIsolated("createHMRServer — replay buffer semantics", () => {
266
271
  let server: HMRServer | null = null;
267
272
  let hmrPort = 0;
268
273
 
269
274
  beforeEach(() => {
270
275
  const basePort = pickPort();
271
276
  hmrPort = basePort + PORTS.HMR_OFFSET;
272
- server = createHMRServer(basePort);
277
+ server = createHMRServer(basePort, { hostname: "127.0.0.1" });
273
278
  });
274
279
 
275
280
  afterEach(() => {
@@ -366,14 +371,14 @@ describe("createHMRServer — replay buffer semantics", () => {
366
371
  // Section C — Wire-format + layout-update + invalidate upstream
367
372
  // ═══════════════════════════════════════════════════════════════════
368
373
 
369
- describe("createHMRServer — wire format + event dispatch", () => {
374
+ describeCoreIsolated("createHMRServer — wire format + event dispatch", () => {
370
375
  let server: HMRServer | null = null;
371
376
  let hmrPort = 0;
372
377
 
373
378
  beforeEach(() => {
374
379
  const basePort = pickPort();
375
380
  hmrPort = basePort + PORTS.HMR_OFFSET;
376
- server = createHMRServer(basePort);
381
+ server = createHMRServer(basePort, { hostname: "127.0.0.1" });
377
382
  });
378
383
 
379
384
  afterEach(() => {
@@ -442,6 +447,39 @@ describe("createHMRServer — wire format + event dispatch", () => {
442
447
  });
443
448
  });
444
449
 
450
+ test("[13a] a build error reaches new browsers until a successful recovery", async () => {
451
+ server!.broadcast({
452
+ type: "error",
453
+ data: {
454
+ name: "BuildError",
455
+ kind: "build",
456
+ message: "synthetic build failure",
457
+ routeId: "home",
458
+ timestamp: Date.now(),
459
+ },
460
+ });
461
+
462
+ const failedClient = await connectWS(hmrPort);
463
+ expect(await failedClient.awaitMessage(0)).toMatchObject({ type: "connected" });
464
+ expect(await failedClient.awaitMessage(1)).toMatchObject({
465
+ type: "error",
466
+ data: {
467
+ name: "BuildError",
468
+ kind: "build",
469
+ message: "synthetic build failure",
470
+ routeId: "home",
471
+ },
472
+ });
473
+ failedClient.ws.close();
474
+
475
+ server!.broadcast({ type: "reload", data: { timestamp: Date.now() } });
476
+ const recoveredClient = await connectWS(hmrPort);
477
+ expect(await recoveredClient.awaitMessage(0)).toMatchObject({ type: "connected" });
478
+ await waitFor(25);
479
+ expect(recoveredClient.peek()).toHaveLength(1);
480
+ recoveredClient.ws.close();
481
+ });
482
+
445
483
  test("[14] reconnect with since=0 after many broadcasts and no buffered survivors → full-reload", async () => {
446
484
  // Fire enough envelopes to push id past MAX_REPLAY_BUFFER — oldestId
447
485
  // becomes > 0, so since=0 is older than oldestId.
@@ -490,7 +528,7 @@ describe("createHMRServer — wire format + event dispatch", () => {
490
528
  // Section D — Integration: runtime + envelope produced by server
491
529
  // ═══════════════════════════════════════════════════════════════════
492
530
 
493
- describe("integration — ManduHot + broadcastVite envelope shape", () => {
531
+ describeCoreIsolated("integration — ManduHot + broadcastVite envelope shape", () => {
494
532
  beforeEach(() => {
495
533
  _resetRegistryForTests();
496
534
  });
@@ -521,7 +559,7 @@ describe("integration — ManduHot + broadcastVite envelope shape", () => {
521
559
 
522
560
  test("[17] HMRReplayEnvelope id is monotonic even across size eviction (ids don't reset)", () => {
523
561
  const envelopes: HMRReplayEnvelope[] = [];
524
- const server = createHMRServer(pickPort());
562
+ const server = createHMRServer(pickPort(), { hostname: "127.0.0.1" });
525
563
  try {
526
564
  for (let i = 0; i < MAX_REPLAY_BUFFER + 3; i++) {
527
565
  envelopes.push(server.broadcastVite({ type: "full-reload", path: `/p-${i}` }));
@@ -1,140 +1,179 @@
1
- /**
2
- * Regression guard for issues #322 / #323 — dev island hydration broke with
3
- * `TypeError: jsxDEV is not a function`.
4
- *
5
- * #322: the shim imported `jsxDEV` from bare `"react"`, which (via the import
6
- * map → `_react.js`) only worked if `_react.js` re-exported jsxDEV.
7
- * #323: the "fix" changed the import to `"react/jsx-dev-runtime"`, but the
8
- * import map maps `react/jsx-dev-runtime` to THIS shim — a circular
9
- * self-import, so jsxDEV stayed `undefined`.
10
- *
11
- * The correct source: import JSX runtime functions from bare `"react"`, which
12
- * the import map resolves to the self-contained `_react.js` vendor bundle
13
- * (built with no `external`, so the real jsx/jsxs/jsxDEV/Fragment are inlined
14
- * and re-exported). The shim must NEVER import from the import-map-aliased
15
- * subpath that points back at itself.
16
- */
17
- import { describe, expect, test } from "bun:test";
18
- import { mkdtemp, rm, writeFile } from "node:fs/promises";
19
- import { tmpdir } from "node:os";
20
- import path from "node:path";
21
- import { pathToFileURL } from "node:url";
22
- import {
23
- _testOnly_generateJsxDevRuntimeShimSource,
24
- _testOnly_generateJsxRuntimeShimSource,
25
- } from "../build";
26
-
27
- describe("JSX runtime shim sources (issues #322 / #323)", () => {
28
- test("dev shim imports jsxDEV/Fragment from bare 'react', never the self-aliased subpath", () => {
29
- const source = _testOnly_generateJsxDevRuntimeShimSource();
30
-
31
- // #323: must NOT import from 'react/jsx-dev-runtime' that is this shim's
32
- // own import-map alias, which would be a circular self-import. (Targets
33
- // the import statement, not comment mentions of the path.)
34
- expect(source).not.toMatch(/from\s*['"]react\/jsx-dev-runtime['"]/);
35
-
36
- // Correct: jsxDEV (+ jsx/jsxs fallback inputs) come from bare 'react'
37
- // (→ _react.js). Import includes jsxDEV and resolves from "react".
38
- expect(source).toMatch(/import\s*\{[^}]*\bjsxDEV\b[^}]*\}\s*from\s*['"]react['"]/);
39
-
40
- // Shim still re-exports what the import map expects.
41
- expect(source).toContain("export { jsxDEV, Fragment }");
42
- });
43
-
44
- test("prod shim imports jsx/jsxs/Fragment from bare 'react', never the self-aliased subpath", () => {
45
- const source = _testOnly_generateJsxRuntimeShimSource();
46
-
47
- // #323: must NOT import from 'react/jsx-runtime' (this shim's own alias).
48
- expect(source).not.toMatch(/from\s*['"]react\/jsx-runtime['"]/);
49
-
50
- expect(source).toMatch(
51
- /import\s*\{\s*jsx\s*,\s*jsxs\s*,\s*Fragment\s*\}\s*from\s*['"]react['"]/,
52
- );
53
-
54
- expect(source).toContain("export { jsx, jsxs, Fragment }");
55
- });
56
-
57
- // #323 build-level guard: the SOURCE test alone missed the real bug because
58
- // the broken 0.54.24 build still emitted `from "react/jsx-dev-runtime"` in
59
- // the OUTPUT (the import-map alias pointing back at this shim). Build the
60
- // shim the same way buildVendorShims does (external: ["react"]) and assert
61
- // the emitted module never self-imports the alias.
62
- test("built dev shim never self-imports react/jsx-dev-runtime", async () => {
63
- const dir = await mkdtemp(path.join(tmpdir(), "mandu-jsx-shim-"));
64
- try {
65
- const srcPath = path.join(dir, "_jsx-dev-runtime.js");
66
- await writeFile(srcPath, _testOnly_generateJsxDevRuntimeShimSource(), "utf-8");
67
-
68
- const result = await Bun.build({
69
- entrypoints: [srcPath],
70
- external: ["react"],
71
- target: "browser",
72
- });
73
-
74
- expect(result.success).toBe(true);
75
- const out = await result.outputs[0]!.text();
76
-
77
- // The emitted shim must source jsxDEV from bare 'react' (→ _react.js),
78
- // NOT from the import-map alias that resolves back to itself.
79
- expect(out).not.toMatch(/from\s*["']react\/jsx-dev-runtime["']/);
80
- expect(out).toMatch(/from\s*["']react["']/);
81
- expect(out).toContain("jsxDEV");
82
- } finally {
83
- await rm(dir, { recursive: true, force: true });
84
- }
85
- });
86
-
87
- // #323 re-regression (0.54.30): a SOURCE/static check passed but at RUNTIME
88
- // `_react.js`'s jsxDEV was `undefined` (jsxDEV is a React dev-only export;
89
- // a production-built _react.js drops it while keeping jsx/jsxs). The shim
90
- // re-exported that undefined "jsxDEV is not a function". Guard the VALUE:
91
- // build the dev shim against a `react` stub whose jsxDEV is undefined (the
92
- // exact failing condition) and assert the shim still exposes a callable
93
- // jsxDEV via its jsx/jsxs fallback.
94
- test("dev shim exposes a callable jsxDEV even when react.jsxDEV is undefined (runtime value)", async () => {
95
- const dir = await mkdtemp(path.join(tmpdir(), "mandu-jsx-shim-rt-"));
96
- try {
97
- // Stub for bare 'react' = a production-built _react.js: jsx/jsxs are real
98
- // functions, jsxDEV is missing.
99
- const reactStub = path.join(dir, "react-stub.js");
100
- await writeFile(
101
- reactStub,
102
- [
103
- "export const jsx = (type) => ({ type, runtime: 'jsx' });",
104
- "export const jsxs = (type) => ({ type, runtime: 'jsxs' });",
105
- "export const Fragment = Symbol.for('react.fragment');",
106
- "export const jsxDEV = undefined;",
107
- ].join("\n"),
108
- "utf-8",
109
- );
110
-
111
- // Generate the real shim source, but resolve its bare `react` import to
112
- // the stub so we can drive the undefined-jsxDEV condition.
113
- const shimSource = _testOnly_generateJsxDevRuntimeShimSource().replace(
114
- /from\s*['"]react['"]/g,
115
- `from ${JSON.stringify(reactStub.replace(/\\/g, "/"))}`,
116
- );
117
- const shimSrc = path.join(dir, "_jsx-dev-runtime.src.js");
118
- await writeFile(shimSrc, shimSource, "utf-8");
119
-
120
- const result = await Bun.build({
121
- entrypoints: [shimSrc],
122
- target: "browser",
123
- define: { "process.env.NODE_ENV": JSON.stringify("production") },
124
- });
125
- expect(result.success).toBe(true);
126
-
127
- const outPath = path.join(dir, "_jsx-dev-runtime.built.js");
128
- await writeFile(outPath, await result.outputs[0]!.text(), "utf-8");
129
- const mod = await import(`${pathToFileURL(outPath).href}?t=${Date.now()}`);
130
-
131
- // The whole point of #323's re-regression: jsxDEV must be CALLABLE.
132
- expect(typeof mod.jsxDEV).toBe("function");
133
- // Fallback routes static-children to jsxs, otherwise jsx.
134
- expect(mod.jsxDEV("div", {}, undefined, false).runtime).toBe("jsx");
135
- expect(mod.jsxDEV("div", {}, undefined, true).runtime).toBe("jsxs");
136
- } finally {
137
- await rm(dir, { recursive: true, force: true });
138
- }
139
- });
140
- });
1
+ /**
2
+ * Regression guard for issues #322 / #323 — dev island hydration broke with
3
+ * `TypeError: jsxDEV is not a function`.
4
+ *
5
+ * #322: the shim imported `jsxDEV` from bare `"react"`, which (via the import
6
+ * map → `_react.js`) only worked if `_react.js` re-exported jsxDEV.
7
+ * #323: the "fix" changed the import to `"react/jsx-dev-runtime"`, but the
8
+ * import map maps `react/jsx-dev-runtime` to THIS shim — a circular
9
+ * self-import, so jsxDEV stayed `undefined`.
10
+ *
11
+ * The correct source: import JSX runtime functions from bare `"react"`, which
12
+ * the import map resolves to the self-contained `_react.js` vendor bundle
13
+ * (built with no `external`, so the real jsx/jsxs/jsxDEV/Fragment are inlined
14
+ * and re-exported). The shim must NEVER import from the import-map-aliased
15
+ * subpath that points back at itself.
16
+ */
17
+ import { describe, expect, test } from "bun:test";
18
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
19
+ import { tmpdir } from "node:os";
20
+ import path from "node:path";
21
+ import {
22
+ _testOnly_generateJsxDevRuntimeShimSource,
23
+ _testOnly_generateJsxRuntimeShimSource,
24
+ } from "../build";
25
+
26
+ const describeBundler = describe.skipIf(
27
+ process.env.MANDU_SKIP_BUNDLER_TESTS === "1",
28
+ );
29
+
30
+ describeBundler("JSX runtime shim sources (issues #322 / #323)", () => {
31
+ test("dev shim imports jsxDEV/Fragment from bare 'react', never the self-aliased subpath", () => {
32
+ const source = _testOnly_generateJsxDevRuntimeShimSource();
33
+
34
+ // #323: must NOT import from 'react/jsx-dev-runtime' — that is this shim's
35
+ // own import-map alias, which would be a circular self-import. (Targets
36
+ // the import statement, not comment mentions of the path.)
37
+ expect(source).not.toMatch(/from\s*['"]react\/jsx-dev-runtime['"]/);
38
+
39
+ // Correct: jsxDEV (+ jsx/jsxs fallback inputs) come from bare 'react'
40
+ // (→ _react.js). Import includes jsxDEV and resolves from "react".
41
+ expect(source).toMatch(/import\s*\{[^}]*\bjsxDEV\b[^}]*\}\s*from\s*['"]react['"]/);
42
+
43
+ // Shim still re-exports what the import map expects.
44
+ expect(source).toContain("export { jsxDEV, Fragment }");
45
+ });
46
+
47
+ test("prod shim imports jsx/jsxs/Fragment from bare 'react', never the self-aliased subpath", () => {
48
+ const source = _testOnly_generateJsxRuntimeShimSource();
49
+
50
+ // #323: must NOT import from 'react/jsx-runtime' (this shim's own alias).
51
+ expect(source).not.toMatch(/from\s*['"]react\/jsx-runtime['"]/);
52
+
53
+ expect(source).toMatch(
54
+ /import\s*\{\s*jsx\s*,\s*jsxs\s*,\s*Fragment\s*\}\s*from\s*['"]react['"]/,
55
+ );
56
+
57
+ expect(source).toContain("export { jsx, jsxs, Fragment }");
58
+ });
59
+
60
+ // #323 build-level guard: the SOURCE test alone missed the real bug because
61
+ // the broken 0.54.24 build still emitted `from "react/jsx-dev-runtime"` in
62
+ // the OUTPUT (the import-map alias pointing back at this shim). Build the
63
+ // shim the same way buildVendorShims does (external: ["react"]) and assert
64
+ // the emitted module never self-imports the alias.
65
+ test("built dev shim never self-imports react/jsx-dev-runtime", async () => {
66
+ const dir = await mkdtemp(path.join(tmpdir(), "mandu-jsx-shim-"));
67
+ try {
68
+ const srcPath = path.join(dir, "_jsx-dev-runtime.js");
69
+ await writeFile(srcPath, _testOnly_generateJsxDevRuntimeShimSource(), "utf-8");
70
+
71
+ const result = await Bun.build({
72
+ entrypoints: [srcPath],
73
+ external: ["react"],
74
+ target: "browser",
75
+ });
76
+
77
+ expect(result.success).toBe(true);
78
+ const out = await result.outputs[0]!.text();
79
+
80
+ // The emitted shim must source jsxDEV from bare 'react' (→ _react.js),
81
+ // NOT from the import-map alias that resolves back to itself.
82
+ expect(out).not.toMatch(/from\s*["']react\/jsx-dev-runtime["']/);
83
+ expect(out).toMatch(/from\s*["']react["']/);
84
+ expect(out).toContain("jsxDEV");
85
+ } finally {
86
+ await rm(dir, { recursive: true, force: true });
87
+ }
88
+ });
89
+
90
+ // #323 re-regression (0.54.30): a SOURCE/static check passed but at RUNTIME
91
+ // `_react.js`'s jsxDEV was `undefined` (jsxDEV is a React dev-only export;
92
+ // a production-built _react.js drops it while keeping jsx/jsxs). The shim
93
+ // re-exported that undefined → "jsxDEV is not a function". Guard the VALUE:
94
+ // build the dev shim against a `react` stub whose jsxDEV is undefined (the
95
+ // exact failing condition) and assert the shim still exposes a callable
96
+ // jsxDEV via its jsx/jsxs fallback.
97
+ test("dev shim exposes a callable jsxDEV even when react.jsxDEV is undefined (runtime value)", async () => {
98
+ const dir = await mkdtemp(path.join(tmpdir(), "mandu-jsx-shim-rt-"));
99
+ try {
100
+ // Stub for bare 'react' = a production-built _react.js: jsx/jsxs are real
101
+ // functions, jsxDEV is missing.
102
+ const reactStub = path.join(dir, "react-stub.js");
103
+ await writeFile(
104
+ reactStub,
105
+ [
106
+ "export const jsx = (type) => ({ type, runtime: 'jsx' });",
107
+ "export const jsxs = (type) => ({ type, runtime: 'jsxs' });",
108
+ "export const Fragment = Symbol.for('react.fragment');",
109
+ "export const jsxDEV = undefined;",
110
+ ].join("\n"),
111
+ "utf-8",
112
+ );
113
+
114
+ // Generate the real shim source, but resolve its bare `react` import to
115
+ // the stub so we can drive the undefined-jsxDEV condition.
116
+ const shimSource = _testOnly_generateJsxDevRuntimeShimSource().replace(
117
+ /from\s*['"]react['"]/g,
118
+ `from ${JSON.stringify(reactStub.replace(/\\/g, "/"))}`,
119
+ );
120
+ const shimSrc = path.join(dir, "_jsx-dev-runtime.src.js");
121
+ await writeFile(shimSrc, shimSource, "utf-8");
122
+
123
+ const result = await Bun.build({
124
+ entrypoints: [shimSrc],
125
+ target: "browser",
126
+ define: { "process.env.NODE_ENV": JSON.stringify("production") },
127
+ });
128
+ expect(result.success).toBe(true);
129
+
130
+ const outPath = path.join(dir, "_jsx-dev-runtime.built.js");
131
+ await writeFile(outPath, await result.outputs[0]!.text(), "utf-8");
132
+
133
+ // Import through a relative specifier in a fresh Bun process. This
134
+ // exercises the public export while avoiding Bun 1.3's unreliable
135
+ // in-process resolution of temporary absolute file URLs on macOS.
136
+ const probePath = path.join(dir, "probe.js");
137
+ await writeFile(
138
+ probePath,
139
+ [
140
+ "import * as runtime from './_jsx-dev-runtime.built.js';",
141
+ "console.log(JSON.stringify({",
142
+ " type: typeof runtime.jsxDEV,",
143
+ " single: runtime.jsxDEV('div', {}, undefined, false).runtime,",
144
+ " multi: runtime.jsxDEV('div', {}, undefined, true).runtime,",
145
+ "}));",
146
+ ].join("\n"),
147
+ "utf-8",
148
+ );
149
+
150
+ const proc = Bun.spawn([process.execPath, "run", probePath], {
151
+ cwd: dir,
152
+ stdin: "ignore",
153
+ stdout: "pipe",
154
+ stderr: "pipe",
155
+ });
156
+ const [stdout, stderr, exitCode] = await Promise.all([
157
+ new Response(proc.stdout).text(),
158
+ new Response(proc.stderr).text(),
159
+ proc.exited,
160
+ ]);
161
+ if (exitCode !== 0) {
162
+ throw new Error(`Built JSX runtime probe failed (${exitCode}): ${stderr}`);
163
+ }
164
+ const probe = JSON.parse(stdout.trim()) as {
165
+ type: string;
166
+ single: string;
167
+ multi: string;
168
+ };
169
+
170
+ // The whole point of #323's re-regression: jsxDEV must be CALLABLE.
171
+ expect(probe.type).toBe("function");
172
+ // Fallback routes static-children to jsxs, otherwise jsx.
173
+ expect(probe.single).toBe("jsx");
174
+ expect(probe.multi).toBe("jsxs");
175
+ } finally {
176
+ await rm(dir, { recursive: true, force: true });
177
+ }
178
+ });
179
+ });