void 1.5.0 → 1.6.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 (178) hide show
  1. package/dist/{account-cmd-ChVKPZ-w.mjs → account-cmd-DRhmCWcm.mjs} +3 -3
  2. package/dist/{application-analysis-2vGZrKzg.mjs → application-analysis-HRFsZOv3.mjs} +3 -3
  3. package/dist/{application-routing-DnUQoOJD.mjs → application-routing-P4TggvWp.mjs} +1 -1
  4. package/dist/{auth-link-D4uMdOsw.mjs → auth-link-CVXP1G6G.mjs} +3 -3
  5. package/dist/{auth-router-62dna450.mjs → auth-router-D1pGdbvB.mjs} +2 -2
  6. package/dist/{better-auth-shared-CiclgPde.mjs → better-auth-shared-C958aM7W.mjs} +28 -3
  7. package/dist/{build-cmd-D93K_4Sa.mjs → build-cmd-DmjbuT6d.mjs} +1 -1
  8. package/dist/{cache-CiIzEED4.mjs → cache-2khBO1MR.mjs} +1 -1
  9. package/dist/{cancel-deploy-BNoGfn2e.mjs → cancel-deploy-_itbbvY3.mjs} +1 -1
  10. package/dist/cli/cli.mjs +27 -27
  11. package/dist/client-CEtr5UOR.mjs +1 -0
  12. package/dist/{client-Qayy9xEh.mjs → client-CoxPEhJq.mjs} +6 -2
  13. package/dist/{cloudflare-cmd-DiFGaLow.mjs → cloudflare-cmd-fZ6AMSWk.mjs} +1 -1
  14. package/dist/{cloudflare-config-Chet188_.mjs → cloudflare-config-eQunqX6A.mjs} +1 -1
  15. package/dist/{cloudflare-connect-BdgAQBc7.mjs → cloudflare-connect-9OZe4XVQ.mjs} +1 -1
  16. package/dist/{cloudflare-operations-CWA24vCh.mjs → cloudflare-operations-CrskD4_O.mjs} +4 -4
  17. package/dist/{cloudflare-operations-D8MoezuN.mjs → cloudflare-operations-oLvAd9Nd.mjs} +1 -1
  18. package/dist/{config-Bt4rw93x.mjs → config-BBlVXZCU.mjs} +1 -1
  19. package/dist/{config-DkA9jYF2.mjs → config-BITKQ3O6.mjs} +2 -1
  20. package/dist/{config-BszFVhpk.mjs → config-BgysUhnm.mjs} +1 -1
  21. package/dist/{config-CzsNzGVH.d.mts → config-CPxJmt4M.d.mts} +2 -0
  22. package/dist/config-entry.d.mts +1 -1
  23. package/dist/{connect-b9mJbb6X.mjs → connect-CKvmkl2R.mjs} +4 -4
  24. package/dist/{create-project-rnjum4_V.mjs → create-project-BiMmR5wA.mjs} +1 -1
  25. package/dist/{create-project-eomwm0wa.mjs → create-project-Bq0M8MtO.mjs} +1 -1
  26. package/dist/{db-UPWmiSk1.mjs → db-cq5RW4Vy.mjs} +17 -17
  27. package/dist/{delete-BeeYi1WO.mjs → delete-CY4L8fi2.mjs} +1 -1
  28. package/dist/deploy-B029oHlE.mjs +2 -0
  29. package/dist/{deploy-CwmCcTlq.mjs → deploy-D_gEojD2.mjs} +79 -42
  30. package/dist/{deploy-managed-static-gPDxyp3v.mjs → deploy-managed-static-BHVbB_-A.mjs} +11 -11
  31. package/dist/{deploy-transport-L6zzPE9T.mjs → deploy-transport-DEyOUfac.mjs} +2 -2
  32. package/dist/deploy.mjs +5 -4
  33. package/dist/{dev-inbox-CwH5VuZj.mjs → dev-inbox-CUUS6iUg.mjs} +1 -1
  34. package/dist/{dispatch-CiJ1Xrba.mjs → dispatch-BNLB5_Gm.mjs} +1 -1
  35. package/dist/{domain-3xdH9p2L.mjs → domain-BlH90Ods.mjs} +2 -2
  36. package/dist/{email-Du3YRnM5.mjs → email-Bkq8ZL1p.mjs} +6 -6
  37. package/dist/{email-cloudflare-CtD8qE13.mjs → email-cloudflare-MvJIxrwx.mjs} +5 -107
  38. package/dist/{env-Cnvp0pGy.mjs → env-AvuCSeCH.mjs} +2 -2
  39. package/dist/{gen-BvVmpZ5f.mjs → gen-BD-dfjxY.mjs} +3 -3
  40. package/dist/gen-CIHXh9I8.mjs +1 -0
  41. package/dist/{github-cmd-X2GKiLi-.mjs → github-cmd-CA-lBdkn.mjs} +1 -1
  42. package/dist/{handler-Drm_lyrV.d.mts → handler-BR6Tvjkp.d.mts} +8 -3
  43. package/dist/{handler-xmzz0U38.mjs → handler-CKeTtYID.mjs} +2 -12
  44. package/dist/headers-CuTEdP9C.mjs +445 -0
  45. package/dist/{help-EWDNxST-.mjs → help-1OCFDsRr.mjs} +9 -1
  46. package/dist/help-Ba8Dq5-r.mjs +1 -0
  47. package/dist/{inbound-DSKSHDUj.d.mts → inbound-BHt4dIlL.d.mts} +16 -5
  48. package/dist/{inbound-DQfekMtz.mjs → inbound-CdO-qY0w.mjs} +2 -76
  49. package/dist/index.d.mts +1 -1
  50. package/dist/index.mjs +65 -37
  51. package/dist/{info-jW8_d3VI.mjs → info-CJxua_db.mjs} +4 -4
  52. package/dist/{init-jDQ5G9QC.mjs → init-B-4CluYx.mjs} +12 -11
  53. package/dist/{isr-config-DhBkzCdY.mjs → isr-config-Czzb4mIq.mjs} +1 -47
  54. package/dist/{link-DOyxX5Xs.mjs → link-DAXOT-G_.mjs} +2 -2
  55. package/dist/{list-C9pTYDtl.mjs → list-BYSOo9fm.mjs} +2 -2
  56. package/dist/{live-CDBHyYiR.d.mts → live-0xrcVpyq.d.mts} +1 -1
  57. package/dist/{local-d1-CKfek6Z4.mjs → local-d1-BLgsNUj9.mjs} +1 -1
  58. package/dist/login-BpbYeu-n.mjs +1 -0
  59. package/dist/{login-koQbjzPd.mjs → login-CJopTWX4.mjs} +2 -2
  60. package/dist/{logs-cTU5TsRW.mjs → logs-DE0weBsR.mjs} +13 -11
  61. package/dist/{migrate-C62pGTfr.mjs → migrate-ChHHZBTi.mjs} +3 -3
  62. package/dist/migrate-HdA6Kh2p.mjs +1 -0
  63. package/dist/{mime-DKkO7ZtA.mjs → mime-CtP6-qAF.mjs} +143 -15
  64. package/dist/nitro.mjs +3 -3
  65. package/dist/{node-BfAt2rz8.mjs → node-CZ6lGNLn.mjs} +1 -1
  66. package/dist/{operator-cmd-CnAvSqJ5.mjs → operator-cmd-BUqsdk2K.mjs} +28 -10
  67. package/dist/operator-cmd-wBYyp8iQ.mjs +1 -0
  68. package/dist/pages/client.d.mts +143 -11
  69. package/dist/pages/client.mjs +173 -12
  70. package/dist/pages/index.d.mts +22 -3
  71. package/dist/pages/index.mjs +18 -4
  72. package/dist/pages/islands-plugin.d.mts +46 -2
  73. package/dist/pages/islands-plugin.mjs +91 -5
  74. package/dist/pages/prefetch.d.mts +2 -2
  75. package/dist/pages/prefetch.mjs +1 -1
  76. package/dist/pages/protocol.d.mts +2 -2
  77. package/dist/pages/protocol.mjs +2 -2
  78. package/dist/platform-args-C7XUw9mw.mjs +1 -0
  79. package/dist/{platform-args-Bv9hoLEL.mjs → platform-args-Cx1M-7bq.mjs} +18 -4
  80. package/dist/{platform-auth-config-CLj0EvnB.mjs → platform-auth-config-K4m_LE8b.mjs} +4 -4
  81. package/dist/{platform-auth-protection-DQDSxVhr.mjs → platform-auth-protection-KF5Vo-1I.mjs} +2 -2
  82. package/dist/{platform-auth-recovery-DD3oLerq.mjs → platform-auth-recovery-BOdFrl7R.mjs} +2 -2
  83. package/dist/{platform-cmd-WnOmdLzR.mjs → platform-cmd-DpCHawGF.mjs} +1 -1
  84. package/dist/{platform-cmd-PLNLg-2N.mjs → platform-cmd-Ds3EAV5t.mjs} +5 -4
  85. package/dist/{platform-domain-Bnq0vg0q.mjs → platform-domain-rWJshybd.mjs} +2 -2
  86. package/dist/{platform-lifecycle-BQiN9HN5.mjs → platform-lifecycle-BH34I0rh.mjs} +1 -1
  87. package/dist/{platform-lifecycle-BCsFg1Tl.mjs → platform-lifecycle-D9RdGub1.mjs} +66 -31
  88. package/dist/{platform-management-nzCDwtiN.mjs → platform-management-BRefdHGD.mjs} +21 -3
  89. package/dist/{platform-management-CMJR8Zi-.mjs → platform-management-BfLW0Zlo.mjs} +1 -1
  90. package/dist/{platform-recovery-DBNoME3I.mjs → platform-recovery-DZuZGJtt.mjs} +2 -2
  91. package/dist/platform-runtime-logs-CdJGnk3f.mjs +68 -0
  92. package/dist/{platform-setup-VEcHu0Vq.mjs → platform-setup-Vw1AaUN8.mjs} +15 -2
  93. package/dist/{plugin-inference-DmwjC3y2.mjs → plugin-inference-CdLbxZL_.mjs} +1 -1
  94. package/dist/{prefetch-L93_1Jk7.mjs → prefetch-Dx2jIbtg.mjs} +19 -1
  95. package/dist/{prefetch-CG0K6JPd.d.mts → prefetch-NdNeubbH.d.mts} +7 -1
  96. package/dist/{prepare-pfl2LIMy.mjs → prepare-BJW-f1f1.mjs} +4 -4
  97. package/dist/{prepare-BPsfLWaW.mjs → prepare-BMGeKL16.mjs} +1 -1
  98. package/dist/prepare-BdxJJCMv.mjs +1 -0
  99. package/dist/{project-cmd-5Izu4Pg3.mjs → project-cmd-B_bUyZ3J.mjs} +15 -15
  100. package/dist/{project-team-DSUyjZFh.mjs → project-team-MjT5K4rQ.mjs} +1 -1
  101. package/dist/{project-token-wj09YQSB.mjs → project-token-BKHGwY3k.mjs} +1 -1
  102. package/dist/{project-zero-trust-BMHf2YF0.mjs → project-zero-trust-Bzdd05-h.mjs} +1 -1
  103. package/dist/{protocol-0-lp9ZYx.mjs → protocol-COyySMki.mjs} +130 -107
  104. package/dist/{protocol-xdrl-In0.d.mts → protocol-CkwjASep.d.mts} +2 -2
  105. package/dist/{provision-CRiNnlfE.mjs → provision-BbCzpbXs.mjs} +1 -1
  106. package/dist/{provision-CxHIGBIZ.mjs → provision-DQF6Kw-6.mjs} +1 -1
  107. package/dist/{requests-DicgB5jU.mjs → requests-daJmVpjk.mjs} +1 -1
  108. package/dist/{rollback-DrDZOKNE.mjs → rollback-BgL0wY1J.mjs} +2 -2
  109. package/dist/{route-types-irZc1txT.mjs → route-types-CZc1YXjF.mjs} +40 -4
  110. package/dist/route-url-C_YIH_zO.d.mts +37 -0
  111. package/dist/routes-stub.d.mts +6 -2
  112. package/dist/runtime/better-auth-mysql.mjs +1 -1
  113. package/dist/runtime/better-auth-pg.mjs +1 -1
  114. package/dist/runtime/better-auth.mjs +1 -1
  115. package/dist/runtime/email/testing.d.mts +1 -1
  116. package/dist/runtime/email/testing.mjs +3 -3
  117. package/dist/runtime/email.d.mts +1 -1
  118. package/dist/runtime/email.mjs +3 -3
  119. package/dist/runtime/handler.d.mts +1 -1
  120. package/dist/runtime/handler.mjs +2 -2
  121. package/dist/runtime/live-client.d.mts +1 -1
  122. package/dist/runtime/live.d.mts +1 -1
  123. package/dist/runtime/route-url.d.mts +2 -2
  124. package/dist/runtime/routing.d.mts +3 -3
  125. package/dist/runtime/routing.mjs +37 -16
  126. package/dist/runtime/validator.d.mts +1 -1
  127. package/dist/runtime/ws-server.d.mts +1 -1
  128. package/dist/runtime/ws.d.mts +1 -1
  129. package/dist/{scan-DSQtH3oS.mjs → scan-X2rDDRNa.mjs} +18 -10
  130. package/dist/{secret-C_QtTzJG.mjs → secret-CPq-B_vp.mjs} +2 -2
  131. package/dist/{static-asset-marker-NR1XS2z5.mjs → static-asset-marker-DsQKz6lt.mjs} +8 -1
  132. package/dist/validation-error-uAAjlsiW.mjs +82 -0
  133. package/dist/{version-metadata-Blf5H9BQ.mjs → version-metadata-C8hLzQkv.mjs} +1 -1
  134. package/dist/{wrangler-p-kLCJqF.mjs → wrangler-DESSbN8L.mjs} +2 -2
  135. package/dist/wrangler-DUB3MGHV.mjs +1 -0
  136. package/dist/{wrapper-iejSJDwL.mjs → wrapper-C9SUxoj7.mjs} +2 -2
  137. package/dist/{ws-DzBD-NUj.d.mts → ws-Dmjg5NH2.d.mts} +1 -1
  138. package/docs/guide/edge/headers.md +2 -0
  139. package/docs/guide/edge/rewrites.md +1 -1
  140. package/docs/guide/email/receiving.md +1 -1
  141. package/docs/guide/email/sending.md +42 -12
  142. package/docs/guide/pages-routing/actions-and-forms.md +21 -1
  143. package/docs/guide/pages-routing/islands.md +3 -3
  144. package/docs/guide/pages-routing/layouts.md +16 -2
  145. package/docs/guide/pages-routing/loaders.md +2 -2
  146. package/docs/guide/pages-routing/markdown.md +1 -1
  147. package/docs/guide/pages-routing/overview.md +103 -0
  148. package/docs/guide/platform/administration/connected-apps.md +4 -2
  149. package/docs/guide/platform/installation/credentials.md +6 -4
  150. package/docs/guide/platform/installation/maintenance.md +13 -0
  151. package/docs/guide/platform/installation/setup.md +22 -1
  152. package/docs/guide/ssg.md +3 -3
  153. package/docs/guide/type-safety.md +42 -1
  154. package/docs/integrations/frameworks/astro.md +17 -12
  155. package/docs/integrations/frameworks/overview.md +2 -2
  156. package/docs/reference/api/pages.md +101 -50
  157. package/docs/reference/api/rewrites.md +4 -1
  158. package/docs/reference/api/types.md +14 -10
  159. package/docs/reference/api.md +1 -1
  160. package/docs/reference/cli/platform-installation.md +4 -1
  161. package/docs/reference/cli/setup.md +1 -1
  162. package/docs/reference/config.md +10 -0
  163. package/package.json +8 -7
  164. package/schema.json +4 -0
  165. package/skills/void/SKILL.md +5 -0
  166. package/dist/client-DVtAKeUm.mjs +0 -1
  167. package/dist/deploy-CfU7CR-b.mjs +0 -2
  168. package/dist/gen-i61rdQgg.mjs +0 -1
  169. package/dist/headers-DEUBAM6W.mjs +0 -225
  170. package/dist/help-BcZDUcTw.mjs +0 -1
  171. package/dist/login-C0MiQrYs.mjs +0 -1
  172. package/dist/migrate-BG09-KOv.mjs +0 -1
  173. package/dist/operator-cmd-BhHXIL2G.mjs +0 -1
  174. package/dist/platform-args-C1kqYUen.mjs +0 -1
  175. package/dist/prepare-BJMmfq3W.mjs +0 -1
  176. package/dist/route-url-BGOiyKNz.d.mts +0 -24
  177. package/dist/validation-error-rDVbUJet.mjs +0 -47
  178. package/dist/wrangler-CPRX2d9A.mjs +0 -1
@@ -1,5 +1,124 @@
1
1
  import { n as bytesToBase64 } from "./base64-ikl9yBy3.mjs";
2
2
  import { validate } from "email-validator";
3
+ // src/runtime/email/threading.ts
4
+ /**
5
+ * Header-value checks shared by the MIME builder and the reply path, and the
6
+ * best-effort cleaning of `In-Reply-To` / `References` ids. Thread ids usually
7
+ * come from remote mail, so an id that cannot be sent is left out instead of
8
+ * failing the message. No imports, so both `mime.ts` and `inbound.ts` can use it.
9
+ */
10
+ /**
11
+ * Index of the first C0 control other than HTAB, or DEL; -1 when there is
12
+ * none. HTAB is folding whitespace (RFC 5322 §3.2.2).
13
+ */
14
+ function indexOfControl(value) {
15
+ for (let i = 0; i < value.length; i++) {
16
+ const c = value.charCodeAt(i);
17
+ if (c < 32 && c !== 9 || c === 127) return i;
18
+ }
19
+ return -1;
20
+ }
21
+ /**
22
+ * `value` without leading or trailing SP and HTAB, the only whitespace a
23
+ * `Headers` value is trimmed of. `String#trim` would also strip U+00A0.
24
+ */
25
+ function trimFws(value) {
26
+ let start = 0;
27
+ let end = value.length;
28
+ while (start < end && (value.charCodeAt(start) === 32 || value.charCodeAt(start) === 9)) start++;
29
+ while (end > start && (value.charCodeAt(end - 1) === 32 || value.charCodeAt(end - 1) === 9)) end--;
30
+ return value.slice(start, end);
31
+ }
32
+ /**
33
+ * Whether `Name: value` fits RFC 5322's 998-octet line once folded. It
34
+ * follows `foldHeader`: a fold point is SP or HTAB outside a quoted string,
35
+ * so the widest run between fold points decides.
36
+ */
37
+ function fitsHeaderLine(name, value) {
38
+ if (!value) return false;
39
+ const budget = 998 - (name.length + 2);
40
+ let run = 0;
41
+ let inQuotes = false;
42
+ let escape = false;
43
+ for (let i = 0; i < value.length; i++) {
44
+ const c = value.charCodeAt(i);
45
+ if (escape) escape = false;
46
+ else if (c === 92 && inQuotes) escape = true;
47
+ else if (c === 34) inQuotes = !inQuotes;
48
+ else if ((c === 32 || c === 9) && !inQuotes) {
49
+ run = 0;
50
+ continue;
51
+ }
52
+ if (c < 128) run += 1;
53
+ else if (c < 2048) run += 2;
54
+ else if (c >= 55296 && c <= 56319 && i + 1 < value.length && (value.charCodeAt(i + 1) & 64512) === 56320) {
55
+ run += 4;
56
+ i++;
57
+ } else run += 3;
58
+ if (run > budget) return false;
59
+ }
60
+ return true;
61
+ }
62
+ /**
63
+ * Longest `References` value, in UTF-16 code units. 8 KiB keeps any real
64
+ * thread whole; past it the newest ids are kept, since mail clients thread on
65
+ * any id they recognise and the parent is `In-Reply-To`.
66
+ */
67
+ const MAX_REFERENCES_CHARS = 8192;
68
+ /**
69
+ * The newest whole ids of `chain` that fit `budget` code units, without the
70
+ * ids that hold a control character.
71
+ */
72
+ function newestIds(chain, budget) {
73
+ if (chain.length > budget) {
74
+ let cut = chain.length - budget;
75
+ while (cut < chain.length) {
76
+ const c = chain.charCodeAt(cut);
77
+ if (c === 32 || c === 9) break;
78
+ cut++;
79
+ }
80
+ chain = chain.slice(cut);
81
+ }
82
+ return dropControlIds(chain);
83
+ }
84
+ /** `chain` without the ids that hold a control character, joined by single spaces. */
85
+ function dropControlIds(chain) {
86
+ if (indexOfControl(chain) === -1) return chain;
87
+ const kept = [];
88
+ let start = -1;
89
+ let tainted = false;
90
+ for (let i = 0; i <= chain.length; i++) {
91
+ const c = i < chain.length ? chain.charCodeAt(i) : 32;
92
+ if (c === 32 || c === 9) {
93
+ if (start >= 0 && !tainted) kept.push(chain.slice(start, i));
94
+ start = -1;
95
+ tainted = false;
96
+ } else {
97
+ if (start < 0) start = i;
98
+ if (c < 32 || c === 127) tainted = true;
99
+ }
100
+ }
101
+ return kept.join(" ");
102
+ }
103
+ /** `id` when it fits one `name:` line and holds no control character, else `''`. */
104
+ function threadingId(name, id) {
105
+ return fitsHeaderLine(name, id) && indexOfControl(id) === -1 ? id : "";
106
+ }
107
+ /** `References` cut to its newest whole ids, or `''` when an id cannot fit a line. */
108
+ function threadingReferences(chain) {
109
+ const kept = newestIds(chain, MAX_REFERENCES_CHARS).trim();
110
+ return fitsHeaderLine("References", kept) ? kept : "";
111
+ }
112
+ /**
113
+ * A reply's `References`, or `''`: the inbound chain plus the parent's id,
114
+ * trimmed to its newest whole ids, or the parent's id alone when an id
115
+ * cannot fit a line. `messageId` was already checked with `threadingId`.
116
+ */
117
+ function replyReferences(originalReferences, messageId) {
118
+ const parent = messageId ? ` ${messageId}` : "";
119
+ const chain = `${newestIds(originalReferences, MAX_REFERENCES_CHARS - parent.length)}${parent}`.trim();
120
+ return fitsHeaderLine("References", chain) ? chain : messageId;
121
+ }
3
122
  // src/runtime/email/mime.ts
4
123
  /**
5
124
  * Minimal RFC 5322 / 2047 / 2045 MIME builder for the void/email runtime.
@@ -29,17 +148,6 @@ function rejectCRLF(field, value) {
29
148
  }
30
149
  }
31
150
  /**
32
- * Index of the first C0 control other than HTAB, or DEL; -1 when there is
33
- * none. HTAB is folding whitespace (RFC 5322 §3.2.2).
34
- */
35
- function indexOfControl(value) {
36
- for (let i = 0; i < value.length; i++) {
37
- const c = value.charCodeAt(i);
38
- if (c < 32 && c !== 9 || c === 127) return i;
39
- }
40
- return -1;
41
- }
42
- /**
43
151
  * Refuse a control in a value rendered verbatim into a header (an
44
152
  * attachment's filename, media type and Content-ID). Names the code point,
45
153
  * never the value.
@@ -350,8 +458,7 @@ async function normalizeEmail(opts) {
350
458
  if (attachmentBytes > MAX_ATTACHMENT_BYTES_TOTAL) throw attachmentsTooLargeError(attachmentBytes);
351
459
  attachments.push(normalized);
352
460
  }
353
- if (opts.threading?.inReplyTo) rejectCRLF("threading.inReplyTo", opts.threading.inReplyTo);
354
- if (opts.threading?.references) rejectCRLF("threading.references", opts.threading.references);
461
+ const threading = normalizeThreading(opts.threading);
355
462
  return {
356
463
  from,
357
464
  to,
@@ -363,7 +470,28 @@ async function normalizeEmail(opts) {
363
470
  html: opts.html,
364
471
  headers: opts.headers ? { ...opts.headers } : {},
365
472
  attachments,
366
- threading: opts.threading
473
+ threading
474
+ };
475
+ }
476
+ /**
477
+ * `threading` from `sendEmail`, `createEmail` or `replyEmail`. A value that is
478
+ * not a string is a caller error. Thread ids often come from remote mail, so a
479
+ * bad id never fails the email: an `inReplyTo` with a control character or
480
+ * too long for one line is left out, and a `references` chain that cannot be
481
+ * sent falls back to `inReplyTo`.
482
+ */
483
+ function normalizeThreading(threading) {
484
+ if (threading === void 0) return;
485
+ if (typeof threading !== "object" || threading === null || Array.isArray(threading)) throw new MimeError("MIME_ERROR", "threading: must be an object.");
486
+ const { inReplyTo = "", references = "" } = threading;
487
+ if (typeof inReplyTo !== "string") throw new MimeError("MIME_ERROR", "threading.inReplyTo: must be a string.");
488
+ if (typeof references !== "string") throw new MimeError("MIME_ERROR", "threading.references: must be a string.");
489
+ const parent = threadingId("In-Reply-To", trimFws(inReplyTo));
490
+ const chain = threadingReferences(references) || parent;
491
+ if (!parent && !chain) return;
492
+ return {
493
+ ...parent ? { inReplyTo: parent } : {},
494
+ ...chain ? { references: chain } : {}
367
495
  };
368
496
  }
369
497
  /**
@@ -873,4 +1001,4 @@ function buildMime(email) {
873
1001
  messageId
874
1002
  };
875
1003
  }
876
- export { newId as a, validateAddressParts as c, indexOfControl as i, MimeError as n, normalizeEmail as o, buildMime as r, parseAddress as s, MAX_MESSAGE_BYTES as t };
1004
+ export { normalizeEmail as a, fitsHeaderLine as c, newId as i, replyReferences as l, MimeError as n, parseAddress as o, buildMime as r, validateAddressParts as s, MAX_MESSAGE_BYTES as t, threadingId as u };
package/dist/nitro.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { a as join, n as dirname } from "./dist-DMYe8CZJ.mjs";
2
- import { l as getDatabaseDialect, p as readConfig } from "./config-DkA9jYF2.mjs";
3
- import { c as voidDbBundlerPlugin } from "./dispatch-CiJ1Xrba.mjs";
4
- import { n as bundleWorkerSqlDriver } from "./wrapper-iejSJDwL.mjs";
2
+ import { l as getDatabaseDialect, p as readConfig } from "./config-BITKQ3O6.mjs";
3
+ import { c as voidDbBundlerPlugin } from "./dispatch-BNLB5_Gm.mjs";
4
+ import { n as bundleWorkerSqlDriver } from "./wrapper-C9SUxoj7.mjs";
5
5
  import { normalizePath } from "vite";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { resolve } from "node:path/win32";
@@ -1,6 +1,6 @@
1
1
  import { n as dirname } from "./dist-DMYe8CZJ.mjs";
2
2
  import { a as projectAuthConfigImporter, i as loadVoidAuthConfig, r as findVoidAuthConfig } from "./config-WlvEcL82.mjs";
3
- import { p as readConfig } from "./config-DkA9jYF2.mjs";
3
+ import { p as readConfig } from "./config-BITKQ3O6.mjs";
4
4
  import { r as getMiniflareDatabasePath } from "./runner-5MCSimKx.mjs";
5
5
  import { s as loadLocalEnv } from "./env-CuzZZyjB.mjs";
6
6
  import { a as pgMigrationRunner, i as mysqlMigrationRunner, n as applyPgAuthMigrations, r as applySqliteAuthMigrations, t as applyMySqlAuthMigrations } from "./auth-migrations-DDeifS3v.mjs";
@@ -1,5 +1,6 @@
1
- import { h as sanitizeTerminalText, m as printSuccess } from "./output-BCdLioKP.mjs";
1
+ import { h as sanitizeTerminalText, i as dim, m as printSuccess } from "./output-BCdLioKP.mjs";
2
2
  import { n as OperatorClient, r as OperatorClientError } from "./operator-client-BIY4-N_6.mjs";
3
+ import { t as MINIMAL_RUNTIME_LOGS_NOTE } from "./platform-runtime-logs-CdJGnk3f.mjs";
3
4
  import { a as resolveOperatorOrigin, i as removeOperatorToken, n as readOperatorApiTokenStdin, o as saveOperatorToken, r as readOperatorToken, t as exchangeOperatorSession } from "./operator-auth-CfDcmzpo.mjs";
4
5
  import { createHash } from "node:crypto";
5
6
  import { setTimeout } from "node:timers/promises";
@@ -81,11 +82,16 @@ function outputMutation(result, args) {
81
82
  if (args.json || result.ok === false || result.partial === true || result.complete === false || result.error || result.operationStatus && result.operationStatus !== "completed" || configuration?.status && configuration.status !== "ready" && configuration.status !== "disabled" || project?.state === "reconciling" || project?.state === "error" || project?.last_error) return;
82
83
  printSuccess(`Platform ${args.group} ${args.action} completed.`);
83
84
  }
84
- function outputLogs(result, json) {
85
+ function outputLogs(result, json, state = {}) {
85
86
  if (json) {
86
87
  output(result, true);
87
88
  return;
88
89
  }
90
+ const minimal = result.runtimeLogs === "minimal";
91
+ if (minimal && !state.runtimeLogsNoted) {
92
+ state.runtimeLogsNoted = true;
93
+ console.log(dim(MINIMAL_RUNTIME_LOGS_NOTE));
94
+ }
89
95
  if (Array.isArray(result.lines)) {
90
96
  for (const entry of result.lines) if (entry && typeof entry === "object") {
91
97
  const line = entry;
@@ -100,15 +106,26 @@ function outputLogs(result, json) {
100
106
  continue;
101
107
  }
102
108
  const row = entry;
103
- console.log(`${printable(row.timestamp ?? row.ts)} ${printable(row.method)} ${printable(row.url)} ${printable(row.status ?? row.statusCode ?? row.outcome)}`);
109
+ const parts = [
110
+ printable(row.timestamp ?? row.ts),
111
+ printable(row.method),
112
+ printable(row.url),
113
+ printable(row.status ?? row.statusCode ?? row.outcome)
114
+ ];
115
+ console.log((minimal ? parts.filter((part) => part !== "") : parts).join(" "));
104
116
  if (Array.isArray(row.logs)) for (const log of row.logs) if (log && typeof log === "object") {
105
117
  const record = log;
106
- console.log(` ${record.level ? `[${printable(record.level)}] ` : ""}${printable(record.message ?? log)}`);
118
+ const level = record.level ? `[${printable(record.level)}] ` : "";
119
+ if (minimal && Array.isArray(record.message) && record.message.length === 0) console.log(` ${level.trimEnd()}`);
120
+ else console.log(` ${level}${printable(record.message ?? log)}`);
107
121
  } else console.log(` ${printable(log)}`);
108
122
  if (Array.isArray(row.exceptions)) for (const exception of row.exceptions) if (exception && typeof exception === "object") {
109
123
  const record = exception;
110
- const name = record.name ? `${printable(record.name)}: ` : "";
111
- console.log(` ${name}${printable(record.message ?? exception)}`);
124
+ if (minimal && record.message === "" && record.name) console.log(` ${printable(record.name)}`);
125
+ else {
126
+ const name = record.name ? `${printable(record.name)}: ` : "";
127
+ console.log(` ${name}${printable(record.message ?? exception)}`);
128
+ }
112
129
  } else console.log(` ${printable(exception)}`);
113
130
  }
114
131
  if (result.nextCursor) console.log(`Next cursor: ${printable(result.nextCursor)}`);
@@ -163,8 +180,8 @@ async function runAuth(origin, args) {
163
180
  if (args.action === "login" || args.action === "token" && args.tokenStdin) {
164
181
  if (!args.tokenStdin && !process.stdin.isTTY) throw new OperatorClientError("Browser login requires an interactive terminal. Use --token-stdin to exchange an API session.", "interactive_login_required");
165
182
  const apiToken = args.tokenStdin ? await readOperatorApiTokenStdin() : await (async () => {
166
- const { discoverPlatform } = await import("./platform-cmd-WnOmdLzR.mjs");
167
- const { selectPlatformLoginMethod } = await import("./login-C0MiQrYs.mjs");
183
+ const { discoverPlatform } = await import("./platform-cmd-DpCHawGF.mjs");
184
+ const { selectPlatformLoginMethod } = await import("./login-BpbYeu-n.mjs");
168
185
  const { runPlatformLogin } = await import("./auth-CL-p_rqV.mjs");
169
186
  return runPlatformLogin(origin, (await selectPlatformLoginMethod(await discoverPlatform(origin), args.provider)).id, (url) => process.stderr.write(`Sign in at ${url}\n`));
170
187
  })();
@@ -230,6 +247,7 @@ async function followOperatorLogs(client, args, signal, pollIntervalMs = 2e3) {
230
247
  let previousRuntimeRows = /* @__PURE__ */ new Map();
231
248
  let currentRuntimeRows = /* @__PURE__ */ new Map();
232
249
  let currentRuntimeRowCount = 0;
250
+ const outputState = {};
233
251
  try {
234
252
  while (!combined.aborted) {
235
253
  const result = await client.request(args.path, {
@@ -252,7 +270,7 @@ async function followOperatorLogs(client, args, signal, pollIntervalMs = 2e3) {
252
270
  data
253
271
  };
254
272
  }
255
- outputLogs(visibleResult, args.json);
273
+ outputLogs(visibleResult, args.json, outputState);
256
274
  if (args.group === "build") {
257
275
  if (typeof result.lastSeq !== "number" || !Number.isSafeInteger(result.lastSeq) || result.lastSeq < Number(query.since ?? 0)) throw new OperatorClientError("Build log response has an invalid cursor.", "invalid_response");
258
276
  const previousSeq = Number(query.since ?? 0);
@@ -344,7 +362,7 @@ async function migrateDeploymentAssets(client, origin, args) {
344
362
  }
345
363
  async function runOperatorCommand(args) {
346
364
  if (!args.action) {
347
- const { printHelpPage } = await import("./help-BcZDUcTw.mjs");
365
+ const { printHelpPage } = await import("./help-Ba8Dq5-r.mjs");
348
366
  printHelpPage(["platform", args.group]);
349
367
  return;
350
368
  }
@@ -0,0 +1 @@
1
+ export { a as runOperatorCommand } from "./operator-cmd-BUqsdk2K.mjs";
@@ -1,8 +1,8 @@
1
- import { l as toUrlString, s as interpolateRouteParams } from "../route-url-BGOiyKNz.mjs";
2
- import { t as PageObject } from "../protocol-xdrl-In0.mjs";
3
- import { n as CacheForInput, r as CacheForResult } from "../prefetch-CG0K6JPd.mjs";
1
+ import { f as toUrlString, u as interpolateRouteParams } from "../route-url-C_YIH_zO.mjs";
2
+ import { t as PageObject } from "../protocol-CkwjASep.mjs";
3
+ import { a as LinkPrefetchValue, i as LinkPrefetchStrategy, n as CacheForInput, r as CacheForResult } from "../prefetch-NdNeubbH.mjs";
4
4
  import { UsageLimitData } from "@void/edge";
5
- import { ActionUrl, ResolveActionBody, ResolveActionParams, RouteUrlInput } from "void/routes";
5
+ import { ActionUrl, Href, ResolveActionBody, ResolveActionParams, RouteUrlInput } from "void/routes";
6
6
  type ActionErrorHandlingScope = "callSite" | "boundary";
7
7
  type ActionResult<T = PageObject | undefined> = {
8
8
  ok: true;
@@ -17,8 +17,9 @@ export declare class VoidActionError extends Error {
17
17
  readonly status: number;
18
18
  readonly statusText: string;
19
19
  readonly url: string;
20
- constructor({ body, status, statusText, url }: {
20
+ constructor({ body, message, status, statusText, url }: {
21
21
  body: unknown;
22
+ message?: string;
22
23
  status: number;
23
24
  statusText: string;
24
25
  url: string;
@@ -38,6 +39,8 @@ type VisitOptions = {
38
39
  preserveState?: boolean;
39
40
  replace?: boolean;
40
41
  viewTransition?: boolean;
42
+ /** React navigation completion: page data readiness or UI commit (default). */
43
+ resolveOn?: "data" | "commit";
41
44
  /** @internal Used by React Actions to avoid waiting for a commit blocked by the action itself. */
42
45
  _resolveOnShell?: boolean;
43
46
  /** @internal Used by popstate handler to pass saved scroll position */
@@ -75,6 +78,8 @@ type PageNavigationEngineConfig = {
75
78
  viewTransitions: boolean;
76
79
  prefetchHoverDelay: number;
77
80
  prefetchDefaultCacheFor: CacheForResult;
81
+ /** How Links without a `prefetch` prop prefetch. Defaults to `false`. */
82
+ prefetchDefaultStrategy?: LinkPrefetchValue;
78
83
  /** Reuse successful GET page shells on later visits, refreshing stale shells in the background. */
79
84
  cacheVisitedPageData?: boolean;
80
85
  };
@@ -99,6 +104,7 @@ type PageNavigationResource = {
99
104
  };
100
105
  type PageNavigationEngine = {
101
106
  _hoverDelay: number;
107
+ _prefetchDefaultStrategy: LinkPrefetchValue;
102
108
  initialPageData: PageData;
103
109
  initialComponent: unknown;
104
110
  initialLayouts: Array<unknown>;
@@ -116,8 +122,82 @@ export declare function hasFiles(data: unknown): boolean;
116
122
  export declare function objectToFormData(source: Record<string, unknown>, form?: FormData, parentKey?: string): FormData;
117
123
  export declare function createPageNavigationEngine(config: PageNavigationEngineConfig): Promise<PageNavigationEngine>;
118
124
  export declare function getValidationErrors(body: unknown): Record<string, string> | null;
119
- export declare function mergeDataIntoHref(href: string, data?: Record<string, unknown>): string;
125
+ export declare function mergeDataIntoHref(href: Href, data?: Record<string, unknown>): Href;
120
126
  export declare function isModifiedEvent(e: Pick<MouseEvent, "currentTarget" | "ctrlKey" | "metaKey" | "shiftKey" | "altKey" | "button">): boolean;
127
+ type LinkNavigateEvent = {
128
+ preventDefault(): void;
129
+ };
130
+ type LinkActiveMatch = "exact" | "prefix";
131
+ /** Present only when the link matches the current URL. */
132
+ type LinkActiveAttributes = {
133
+ "aria-current"?: "page";
134
+ "data-void-active"?: "";
135
+ };
136
+ /** Present only while a visit to the link's destination is loading. */
137
+ type LinkPendingAttributes = {
138
+ "data-void-pending"?: "";
139
+ };
140
+ /** Props every adapter's Link accepts. Adapters add element attributes and children. */
141
+ type BaseLinkProps = {
142
+ href: Href;
143
+ method?: NavigationMethod | Lowercase<NavigationMethod>;
144
+ data?: Record<string, unknown>;
145
+ preserveScroll?: boolean;
146
+ preserveState?: boolean;
147
+ replace?: boolean;
148
+ reloadDocument?: boolean;
149
+ viewTransition?: boolean;
150
+ /** If omitted, the Link uses the app's `prefetch.defaultStrategy`. */
151
+ prefetch?: LinkPrefetchValue;
152
+ cacheFor?: CacheForInput;
153
+ activeMatch?: LinkActiveMatch;
154
+ onNavigate?: (event: LinkNavigateEvent) => void;
155
+ };
156
+ type ResolvedLink = {
157
+ method: NavigationMethod;
158
+ isGet: boolean;
159
+ /** The destination, with GET data merged into its query. */
160
+ href: Href;
161
+ };
162
+ type LinkClickEvent = Pick<MouseEvent, "currentTarget" | "ctrlKey" | "metaKey" | "shiftKey" | "altKey" | "button" | "defaultPrevented" | "preventDefault">;
163
+ type LinkClickProps = Pick<BaseLinkProps, "data" | "preserveScroll" | "preserveState" | "replace" | "reloadDocument" | "viewTransition" | "onNavigate">;
164
+ /** Normalizes the method and destination, rejecting options that only GET links support. */
165
+ export declare function resolveLink(props: Pick<BaseLinkProps, "href" | "method" | "data" | "prefetch" | "reloadDocument">): ResolvedLink;
166
+ /**
167
+ * The events that prefetch a Link. A Link without a `prefetch` prop uses the app's
168
+ * `defaultStrategy`, but only when it is a GET link, the only kind that can prefetch.
169
+ */
170
+ export declare function linkPrefetchStrategies(props: Pick<BaseLinkProps, "prefetch" | "reloadDocument">, link: Pick<ResolvedLink, "isGet">, defaultStrategy?: LinkPrefetchValue): ReadonlyArray<LinkPrefetchStrategy>;
171
+ /**
172
+ * Marks a GET link to the current page. Pathnames compare the way the server
173
+ * matches pages: case-sensitive, trailing slash significant, decoded like Hono's
174
+ * getPath. The query and hash are ignored. `prefix` also matches nested pages by
175
+ * whole segment, except for `/`, but only an exact match is `aria-current`.
176
+ * Spread the result before the user's attributes so theirs win.
177
+ */
178
+ export declare function linkActiveAttributes(router: VoidRouter | null | undefined, link: ResolvedLink, match?: LinkActiveMatch): LinkActiveAttributes;
179
+ /**
180
+ * Marks a link while a visit to its destination is loading: the visit uses the link's
181
+ * method and goes to its path, query and hash. Unlike active links, the query counts,
182
+ * so `?page=2` isn't pending during a visit to `?page=3`. Every link to the destination
183
+ * is marked, not only the one that was clicked.
184
+ * Spread the result before the user's attributes so theirs win.
185
+ */
186
+ export declare function linkPendingAttributes(router: VoidRouter | null | undefined, navigation: NavigationState | null | undefined, link: ResolvedLink): LinkPendingAttributes;
187
+ /** Link's automatic prefetch. `router.prefetch()` called directly is not limited by the connection. */
188
+ export declare function prefetchLink(router: VoidRouter | null | undefined, href: Href, cacheFor: CacheForInput | undefined): void;
189
+ /**
190
+ * Runs a client-side visit for a plain same-origin click. Modified clicks, downloads,
191
+ * cross-origin destinations and `reloadDocument` links are left to the browser.
192
+ * Call it after the user's own click handler so its `preventDefault()` is respected.
193
+ */
194
+ export declare function handleLinkClick(event: LinkClickEvent, router: VoidRouter | null | undefined, link: ResolvedLink, props: LinkClickProps): void;
195
+ /**
196
+ * Calls `onVisible` once, after `element` has stayed in the viewport for
197
+ * `LINK_VISIBLE_PREFETCH_DELAY` ms. Leaving the viewport cancels the wait and entering
198
+ * again restarts it. Returns a cleanup that also cancels a pending wait.
199
+ */
200
+ export declare function observeLinkVisible(element: Element, onVisible: () => void): () => void;
121
201
  type IslandActionResult = {
122
202
  kind: "redirect";
123
203
  url: string;
@@ -142,11 +222,60 @@ export declare function parseFormResetArgs(args: ReadonlyArray<string | FormRese
142
222
  fields: ReadonlyArray<string>;
143
223
  };
144
224
  type FormMethod = "post" | "put" | "patch" | "delete";
145
- type FormModel<Args extends Array<unknown> = []> = {
146
- readonly pending: boolean;
147
- readonly error: VoidActionError | null;
225
+ type FormModel<Args extends Array<unknown> = []> = Pick<FormStatus, "pending" | "error"> & {
148
226
  readonly errors: Readonly<Record<string, string | undefined>>;
149
227
  } & { [K in FormMethod]: (...args: Args) => void | Promise<void>; };
228
+ /** Router options a `useForm()` submission accepts in adapters whose submit methods take options. */
229
+ type FormSubmitOptions = Omit<VisitOptions, "method" | "data"> & {
230
+ data?: Record<string, unknown>;
231
+ };
232
+ /** Submission state that `useForm()` and `useIslandForm()` report in every adapter. */
233
+ type FormStatus = {
234
+ readonly error: VoidActionError | null;
235
+ readonly pending: boolean;
236
+ readonly hasChanges: boolean;
237
+ readonly wasSuccessful: boolean;
238
+ readonly recentlySuccessful: boolean;
239
+ };
240
+ /** Field-keyed validation messages; a field without an error is absent. */
241
+ type FormErrors<TData> = Partial<Record<keyof TData & string, string>>;
242
+ /**
243
+ * How an adapter's apps change `data` and `errors`, following its framework's idiom.
244
+ * `'in-place'`: apps edit them directly (Vue, Svelte).
245
+ * `'setters'`: they are read-only and change through adapter setters such as `setData` (React, Solid).
246
+ */
247
+ type FormEditing = "in-place" | "setters";
248
+ type FormFields<TData, TErrors, TEditing extends FormEditing> = [TEditing] extends ["setters"] ? {
249
+ readonly data: Readonly<TData>;
250
+ readonly errors: Readonly<TErrors>;
251
+ } : {
252
+ readonly data: TData;
253
+ readonly errors: TErrors;
254
+ };
255
+ /**
256
+ * The `useForm()` contract every adapter shares. Field names are typed from the action body.
257
+ * Adapters add their submit methods.
258
+ */
259
+ type FormState<TData, TEditing extends FormEditing> = FormStatus & FormFields<TData, FormErrors<TData>, TEditing> & Readonly<{
260
+ reset(options: FormResetOptions, ...fields: ReadonlyArray<keyof TData & string>): void;
261
+ reset(...fields: ReadonlyArray<keyof TData & string>): void;
262
+ setError(field: keyof TData & string, message: string): void;
263
+ clearErrors(...fields: ReadonlyArray<keyof TData & string>): void;
264
+ clearError(): void;
265
+ }>;
266
+ /**
267
+ * The `useIslandForm()` contract every adapter shares. Errors are keyed by whatever names the
268
+ * action returns, not only the default fields. Submit methods take the action URL.
269
+ */
270
+ type IslandFormState<TData, TEditing extends FormEditing> = FormStatus & FormFields<TData, Partial<Record<string, string>>, TEditing> & Readonly<{
271
+ reset(...fields: ReadonlyArray<keyof TData & string>): void;
272
+ clearErrors(...fields: ReadonlyArray<string>): void;
273
+ clearError(): void;
274
+ post(url: string): Promise<void>;
275
+ put(url: string): Promise<void>;
276
+ patch(url: string): Promise<void>;
277
+ delete(url: string): Promise<void>;
278
+ }>;
150
279
  export declare function formErrorMessage(form: Pick<FormModel, "error" | "errors">): string | null;
151
280
  export declare function formRetryMessage(error: VoidActionError | null): string | null;
152
281
  export declare function formSubmissionBlocked(form: Pick<FormModel, "pending" | "error">, now?: number): boolean;
@@ -161,6 +290,8 @@ export type NavigationState = {
161
290
  };
162
291
  export type VoidRouter = {
163
292
  _hoverDelay: number;
293
+ /** How Links without a `prefetch` prop prefetch. Absent during SSR. */
294
+ _prefetchDefaultStrategy?: LinkPrefetchValue;
164
295
  readonly url: URL;
165
296
  readonly path: string;
166
297
  readonly query: URLSearchParams;
@@ -183,7 +314,7 @@ export type VoidRouterConfig = Omit<PageNavigationEngineConfig, "adapter"> & {
183
314
  };
184
315
  export declare function idleNavigationState(): NavigationState;
185
316
  export declare function createRouterFacade(router: VoidRouter, getCurrentUrl: () => string, getCurrentParams?: () => Record<string, string>): VoidRouter;
186
- export declare function createSsrRouter(url?: string, params?: Record<string, string>): VoidRouter;
317
+ export declare function createSsrRouter(url?: string, params?: Record<string, string>, requestUrl?: string): VoidRouter;
187
318
  export declare const ssrProxy: VoidRouter;
188
319
  /** Refetch the current page in place: same history entry, URL hash, state and scroll. */
189
320
  export declare function refreshPage(router: Pick<VoidRouter, "visit">, options?: VisitOptions): Promise<unknown>;
@@ -193,6 +324,7 @@ type HasParams<U extends string> = [ResolveActionParams<U>] extends [never] ? fa
193
324
  type ActionOptions<U extends string> = {
194
325
  data?: ResolveActionBody<U>;
195
326
  method?: ActionMethod;
327
+ preserveScroll?: boolean;
196
328
  } & (HasParams<U> extends true ? {
197
329
  params: ResolveActionParams<U>;
198
330
  } : {
@@ -214,4 +346,4 @@ export declare function createVoidRouter(config: VoidRouterConfig): Promise<{
214
346
  }>;
215
347
  export declare function scheduleHydration(el: Element, loader: () => Promise<unknown>, props: Record<string, unknown>, strategy: string, hydrateFn: (el: Element, mod: unknown, props: Record<string, unknown>) => void | Promise<void>): void;
216
348
  export declare function initIslands(islands: Record<string, () => Promise<unknown>>, hydrateFn: (el: Element, mod: unknown, props: Record<string, unknown>, frontmatter: Record<string, unknown>) => void | Promise<void>): void;
217
- export { type ActionErrorHandlingScope, type ActionResult, type FormMethod, type FormModel, type FormResetOptions, type IslandActionResult, type PageNavigationEngine, type PageNavigationResource, type PageNavigationResult, type PrefetchOptions, type VisitOptions, interpolateRouteParams, toUrlString };
349
+ export { type ActionErrorHandlingScope, type ActionResult, type BaseLinkProps, type FormMethod, type FormModel, type FormResetOptions, type FormState, type FormSubmitOptions, type IslandActionResult, type IslandFormState, type LinkActiveAttributes, type LinkActiveMatch, type LinkNavigateEvent, type LinkPendingAttributes, type LinkPrefetchStrategy, type LinkPrefetchValue, type PageNavigationEngine, type PageNavigationResource, type PageNavigationResult, type PrefetchOptions, type ResolvedLink, type VisitOptions, interpolateRouteParams, toUrlString };