@volter/world-runtime 3.0.35 → 3.0.36

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.
@@ -3,9 +3,9 @@
3
3
  // parent through its own doors (its history cut at an instant, when one is asked), its clock frozen at
4
4
  // that instant so no twin's catch-up walks it forward, and removed when its time runs out. world-host
5
5
  // and `volter world view` both make them with this; a hosted World's supervisor makes its own.
6
- import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
6
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
7
7
  import { dirname, join } from 'node:path';
8
- import { stateDirName, withStateRemoval } from '@volter/world-core/runtime';
8
+ import { readBranchMeta, stateDirName, withHistoryLock, withStateRemoval, worldPaths, worldStateRoot, writeBranchMeta } from '@volter/world-core/runtime';
9
9
  import { inheritWorldBrowsers, materializeBrowserFiles } from "./browsers.js";
10
10
  import { clockFile, statusWorld } from "./runtime.js";
11
11
  import { loadWorldConfig } from "./configs.js";
@@ -169,7 +169,25 @@ export class LocalBranches {
169
169
  writeFileSync(file, `${clock}\n`);
170
170
  }
171
171
  const child = statusWorld(id, root);
172
- inheritWorldBrowsers(statusWorld(world, from.root).dirs.data, child.dirs.data);
172
+ // The HTTP clone holds the history view here, but its URL parent holds no local resources.
173
+ // Retain the actual parent's state through the kernel's pointer/pin protocol: blob reads can
174
+ // follow it without copying uploads, while history keeps using the downloaded immutable view.
175
+ const base = statusWorld(world, from.root);
176
+ for (const service of Object.keys(child.services)) {
177
+ const control = join(child.dirs.data, service);
178
+ for (const state of readdirSync(worldStateRoot(control), { withFileTypes: true })) {
179
+ if (!state.isDirectory())
180
+ continue;
181
+ const directory = worldPaths(state.name, control).dir;
182
+ withHistoryLock(directory, () => {
183
+ const meta = readBranchMeta(state.name, control);
184
+ if (!meta?.parent)
185
+ throw new Error(`cloning ${parent}: ${service}/${state.name} has no parent`);
186
+ writeBranchMeta(state.name, { ...meta, parent: { ...meta.parent, at: join(base.dirs.data, service), viewDirectory: directory } }, control);
187
+ });
188
+ }
189
+ }
190
+ inheritWorldBrowsers(base.dirs.data, child.dirs.data);
173
191
  materializeBrowserFiles(child.dirs.data, root, id, child.config);
174
192
  const createdAt = new Date().toISOString();
175
193
  const expiresAt = ttlSeconds === null ? null : new Date(Date.now() + ttlSeconds * 1000).toISOString();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/world-runtime",
3
- "version": "3.0.35",
3
+ "version": "3.0.36",
4
4
  "description": "World configs for twins: boot named local runtimes, allocate ports, generate world.env/instance.json, and run apps against fake-key twin worlds.",
5
5
  "keywords": [
6
6
  "twin",
@@ -68,14 +68,14 @@
68
68
  "node": ">=22.3"
69
69
  },
70
70
  "peerDependencies": {
71
- "@volter/world-core": "3.0.35",
72
- "@volter/world-console": "3.0.30"
71
+ "@volter/world-core": "3.0.36",
72
+ "@volter/world-console": "3.0.31"
73
73
  },
74
74
  "dependencies": {
75
75
  "@electric-sql/pglite": "0.5.8",
76
76
  "@electric-sql/pglite-pgvector": "0.0.9",
77
77
  "@volter/world-access": "3.0.1",
78
- "@volter/world-core": "3.0.35",
78
+ "@volter/world-core": "3.0.36",
79
79
  "pg-gateway": "0.3.0-beta.4",
80
80
  "smol-toml": "^1.8.0",
81
81
  "yaml": "2.9.0"
@@ -3,9 +3,9 @@
3
3
  // parent through its own doors (its history cut at an instant, when one is asked), its clock frozen at
4
4
  // that instant so no twin's catch-up walks it forward, and removed when its time runs out. world-host
5
5
  // and `volter world view` both make them with this; a hosted World's supervisor makes its own.
6
- import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
6
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
7
7
  import { dirname, join } from 'node:path';
8
- import { stateDirName, withStateRemoval } from '@volter/world-core/runtime';
8
+ import { readBranchMeta, stateDirName, withHistoryLock, withStateRemoval, worldPaths, worldStateRoot, writeBranchMeta } from '@volter/world-core/runtime';
9
9
  import { inheritWorldBrowsers, materializeBrowserFiles } from './browsers.ts';
10
10
  import { clockFile, statusWorld } from './runtime.ts';
11
11
  import { loadWorldConfig } from './configs.ts';
@@ -162,7 +162,23 @@ export class LocalBranches {
162
162
  const clock = at.instant ?? this.frozenClock(from) ?? (at.live ? null : new Date().toISOString());
163
163
  if (clock) { const file = clockFile(root, id); mkdirSync(dirname(file), { recursive: true }); writeFileSync(file, `${clock}\n`); }
164
164
  const child = statusWorld(id, root);
165
- inheritWorldBrowsers(statusWorld(world, from.root).dirs.data, child.dirs.data);
165
+ // The HTTP clone holds the history view here, but its URL parent holds no local resources.
166
+ // Retain the actual parent's state through the kernel's pointer/pin protocol: blob reads can
167
+ // follow it without copying uploads, while history keeps using the downloaded immutable view.
168
+ const base = statusWorld(world, from.root);
169
+ for (const service of Object.keys(child.services)) {
170
+ const control = join(child.dirs.data, service);
171
+ for (const state of readdirSync(worldStateRoot(control), { withFileTypes: true })) {
172
+ if (!state.isDirectory()) continue;
173
+ const directory = worldPaths(state.name, control).dir;
174
+ withHistoryLock(directory, () => {
175
+ const meta = readBranchMeta(state.name, control);
176
+ if (!meta?.parent) throw new Error(`cloning ${parent}: ${service}/${state.name} has no parent`);
177
+ writeBranchMeta(state.name, { ...meta, parent: { ...meta.parent, at: join(base.dirs.data, service), viewDirectory: directory } }, control);
178
+ });
179
+ }
180
+ }
181
+ inheritWorldBrowsers(base.dirs.data, child.dirs.data);
166
182
  materializeBrowserFiles(child.dirs.data, root, id, child.config);
167
183
  const createdAt = new Date().toISOString();
168
184
  const expiresAt = ttlSeconds === null ? null : new Date(Date.now() + ttlSeconds * 1000).toISOString();