void 0.24.0 → 0.26.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 (199) hide show
  1. package/README.md +19 -106
  2. package/dist/{account-cmd-vJhh5lrb.mjs → account-cmd-CDry3B5V.mjs} +5 -5
  3. package/dist/{application-analysis-BVsVqc11.mjs → application-analysis-DC2yPvzY.mjs} +1 -1
  4. package/dist/{application-routing-B7QEjqSR.mjs → application-routing-C9khgLiS.mjs} +1 -1
  5. package/dist/{auth-DX3JURcX.mjs → auth-B60QDbjg.mjs} +1 -1
  6. package/dist/{auth-CQkSDS50.mjs → auth-D52yG7hl.mjs} +3 -3
  7. package/dist/{auth-link-D75t9wO2.mjs → auth-link-DjeOptYi.mjs} +5 -6
  8. package/dist/{auth-router-ClfhL1J7.mjs → auth-router-BRxIuqDi.mjs} +7 -7
  9. package/dist/{build-cmd-zMi1iFnS.mjs → build-cmd-Ce3C8huo.mjs} +6 -7
  10. package/dist/{cache-ZtQmyxVV.mjs → cache-CS8Yxr5a.mjs} +6 -7
  11. package/dist/{cancel-deploy-Box0kkEV.mjs → cancel-deploy-mZsD88Xa.mjs} +4 -6
  12. package/dist/{cf-access-BGe5sWXF.mjs → cf-access-YTlqvAsk.mjs} +1 -1
  13. package/dist/cf-build-output-ChY6-XWP.mjs +2 -0
  14. package/dist/cli/cli.mjs +45 -45
  15. package/dist/cli/cloudflare-operation-process.mjs +3 -3
  16. package/dist/cli/env-schema-probe.d.mts +1 -1
  17. package/dist/cli/env-schema-probe.mjs +2 -2
  18. package/dist/client-BxVixJBI.mjs +2 -0
  19. package/dist/{client-DKAsFA4X.mjs → client-mC-dFGDD.mjs} +103 -25
  20. package/dist/{cloudflare-cmd-CmY8dGkd.mjs → cloudflare-cmd-bhwCxAN6.mjs} +2 -2
  21. package/dist/{cloudflare-connect-IiR3ZieC.mjs → cloudflare-connect-CuhRgk3k.mjs} +2 -2
  22. package/dist/{cloudflare-operations-DzH-A966.mjs → cloudflare-operations-DYa3coIk.mjs} +2 -2
  23. package/dist/{cloudflare-operations-BCdXSsmo.mjs → cloudflare-operations-DoQrVHAt.mjs} +1 -1
  24. package/dist/{connect-B-usTnlF.mjs → connect-H6EvP62X.mjs} +12 -9
  25. package/dist/{create-project-CYOOAYcn.mjs → create-project-B2kk9Q0o.mjs} +6 -6
  26. package/dist/{create-project-FWbf5Olo.mjs → create-project-Dbb4uiN-.mjs} +1 -1
  27. package/dist/{db-Ck2eZ2iB.mjs → db-DpCKZto0.mjs} +35 -38
  28. package/dist/{delete-sK56qtzZ.mjs → delete-CxlSvsvW.mjs} +6 -7
  29. package/dist/{deploy-gCVaiJbS.mjs → deploy-CeEbnv4b.mjs} +9249 -8925
  30. package/dist/deploy-qmiLE1G1.mjs +2 -0
  31. package/dist/{dev-inbox-P0u4tM8Y.mjs → dev-inbox-D64ZKUod.mjs} +5 -6
  32. package/dist/{domain-DFfQE8jg.mjs → domain-B_9VgOm6.mjs} +8 -8
  33. package/dist/{email-CdnhUHvJ.mjs → email-BokHgjKj.mjs} +7 -7
  34. package/dist/{env-DmGdHi5i.mjs → env-BdTc-K2L.mjs} +7 -8
  35. package/dist/{env-public-BX_r8HR6.d.mts → env-public-DR7ZM6d-.d.mts} +1 -1
  36. package/dist/{env-validation-zZOCcQVZ.mjs → env-validation-cZBvGWaP.mjs} +1 -1
  37. package/dist/{fetch-stream-IvCYKyQL.mjs → fetch-stream-Nm3hkZbT.mjs} +8 -1
  38. package/dist/{gen-CshAkukR.mjs → gen-BhDlTpwW.mjs} +2 -4
  39. package/dist/gen-qCBwH3fZ.mjs +2 -0
  40. package/dist/{github-cmd-DftuEvIt.mjs → github-cmd-hhkTzlGS.mjs} +7 -16
  41. package/dist/{handler-CZ4nAylQ.d.mts → handler-BeK3weD4.d.mts} +1 -1
  42. package/dist/{help-Dotbf6iz.mjs → help-Bv44e2tm.mjs} +13 -9
  43. package/dist/help-Dw5f9Xrg.mjs +2 -0
  44. package/dist/index.d.mts +19 -15
  45. package/dist/index.mjs +2225 -2142
  46. package/dist/{info-B97bTX9N.mjs → info-DhtTKh65.mjs} +2 -4
  47. package/dist/{init-BTQEZZGJ.mjs → init-BMf4T03q.mjs} +17 -18
  48. package/dist/{limits-Bq5LG8Id.d.mts → limits-CFsDKQvU.d.mts} +1 -10
  49. package/dist/{limits-Cjuk2VPm.mjs → limits-D0vD1M9A.mjs} +1 -22
  50. package/dist/{link-B46sYH0K.mjs → link-BqYsSS_I.mjs} +6 -7
  51. package/dist/{list-BnPrIsU_.mjs → list-_kBToO-l.mjs} +10 -10
  52. package/dist/{live-Chw1eIMv.d.mts → live-iAuEH1hd.d.mts} +1 -1
  53. package/dist/{local-d1-2CMnpuW_.mjs → local-d1-fGxYrVD6.mjs} +2 -2
  54. package/dist/login-D7meQg_3.mjs +2 -0
  55. package/dist/{login-BuiMyUrx.mjs → login-DFuo-RWO.mjs} +9 -7
  56. package/dist/{logs-CZG9d-ic.mjs → logs-DYgnh6dH.mjs} +7 -8
  57. package/dist/migrate-CEu2X5DB.mjs +2 -0
  58. package/dist/{migrate-q4_njtaW.mjs → migrate-CV1on-yJ.mjs} +2 -4
  59. package/dist/{node-BkyRWRx8.mjs → node-C6Q6e1Es.mjs} +1 -1
  60. package/dist/{operator-args-B3BTmSoi.mjs → operator-args-DdY54Bgb.mjs} +1 -1
  61. package/dist/{operator-auth-7erYc6Lt.mjs → operator-auth-2dsGlTT5.mjs} +4 -8
  62. package/dist/{operator-client-CpHjTd0t.mjs → operator-client-BFqpp6z0.mjs} +3 -3
  63. package/dist/{operator-cmd-DGqPJUD3.mjs → operator-cmd-CUGHXrQf.mjs} +27 -9
  64. package/dist/operator-cmd-DRPvhpjM.mjs +2 -0
  65. package/dist/{output-CbM85T4k.mjs → output-BvdaehtE.mjs} +28 -4
  66. package/dist/pages/client.d.mts +4 -1
  67. package/dist/pages/client.mjs +120 -29
  68. package/dist/pages/index.mjs +1 -1
  69. package/dist/pages/islands-plugin.mjs +1 -1
  70. package/dist/pages/protocol.d.mts +2 -2
  71. package/dist/{plan-NPpwZ_kc.mjs → plan-CJGEeTEI.mjs} +2 -2
  72. package/dist/plan-COtUvdMA.mjs +2 -0
  73. package/dist/{platform-args-3k8X9-H_.mjs → platform-args-DSV2p4nY.mjs} +4 -2
  74. package/dist/platform-args-Dcy_5b_Y.mjs +2 -0
  75. package/dist/{platform-auth-config-DDrxUy4m.mjs → platform-auth-config-Bosx7U1h.mjs} +20 -19
  76. package/dist/{platform-auth-protection-BLadnnct.mjs → platform-auth-protection-DcbL_LW_.mjs} +8 -8
  77. package/dist/{platform-auth-recovery-CmCzX2Fl.mjs → platform-auth-recovery-WfTZ8K6o.mjs} +7 -7
  78. package/dist/{platform-cmd-DMDEc9uS.mjs → platform-cmd-DbKtQb_4.mjs} +73 -38
  79. package/dist/{platform-cmd-pMTRhvYs.mjs → platform-cmd-dyFUof0t.mjs} +1 -1
  80. package/dist/platform-discovery-BC0HCKYt.mjs +41 -0
  81. package/dist/{platform-domain-Di6EYrQl.mjs → platform-domain-Bsq43AJp.mjs} +5 -4
  82. package/dist/{platform-lifecycle-BFdSi9Qt.mjs → platform-lifecycle--5gWmDoI.mjs} +1 -1
  83. package/dist/{platform-lifecycle-BBoNzojY.mjs → platform-lifecycle-Cfi0o6xM.mjs} +4605 -3527
  84. package/dist/platform-management-Bbwf6-Dq.mjs +2 -0
  85. package/dist/{platform-management-CWOQOWXm.mjs → platform-management-BrF9STZp.mjs} +211 -31
  86. package/dist/{platform-plans-config-Vl9BP3H4.mjs → platform-plans-config-DU-8nC2Y.mjs} +3 -3
  87. package/dist/{platform-recovery-BJnQJEtQ.mjs → platform-recovery-DQAqAQYu.mjs} +3 -3
  88. package/dist/{platform-registry-DkPPXfp_.mjs → platform-registry-P387v42A.mjs} +18 -11
  89. package/dist/prepare-BBknoZI1.mjs +2 -0
  90. package/dist/{prepare-CBLT3CHH.mjs → prepare-BMrRWLwP.mjs} +3 -4
  91. package/dist/{prepare-DnaKBi--.mjs → prepare-WoUubFKL.mjs} +1 -1
  92. package/dist/{project-DsblYifa.mjs → project-BiaPQ7ur.mjs} +1 -1
  93. package/dist/{project-DKG5Ra8p.mjs → project-DQstYTxO.mjs} +1 -1
  94. package/dist/{project-cmd-DxnXstAq.mjs → project-cmd-BbH2LptN.mjs} +21 -22
  95. package/dist/{project-team-BmHcaALJ.mjs → project-team-Yiww3-go.mjs} +8 -9
  96. package/dist/{project-token-GionZlBI.mjs → project-token-BrtT2NkY.mjs} +6 -9
  97. package/dist/{project-zero-trust-JLCjVQA7.mjs → project-zero-trust-nYJ2V2nc.mjs} +5 -6
  98. package/dist/{prompts-BNUoTiaf.mjs → prompts-6OSVA7DJ.mjs} +58 -15
  99. package/dist/{prompts-2TGE6oXx.mjs → prompts-ZAuJlyCj.mjs} +1 -1
  100. package/dist/{protocol-CjF_iI9X.d.mts → protocol-BX8t2jiw.d.mts} +1 -1
  101. package/dist/{provision-CVku1JFU.mjs → provision-DMTPG8Rh.mjs} +1 -1
  102. package/dist/{provision-CaoxO_U7.mjs → provision-VeqAC77A.mjs} +18 -8
  103. package/dist/{requests-BOjIVAeF.mjs → requests-TIz_jtSu.mjs} +5 -6
  104. package/dist/{rollback-CwR3pLj3.mjs → rollback-dBqICPzj.mjs} +9 -10
  105. package/dist/{runner-Ol0TNjk6.mjs → runner--2KF6Kua.mjs} +1 -1
  106. package/dist/{runner-CXA9Fh8h.mjs → runner-voIltZrY.mjs} +1 -1
  107. package/dist/runtime/ai.d.mts +10 -11
  108. package/dist/runtime/ai.mjs +13 -18
  109. package/dist/runtime/client-react.mjs +1 -1
  110. package/dist/runtime/client-solid.mjs +1 -1
  111. package/dist/runtime/client-svelte.mjs +1 -1
  112. package/dist/runtime/client-vue.mjs +1 -1
  113. package/dist/runtime/client.mjs +1 -1
  114. package/dist/runtime/email/testing.mjs +1 -1
  115. package/dist/runtime/email.mjs +35 -17
  116. package/dist/runtime/env-public.d.mts +1 -1
  117. package/dist/runtime/fetch-stream.mjs +1 -1
  118. package/dist/runtime/handler.d.mts +1 -1
  119. package/dist/runtime/limits.d.mts +2 -2
  120. package/dist/runtime/limits.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/migration-handler.mjs +33 -7
  124. package/dist/runtime/routing.d.mts +1 -1
  125. package/dist/runtime/routing.mjs +1 -1
  126. package/dist/runtime/sandbox.d.mts +1 -1
  127. package/dist/runtime/sandbox.mjs +12 -22
  128. package/dist/runtime/validator.d.mts +1 -1
  129. package/dist/runtime/ws-server.d.mts +1 -1
  130. package/dist/runtime/ws.d.mts +1 -1
  131. package/dist/{sandbox-XZAqzFlG.d.mts → sandbox-C5LFoJMf.d.mts} +7 -7
  132. package/dist/{scan-C7okrLyM.mjs → scan-C8dA7iM4.mjs} +10 -6
  133. package/dist/{secret-ByWJWBUG.mjs → secret-AKnNXNP5.mjs} +15 -16
  134. package/dist/{skills-C1PlclPt.mjs → skills-BPQUGClu.mjs} +1 -1
  135. package/dist/{subcommand-prompt-klFCfcor.mjs → subcommand-prompt-B6WS9Aoz.mjs} +2 -2
  136. package/dist/sveltekit.d.mts +1 -1
  137. package/dist/sveltekit.mjs +4 -9
  138. package/dist/validate-pna7R3Pv.mjs +2 -0
  139. package/dist/{validate-ctOrgiS3.mjs → validate-ymhap6M_.mjs} +1 -1
  140. package/dist/{wrangler-7K-bW_DL.mjs → wrangler-DhUerFkW.mjs} +10 -15
  141. package/dist/{ws-CL1w7GXU.d.mts → ws-C79j4aED.d.mts} +1 -1
  142. package/package.json +21 -21
  143. package/sandbox.Dockerfile +1 -1
  144. package/skills/void/SKILL.md +5 -2
  145. package/skills/void/docs/guide/ai.md +78 -137
  146. package/skills/void/docs/guide/app-types.md +1 -1
  147. package/skills/void/docs/guide/auth.md +0 -2
  148. package/skills/void/docs/guide/database/d1.md +7 -7
  149. package/skills/void/docs/guide/database.md +15 -0
  150. package/skills/void/docs/guide/deployment.md +58 -124
  151. package/skills/void/docs/guide/env-vars.md +1 -5
  152. package/skills/void/docs/guide/index.md +19 -18
  153. package/skills/void/docs/guide/kv.md +0 -2
  154. package/skills/void/docs/guide/live.md +2 -0
  155. package/skills/void/docs/guide/pages-routing/actions-and-forms.md +49 -47
  156. package/skills/void/docs/guide/pages-routing/overview.md +2 -2
  157. package/skills/void/docs/guide/platform/administration/email.md +0 -2
  158. package/skills/void/docs/guide/platform/administration/operations.md +11 -22
  159. package/skills/void/docs/guide/platform/administration/plans.md +1 -5
  160. package/skills/void/docs/guide/platform/administration/zero-trust.md +1 -4
  161. package/skills/void/docs/guide/platform/development/schema-ci.md +7 -1
  162. package/skills/void/docs/guide/platform/installation/credentials.md +2 -2
  163. package/skills/void/docs/guide/platform/installation/first-deployment.md +5 -1
  164. package/skills/void/docs/guide/platform/installation/maintenance.md +33 -11
  165. package/skills/void/docs/guide/platform/installation/prerequisites.md +79 -7
  166. package/skills/void/docs/guide/platform/installation/setup.md +1 -1
  167. package/skills/void/docs/guide/platform/installation/uninstall.md +44 -11
  168. package/skills/void/docs/guide/quickstart.md +37 -80
  169. package/skills/void/docs/guide/sandboxes.md +75 -66
  170. package/skills/void/docs/guide/self-hosted-platform.md +20 -0
  171. package/skills/void/docs/guide/websockets.md +0 -2
  172. package/skills/void/docs/integrations/frameworks/overview.md +2 -2
  173. package/skills/void/docs/integrations/frameworks/sveltekit.md +40 -25
  174. package/skills/void/docs/integrations/nodejs-bun-deno.md +7 -2
  175. package/skills/void/docs/reference/api/resources.md +38 -14
  176. package/skills/void/docs/reference/api.md +35 -34
  177. package/skills/void/docs/reference/cli/auth.md +3 -1
  178. package/skills/void/docs/reference/cli/deploy.md +1 -1
  179. package/skills/void/docs/reference/cli/platform-config.md +2 -2
  180. package/skills/void/docs/reference/cli/platform-installation.md +14 -12
  181. package/skills/void/docs/reference/cli/platform-operations.md +4 -8
  182. package/skills/void/docs/reference/cli/platform.md +9 -2
  183. package/skills/void/docs/reference/cli.md +1 -1
  184. package/skills/void/docs/reference/resource-inference.md +12 -8
  185. package/dist/cf-build-output-_0HNWysu.mjs +0 -2
  186. package/dist/client-B9UBI03V.mjs +0 -2
  187. package/dist/deploy-irP5q0-x.mjs +0 -2
  188. package/dist/gen-DvQTWzDU.mjs +0 -2
  189. package/dist/help-mabuIV98.mjs +0 -2
  190. package/dist/login-DIy9Sb-U.mjs +0 -2
  191. package/dist/migrate-BCiJ8w0f.mjs +0 -2
  192. package/dist/plan-D1Q5rf-r.mjs +0 -2
  193. package/dist/platform-args-DdnM6WIf.mjs +0 -2
  194. package/dist/platform-management-DG47jys8.mjs +0 -2
  195. package/dist/prepare-CnjcTV2s.mjs +0 -2
  196. package/dist/validate-Dq_L3s0S.mjs +0 -2
  197. package/skills/void/docs/guide/env-migration.md +0 -109
  198. package/dist/{cf-build-output-BPqOT964.mjs → cf-build-output-U8o1Gl6X.mjs} +1 -1
  199. package/dist/{env-validation-C_8tPdhs.mjs → env-validation-vBSQ8gw5.mjs} +1 -1
@@ -60,6 +60,103 @@ async function createActionErrorFromResponse(response, url) {
60
60
  });
61
61
  }
62
62
  //#endregion
63
+ //#region src/pages/scroll-restoration.ts
64
+ const STORAGE_PREFIX = "void:scroll:";
65
+ function readKey(state) {
66
+ return typeof state?.__voidScrollKey === "string" ? state.__voidScrollKey : null;
67
+ }
68
+ function readPosition(value) {
69
+ if (!value || typeof value !== "object") return null;
70
+ const { x, y } = value;
71
+ return typeof x === "number" && Number.isFinite(x) && typeof y === "number" && Number.isFinite(y) ? {
72
+ x,
73
+ y
74
+ } : null;
75
+ }
76
+ function newKey() {
77
+ return crypto.getRandomValues(/* @__PURE__ */ new Uint32Array(4)).join("-");
78
+ }
79
+ function currentUrl$1() {
80
+ return window.location.pathname + window.location.search + window.location.hash;
81
+ }
82
+ /** Positions belong to the rendered entry, even after the browser starts a traversal. */
83
+ function createScrollRestoration() {
84
+ const positions = /* @__PURE__ */ new Map();
85
+ let renderedKey = null;
86
+ let renderedUrl = currentUrl$1();
87
+ let ready = false;
88
+ function read(key) {
89
+ if (!key) return null;
90
+ const position = positions.get(key);
91
+ if (position) return position;
92
+ try {
93
+ const saved = readPosition(JSON.parse(sessionStorage.getItem(STORAGE_PREFIX + key) || "null"));
94
+ if (saved) return saved;
95
+ } catch {}
96
+ return null;
97
+ }
98
+ function save() {
99
+ if (!ready || !renderedKey) return;
100
+ const position = {
101
+ x: window.scrollX,
102
+ y: window.scrollY
103
+ };
104
+ positions.set(renderedKey, position);
105
+ try {
106
+ sessionStorage.setItem(STORAGE_PREFIX + renderedKey, JSON.stringify(position));
107
+ } catch {}
108
+ }
109
+ return {
110
+ get ready() {
111
+ return ready;
112
+ },
113
+ start() {
114
+ renderedKey = readKey(history.state);
115
+ if (!renderedKey) {
116
+ renderedKey = newKey();
117
+ history.replaceState({
118
+ ...history.state,
119
+ __voidScrollKey: renderedKey
120
+ }, "");
121
+ }
122
+ history.scrollRestoration = "manual";
123
+ window.addEventListener("pagehide", save);
124
+ return read(renderedKey);
125
+ },
126
+ save,
127
+ writeHistory(url, replace) {
128
+ renderedKey = newKey();
129
+ const state = {
130
+ ...replace ? history.state : {},
131
+ __voidScrollKey: renderedKey
132
+ };
133
+ if (replace) history.replaceState(state, "", url);
134
+ else history.pushState(state, "", url);
135
+ },
136
+ commit() {
137
+ renderedKey = readKey(history.state) ?? renderedKey;
138
+ renderedUrl = currentUrl$1();
139
+ ready = true;
140
+ },
141
+ pop(state) {
142
+ save();
143
+ let key = readKey(state);
144
+ const newFragment = key === renderedKey && currentUrl$1() !== renderedUrl;
145
+ if (!key || newFragment) {
146
+ key = newKey();
147
+ history.replaceState({
148
+ ...state,
149
+ __voidScrollKey: key
150
+ }, "");
151
+ }
152
+ return newFragment ? null : read(key) ?? readPosition({
153
+ x: state?.scrollX,
154
+ y: state?.scrollY
155
+ });
156
+ }
157
+ };
158
+ }
159
+ //#endregion
63
160
  //#region src/pages/navigation-engine.ts
64
161
  const PAGE_DATA_SCRIPT_ID = "__VOID_PAGE_DATA__";
65
162
  const STATIC_PAGE_DATA_PREFIX = "/_void/pages";
@@ -138,6 +235,9 @@ async function createPageNavigationEngine(config) {
138
235
  let _htmlDeferredRegistry = null;
139
236
  let _currentFetchUrl = window.location.pathname + window.location.search;
140
237
  let popStateHandler = null;
238
+ let initialScrollPosition = null;
239
+ const initialUrl = window.location.pathname + window.location.search + window.location.hash;
240
+ const scrollRestoration = createScrollRestoration();
141
241
  function getPageDataCacheKey(url, method = "GET") {
142
242
  return `${method}:${url}`;
143
243
  }
@@ -329,16 +429,8 @@ async function createPageNavigationEngine(config) {
329
429
  deferredWindow.__rejectDeferred = (group, error) => _htmlDeferredRegistry?.resolve(group, void 0, error);
330
430
  function commitHashNavigation(effectiveFetchUrl, hash, options, writeHistory) {
331
431
  _currentFetchUrl = effectiveFetchUrl;
332
- if (writeHistory) {
333
- if (options.replace) history.replaceState({}, "", effectiveFetchUrl + hash);
334
- else {
335
- history.replaceState({
336
- scrollX: window.scrollX,
337
- scrollY: window.scrollY
338
- }, "");
339
- history.pushState({}, "", effectiveFetchUrl + hash);
340
- }
341
- }
432
+ if (writeHistory) scrollRestoration.writeHistory(effectiveFetchUrl + hash, !!options.replace);
433
+ scrollRestoration.commit();
342
434
  if (options._scrollPosition) {
343
435
  window.scrollTo(options._scrollPosition.x, options._scrollPosition.y);
344
436
  return;
@@ -536,15 +628,9 @@ async function createPageNavigationEngine(config) {
536
628
  _currentFetchUrl = commitTarget.fetchUrl;
537
629
  if (!options.preserveState) {
538
630
  const historyUrl = commitTarget.fetchUrl + commitTarget.hash;
539
- if (options.replace) history.replaceState({}, "", historyUrl);
540
- else {
541
- history.replaceState({
542
- scrollX: window.scrollX,
543
- scrollY: window.scrollY
544
- }, "");
545
- history.pushState({}, "", historyUrl);
546
- }
631
+ scrollRestoration.writeHistory(historyUrl, !!options.replace);
547
632
  }
633
+ scrollRestoration.commit();
548
634
  const doScroll = () => {
549
635
  if (options.preserveScroll) return;
550
636
  if (options._scrollPosition) window.scrollTo(options._scrollPosition.x, options._scrollPosition.y);
@@ -570,6 +656,7 @@ async function createPageNavigationEngine(config) {
570
656
  initialComponent,
571
657
  initialLayouts,
572
658
  prepareVisit(url, options = {}) {
659
+ if (!options._popstate) scrollRestoration.save();
573
660
  const hashIndex = url.indexOf("#");
574
661
  const hash = hashIndex !== -1 ? url.slice(hashIndex) : "";
575
662
  const fetchUrl = hashIndex !== -1 ? url.slice(0, hashIndex) : url;
@@ -686,12 +773,14 @@ async function createPageNavigationEngine(config) {
686
773
  setPopStateHandler(handler) {
687
774
  popStateHandler = handler;
688
775
  },
776
+ commitInitialRender() {
777
+ const saved = initialScrollPosition;
778
+ initialScrollPosition = null;
779
+ scrollRestoration.commit();
780
+ if (saved && _nextNavigationId === 0) window.scrollTo(saved.x, saved.y);
781
+ },
689
782
  start() {
690
- history.scrollRestoration = "manual";
691
- history.replaceState({
692
- scrollX: window.scrollX,
693
- scrollY: window.scrollY
694
- }, "");
783
+ initialScrollPosition = scrollRestoration.start();
695
784
  initClientHead(initialPageData.head);
696
785
  if (deferredWindow.__deferredQueue) {
697
786
  for (const entry of deferredWindow.__deferredQueue) if (entry.length === 3) _htmlDeferredRegistry?.resolve(entry[0], void 0, entry[2]);
@@ -699,14 +788,15 @@ async function createPageNavigationEngine(config) {
699
788
  delete deferredWindow.__deferredQueue;
700
789
  }
701
790
  window.addEventListener("popstate", (e) => {
702
- const saved = e.state;
703
791
  const url = window.location.pathname + window.location.search + window.location.hash;
792
+ const saved = scrollRestoration.pop(e.state);
793
+ if (!scrollRestoration.ready && url === initialUrl) {
794
+ initialScrollPosition = saved;
795
+ return;
796
+ }
704
797
  const options = {
705
798
  preserveState: true,
706
- _scrollPosition: saved ? {
707
- x: saved.scrollX ?? 0,
708
- y: saved.scrollY ?? 0
709
- } : null,
799
+ _scrollPosition: saved,
710
800
  _popstate: true
711
801
  };
712
802
  if (popStateHandler) popStateHandler(url, options);
@@ -1020,7 +1110,8 @@ async function createVoidRouter(config) {
1020
1110
  initialPageData: engine.initialPageData,
1021
1111
  initialComponent: engine.initialComponent,
1022
1112
  initialLayouts: engine.initialLayouts,
1023
- start: engine.start
1113
+ start: engine.start,
1114
+ commitInitialRender: engine.commitInitialRender
1024
1115
  };
1025
1116
  }
1026
1117
  }
@@ -1,7 +1,7 @@
1
1
  import { a as join } from "../dist-BVqXeR_h.mjs";
2
2
  import { r as resolvePagesDir } from "../project-paths-GgcMozYz.mjs";
3
3
  import { m as readConfig } from "../config-Br_JZD6u.mjs";
4
- import { a as resolveNamedLayout, i as resolveLayoutIds, n as resolveEffectiveLayoutChain, r as resolveLayoutChain, t as scanPages } from "../scan-C7okrLyM.mjs";
4
+ import { a as resolveNamedLayout, i as resolveLayoutIds, n as resolveEffectiveLayoutChain, r as resolveLayoutChain, t as scanPages } from "../scan-C8dA7iM4.mjs";
5
5
  import { i as parseRedirectsFile } from "../headers-2rKda9Y6.mjs";
6
6
  import { i as resolveHead, n as renderHeadToString, r as renderHtmlAttrs, t as renderBodyAttrs } from "../head-D_QRR5Yd.mjs";
7
7
  import { t as serializePageData } from "../serialize-BPvnNQuA.mjs";
@@ -1,6 +1,6 @@
1
1
  import { n as dirname, u as resolve } from "../dist-BVqXeR_h.mjs";
2
2
  import { n as isIdentifier, r as isLiteral } from "../ast-CPGPjb0V.mjs";
3
- import { n as resolveEffectiveLayoutChain, t as scanPages } from "../scan-C7okrLyM.mjs";
3
+ import { n as resolveEffectiveLayoutChain, t as scanPages } from "../scan-C8dA7iM4.mjs";
4
4
  import { t as MagicString } from "../dist-AoCzRTJE.mjs";
5
5
  import { existsSync, readFileSync, readdirSync } from "node:fs";
6
6
  import { normalizePath, parseSync } from "vite";
@@ -1,3 +1,3 @@
1
- import { w as ValidationError } from "../handler-CZ4nAylQ.mjs";
2
- import { a as handlePageMutation, i as handlePageGet, n as PageRenderResult, o as safeJsonStringify, r as flattenValidationErrors, t as PageObject } from "../protocol-CjF_iI9X.mjs";
1
+ import { w as ValidationError } from "../handler-BeK3weD4.mjs";
2
+ import { a as handlePageMutation, i as handlePageGet, n as PageRenderResult, o as safeJsonStringify, r as flattenValidationErrors, t as PageObject } from "../protocol-BX8t2jiw.mjs";
3
3
  export { PageObject, PageRenderResult, ValidationError, flattenValidationErrors, handlePageGet, handlePageMutation, safeJsonStringify };
@@ -1,4 +1,4 @@
1
- import { MIGRATION_CLASSIFIER_VERSION, canonicalJson, canonicalSql, classifySqlMigration, getMigrationPlanHashInput, tokenizeSql } from "@void/deploy-core";
1
+ import { MIGRATION_CLASSIFIER_VERSION, canonicalJson, canonicalSql, classifySqlMigration, getMigrationPlanHashInput, splitSqlStatements, tokenizeSql } from "@void/deploy-core";
2
2
  import { createHash } from "node:crypto";
3
3
  //#region src/migrations/plan.ts
4
4
  const DESTRUCTIVE_PRAGMA = "-- void:allow-destructive";
@@ -41,7 +41,7 @@ function classifyMigration(migration) {
41
41
  return {
42
42
  ...base,
43
43
  planHash: hashPlan(base),
44
- ...classification.kind === "legacy-unsplit-multi-statement" ? { warnings: [`Migration ${migration.name} contains multiple statements without Drizzle statement breakpoints; it will run through the legacy D1 path.`] } : {}
44
+ ...classification.kind === "legacy-unsplit-multi-statement" && splitSqlStatements(sql) === null ? { warnings: [`Add a \`--> statement-breakpoint\` line after each complete SQL statement in migration ${migration.name}.`] } : {}
45
45
  };
46
46
  }
47
47
  function buildMigrationPlanBundle(migrations) {
@@ -0,0 +1,2 @@
1
+ import { n as buildMigrationPlanBundle } from "./plan-CJGEeTEI.mjs";
2
+ export { buildMigrationPlanBundle };
@@ -1,4 +1,4 @@
1
- import { n as operatorGroups, r as parseOperatorArgs } from "./operator-args-B3BTmSoi.mjs";
1
+ import { n as operatorGroups, r as parseOperatorArgs } from "./operator-args-DdY54Bgb.mjs";
2
2
  import { PLATFORM_LOGIN_KINDS, normalizePlatformDashboardUrl, parsePlatformLoginId } from "@void/platform";
3
3
  import { parsePlatformPlanId } from "@void/platform/plans";
4
4
  //#region src/cli/platform-config-args.ts
@@ -416,6 +416,7 @@ function parsePlatformArgs(args) {
416
416
  if (subcommand === "uninstall") {
417
417
  const parsed = parseSelector(rest.filter((arg) => ![
418
418
  "--purge-data",
419
+ "--purge-resources",
419
420
  "--delete-zone",
420
421
  "--keep-zone"
421
422
  ].includes(arg)), subcommand, { allowYes: true });
@@ -424,7 +425,8 @@ function parsePlatformArgs(args) {
424
425
  subcommand,
425
426
  selector: parsed.selector,
426
427
  plan: parsed.plan,
427
- purgeData: rest.includes("--purge-data"),
428
+ purgeData: rest.includes("--purge-data") || rest.includes("--purge-resources"),
429
+ purgeResources: rest.includes("--purge-resources"),
428
430
  yes: parsed.yes,
429
431
  deleteZone: rest.includes("--delete-zone") ? true : rest.includes("--keep-zone") ? false : null
430
432
  };
@@ -0,0 +1,2 @@
1
+ import { t as parsePlatformArgs } from "./platform-args-DSV2p4nY.mjs";
2
+ export { parsePlatformArgs };
@@ -1,10 +1,11 @@
1
- import { u as openBrowser } from "./auth-CQkSDS50.mjs";
2
- import { A as confirm, K as select, U as password, X as text, tt as isCancel, z as multiselect } from "./prompts-BNUoTiaf.mjs";
3
- import { n as OperatorClient } from "./operator-client-CpHjTd0t.mjs";
4
- import { a as resolveOperatorOrigin, r as readOperatorToken } from "./operator-auth-7erYc6Lt.mjs";
5
- import { execFile } from "node:child_process";
1
+ import { u as openBrowser } from "./auth-D52yG7hl.mjs";
2
+ import { A as confirm, K as select, U as password, X as text, tt as isCancel, z as multiselect } from "./prompts-6OSVA7DJ.mjs";
3
+ import { n as OperatorClient } from "./operator-client-BFqpp6z0.mjs";
4
+ import { a as resolveOperatorOrigin, r as readOperatorToken } from "./operator-auth-2dsGlTT5.mjs";
5
+ import { i as humanLines } from "./operator-cmd-CUGHXrQf.mjs";
6
6
  import { parsePlatformAdmissionPolicy, parsePlatformLoginConfiguration } from "@void/platform";
7
7
  import { stripVTControlCharacters } from "node:util";
8
+ import { execFile } from "node:child_process";
8
9
  import { setTimeout } from "node:timers/promises";
9
10
  import { readFile } from "node:fs/promises";
10
11
  //#region src/cli/platform-auth-config.ts
@@ -12,8 +13,8 @@ function value(input) {
12
13
  if (isCancel(input) || typeof input === "symbol") throw new Error("platform: Cancelled.");
13
14
  return input;
14
15
  }
15
- function print(result) {
16
- console.log(JSON.stringify(result, null, 2));
16
+ function print(result, json) {
17
+ console.log(json ? JSON.stringify(result, null, 2) : humanLines(result).join("\n"));
17
18
  }
18
19
  async function apply(client, path, body, args) {
19
20
  const preview = await client.request(path, {
@@ -140,11 +141,11 @@ async function configurationInput(args, existing) {
140
141
  }
141
142
  async function runPlatformAuthConfig(args) {
142
143
  if (args.action === "recover") {
143
- const { runPlatformAuthRecovery } = await import("./platform-auth-recovery-CmCzX2Fl.mjs");
144
+ const { runPlatformAuthRecovery } = await import("./platform-auth-recovery-WfTZ8K6o.mjs");
144
145
  return runPlatformAuthRecovery(args);
145
146
  }
146
147
  if (args.action === "protection") {
147
- const { runPlatformProtectionConfig } = await import("./platform-auth-protection-BLadnnct.mjs");
148
+ const { runPlatformProtectionConfig } = await import("./platform-auth-protection-DcbL_LW_.mjs");
148
149
  return runPlatformProtectionConfig(args);
149
150
  }
150
151
  const origin = resolveOperatorOrigin(args.connection);
@@ -152,11 +153,11 @@ async function runPlatformAuthConfig(args) {
152
153
  const listing = await client.request("/config/auth");
153
154
  if (!args.action) {
154
155
  if (!process.stdin.isTTY || args.json) {
155
- print(listing);
156
+ print(listing, args.json);
156
157
  return;
157
158
  }
158
159
  if (!listing.initialized) {
159
- print(await apply(client, "/config/auth/initialize", {}, args));
160
+ print(await apply(client, "/config/auth/initialize", {}, args), args.json);
160
161
  console.log("Run void platform auth login, then return to void platform config auth.");
161
162
  return;
162
163
  }
@@ -266,11 +267,11 @@ async function runPlatformAuthConfig(args) {
266
267
  });
267
268
  }
268
269
  if (args.action === "list") {
269
- print(listing);
270
+ print(listing, args.json);
270
271
  return;
271
272
  }
272
273
  if (args.action === "initialize") {
273
- print(await apply(client, "/config/auth/initialize", {}, args));
274
+ print(await apply(client, "/config/auth/initialize", {}, args), args.json);
274
275
  return;
275
276
  }
276
277
  if (!listing.initialized) throw new Error("platform: Run void platform config auth initialize, then sign in again.");
@@ -321,17 +322,17 @@ async function runPlatformAuthConfig(args) {
321
322
  print(await apply(client, "/config/auth/admission", {
322
323
  revision: listing.revision,
323
324
  admission: parsePlatformAdmissionPolicy(admission)
324
- }, args));
325
+ }, args), args.json);
325
326
  return;
326
327
  }
327
328
  const method = listing.methods.find((method) => method.id === args.target);
328
329
  if (args.action !== "add" && !method) throw new Error("platform: Login method not found. Run void platform config auth list.");
329
330
  if (args.action === "show") {
330
- print(method);
331
+ print(method, args.json);
331
332
  return;
332
333
  }
333
334
  if (args.action === "test") {
334
- print(await testMethod(client, args.target, args));
335
+ print(await testMethod(client, args.target, args), args.json);
335
336
  return;
336
337
  }
337
338
  if (args.action === "add" || args.action === "configure") {
@@ -340,7 +341,7 @@ async function runPlatformAuthConfig(args) {
340
341
  print(await apply(client, `/config/auth/connections/${encodeURIComponent(input.configuration.id)}/configure`, {
341
342
  ...input,
342
343
  revision: args.action === "add" ? null : method.revision
343
- }, args));
344
+ }, args), args.json);
344
345
  if (!args.plan && !args.json) console.log(`Test and enable it with void platform config auth enable ${input.configuration.id}.`);
345
346
  return;
346
347
  }
@@ -348,7 +349,7 @@ async function runPlatformAuthConfig(args) {
348
349
  if ((args.action === "enable" || args.action === "link") && !testId) {
349
350
  if (!process.stdin.isTTY || args.plan || args.json) throw new Error("platform: Complete a login test and supply its --test-id.");
350
351
  const tested = await testMethod(client, args.target, args);
351
- print(tested);
352
+ print(tested, args.json);
352
353
  if (tested.complete !== true || typeof tested.id !== "string") throw new Error("platform: Complete the browser test before enabling or linking this login.");
353
354
  testId = tested.id;
354
355
  if (args.action === "enable" && value(await confirm({
@@ -362,7 +363,7 @@ async function runPlatformAuthConfig(args) {
362
363
  print(await apply(client, `/config/auth/connections/${encodeURIComponent(args.target)}/${args.action}`, {
363
364
  revision: method.revision,
364
365
  ...testId ? { testId } : {}
365
- }, args));
366
+ }, args), args.json);
366
367
  }
367
368
  //#endregion
368
369
  export { runPlatformAuthConfig };
@@ -1,13 +1,13 @@
1
+ import { S as writePendingInstallationSecrets, c as normalizePlatformApiUrl, m as readInstallationRecoverySecrets, p as promoteInstallationSecrets, t as acquirePlatformLifecycleLock, v as resolveInstallationManifest, x as writeInstallationManifest } from "./platform-registry-P387v42A.mjs";
1
2
  import { t as cfAccessHeaders } from "./cf-access-TWNzXltp.mjs";
2
- import { b as writePendingInstallationSecrets, d as promoteInstallationSecrets, f as readInstallationRecoverySecrets, g as resolveInstallationManifest, s as normalizePlatformApiUrl, t as acquirePlatformLifecycleLock, y as writeInstallationManifest } from "./platform-registry-DkPPXfp_.mjs";
3
- import { n as ensurePlatformAccessToken } from "./cf-access-BGe5sWXF.mjs";
4
- import { A as confirm, tt as isCancel } from "./prompts-BNUoTiaf.mjs";
5
- import { n as OperatorClient } from "./operator-client-CpHjTd0t.mjs";
6
- import { a as resolveOperatorOrigin, r as readOperatorToken } from "./operator-auth-7erYc6Lt.mjs";
7
- import { A as PlatformCloudflareClient, D as checkpointPlatformAccessResources, E as resolvePlatformCloudflareCredential, O as parsePlatformAccessSetupSpec, k as preparePlatformAccessSetup, n as resolvePlatformInstallDatabaseUrl, o as acquirePlatformDatabaseLifecycleLock } from "./platform-lifecycle-BBoNzojY.mjs";
8
- import { c as selectAuthoritativePlatformManifest, u as verifyPlatformInstallationOwnership } from "./platform-management-CWOQOWXm.mjs";
9
- import { createHmac } from "node:crypto";
3
+ import { n as ensurePlatformAccessToken } from "./cf-access-YTlqvAsk.mjs";
4
+ import { A as confirm, tt as isCancel } from "./prompts-6OSVA7DJ.mjs";
5
+ import { n as OperatorClient } from "./operator-client-BFqpp6z0.mjs";
6
+ import { a as resolveOperatorOrigin, r as readOperatorToken } from "./operator-auth-2dsGlTT5.mjs";
7
+ import { G as preparePlatformAccessSetup, K as PlatformCloudflareClient, U as checkpointPlatformAccessResources, V as resolvePlatformCloudflareCredential, W as parsePlatformAccessSetupSpec, n as resolvePlatformInstallDatabaseUrl, s as acquirePlatformDatabaseLifecycleLock } from "./platform-lifecycle-Cfi0o6xM.mjs";
8
+ import { d as verifyPlatformInstallationOwnership, l as selectAuthoritativePlatformManifest } from "./platform-management-BrF9STZp.mjs";
10
9
  import { parsePlatformAccessProtection, platformProtectionProofMessage } from "@void/platform";
10
+ import { createHmac } from "node:crypto";
11
11
  import { readFile } from "node:fs/promises";
12
12
  //#region src/cli/platform-auth-protection.ts
13
13
  /** Read every externally routed control-plane Worker before changing its preview settings. */
@@ -1,12 +1,12 @@
1
- import { f as readInstallationRecoverySecrets, g as resolveInstallationManifest, t as acquirePlatformLifecycleLock } from "./platform-registry-DkPPXfp_.mjs";
2
- import { u as openBrowser } from "./auth-CQkSDS50.mjs";
3
- import { A as confirm, tt as isCancel } from "./prompts-BNUoTiaf.mjs";
4
- import { a as resolveOperatorOrigin } from "./operator-auth-7erYc6Lt.mjs";
5
- import { A as PlatformCloudflareClient, E as resolvePlatformCloudflareCredential, f as platformDatabaseClientUrl, n as resolvePlatformInstallDatabaseUrl, s as acquirePlatformDatabaseLifecycleLockConnection } from "./platform-lifecycle-BBoNzojY.mjs";
6
- import { c as selectAuthoritativePlatformManifest, u as verifyPlatformInstallationOwnership } from "./platform-management-CWOQOWXm.mjs";
1
+ import { m as readInstallationRecoverySecrets, t as acquirePlatformLifecycleLock, v as resolveInstallationManifest } from "./platform-registry-P387v42A.mjs";
2
+ import { u as openBrowser } from "./auth-D52yG7hl.mjs";
3
+ import { A as confirm, tt as isCancel } from "./prompts-6OSVA7DJ.mjs";
4
+ import { a as resolveOperatorOrigin } from "./operator-auth-2dsGlTT5.mjs";
5
+ import { K as PlatformCloudflareClient, V as resolvePlatformCloudflareCredential, c as acquirePlatformDatabaseLifecycleLockConnection, l as platformDatabaseClientUrl, n as resolvePlatformInstallDatabaseUrl } from "./platform-lifecycle-Cfi0o6xM.mjs";
6
+ import { d as verifyPlatformInstallationOwnership, l as selectAuthoritativePlatformManifest } from "./platform-management-BrF9STZp.mjs";
7
+ import { parsePlatformAccessProtection, parsePlatformAdmissionPolicy, parsePlatformLoginConfiguration, platformAuthenticationRecoveryMessage, validatePlatformAdmissionPolicy } from "@void/platform";
7
8
  import { createCipheriv, createDecipheriv, createHash, createHmac, hkdfSync, randomBytes, randomUUID } from "node:crypto";
8
9
  import { execFile } from "node:child_process";
9
- import { parsePlatformAccessProtection, parsePlatformAdmissionPolicy, parsePlatformLoginConfiguration, platformAuthenticationRecoveryMessage, validatePlatformAdmissionPolicy } from "@void/platform";
10
10
  import { setTimeout } from "node:timers/promises";
11
11
  import { readFile } from "node:fs/promises";
12
12
  //#region src/cli/platform-auth-recovery-core.ts
@@ -1,12 +1,16 @@
1
+ import { b as selectPlatformConnection, c as normalizePlatformApiUrl, i as getActivePlatformConnection, l as platformConnectionSlug, o as listInstallationManifests, s as listPlatformConnections, y as savePlatformConnection } from "./platform-registry-P387v42A.mjs";
1
2
  import { t as cfAccessHeaders } from "./cf-access-TWNzXltp.mjs";
2
- import { _ as savePlatformConnection, o as listPlatformConnections, r as getActivePlatformConnection, s as normalizePlatformApiUrl, v as selectPlatformConnection } from "./platform-registry-DkPPXfp_.mjs";
3
- import { i as isCloudflareAccessChallenge, n as ensurePlatformAccessToken, t as ensureCloudflaredToken } from "./cf-access-BGe5sWXF.mjs";
4
- import { K as select, L as log, X as text, tt as isCancel } from "./prompts-BNUoTiaf.mjs";
5
- import { c as import_picocolors } from "./output-CbM85T4k.mjs";
6
- import { parsePlatformDiscoveryDocument } from "@void/platform";
3
+ import { i as isCloudflareAccessChallenge, n as ensurePlatformAccessToken, t as ensureCloudflaredToken } from "./cf-access-YTlqvAsk.mjs";
4
+ import { K as select, L as log, X as text, tt as isCancel } from "./prompts-6OSVA7DJ.mjs";
5
+ import { n as readPlatformDiscoveryResponse, t as PlatformDisabledError } from "./platform-discovery-BC0HCKYt.mjs";
6
+ import { c as import_picocolors } from "./output-BvdaehtE.mjs";
7
7
  //#region src/cli/platform-cmd.ts
8
+ function normalizePlatformInputUrl(input) {
9
+ const value = input.trim();
10
+ return normalizePlatformApiUrl(value.includes("://") ? value : `https://${value}`);
11
+ }
8
12
  async function discoverPlatform(input, fetcher = fetch) {
9
- const apiUrl = normalizePlatformApiUrl(input);
13
+ const apiUrl = normalizePlatformInputUrl(input);
10
14
  ensureCloudflaredToken(apiUrl);
11
15
  const request = () => fetcher(`${apiUrl}/.well-known/void-platform`, {
12
16
  headers: {
@@ -22,32 +26,17 @@ async function discoverPlatform(input, fetcher = fetch) {
22
26
  ensurePlatformAccessToken(apiUrl, true);
23
27
  response = await request();
24
28
  }
25
- if (!response.ok) throw new Error(`platform: Discovery failed at ${apiUrl} (HTTP ${response.status}).`);
26
- let value;
27
- try {
28
- value = await response.json();
29
- } catch {
30
- throw new Error(`platform: ${apiUrl} returned invalid discovery metadata.`);
31
- }
32
- let discovery;
33
- try {
34
- discovery = parsePlatformDiscoveryDocument(value);
35
- } catch (error) {
36
- throw new Error(`platform: ${apiUrl} returned invalid discovery metadata: ${error instanceof Error ? error.message : String(error)}`);
37
- }
38
- const finalOrigin = normalizePlatformApiUrl(response.url ? new URL(response.url).origin : apiUrl);
39
- if (discovery.apiUrl !== finalOrigin) throw new Error(`platform: Discovery origin mismatch. The response came from ${finalOrigin}, but identifies ${discovery.apiUrl}.`);
40
- return discovery;
29
+ return readPlatformDiscoveryResponse(apiUrl, response);
41
30
  }
42
31
  async function promptPlatformUrl() {
43
32
  if (!process.stdin.isTTY) throw new Error("platform: A platform URL is required in non-interactive mode.");
44
33
  const value = await text({
45
34
  message: "Void platform API URL:",
46
- placeholder: "https://platform.example.com",
35
+ placeholder: "platform.example.com",
47
36
  validate: (input) => {
48
37
  if (!input) return "Enter a platform URL.";
49
38
  try {
50
- normalizePlatformApiUrl(input);
39
+ normalizePlatformInputUrl(input);
51
40
  } catch (error) {
52
41
  return error instanceof Error ? error.message : String(error);
53
42
  }
@@ -61,7 +50,7 @@ async function resolveConnection(selector) {
61
50
  const connections = listPlatformConnections();
62
51
  if (connections.length === 0) throw new Error("platform: No platforms configured. Run `void connect <url>`.");
63
52
  if (connections.length === 1) return selectPlatformConnection(connections[0].id);
64
- if (!process.stdin.isTTY) throw new Error("platform: Multiple platforms are configured; specify an id or URL.");
53
+ if (!process.stdin.isTTY) throw new Error("platform: Multiple platforms are configured; specify a slug, name, ID, or URL.");
65
54
  const picked = await select({
66
55
  message: "Select a Void platform:",
67
56
  options: connections.map((connection) => ({
@@ -73,11 +62,11 @@ async function resolveConnection(selector) {
73
62
  if (isCancel(picked)) throw new Error("platform: Cancelled.");
74
63
  return selectPlatformConnection(String(picked));
75
64
  }
76
- function showConnection(connection, activeId) {
77
- const marker = connection.id === activeId ? import_picocolors.default.green("●") : import_picocolors.default.dim("○");
78
- console.log(`${marker} ${import_picocolors.default.bold(connection.displayName)} ${import_picocolors.default.dim(connection.id)}`);
79
- console.log(` ${connection.apiUrl}`);
80
- if (connection.applicationDomain) console.log(connection.applicationDomain.endsWith(".workers.dev") ? " apps: workers.dev (testing)" : ` apps: *.${connection.applicationDomain}`);
65
+ function showPlatform(connection, installations) {
66
+ const slug = platformConnectionSlug(connection, installations);
67
+ console.log(` ${import_picocolors.default.bold(connection.displayName)}${slug ? ` ${import_picocolors.default.dim(`(${slug})`)}` : ""}`);
68
+ console.log(` ${connection.apiUrl}`);
69
+ if (connection.applicationDomain) console.log(connection.applicationDomain.endsWith(".workers.dev") ? " apps: workers.dev (testing)" : ` apps: *.${connection.applicationDomain}`);
81
70
  }
82
71
  function saveDiscoveredPlatform(discovery) {
83
72
  return savePlatformConnection({
@@ -106,19 +95,19 @@ async function runPlatformCommand(_root, args) {
106
95
  }]
107
96
  });
108
97
  if (isCancel(group)) return;
109
- const { parsePlatformArgs } = await import("./platform-args-DdnM6WIf.mjs");
98
+ const { parsePlatformArgs } = await import("./platform-args-Dcy_5b_Y.mjs");
110
99
  return runPlatformCommand(_root, parsePlatformArgs(["config", group]));
111
100
  }
112
- const { runPlatformPlansConfig } = await import("./platform-plans-config-Vl9BP3H4.mjs");
101
+ const { runPlatformPlansConfig } = await import("./platform-plans-config-DU-8nC2Y.mjs");
113
102
  await runPlatformPlansConfig(args);
114
103
  return;
115
104
  }
116
- const { runPlatformAuthConfig } = await import("./platform-auth-config-DDrxUy4m.mjs");
105
+ const { runPlatformAuthConfig } = await import("./platform-auth-config-Bosx7U1h.mjs");
117
106
  await runPlatformAuthConfig(args);
118
107
  return;
119
108
  }
120
109
  if (args.subcommand === "operator") {
121
- const { runOperatorCommand } = await import("./operator-cmd-DGqPJUD3.mjs");
110
+ const { runOperatorCommand } = await import("./operator-cmd-DRPvhpjM.mjs");
122
111
  await runOperatorCommand(args);
123
112
  return;
124
113
  }
@@ -128,8 +117,23 @@ async function runPlatformCommand(_root, args) {
128
117
  log.info("No platforms configured. Run `void connect <url>`.");
129
118
  return;
130
119
  }
131
- const activeId = getActivePlatformConnection()?.id ?? null;
132
- for (const connection of connections) showConnection(connection, activeId);
120
+ const active = getActivePlatformConnection();
121
+ const installations = listInstallationManifests();
122
+ if (active) {
123
+ console.log(import_picocolors.default.blue(import_picocolors.default.bold("Currently selected platform:")));
124
+ showPlatform(active, installations);
125
+ } else console.log("No platform selected.");
126
+ const others = connections.filter((connection) => connection.id !== active?.id);
127
+ if (others.length > 0) {
128
+ console.log("");
129
+ console.log(import_picocolors.default.blue(import_picocolors.default.bold("Other platforms:")));
130
+ for (const [index, connection] of others.entries()) {
131
+ if (index > 0) console.log("");
132
+ showPlatform(connection, installations);
133
+ }
134
+ console.log("");
135
+ console.log(import_picocolors.default.gray("run `void platform use <id>` to select one"));
136
+ }
133
137
  return;
134
138
  }
135
139
  if (args.subcommand === "use") {
@@ -138,7 +142,28 @@ async function runPlatformCommand(_root, args) {
138
142
  return;
139
143
  }
140
144
  if (args.subcommand === "status") {
141
- const discovery = await discoverPlatform((await resolveConnection(args.selector)).apiUrl);
145
+ const local = args.selector ? listInstallationManifests().find((manifest) => manifest.id === args.selector && manifest.status !== "uninstalled") : void 0;
146
+ const connection = local ? null : await resolveConnection(args.selector);
147
+ const saved = local ?? (connection?.installationId ? listInstallationManifests().find((manifest) => manifest.id === connection.installationId) : void 0);
148
+ if (saved) showSavedInstallationStatus(saved);
149
+ const apiUrl = local?.endpoints.apiUrl ?? connection?.apiUrl;
150
+ if (!apiUrl) {
151
+ log.info("No verified API endpoint is saved yet. Live traffic availability is unknown.");
152
+ return;
153
+ }
154
+ let discovery;
155
+ try {
156
+ discovery = await discoverPlatform(apiUrl);
157
+ } catch (error) {
158
+ if (error instanceof PlatformDisabledError && !error.maintenance) {
159
+ console.log("Platform: disabled (API and application traffic are paused).");
160
+ if (!saved?.operation) console.log(`Enable it: void platform enable${saved ? ` ${saved.id}` : ""}`);
161
+ return;
162
+ }
163
+ if (saved) log.info("Live availability could not be confirmed. The saved checkpoint above may be out of date.");
164
+ if (error instanceof PlatformDisabledError) throw new Error(`platform: Traffic at ${apiUrl} is paused for an upgrade or repair. Check again when it finishes.`, { cause: error });
165
+ throw error;
166
+ }
142
167
  log.success(`${discovery.displayName} is reachable.`);
143
168
  console.log(`API: ${discovery.apiUrl}`);
144
169
  console.log(`Proxy: ${discovery.proxyUrl}`);
@@ -150,8 +175,18 @@ async function runPlatformCommand(_root, args) {
150
175
  console.log(`Capabilities: ${Object.entries(discovery.capabilities).filter(([, enabled]) => enabled).map(([name]) => name).join(", ")}`);
151
176
  return;
152
177
  }
153
- const { runPlatformLifecycleCommand } = await import("./platform-lifecycle-BFdSi9Qt.mjs");
178
+ const { runPlatformLifecycleCommand } = await import("./platform-lifecycle--5gWmDoI.mjs");
154
179
  await runPlatformLifecycleCommand(args);
155
180
  }
181
+ function showSavedInstallationStatus(manifest) {
182
+ console.log(`Saved installation: ${manifest.id} (${manifest.status})`);
183
+ console.log(`Checkpoint: ${manifest.updatedAt}`);
184
+ if (manifest.operation) {
185
+ const operation = manifest.operation;
186
+ console.log(`Saved operation: ${operation.action} — ${operation.phase}`);
187
+ console.log(`Runtime: ${operation.fromVersion ?? "new installation"} → ${operation.toVersion}`);
188
+ }
189
+ if (manifest.endpoints.apiUrl) console.log(`Administrator status: ${manifest.endpoints.apiUrl}/admin/status`);
190
+ }
156
191
  //#endregion
157
192
  export { saveDiscoveredPlatform as i, promptPlatformUrl as n, runPlatformCommand as r, discoverPlatform as t };
@@ -1,2 +1,2 @@
1
- import { r as runPlatformCommand, t as discoverPlatform } from "./platform-cmd-DMDEc9uS.mjs";
1
+ import { r as runPlatformCommand, t as discoverPlatform } from "./platform-cmd-DbKtQb_4.mjs";
2
2
  export { discoverPlatform, runPlatformCommand };