@volter/world-runtime 3.0.47 → 3.0.49

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/world-runtime",
3
- "version": "3.0.47",
3
+ "version": "3.0.49",
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",
@@ -69,14 +69,14 @@
69
69
  "node": ">=22.3"
70
70
  },
71
71
  "peerDependencies": {
72
- "@volter/world-core": "3.0.47",
73
- "@volter/world-console": "3.0.42"
72
+ "@volter/world-core": "3.0.49",
73
+ "@volter/world-console": "3.0.44"
74
74
  },
75
75
  "dependencies": {
76
76
  "@electric-sql/pglite": "0.5.8",
77
77
  "@electric-sql/pglite-pgvector": "0.0.9",
78
78
  "@volter/world-access": "3.0.1",
79
- "@volter/world-core": "3.0.47",
79
+ "@volter/world-core": "3.0.49",
80
80
  "mongodb": "~6.20.0",
81
81
  "pg-gateway": "0.3.0-beta.4",
82
82
  "smol-toml": "^1.8.0",
@@ -23,7 +23,7 @@ import { fileURLToPath } from 'node:url';
23
23
  import { parse } from 'yaml';
24
24
  import { mongodbArgv, mongodbListening, mongodbReady } from './mongodb-backing.ts';
25
25
 
26
- export interface InfraService { kind: string; hostPort: number; replicaSet?: string }
26
+ export interface InfraService { kind: string; hostPort: number; replicaSet?: string; postgres?: { user: string; database: string; password?: string } }
27
27
 
28
28
  /** Read the generated definition's loopback port mappings. MongoDB may explicitly request
29
29
  * one replica-set member through its Compose-compatible command; other mongod options are refused. */
@@ -31,7 +31,7 @@ export function parseInfraDefinition(text: string): InfraService[] {
31
31
  const definition = parse(text);
32
32
  const services: InfraService[] = [];
33
33
  for (const [kind, value] of Object.entries(definition?.services ?? {})) {
34
- const declared = value as { ports?: unknown[]; command?: unknown };
34
+ const declared = value as { ports?: unknown[]; command?: unknown; environment?: Record<string, unknown> };
35
35
  let replicaSet: string | undefined;
36
36
  if (kind === 'mongodb' && declared.command !== undefined) {
37
37
  const command = declared.command;
@@ -46,7 +46,19 @@ export function parseInfraDefinition(text: string): InfraService[] {
46
46
  return match ? [Number(match[1])] : [];
47
47
  });
48
48
  if (ports.length !== 1) throw new Error(`managed infrastructure ${kind} needs exactly one declared loopback port`);
49
- services.push({ kind, hostPort: ports[0]!, ...(replicaSet ? { replicaSet } : {}) });
49
+ let postgres: InfraService['postgres'];
50
+ if (kind === 'postgres') {
51
+ const environment = declared.environment ?? {};
52
+ const user = environment.POSTGRES_USER ?? 'postgres';
53
+ const database = environment.POSTGRES_DB ?? user;
54
+ const password = environment.POSTGRES_PASSWORD;
55
+ if ([user, database, password].some(value => value !== undefined && (typeof value !== 'string' || !value || /[\r\n\0]|\$\{/.test(value)))) {
56
+ throw new Error('World-managed PGlite requires literal POSTGRES_USER, POSTGRES_DB and POSTGRES_PASSWORD');
57
+ }
58
+ if ([user, database].some(value => Buffer.byteLength(value as string, 'utf8') > 63)) throw new Error('World-managed PGlite identifiers must fit PostgreSQL\'s 63-byte name limit');
59
+ postgres = { user: user as string, database: database as string, ...(password !== undefined ? { password: password as string } : {}) };
60
+ }
61
+ services.push({ kind, hostPort: ports[0]!, ...(replicaSet ? { replicaSet } : {}), ...(postgres ? { postgres } : {}) });
50
62
  }
51
63
  return services;
52
64
  }
@@ -167,6 +179,7 @@ export async function pgliteUp(services: InfraService[], dataDir: string, launch
167
179
  }
168
180
  const name = CONTAINERLESS[service.kind] ?? `pglite-${service.kind}`;
169
181
  const serviceData = join(dataDir, containerlessDataDirectory(service.kind) ?? `${name}-data`);
182
+ if (service.kind === 'postgres' && !service.postgres?.password) throw new Error('World-managed PGlite requires a literal POSTGRES_PASSWORD; declare a throwaway World credential');
170
183
  const log = join(dataDir, `${name}.log`);
171
184
  if (await listening(service.hostPort)) {
172
185
  throw new Error(`${name} cannot serve port ${service.hostPort}: another process is already listening on it`);
@@ -184,7 +197,8 @@ export async function pgliteUp(services: InfraService[], dataDir: string, launch
184
197
  const logFd = openSync(log, 'a');
185
198
  const child = spawn(command!, args, {
186
199
  windowsHide: true,
187
- env,
200
+ env: service.postgres ? { ...env, VOLTER_WORLD_PGLITE_USER: service.postgres.user,
201
+ VOLTER_WORLD_PGLITE_DATABASE: service.postgres.database, VOLTER_WORLD_PGLITE_PASSWORD: service.postgres.password } : env,
188
202
  detached: true,
189
203
  stdio: ['ignore', logFd, logFd],
190
204
  });