@volter/world-console 2.0.7 → 2.0.9

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.
@@ -429,7 +429,7 @@ type Diff = { base: { id: string; at: string | null }; changes: Array<{ twin: st
429
429
  type Branch = { name: string; at?: { instant?: string }; createdAt: string; expiresAt: string | null };
430
430
  /** The branches door: the host's snapshots of this World, and the World's own named branches (`volter world branch`),
431
431
  * one of which, `checkedOut`, is the one this serve holds. */
432
- type BranchesDoor = { branches: Branch[]; checkedOut?: string; named?: Array<{ name: string; running: boolean }> };
432
+ type BranchesDoor = { branches: Branch[]; checkedOut?: string; named?: Array<{ name: string; running: boolean }>; canServe?: boolean };
433
433
  /** What the World's session answered: its scope; `unknown` when the host has no session door (a write then says). */
434
434
  type Scope = 'pending' | 'read' | 'write' | 'unknown';
435
435
 
@@ -936,6 +936,15 @@ function BranchList({ name, token, canWrite, branches, opens, note, remove, onCh
936
936
  const list = branches.state === 'ok' ? branches.data.branches : [];
937
937
  const [making, setMaking] = useState(false); const [busy, setBusy] = useState(false); const [error, setError] = useState<string | null>(null);
938
938
  const [label, setLabel] = useState(''); const [when, setWhen] = useState<'now' | 'at'>('now'); const [at, setAt] = useState(''); const [hours, setHours] = useState('24');
939
+ // SERVE ANOTHER of the World's own branches here: the World switches under this page, which then reads it afresh
940
+ const [serving, setServing] = useState<string | null>(null); const [serveError, setServeError] = useState<string | null>(null);
941
+ const serveHere = async (branch: string): Promise<void> => {
942
+ setServing(branch); setServeError(null);
943
+ const r = await door(token, `/-/${name}/branches/${encodeURIComponent(branch)}/serve`, { method: 'POST' }).catch(() => null);
944
+ if (r?.ok) { location.reload(); return; }
945
+ setServing(null);
946
+ setServeError(r ? ((await r.json().catch(() => null)) as { error?: string } | null)?.error ?? `${r.status}` : `${ORIGIN} did not answer`);
947
+ };
939
948
  // made here: kept with its tokens so it opens in this tab; not `made` (a snapshot's "Return to live" never removes it: it lives as long as it was given)
940
949
  const make = async (body: Record<string, unknown>, opened: string): Promise<{ name: string } | string> => {
941
950
  const r = await door(token, `/-/${name}/branches`, { method: 'POST', body: JSON.stringify(body) }).catch(() => null);
@@ -1010,15 +1019,17 @@ function BranchList({ name, token, canWrite, branches, opens, note, remove, onCh
1010
1019
  ) : null}
1011
1020
  {branches.state === 'ok' && (branches.data.named?.length ?? 0) > 0 ? (
1012
1021
  <>
1013
- <p className="lede">This World's own branches (<code>volter world branch</code>). One runs at a time; this page shows the one served here. Another is served by stopping this serve, <code>volter world checkout &lt;branch&gt;</code>, and serving again.</p>
1022
+ <p className="lede">This World's own branches (<code>volter world branch</code>). One runs at a time; {branches.data.canServe ? <>“Serve here” stops this one's twins and serves that one in its place.</> : <>this host serves one of them; another is served by <code>volter world checkout &lt;branch&gt;</code> where the World lives, then serving again.</>}</p>
1023
+ {serveError ? <p role="alert">{serveError}</p> : null}
1014
1024
  <div className="block">
1015
1025
  <table className="dense" aria-label="World branches">
1016
- <thead><tr><th>Branch</th><th>State</th></tr></thead>
1026
+ <thead><tr><th>Branch</th><th>State</th><th /></tr></thead>
1017
1027
  <tbody>
1018
1028
  {branches.data.named!.map((b) => (
1019
1029
  <tr key={b.name}>
1020
1030
  <td><b>{b.name}</b>{b.name === branches.data.checkedOut ? <> <span className="badge">served here</span></> : null}</td>
1021
1031
  <td className="mode">{b.running ? 'running' : 'stopped'}</td>
1032
+ <td className="num row-actions">{canWrite && branches.data.canServe && b.name !== branches.data.checkedOut ? <button type="button" disabled={serving !== null} onClick={() => void serveHere(b.name)}>{serving === b.name ? 'Switching…' : 'Serve here'}</button> : null}</td>
1022
1033
  </tr>
1023
1034
  ))}
1024
1035
  </tbody>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/world-console",
3
- "version": "2.0.7",
3
+ "version": "2.0.9",
4
4
  "description": "The dashboard of Volter World: a World's pages, the same on a laptop, a self-hosted host and the hosted cloud — mounted by the host at /-/console/. A pure frontend over the World's own doors; its kit (./kit) is the pieces the platform's pages share.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -23,8 +23,8 @@
23
23
  "react-dom": "^19.2.7"
24
24
  },
25
25
  "devDependencies": {
26
- "@volter/world-host": "2.0.11",
27
- "@volter/world-runtime": "2.0.12",
26
+ "@volter/world-host": "2.0.14",
27
+ "@volter/world-runtime": "2.0.15",
28
28
  "@volter/world-tooling": "0.1.0",
29
29
  "@types/bun": "^1.2.20",
30
30
  "@types/node": "^24.0.0",