@volter/world-runtime 2.0.44 → 2.0.46
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.
- package/dist/src/served-world.js +26 -3
- package/package.json +4 -4
- package/src/served-world.ts +21 -2
package/dist/src/served-world.js
CHANGED
|
@@ -31,7 +31,7 @@ import { APP_READ_ENDPOINT_ENV } from "./init.js";
|
|
|
31
31
|
import { grantOf, presentedSecrets, sameSecret, spentPasses, verifyPass } from '@volter/world-access';
|
|
32
32
|
import { createHash } from 'node:crypto';
|
|
33
33
|
import { dirname, join, resolve } from 'node:path';
|
|
34
|
-
import { appendActionIfAbsent, branchEntries, branchLogPath, branchMetaPath, changesetContentHash, confirmAction, parentLogPath, readTree, stateDirName, wholeLog, worldNow, parentEntries, rebaseBranch, } from '@volter/world-core';
|
|
34
|
+
import { appendActionIfAbsent, branchEntries, branchLogPath, branchMetaPath, changesetContentHash, confirmAction, parentLogPath, readTree, stateDirName, wholeLog, worldNow, parentEntries, readBranchMeta, rebaseBranch, } from '@volter/world-core';
|
|
35
35
|
import { approveWorldChangeset, createWorldChangeset, diffWorld, findWorldChangeset, listWorldChangesets, pushWorldChangeset, verifyWorldChangeset, worldChangesetsDir } from "./changeset.js";
|
|
36
36
|
import { fetchFromOrigin } from "./origin.js";
|
|
37
37
|
import { CONSOLE_BASE, consoleRedirect, serveConsoleApart } from "./console-apart.js";
|
|
@@ -1315,8 +1315,31 @@ export class WorldDoors {
|
|
|
1315
1315
|
const store = getActiveWorldStore();
|
|
1316
1316
|
const key = () => { const t = store.read(tokenPath)?.trim(); if (!t)
|
|
1317
1317
|
throw new Error(`${this.served} has no origin — PUT /-/${this.served}/origin { url, token }`); return t; };
|
|
1318
|
-
if (!name && request.method === 'GET')
|
|
1319
|
-
|
|
1318
|
+
if (!name && request.method === 'GET') {
|
|
1319
|
+
const origin = statusWorld(this.name, this.worldRoot).origin ?? null;
|
|
1320
|
+
if (!origin)
|
|
1321
|
+
return Response.json({ origin: null });
|
|
1322
|
+
// git's "ahead, behind" for this World and its origin, from what is here: ahead, the changes not cut and the
|
|
1323
|
+
// changesets not pushed; behind, per twin, what the last fetch brought that this branch has not taken (a pull
|
|
1324
|
+
// rebases onto it). As of the last fetch: what the origin gained since is known at the next one.
|
|
1325
|
+
const changes = diffWorld(this.name, { root: this.worldRoot }).actions.length;
|
|
1326
|
+
const changesets = listWorldChangesets({ root: this.worldRoot, world: this.name }).filter((l) => !l.changeset.applied || l.changeset.applied.outcome === 'refused').length;
|
|
1327
|
+
const behind = {};
|
|
1328
|
+
for (const twin of Object.keys(this.up().services)) {
|
|
1329
|
+
const meta = readBranchMeta(this.stateOf(twin), this.controlRoot(twin));
|
|
1330
|
+
// nothing fetched since the branch took it (a pull, a push or a rebase clears it) is nothing behind
|
|
1331
|
+
const fetched = meta?.fetchedOrigin;
|
|
1332
|
+
const on = meta?.origin ?? meta?.parent;
|
|
1333
|
+
if (!fetched || !on) {
|
|
1334
|
+
behind[twin] = 0;
|
|
1335
|
+
continue;
|
|
1336
|
+
}
|
|
1337
|
+
const gained = fetched.position - on.position;
|
|
1338
|
+
// a same-length history rewritten is drift too, read as the fetch reads it (a path origin has no remote view)
|
|
1339
|
+
behind[twin] = gained > 0 ? gained : (fetched.remoteView ?? fetched.view) !== (on.remoteView ?? on.view) ? 1 : 0;
|
|
1340
|
+
}
|
|
1341
|
+
return Response.json({ origin, ahead: { changes, changesets }, behind, asOf: origin.fetchedAt ?? null });
|
|
1342
|
+
}
|
|
1320
1343
|
if (!name && request.method === 'PUT') {
|
|
1321
1344
|
const body = (await request.json());
|
|
1322
1345
|
const at = /^(https?:\/\/[^/]+)\/([a-z0-9][a-z0-9_-]*\/[a-z0-9][a-z0-9_-]*)\/?$/i.exec(body.url ?? '');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/world-runtime",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.46",
|
|
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",
|
|
@@ -67,14 +67,14 @@
|
|
|
67
67
|
"node": ">=22.3"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
|
-
"@volter/world-core": "2.0.
|
|
70
|
+
"@volter/world-core": "2.0.28",
|
|
71
71
|
"@volter/world-console": "2.0.13"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"@electric-sql/pglite": "0.5.8",
|
|
75
75
|
"@electric-sql/pglite-pgvector": "0.0.9",
|
|
76
76
|
"@volter/world-access": "2.0.2",
|
|
77
|
-
"@volter/world-core": "2.0.
|
|
77
|
+
"@volter/world-core": "2.0.28",
|
|
78
78
|
"pg-gateway": "0.3.0-beta.4",
|
|
79
79
|
"smol-toml": "^1.8.0"
|
|
80
80
|
},
|
|
@@ -84,6 +84,6 @@
|
|
|
84
84
|
}
|
|
85
85
|
},
|
|
86
86
|
"optionalDependencies": {
|
|
87
|
-
"@volter/twin-mongodb": "0.1.
|
|
87
|
+
"@volter/twin-mongodb": "0.1.28"
|
|
88
88
|
}
|
|
89
89
|
}
|
package/src/served-world.ts
CHANGED
|
@@ -33,7 +33,7 @@ import { createHash } from 'node:crypto';
|
|
|
33
33
|
import { dirname, join, resolve } from 'node:path';
|
|
34
34
|
import {
|
|
35
35
|
appendActionIfAbsent, branchEntries, branchLogPath, branchMetaPath, changesetContentHash, confirmAction, parentLogPath, readTree, stateDirName, wholeLog, worldNow,
|
|
36
|
-
parentEntries, rebaseBranch, type Changeset, type Entry, type Receipt, type RootConfig,
|
|
36
|
+
parentEntries, readBranchMeta, rebaseBranch, type Changeset, type Entry, type Receipt, type RootConfig,
|
|
37
37
|
} from '@volter/world-core';
|
|
38
38
|
import { approveWorldChangeset, createWorldChangeset, diffWorld, findWorldChangeset, listWorldChangesets, pushWorldChangeset, verifyWorldChangeset, worldChangesetsDir } from './changeset.ts';
|
|
39
39
|
import { fetchFromOrigin } from './origin.ts';
|
|
@@ -1131,7 +1131,26 @@ export class WorldDoors {
|
|
|
1131
1131
|
const tokenPath = join(this.worldRoot, stateDirName(), 'origin.token');
|
|
1132
1132
|
const store = getActiveWorldStore();
|
|
1133
1133
|
const key = (): string => { const t = store.read(tokenPath)?.trim(); if (!t) throw new Error(`${this.served} has no origin — PUT /-/${this.served}/origin { url, token }`); return t; };
|
|
1134
|
-
if (!name && request.method === 'GET')
|
|
1134
|
+
if (!name && request.method === 'GET') {
|
|
1135
|
+
const origin = statusWorld(this.name, this.worldRoot).origin ?? null;
|
|
1136
|
+
if (!origin) return Response.json({ origin: null });
|
|
1137
|
+
// git's "ahead, behind" for this World and its origin, from what is here: ahead, the changes not cut and the
|
|
1138
|
+
// changesets not pushed; behind, per twin, what the last fetch brought that this branch has not taken (a pull
|
|
1139
|
+
// rebases onto it). As of the last fetch: what the origin gained since is known at the next one.
|
|
1140
|
+
const changes = diffWorld(this.name, { root: this.worldRoot }).actions.length;
|
|
1141
|
+
const changesets = listWorldChangesets({ root: this.worldRoot, world: this.name }).filter((l) => !l.changeset.applied || l.changeset.applied.outcome === 'refused').length;
|
|
1142
|
+
const behind: Record<string, number> = {};
|
|
1143
|
+
for (const twin of Object.keys(this.up().services)) {
|
|
1144
|
+
const meta = readBranchMeta(this.stateOf(twin), this.controlRoot(twin));
|
|
1145
|
+
// nothing fetched since the branch took it (a pull, a push or a rebase clears it) is nothing behind
|
|
1146
|
+
const fetched = meta?.fetchedOrigin; const on = meta?.origin ?? meta?.parent;
|
|
1147
|
+
if (!fetched || !on) { behind[twin] = 0; continue; }
|
|
1148
|
+
const gained = fetched.position - on.position;
|
|
1149
|
+
// a same-length history rewritten is drift too, read as the fetch reads it (a path origin has no remote view)
|
|
1150
|
+
behind[twin] = gained > 0 ? gained : (fetched.remoteView ?? fetched.view) !== (on.remoteView ?? on.view) ? 1 : 0;
|
|
1151
|
+
}
|
|
1152
|
+
return Response.json({ origin, ahead: { changes, changesets }, behind, asOf: origin.fetchedAt ?? null });
|
|
1153
|
+
}
|
|
1135
1154
|
if (!name && request.method === 'PUT') {
|
|
1136
1155
|
const body = (await request.json()) as { url?: string; token?: string; views?: Record<string, HistoryReference> };
|
|
1137
1156
|
const at = /^(https?:\/\/[^/]+)\/([a-z0-9][a-z0-9_-]*\/[a-z0-9][a-z0-9_-]*)\/?$/i.exec(body.url ?? '');
|