@volter/world 2.0.10 → 2.0.12

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.
@@ -158,6 +158,9 @@ export declare class World {
158
158
  /** Switch to a branch: its twins come back with their state; this branch's stop. */
159
159
  checkout(name: string): Promise<World>;
160
160
  branches(): string[];
161
+ /** A served World stays bound to the branch it was served on: switching under it would leave its doors forwarding to
162
+ * the stopped branch's twins. So a switch waits for the serve to stop. */
163
+ private refuseWhileServed;
161
164
  /** Is this the main branch? */
162
165
  isMain(): boolean;
163
166
  /** What this branch's changes are measured from, as `diff` says it: the branch point, origin, or the story. */
package/dist/src/world.js CHANGED
@@ -256,6 +256,7 @@ export class World {
256
256
  async branch(name, opts = {}) {
257
257
  if (listWorlds(this.root).some((w) => w.name === name))
258
258
  throw new Error(`A branch "${name}" already exists — \`volter world checkout ${name}\` switches to it`);
259
+ this.refuseWhileServed('branch');
259
260
  // this branch stops first (a managed database is copied from a stopped World, and the two would share its port),
260
261
  // and comes back if the new one fails
261
262
  const wasRunning = !!this.instance()?.running;
@@ -280,6 +281,7 @@ export class World {
280
281
  return this;
281
282
  if (!listWorlds(this.root).some((w) => w.name === name))
282
283
  throw new Error(`No branch "${name}" in this world (branches: ${listWorlds(this.root).map((w) => w.name).sort().join(', ') || 'none'})`);
284
+ this.refuseWhileServed('checkout');
283
285
  const wasRunning = this.instance()?.running ?? false;
284
286
  if (wasRunning)
285
287
  await downWorld(this.name, this.root);
@@ -290,6 +292,13 @@ export class World {
290
292
  return target;
291
293
  }
292
294
  branches() { return listWorlds(this.root).map((w) => w.name).sort(); }
295
+ /** A served World stays bound to the branch it was served on: switching under it would leave its doors forwarding to
296
+ * the stopped branch's twins. So a switch waits for the serve to stop. */
297
+ refuseWhileServed(verb) {
298
+ const served = readServeRecord(this.root);
299
+ if (served)
300
+ throw new Error(`this World is served at ${served.base} (pid ${served.pid}); stop that serve before \`volter world ${verb}\`, then serve again`);
301
+ }
293
302
  /** Is this the main branch? */
294
303
  isMain() { return this.name === mainBranch(this.root); }
295
304
  /** What this branch's changes are measured from, as `diff` says it: the branch point, origin, or the story. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/world",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Run your app against a world of twins. `World` and `Repo` — one method per verb: init, up, run, log, diff, reset, branch, checkout, clone, fetch, changeset, push — and the `volter` command, one client of them.",
5
5
  "keywords": [
6
6
  "volter",
@@ -31,7 +31,7 @@
31
31
  "dependencies": {
32
32
  "@modelcontextprotocol/sdk": "^1.30.1",
33
33
  "@volter/world-core": "2.0.7",
34
- "@volter/world-runtime": "2.0.10",
34
+ "@volter/world-runtime": "2.0.11",
35
35
  "zod": "^4.6.5"
36
36
  },
37
37
  "peerDependencies": {
package/src/world.ts CHANGED
@@ -241,6 +241,7 @@ export class World {
241
241
  */
242
242
  async branch(name: string, opts: { at?: { instant?: string; positions?: Record<string, number>; views?: Record<string, string> } } = {}): Promise<World> {
243
243
  if (listWorlds(this.root).some((w) => w.name === name)) throw new Error(`A branch "${name}" already exists — \`volter world checkout ${name}\` switches to it`);
244
+ this.refuseWhileServed('branch');
244
245
  // this branch stops first (a managed database is copied from a stopped World, and the two would share its port),
245
246
  // and comes back if the new one fails
246
247
  const wasRunning = !!this.instance()?.running;
@@ -259,6 +260,7 @@ export class World {
259
260
  if (name === 'main') name = mainBranch(this.root); // the main branch answers to its name and to `main`
260
261
  if (name === this.name) return this;
261
262
  if (!listWorlds(this.root).some((w) => w.name === name)) throw new Error(`No branch "${name}" in this world (branches: ${listWorlds(this.root).map((w) => w.name).sort().join(', ') || 'none'})`);
263
+ this.refuseWhileServed('checkout');
262
264
  const wasRunning = this.instance()?.running ?? false;
263
265
  if (wasRunning) await downWorld(this.name, this.root);
264
266
  const target = new World(name, this.root);
@@ -267,6 +269,12 @@ export class World {
267
269
  return target;
268
270
  }
269
271
  branches(): string[] { return listWorlds(this.root).map((w) => w.name).sort(); }
272
+ /** A served World stays bound to the branch it was served on: switching under it would leave its doors forwarding to
273
+ * the stopped branch's twins. So a switch waits for the serve to stop. */
274
+ private refuseWhileServed(verb: 'branch' | 'checkout'): void {
275
+ const served = readServeRecord(this.root);
276
+ if (served) throw new Error(`this World is served at ${served.base} (pid ${served.pid}); stop that serve before \`volter world ${verb}\`, then serve again`);
277
+ }
270
278
  /** Is this the main branch? */
271
279
  isMain(): boolean { return this.name === mainBranch(this.root); }
272
280
  /** What this branch's changes are measured from, as `diff` says it: the branch point, origin, or the story. */